From 8e15b6a3a5f8713502096b7e9fa26700bafa7031 Mon Sep 17 00:00:00 2001 From: Mike Phares Date: Fri, 24 Feb 2023 20:34:23 -0700 Subject: [PATCH] InfinityQS --- Server/ApiControllers/InfinityQSController.cs | 45 ++++++ Server/ApiControllers/PinController.cs | 2 +- Server/Program.cs | 1 + Server/Repositories/IInfinityQSRepository.cs | 151 ++++++++++++++++++ Server/Repositories/MetrologyRepository.cs | 64 ++++---- Shared/DataModels/InfinityQSBase.cs | 41 +++++ Shared/DataModels/InfinityQSEvent.cs | 74 +++++++++ .../Models/Stateless/IInfinityQSController.cs | 18 +++ .../Models/Stateless/IInfinityQSRepository.cs | 13 ++ Shared/Models/Stateless/IPinController.cs | 3 +- Tests/UnitTestInfinityQSController.cs | 133 +++++++++++++++ azure-pipelines-server-development.yml | 2 +- azure-pipelines-server.yml | 20 +++ 13 files changed, 531 insertions(+), 36 deletions(-) create mode 100644 Server/ApiControllers/InfinityQSController.cs create mode 100644 Server/Repositories/IInfinityQSRepository.cs create mode 100644 Shared/DataModels/InfinityQSBase.cs create mode 100644 Shared/DataModels/InfinityQSEvent.cs create mode 100644 Shared/Models/Stateless/IInfinityQSController.cs create mode 100644 Shared/Models/Stateless/IInfinityQSRepository.cs create mode 100644 Tests/UnitTestInfinityQSController.cs diff --git a/Server/ApiControllers/InfinityQSController.cs b/Server/ApiControllers/InfinityQSController.cs new file mode 100644 index 0000000..a4c4654 --- /dev/null +++ b/Server/ApiControllers/InfinityQSController.cs @@ -0,0 +1,45 @@ +using Microsoft.AspNetCore.Mvc; + +namespace OI.Metrology.Server.ApiControllers; + +using OI.Metrology.Shared.DataModels; +using OI.Metrology.Shared.Models.Stateless; +using System.Text.Json; + +[Route("api/[controller]")] +public class InfinityQSController : Controller, IInfinityQSController +{ + + private readonly IInfinityQSRepository _InfinityQSRepository; + + public InfinityQSController(IInfinityQSRepository InfinityQSRepository) => _InfinityQSRepository = InfinityQSRepository; + + [HttpGet("commandText")] + public IActionResult GetCommandText(string sub_group_id, string process, string job, string part, string lot, string date_time) + { + string commandText = _InfinityQSRepository.GetCommandText(sub_group_id, process, job, part, lot, date_time); + return Content(commandText, "text/plain; charset=utf-8"); + } + + [HttpGet("{sub_group_id}/data")] + public IActionResult GetData(string sub_group_id) + { + Result result = _InfinityQSRepository.GetData(sub_group_id); + return Json(result, new JsonSerializerOptions { PropertyNamingPolicy = null, WriteIndented = true }); + } + + [HttpGet("{sub_group_id}/events")] + public IActionResult GetEvents(string sub_group_id) + { + Result result = _InfinityQSRepository.GetEvents(sub_group_id); + return Json(result, new JsonSerializerOptions { PropertyNamingPolicy = null, WriteIndented = true }); + } + + [HttpGet("{sub_group_id}/header")] + public IActionResult GetHeader(string sub_group_id) + { + Result result = _InfinityQSRepository.GetHeader(sub_group_id); + return Json(result, new JsonSerializerOptions { PropertyNamingPolicy = null, WriteIndented = true }); + } + +} \ No newline at end of file diff --git a/Server/ApiControllers/PinController.cs b/Server/ApiControllers/PinController.cs index c403959..585db91 100644 --- a/Server/ApiControllers/PinController.cs +++ b/Server/ApiControllers/PinController.cs @@ -12,7 +12,7 @@ public class PinController : Controller, IPinController private readonly IPinRepository _PinRepository; private readonly IMetrologyRepository _MetrologyRepository; - public PinController(ILogger logger, IMetrologyRepository metrologyRepository, IPinRepository pinRepository) + public PinController(IMetrologyRepository metrologyRepository, IPinRepository pinRepository) { _MetrologyRepository = metrologyRepository; _PinRepository = pinRepository; diff --git a/Server/Program.cs b/Server/Program.cs index 0263553..8d0c09c 100644 --- a/Server/Program.cs +++ b/Server/Program.cs @@ -67,6 +67,7 @@ public class Program _ = webApplicationBuilder.Services.AddSingleton(_ => appSettings); _ = webApplicationBuilder.Services.AddSingleton(); + _ = webApplicationBuilder.Services.AddSingleton(); _ = webApplicationBuilder.Services.AddSingleton(_ => clientSettingsRepository); _ = webApplicationBuilder.Services.AddSingleton(); _ = webApplicationBuilder.Services.AddSingleton(_ => new(appSettings.MockRoot)); diff --git a/Server/Repositories/IInfinityQSRepository.cs b/Server/Repositories/IInfinityQSRepository.cs new file mode 100644 index 0000000..e6846d7 --- /dev/null +++ b/Server/Repositories/IInfinityQSRepository.cs @@ -0,0 +1,151 @@ +using OI.Metrology.Shared.DataModels; +using OI.Metrology.Shared.Models.Stateless; +using OI.Metrology.Shared.Repositories; +using System.Data; +using System.Data.Common; +using System.Text; +using System.Text.Json; + +namespace OI.Metrology.Server.Repository; + +public class InfinityQSRepository : IInfinityQSRepository +{ + + private readonly IDbConnectionFactory _DBConnectionFactory; + + public InfinityQSRepository(IDbConnectionFactory dbConnectionFactory) => _DBConnectionFactory = dbConnectionFactory; + + string IInfinityQSRepository.GetCommandText(string? subGroupId, string? process, string? job, string? part, string? lot, string? dateTime) + { + StringBuilder result = new(); + const string dateTimeFormat = "yyyy-MM-dd HH:mm:ss"; + if (!string.IsNullOrEmpty(dateTime) && (dateTime.Contains('-') || dateTime.Contains(' ') || dateTime.Contains(':')) && dateTime.Length != dateTimeFormat.Length) + throw new ArgumentException(nameof(dateTime)); + _ = result + .AppendLine(" select ") + .AppendLine(" se.f_sgrp se_sgrp, ") + .AppendLine(" se.f_sgtm se_sgtm, ") + .AppendLine(" se.f_tsno se_tsno, ") + .AppendLine(" se.f_val se_val, ") + .AppendLine(" rd.f_name rd_name, ") + .AppendLine(" jd.f_name jd_name, ") + .AppendLine(" pl.f_name pl_name, ") + .AppendLine(" pd.f_name pd_name, ") + .AppendLine(" td.f_test td_test, ") + .AppendLine(" td.f_name td_name, ") + .AppendLine(" (select count(ev.f_evnt) ") + .AppendLine(" from [spcepiworld].[dbo].[evnt_inf] ev ") + .AppendLine(" where ev.f_prcs = rd.f_prcs ") + .AppendLine(" and ev.f_part = pd.f_part ") + .AppendLine(" and ev.f_sgtm = se.f_sgtm) ev_count ") + .AppendLine(" from [spcepiworld].[dbo].[sgrp_ext] se ") + .AppendLine(" join [spcepiworld].[dbo].[prcs_dat] rd ") + .AppendLine(" on se.f_prcs = rd.f_prcs ") + .AppendLine(" join [spcepiworld].[dbo].[job_dat] jd ") + .AppendLine(" on se.f_job = jd.f_job ") + .AppendLine(" join [spcepiworld].[dbo].[part_lot] pl ") + .AppendLine(" on se.f_lot = pl.f_lot ") + .AppendLine(" join [spcepiworld].[dbo].[part_dat] pd ") + .AppendLine(" on se.f_part = pd.f_part ") + .AppendLine(" join [spcepiworld].[dbo].[test_dat] td ") + .AppendLine(" on se.f_test = td.f_test ") + .AppendLine(" where se.f_flag = 0 "); + if (!string.IsNullOrEmpty(subGroupId)) + _ = result.Append(" and se.f_sgrp = ").Append(subGroupId.Split(" ")[0]).AppendLine(" "); + if (!string.IsNullOrEmpty(process)) + _ = result.Append(" and rd.f_name = '").Append(process).AppendLine("' "); + if (!string.IsNullOrEmpty(part)) + _ = result.Append(" and pd.f_name = '").Append(part).AppendLine("' "); + if (!string.IsNullOrEmpty(job)) + _ = result.Append(" and jd.f_name = '").Append(job).AppendLine("' "); + if (!string.IsNullOrEmpty(lot)) + _ = result.Append(" and pl.f_name = '").Append(lot).AppendLine("' "); + if (!string.IsNullOrEmpty(dateTime) && (dateTime.Contains('-') || dateTime.Contains(' ') || dateTime.Contains(':'))) + _ = result.Append(" and dateadd(HH, -7, (dateadd(SS, convert(bigint, se.f_sgtm), '19700101'))) = '").Append(dateTime).AppendLine("' "); + _ = result.AppendLine(" for json path "); + return result.ToString(); + } + + private static StringBuilder GetForJsonPath(IDbConnectionFactory dbConnectionFactory, string commandText) + { + StringBuilder stringBuilder = new(); + using DbConnection dbConnection = dbConnectionFactory.GetDbConnection(); + DbCommand dbCommand = dbConnection.CreateCommand(); + dbCommand.CommandText = commandText; + DbDataReader dbDataReader = dbCommand.ExecuteReader(CommandBehavior.SequentialAccess); + while (dbDataReader.Read()) + _ = stringBuilder.Append(dbDataReader.GetString(0)); + return stringBuilder; + } + + private static InfinityQSBase GetInfinityQSBase(IDbConnectionFactory dbConnectionFactory, IInfinityQSRepository infinityQSRepository, string subGroupId) + { + InfinityQSBase result; + string commandText = infinityQSRepository.GetCommandText(subGroupId, process: string.Empty, job: string.Empty, part: string.Empty, lot: string.Empty, dateTime: string.Empty); + StringBuilder stringBuilder = GetForJsonPath(dbConnectionFactory, commandText); + InfinityQSBase[]? results = JsonSerializer.Deserialize(stringBuilder.ToString()); + if (results is null) + throw new NullReferenceException(nameof(results)); + if (results.Select(l => l.SubGroupId).Distinct().Count() != 1) + throw new NotSupportedException("Multiple ids are present!"); + result = results.First(); + return result; + } + + Result IInfinityQSRepository.GetData(string subGroupId) + { + Result? result; + IInfinityQSRepository infinityQSRepository = this; + InfinityQSBase infinityQSBase = GetInfinityQSBase(_DBConnectionFactory, infinityQSRepository, subGroupId); + string commandText = infinityQSRepository.GetCommandText(subGroupId, process: infinityQSBase.Process, job: infinityQSBase.Job, part: infinityQSBase.Part, lot: infinityQSBase.Lot, dateTime: string.Concat(infinityQSBase.SubGroupDateTime)); + StringBuilder stringBuilder = GetForJsonPath(_DBConnectionFactory, commandText); + InfinityQSBase[]? results = JsonSerializer.Deserialize(stringBuilder.ToString()); + if (results is null) + throw new NullReferenceException(nameof(results)); + result = new() + { + Results = results, + TotalRows = results.Length, + }; + return result; + } + + Result IInfinityQSRepository.GetEvents(string subGroupId) + { + Result? result; + IInfinityQSRepository infinityQSRepository = this; + InfinityQSEvent[]? results; + InfinityQSBase infinityQSBase = GetInfinityQSBase(_DBConnectionFactory, infinityQSRepository, subGroupId); + if (!infinityQSBase.EventCount.HasValue || infinityQSBase.EventCount.Value <= 0) + results = Array.Empty(); + else + { + string commandText = $"select * from [spcepiworld].[dbo].[evnt_inf] ev where ev.f_prcs = '{infinityQSBase.Process}' and ev.f_part = '{infinityQSBase.Part}' and ev.f_sgtm = {infinityQSBase.SubGroupDateTime} "; + StringBuilder stringBuilder = GetForJsonPath(_DBConnectionFactory, commandText); + results = JsonSerializer.Deserialize(stringBuilder.ToString()); + if (results is null) + throw new NullReferenceException(nameof(results)); + } + result = new() + { + Results = results, + TotalRows = results.Length, + }; + return result; + } + + Result IInfinityQSRepository.GetHeader(string subGroupId) + { + Result? result; + IInfinityQSRepository infinityQSRepository = this; + InfinityQSBase infinityQSBase = GetInfinityQSBase(_DBConnectionFactory, infinityQSRepository, subGroupId); + InfinityQSBase[] results = new InfinityQSBase[] { infinityQSBase }; + result = new() + { + Results = results, + TotalRows = results.Length, + }; + return result; + } + +} \ No newline at end of file diff --git a/Server/Repositories/MetrologyRepository.cs b/Server/Repositories/MetrologyRepository.cs index 99542ad..11dddfe 100644 --- a/Server/Repositories/MetrologyRepository.cs +++ b/Server/Repositories/MetrologyRepository.cs @@ -17,18 +17,16 @@ namespace OI.Metrology.Server.Repositories; public class MetrologyRepository : IMetrologyRepository { private readonly string _MockRoot; - private readonly IMemoryCache _Cache; + private readonly IMemoryCache _MemoryCache; private readonly IDbConnectionFactory _DBConnectionFactory; public MetrologyRepository(AppSettings appSettings, IDbConnectionFactory dbConnectionFactory, IMemoryCache memoryCache) { - _Cache = memoryCache; + _MemoryCache = memoryCache; _MockRoot = appSettings.MockRoot; _DBConnectionFactory = dbConnectionFactory; } - private DbConnection GetDbConnection() => _DBConnectionFactory.GetDbConnection(); - protected DbProviderFactory GetDbProviderFactory(IDbConnection conn) => DbProviderFactories.GetFactory(conn.GetType().Namespace); @@ -38,17 +36,17 @@ public class MetrologyRepository : IMetrologyRepository { System.Diagnostics.Debug.WriteLine("CacheItem: " + key); - _ = _Cache.Set(key, v, new MemoryCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromHours(1))); + _ = _MemoryCache.Set(key, v, new MemoryCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromHours(1))); } internal IEnumerable GetToolTypes() { IEnumerable cached; string cacheKey = "GetToolTypes"; - if (_Cache.TryGetValue(cacheKey, out cached)) + if (_MemoryCache.TryGetValue(cacheKey, out cached)) return cached; - using DbConnection conn = GetDbConnection(); + using DbConnection conn = _DBConnectionFactory.GetDbConnection(); IEnumerable r = conn.Query("SELECT * FROM ToolType"); CacheItem(cacheKey, r); @@ -60,10 +58,10 @@ public class MetrologyRepository : IMetrologyRepository { ToolType cached; string cacheKey = "GetToolTypeByName_" + name; - if (_Cache.TryGetValue(cacheKey, out cached)) + if (_MemoryCache.TryGetValue(cacheKey, out cached)) return cached; - using DbConnection conn = GetDbConnection(); + using DbConnection conn = _DBConnectionFactory.GetDbConnection(); ToolType r = conn.QueryFirstOrDefault( "SELECT * FROM ToolType WHERE ToolTypeName = @name", new { name }); @@ -77,10 +75,10 @@ public class MetrologyRepository : IMetrologyRepository { ToolType cached; string cacheKey = "GetToolTypeByID_" + id.ToString(); - if (_Cache.TryGetValue(cacheKey, out cached)) + if (_MemoryCache.TryGetValue(cacheKey, out cached)) return cached; - using DbConnection conn = GetDbConnection(); + using DbConnection conn = _DBConnectionFactory.GetDbConnection(); ToolType r = conn.QueryFirstOrDefault( "SELECT * FROM ToolType WHERE ID = @id", new { id }); @@ -94,10 +92,10 @@ public class MetrologyRepository : IMetrologyRepository { IEnumerable cached; string cacheKey = "GetToolTypeMetadataByToolTypeID_" + id.ToString(); - if (_Cache.TryGetValue(cacheKey, out cached)) + if (_MemoryCache.TryGetValue(cacheKey, out cached)) return cached; - using DbConnection conn = GetDbConnection(); + using DbConnection conn = _DBConnectionFactory.GetDbConnection(); IEnumerable r = conn.Query( "SELECT * FROM ToolTypeMetadata WHERE ToolTypeID = @id", new { id }); @@ -110,7 +108,7 @@ public class MetrologyRepository : IMetrologyRepository internal long InsertToolDataJSON(JToken jsonrow, long headerId, List metaData, string tableName) { long r = -1; - using (DbConnection conn = GetDbConnection()) + using (DbConnection conn = _DBConnectionFactory.GetDbConnection()) { bool isHeader = headerId <= 0; @@ -267,7 +265,7 @@ public class MetrologyRepository : IMetrologyRepository DataTable dt = new(); DateTime endTimeLocal = endTime.ToLocalTime(); DateTime startTimeLocal = startTime.ToLocalTime(); - using (DbConnection conn = GetDbConnection()) + using (DbConnection conn = _DBConnectionFactory.GetDbConnection()) { DbProviderFactory factory = GetDbProviderFactory(conn); @@ -323,7 +321,7 @@ public class MetrologyRepository : IMetrologyRepository throw new Exception("Invalid tool type metadata"); DataTable dt = new(); - using (DbConnection conn = GetDbConnection()) + using (DbConnection conn = _DBConnectionFactory.GetDbConnection()) { StringBuilder sb = new(); _ = sb.Append( @@ -416,7 +414,7 @@ public class MetrologyRepository : IMetrologyRepository throw new Exception("Invalid tool type metadata"); DataTable dt = new(); - using (DbConnection conn = GetDbConnection()) + using (DbConnection conn = _DBConnectionFactory.GetDbConnection()) { StringBuilder sb = new(); _ = sb.Append( @@ -506,7 +504,7 @@ public class MetrologyRepository : IMetrologyRepository if (tt is null) throw new Exception("Invalid tool type ID"); - using DbConnection conn = GetDbConnection(); + using DbConnection conn = _DBConnectionFactory.GetDbConnection(); string sql = $"UPDATE [{tt.HeaderTableName}] SET AttachmentID = NEWID() WHERE ID = @HeaderID AND AttachmentID IS NULL; " + $"SELECT AttachmentID FROM [{tt.HeaderTableName}] WHERE ID = @HeaderID"; @@ -518,14 +516,14 @@ public class MetrologyRepository : IMetrologyRepository if (tt is null) throw new Exception("Invalid tool type ID"); - using DbConnection conn = GetDbConnection(); + using DbConnection conn = _DBConnectionFactory.GetDbConnection(); string sql = $"SELECT CONVERT(varchar, case when [InsertDate] < [Date] or [Date] is null then [InsertDate] else [Date] end, 120) d FROM[{tt.HeaderTableName}] where ID = @HeaderID"; return conn.ExecuteScalar(sql, param: new { HeaderID = headerId }); } internal string GetAttachmentInsertDateByGUID(string tableName, Guid attachmentId) { - using DbConnection conn = GetDbConnection(); + using DbConnection conn = _DBConnectionFactory.GetDbConnection(); string sql = ""; if (tableName is "SP1RunData" or "TencorRunData") { @@ -540,7 +538,7 @@ public class MetrologyRepository : IMetrologyRepository } internal void SetHeaderDirName(string tableName, long headerId, string dateDir) { - using DbConnection conn = GetDbConnection(); + using DbConnection conn = _DBConnectionFactory.GetDbConnection(); _ = conn.Execute($"UPDATE [{tableName}] SET AttachDirName = @AttachDirName WHERE ID = @HeaderID;", new { HeaderID = headerId, AttachDirName = dateDir }); } @@ -550,7 +548,7 @@ public class MetrologyRepository : IMetrologyRepository if (tt is null) throw new Exception("Invalid tool type ID"); - using DbConnection conn = GetDbConnection(); + using DbConnection conn = _DBConnectionFactory.GetDbConnection(); string sql = $"UPDATE [{tt.DataTableName}] SET AttachmentID = NEWID() WHERE HeaderID = @HeaderID AND Title = @Title AND AttachmentID IS NULL; " + $"SELECT AttachmentID FROM [{tt.DataTableName}] WHERE HeaderID = @HeaderID AND Title = @Title"; @@ -563,7 +561,7 @@ public class MetrologyRepository : IMetrologyRepository if (tt is null) throw new Exception("Invalid tool type ID"); - using DbConnection conn = GetDbConnection(); + using DbConnection conn = _DBConnectionFactory.GetDbConnection(); string sql = ""; if (tt.DataTableName is "" or "") { @@ -578,7 +576,7 @@ public class MetrologyRepository : IMetrologyRepository } internal void SetDataDirName(string tableName, long headerId, string title, string dateDir) { - using DbConnection conn = GetDbConnection(); + using DbConnection conn = _DBConnectionFactory.GetDbConnection(); string sql = $"UPDATE [{tableName}] SET AttachDirName = @AttachDirName WHERE HeaderID = @HeaderID AND Title = @Title;"; _ = conn.Execute(sql, param: new { HeaderID = headerId, Title = title, AttachDirName = dateDir }); @@ -586,7 +584,7 @@ public class MetrologyRepository : IMetrologyRepository internal void PurgeExistingData(int toolTypeId, string title) { - using DbConnection conn = GetDbConnection(); + using DbConnection conn = _DBConnectionFactory.GetDbConnection(); _ = conn.Execute("PurgeExistingData", param: new { ToolTypeID = toolTypeId, Title = title }, commandType: CommandType.StoredProcedure); } @@ -600,7 +598,7 @@ public class MetrologyRepository : IMetrologyRepository throw new Exception("OpenInsight export not available for " + tt.ToolTypeName); DataSet ds = new(); - using (DbConnection conn = GetDbConnection()) + using (DbConnection conn = _DBConnectionFactory.GetDbConnection()) { DbProviderFactory factory = GetDbProviderFactory(conn); @@ -629,7 +627,7 @@ public class MetrologyRepository : IMetrologyRepository ToolType tt; StringBuilder stringBuilder = new(); - using DbConnection conn = GetDbConnection(); + using DbConnection conn = _DBConnectionFactory.GetDbConnection(); _ = stringBuilder.Append(" SELECT * FROM ( "); for (int i = 0; i < toolTypes.Length; i++) { @@ -661,7 +659,7 @@ public class MetrologyRepository : IMetrologyRepository if (tt is null) throw new Exception("Invalid tool type ID"); - using DbConnection conn = GetDbConnection(); + using DbConnection conn = _DBConnectionFactory.GetDbConnection(); string sql = $"SELECT ID, InsertDate, AttachmentID, Title, [Date], {tt.ID} AS ToolTypeID, '{tt.ToolTypeName}' AS ToolTypeName, Reactor, RDS, PSN FROM {tt.HeaderTableName} ORDER BY [Date] DESC "; if (pageNo.HasValue && pageSize.HasValue) @@ -694,7 +692,7 @@ public class MetrologyRepository : IMetrologyRepository List> r = new(); - using (DbConnection conn = GetDbConnection()) + using (DbConnection conn = _DBConnectionFactory.GetDbConnection()) { DbProviderFactory factory = GetDbProviderFactory(conn); @@ -741,7 +739,7 @@ public class MetrologyRepository : IMetrologyRepository } else { - using DbConnection conn = GetDbConnection(); + using DbConnection conn = _DBConnectionFactory.GetDbConnection(); r = conn.Query("GetAwaitingDispo", commandType: CommandType.StoredProcedure); } return r; @@ -753,7 +751,7 @@ public class MetrologyRepository : IMetrologyRepository if (tt is null) throw new Exception("Invalid tool type ID"); - using DbConnection conn = GetDbConnection(); + using DbConnection conn = _DBConnectionFactory.GetDbConnection(); if (clearDate) { // if it's already past the 6 hour window, then it won't show in queue anyway, so need to return value so we can show that @@ -775,7 +773,7 @@ public class MetrologyRepository : IMetrologyRepository if (tt is null) throw new Exception("Invalid tool type ID"); - using DbConnection conn = GetDbConnection(); + using DbConnection conn = _DBConnectionFactory.GetDbConnection(); string sql = $"SELECT TOP 1 AttachmentID FROM [{tt.HeaderTableName}] WHERE Title = @Title ORDER BY InsertDate DESC"; return conn.ExecuteScalar(sql, param: new { Title = title }); @@ -787,7 +785,7 @@ public class MetrologyRepository : IMetrologyRepository if (tt is null) throw new Exception("Invalid tool type ID"); - using DbConnection conn = GetDbConnection(); + using DbConnection conn = _DBConnectionFactory.GetDbConnection(); string sql = $"SELECT TOP 1 AttachmentID FROM [{tt.DataTableName}] WHERE Title = @Title ORDER BY InsertDate DESC"; return conn.ExecuteScalar(sql, param: new { Title = title }); diff --git a/Shared/DataModels/InfinityQSBase.cs b/Shared/DataModels/InfinityQSBase.cs new file mode 100644 index 0000000..54afb70 --- /dev/null +++ b/Shared/DataModels/InfinityQSBase.cs @@ -0,0 +1,41 @@ +using System.Text.Json.Serialization; + +namespace OI.Metrology.Shared.DataModels; + +public class InfinityQSBase +{ + + [JsonPropertyName("se_sgrp")] + public int? SubGroupId { get; set; } + + [JsonPropertyName("se_sgtm")] + public int? SubGroupDateTime { get; set; } + + [JsonPropertyName("se_tsno")] + public int? TestNumber { get; set; } + + [JsonPropertyName("rd_name")] + public string? Process { get; set; } + + [JsonPropertyName("jd_name")] + public string? Job { get; set; } + + [JsonPropertyName("pl_name")] + public string? Lot { get; set; } + + [JsonPropertyName("pd_name")] + public string? Part { get; set; } + + [JsonPropertyName("td_test")] + public int? Test { get; set; } + + [JsonPropertyName("td_name")] + public string? TestName { get; set; } + + [JsonPropertyName("se_val")] + public double? Value { get; set; } + + [JsonPropertyName("ev_count")] + public int? EventCount { get; set; } + +} \ No newline at end of file diff --git a/Shared/DataModels/InfinityQSEvent.cs b/Shared/DataModels/InfinityQSEvent.cs new file mode 100644 index 0000000..63d0513 --- /dev/null +++ b/Shared/DataModels/InfinityQSEvent.cs @@ -0,0 +1,74 @@ +using System.Text.Json.Serialization; + +namespace OI.Metrology.Shared.DataModels; + +public class InfinityQSEvent +{ + + [JsonPropertyName("F_EVNT")] + public int Evnt { get; set; } + + [JsonPropertyName("F_CRTM")] + public int Crtm { get; set; } + + [JsonPropertyName("F_EDTM")] + public int Edtm { get; set; } + + [JsonPropertyName("F_TYPE")] + public int Type { get; set; } + + [JsonPropertyName("F_NAME")] + public string? Name { get; set; } + + [JsonPropertyName("F_EMPL")] + public int Empl { get; set; } + + [JsonPropertyName("F_EVTM")] + public int Evtm { get; set; } + + [JsonPropertyName("F_PRCS")] + public int Prcs { get; set; } + + [JsonPropertyName("F_PART")] + public int Part { get; set; } + + [JsonPropertyName("F_TEST")] + public int Test { get; set; } + + [JsonPropertyName("F_SGTM")] + public int Sgtm { get; set; } + + [JsonPropertyName("F_ACC")] + public int Acc { get; set; } + + [JsonPropertyName("F_ACEM")] + public int Acem { get; set; } + + [JsonPropertyName("F_ACTM")] + public int Actm { get; set; } + + [JsonPropertyName("F_CAC")] + public int Cac { get; set; } + + [JsonPropertyName("F_CAEM")] + public int Caem { get; set; } + + [JsonPropertyName("F_CATM")] + public int Catm { get; set; } + + [JsonPropertyName("F_FLAG")] + public int Flag { get; set; } + + [JsonPropertyName("F_USER")] + public int User { get; set; } + + [JsonPropertyName("F_DSBL")] + public int Dsbl { get; set; } + + [JsonPropertyName("F_RFC")] + public int Rfc { get; set; } + + [JsonPropertyName("F_TRTM")] + public int Trtm { get; set; } + +} \ No newline at end of file diff --git a/Shared/Models/Stateless/IInfinityQSController.cs b/Shared/Models/Stateless/IInfinityQSController.cs new file mode 100644 index 0000000..a98716d --- /dev/null +++ b/Shared/Models/Stateless/IInfinityQSController.cs @@ -0,0 +1,18 @@ +namespace OI.Metrology.Shared.Models.Stateless; + +public interface IInfinityQSController +{ + + enum Action : int + { + Index = 0, + MarkAsPinned = 1 + } + + static string GetRouteName() => nameof(IInfinityQSController)[1..^10]; + T GetCommandText(string sub_group_id, string process, string job, string part, string lot, string date_time); + T GetData(string sub_group_id); + T GetEvents(string sub_group_id); + T GetHeader(string sub_group_id); + +} \ No newline at end of file diff --git a/Shared/Models/Stateless/IInfinityQSRepository.cs b/Shared/Models/Stateless/IInfinityQSRepository.cs new file mode 100644 index 0000000..45c9a03 --- /dev/null +++ b/Shared/Models/Stateless/IInfinityQSRepository.cs @@ -0,0 +1,13 @@ +using OI.Metrology.Shared.DataModels; + +namespace OI.Metrology.Shared.Models.Stateless; + +public interface IInfinityQSRepository +{ + + string GetCommandText(string? subGroupId, string? process, string? job, string? part, string? lot, string? dateTime); + Result GetData(string subGroupId); + Result GetHeader(string subGroupId); + Result GetEvents(string subGroupId); + +} \ No newline at end of file diff --git a/Shared/Models/Stateless/IPinController.cs b/Shared/Models/Stateless/IPinController.cs index 61c099f..59c0ac1 100644 --- a/Shared/Models/Stateless/IPinController.cs +++ b/Shared/Models/Stateless/IPinController.cs @@ -6,7 +6,8 @@ public interface IPinController enum Action : int { Index = 0, - MarkAsPinned = 1 + MarkAsPinned = 1, + PinnedTable = 2 } static string GetRouteName() => nameof(IPinController)[1..^10]; diff --git a/Tests/UnitTestInfinityQSController.cs b/Tests/UnitTestInfinityQSController.cs new file mode 100644 index 0000000..53b1a1e --- /dev/null +++ b/Tests/UnitTestInfinityQSController.cs @@ -0,0 +1,133 @@ +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.Extensions.DependencyInjection; +using OI.Metrology.Shared.DataModels; +using OI.Metrology.Shared.Models.Stateless; +using Serilog; + +namespace OI.Metrology.Tests; + +[TestClass] +public class UnitTestInfinityQSController +{ + +#pragma warning disable CS8618 + + private static ILogger _Logger; + private static string _ControllerName; + private static TestContext _TestContext; + private static WebApplicationFactory _WebApplicationFactory; + +#pragma warning restore + + [ClassInitialize] + public static void ClassInitAsync(TestContext testContext) + { + _TestContext = testContext; + _Logger = Log.ForContext(); + _WebApplicationFactory = new WebApplicationFactory(); + _ControllerName = nameof(Server.ApiControllers.InfinityQSController)[..^10]; + } + + [TestMethod] + public void TestControllerName() + { + _Logger.Information("Starting Web Application"); + Assert.AreEqual(IInfinityQSController.GetRouteName(), _ControllerName); + _Logger.Information($"{_TestContext?.TestName} completed"); + } + + [TestMethod] + public void GetCommandText() + { + _Logger.Information("Starting Web Application"); + IServiceProvider serviceProvider = _WebApplicationFactory.Services.CreateScope().ServiceProvider; + IInfinityQSRepository infinityQSRepository = serviceProvider.GetRequiredService(); + string result = infinityQSRepository.GetCommandText("1677273357", "61", "CDE5", "5012", "575908", ""); + Assert.IsNotNull(result); + _Logger.Information($"{_TestContext?.TestName} completed"); + } + + [TestMethod] + public async Task GetCommandTextApi() + { + HttpClient httpClient = _WebApplicationFactory.CreateClient(); + _Logger.Information("Starting Web Application"); + string? json = await httpClient.GetStringAsync($"api/{_ControllerName}/commandText/?sub_group_id=1677273357&process=61&job=CDE5&part=5012&lot=575908&date_time=2023-02-24 15:15:00"); + File.WriteAllText(Path.Combine(AppContext.BaseDirectory, $"{nameof(GetCommandTextApi)}.json"), json); + Assert.IsNotNull(json); + _Logger.Information($"{_TestContext?.TestName} completed"); + } + + [TestMethod] + public void GetData() + { + _Logger.Information("Starting Web Application"); + IServiceProvider serviceProvider = _WebApplicationFactory.Services.CreateScope().ServiceProvider; + IInfinityQSRepository infinityQSRepository = serviceProvider.GetRequiredService(); + Result result = infinityQSRepository.GetData("1677273357"); + Assert.IsNotNull(result?.Results); + Assert.IsTrue(result?.Results.Any()); + Assert.IsNotNull(result?.Results[0].SubGroupDateTime); + _Logger.Information($"{_TestContext?.TestName} completed"); + } + + [TestMethod] + public async Task GetDataApi() + { + HttpClient httpClient = _WebApplicationFactory.CreateClient(); + _Logger.Information("Starting Web Application"); + //string? json = await httpClient.GetStringAsync($"api/{_ControllerName}/1677273357 575908_2023-02-24 14-18-05.txt/data"); + string? json = await httpClient.GetStringAsync($"api/{_ControllerName}/1677273357/data"); + File.WriteAllText(Path.Combine(AppContext.BaseDirectory, $"{nameof(GetDataApi)}.json"), json); + Result? result = System.Text.Json.JsonSerializer.Deserialize>(json); + Assert.IsNotNull(result?.Results); + _Logger.Information($"{_TestContext?.TestName} completed"); + } + + [TestMethod] + public void GetEvents() + { + _Logger.Information("Starting Web Application"); + IServiceProvider serviceProvider = _WebApplicationFactory.Services.CreateScope().ServiceProvider; + IInfinityQSRepository infinityQSRepository = serviceProvider.GetRequiredService(); + Result result = infinityQSRepository.GetEvents("1677273357"); + Assert.IsNotNull(result?.Results); + _Logger.Information($"{_TestContext?.TestName} completed"); + } + + [TestMethod] + public async Task GetEventsApi() + { + HttpClient httpClient = _WebApplicationFactory.CreateClient(); + _Logger.Information("Starting Web Application"); + string? json = await httpClient.GetStringAsync($"api/{_ControllerName}/1677273357/events"); + File.WriteAllText(Path.Combine(AppContext.BaseDirectory, $"{nameof(GetEventsApi)}.json"), json); + Result? result = System.Text.Json.JsonSerializer.Deserialize>(json); + Assert.IsNotNull(result?.Results); + _Logger.Information($"{_TestContext?.TestName} completed"); + } + + [TestMethod] + public void GetHeader() + { + _Logger.Information("Starting Web Application"); + IServiceProvider serviceProvider = _WebApplicationFactory.Services.CreateScope().ServiceProvider; + IInfinityQSRepository infinityQSRepository = serviceProvider.GetRequiredService(); + Result result = infinityQSRepository.GetHeader("1677273357"); + Assert.IsNotNull(result?.Results); + _Logger.Information($"{_TestContext?.TestName} completed"); + } + + [TestMethod] + public async Task GetHeaderApi() + { + HttpClient httpClient = _WebApplicationFactory.CreateClient(); + _Logger.Information("Starting Web Application"); + string? json = await httpClient.GetStringAsync($"api/{_ControllerName}/1677273357/header"); + File.WriteAllText(Path.Combine(AppContext.BaseDirectory, $"{nameof(GetHeaderApi)}.json"), json); + Result? result = System.Text.Json.JsonSerializer.Deserialize>(json); + Assert.IsNotNull(result?.Results); + _Logger.Information($"{_TestContext?.TestName} completed"); + } + +} \ No newline at end of file diff --git a/azure-pipelines-server-development.yml b/azure-pipelines-server-development.yml index 920ab21..883f576 100644 --- a/azure-pipelines-server-development.yml +++ b/azure-pipelines-server-development.yml @@ -84,7 +84,7 @@ steps: - script: "dotnet test --configuration $(Configuration)" workingDirectory: Tests displayName: "Core Test" - # enabled: false + enabled: false - script: '"C:\program files\dotnet\dotnet.exe" tool restore' workingDirectory: Server diff --git a/azure-pipelines-server.yml b/azure-pipelines-server.yml index 8adc99a..b22bb8a 100644 --- a/azure-pipelines-server.yml +++ b/azure-pipelines-server.yml @@ -76,6 +76,10 @@ steps: - script: '"C:\program files\dotnet\dotnet.exe" build --configuration $(Configuration) --source $(NugetSource)' workingDirectory: Server displayName: "Core Build - Server" + + - powershell: Get-ChildItem .\ -include TestResults -Recurse | foreach ($_) { remove-item $_.fullname -Force -Recurse } + workingDirectory: "$(System.DefaultWorkingDirectory)/.vscode" + displayName: 'PowerShell Script' - script: "dotnet test --configuration $(Configuration)" workingDirectory: Tests @@ -92,6 +96,22 @@ steps: displayName: "Report Generator" enabled: false + - task: PublishTestResults@2 + displayName: "Publish Test Results **/*.trx" + inputs: + testResultsFormat: VSTest + testResultsFiles: "**/*.trx" + searchFolder: "$(System.DefaultWorkingDirectory)/.vscode" + + - task: mspremier.CreateWorkItem.CreateWorkItem-task.CreateWorkItem@1 + displayName: "Create work item" + inputs: + teamProject: "Mesa_FI" + workItemType: Bug + title: $(GitCommitSeven)-$(Build.BuildId)-$(Build.Repository.Name)-$(Configuration) + assignedTo: "$(Build.RequestedForId)" + enabled: false + - script: '"C:\program files\dotnet\dotnet.exe" publish --configuration $(Configuration) --runtime win-x64 --self-contained -o $(Build.ArtifactStagingDirectory)\Server --source $(NugetSource)' workingDirectory: Server displayName: "Core Publish"