From 2346f0ba4d63315487828de46d81ff40370e12a7 Mon Sep 17 00:00:00 2001 From: Mike Phares Date: Thu, 29 Jun 2023 09:31:53 -0700 Subject: [PATCH] Barcode-Host Job --- .../FileHandlers/TIBCO/Transport/Input.cs | 44 ++++- .../FileHandlers/TIBCO/Transport/Job.cs | 151 +++++++++++++----- Adaptation/_Tests/Static/Job.cs | 24 +++ 3 files changed, 171 insertions(+), 48 deletions(-) diff --git a/Adaptation/FileHandlers/TIBCO/Transport/Input.cs b/Adaptation/FileHandlers/TIBCO/Transport/Input.cs index d275677..b0edbcd 100644 --- a/Adaptation/FileHandlers/TIBCO/Transport/Input.cs +++ b/Adaptation/FileHandlers/TIBCO/Transport/Input.cs @@ -3,12 +3,42 @@ namespace Adaptation.FileHandlers.TIBCO.Transport; public class Input { - public string Area { get; set; } - public string EquipmentType { get; set; } - public string MID { get; set; } - public string Slot { get; set; } - public string MesEntity { get; set; } - public string Recipe { get; set; } - public string Sequence { get; set; } + public string Area { get; } + public string EquipmentType { get; } + public string MID { get; } + public string Slot { get; } + public string MesEntity { get; } + public string Recipe { get; } + public string Sequence { get; } + + [System.Text.Json.Serialization.JsonConstructor] + public Input(string area, + string equipmentType, + string mid, + string slot, + string mesEntity, + string recipe, + string sequence) + { + + Area = area; + EquipmentType = equipmentType; + MID = mid; + Slot = slot; + MesEntity = mesEntity; + Recipe = recipe; + Sequence = sequence; + } + + internal Input(Input input, string mid) + { + Area = input.Area; + EquipmentType = input.EquipmentType; + MID = mid; + Slot = input.Slot; + MesEntity = input.MesEntity; + Recipe = input.Recipe; + Sequence = input.Sequence; + } } \ No newline at end of file diff --git a/Adaptation/FileHandlers/TIBCO/Transport/Job.cs b/Adaptation/FileHandlers/TIBCO/Transport/Job.cs index 5c39616..77d3dc7 100644 --- a/Adaptation/FileHandlers/TIBCO/Transport/Job.cs +++ b/Adaptation/FileHandlers/TIBCO/Transport/Job.cs @@ -39,6 +39,26 @@ public class Job public DateTime DateTime { get; } public List Items { get; } + private class Common + { + + public string Layer { get; } + public string PSN { get; } + public int? RDSNumber { get; } + public int? Reactor { get; } + public string Zone { get; } + + public Common(string layer, string psn, int? rdsNumber, int? reactor, string zone) + { + Layer = layer; + PSN = psn; + RDSNumber = rdsNumber; + Reactor = reactor; + Zone = zone; + } + + } + public Job(string lsl2SQLConnectionString, string metrologyFileShare, string barcodeHostFileShare, string mid) { const int zero = 0; @@ -50,30 +70,39 @@ public class Job string psn; string zone; string layer; + Common common; int? rdsNumber; string comment; + int? slotNumber; + bool isWorkOrder; + int? reactorNumber; + int? workOrderNumber; + int? workOrderCassette; const string hyphen = "-"; Input input = JsonSerializer.Deserialize(mid); if (!long.TryParse(input.Sequence, out long sequence)) DateTime = DateTime.Now; else DateTime = new DateTime(sequence); - int? reactorNumber = GetReactorNumber(input); - (int? workOrderNumber, int? _, int? workOrderCassette, int? slotNumber, bool isWorkOrder) = GetWorkOrder(input); - if (isWorkOrder || reactorNumber.HasValue) - (layer, psn, rdsNumber, zone) = (string.Empty, string.Empty, null, string.Empty); - else if (!string.IsNullOrEmpty(input.MID) && input.MID.Length is 2 or 3 && Regex.IsMatch(input.MID, "^[a-zA-z]{2,3}")) - (layer, psn, rdsNumber, reactorNumber, zone) = Get(metrologyFileShare, input); - else if (!string.IsNullOrEmpty(input.MID) && !string.IsNullOrEmpty(input.MesEntity) && input.MesEntity is "BIORAD2" or "BIORAD3" && Regex.IsMatch(input.MID, @"^[0-9]{2}[.][0-9]{1}[.]?[0-9]{0,1}")) - (layer, psn, rdsNumber, reactorNumber, zone) = Get(input, barcodeHostFileShare); + if (!string.IsNullOrEmpty(input.MID) && !string.IsNullOrEmpty(input.MesEntity) && Regex.IsMatch(input.MID, @"^[0-9]{2}--") && input.MesEntity is "BIORAD2" or "BIORAD3") + (common, workOrderNumber, _, workOrderCassette, slotNumber, isWorkOrder) = Get(input, barcodeHostFileShare); else - (layer, psn, rdsNumber, reactorNumber, zone) = Get(input); - if (IsValid(rdsNumber)) - (comment, layer, rdsNumber, psn, reactorNumber, zone) = GetWithValidRDS(lsl2SQLConnectionString, layer, psn, rdsNumber, reactorNumber, zone); - else if (isWorkOrder || reactorNumber.HasValue) - (comment, layer, rdsNumber, psn, reactorNumber, zone) = Get(lsl2SQLConnectionString, layer, psn, reactorNumber, slotNumber, workOrderNumber, workOrderCassette, zone); + { + reactorNumber = GetReactorNumber(input); + (workOrderNumber, _, workOrderCassette, slotNumber, isWorkOrder) = GetWorkOrder(input); + if (isWorkOrder || reactorNumber.HasValue) + common = new(string.Empty, string.Empty, null, null, string.Empty); + else if (!string.IsNullOrEmpty(input.MID) && input.MID.Length is 2 or 3 && Regex.IsMatch(input.MID, "^[a-zA-z]{2,3}")) + common = Get(metrologyFileShare, input); + else + common = Get(input); + } + if (IsValid(common.RDSNumber)) + (comment, layer, rdsNumber, psn, reactorNumber, zone) = GetWithValidRDS(lsl2SQLConnectionString, common.Layer, common.PSN, common.RDSNumber, common.Reactor, common.Zone); + else if (isWorkOrder || common.RDSNumber.HasValue) + (comment, layer, rdsNumber, psn, reactorNumber, zone) = Get(lsl2SQLConnectionString, common.Layer, common.PSN, common.Reactor, slotNumber, workOrderNumber, workOrderCassette, common.Zone); else - (comment, layer, zone) = (hyphen, hyphen, hyphen); + (comment, layer, rdsNumber, psn, reactorNumber, zone) = (hyphen, hyphen, common.RDSNumber, common.PSN, common.Reactor, hyphen); Qty = "1"; Status = hyphen; // INFO CreationUser = hyphen; // ? @@ -211,7 +240,7 @@ public class Job return result; } - private static (string, string, int, int?, string) Get(Input input) + private static Common Get(Input input) { string psn; string rds; @@ -264,7 +293,7 @@ public class Job #nullable enable - private static (string, string, int?, int?, string) Get(string metrologyFileShare, Input input) + private static Common Get(string metrologyFileShare, Input input) { string lines; const int zero = 0; @@ -308,41 +337,81 @@ public class Job return new(layer, psn, rdsNumber, reactor, zone); } - private static (string, string, int?, int?, string) Get(Input input, string barcodeHostFileShare) + private static List GetFiles(Input input, string barcodeHostFileShare) { - string text; - int? rds = null; - FileInfo fileInfo; - long sequence = 0; - string psn = string.Empty; - List files = new(); - string[] segments = input.MID.Split('.'); - string layer = segments[1]; - string zone = segments.Length <= 2 ? string.Empty : segments[2]; - int? reactor = !int.TryParse(segments[0], out int reactorNumber) ? null : reactorNumber; - bool parsed = !string.IsNullOrEmpty(input.Sequence) && long.TryParse(input.Sequence, out sequence); - if (string.IsNullOrEmpty(barcodeHostFileShare) || !Directory.Exists(barcodeHostFileShare)) - throw new Exception($"Unable to access file-share <{barcodeHostFileShare}>"); - if (parsed && !string.IsNullOrEmpty(input.MID)) + List results = new(); + string[] checkDirectories = GetDirectories(barcodeHostFileShare); + foreach (string checkDirectory in checkDirectories) { - string[] checkDirectories = GetDirectories(barcodeHostFileShare); - foreach (string checkDirectory in checkDirectories) - { - if (!Directory.Exists(checkDirectory)) - _ = Directory.CreateDirectory(checkDirectory); - files.AddRange(Directory.GetFiles(checkDirectory, $"{input.MesEntity}.csv", SearchOption.TopDirectoryOnly)); - } + if (!Directory.Exists(checkDirectory)) + _ = Directory.CreateDirectory(checkDirectory); + results.AddRange(Directory.GetFiles(checkDirectory, $"{input.MesEntity}.csv", SearchOption.TopDirectoryOnly)); } + return results; + } + + private static string? GetText(long sequence, List files) + { + string? result = null; + string text; + string[] lines; + FileInfo fileInfo; foreach (string file in files.OrderByDescending(l => new FileInfo(l).LastWriteTime)) { fileInfo = new FileInfo(file); if (fileInfo.LastWriteTime.Ticks > sequence) continue; - text = File.ReadAllText(file); - rds = !int.TryParse(segments[0], out int rdsNumber) ? null : rdsNumber; + lines = File.ReadAllLines(file); + if (!lines.Any()) + continue; + text = lines.First(); + if (string.IsNullOrEmpty(text) || text.Length < 3 || text[0] != '1' || (text[1] != 't' && text[1] != 'T')) + continue; + result = text; break; } - return new(layer, psn, rds, reactor, zone); + return result; + } + + private static (Common common, int?, int?, int?, int?, bool) Get(Input input, string barcodeHostFileShare) + { + if (string.IsNullOrEmpty(barcodeHostFileShare) || !Directory.Exists(barcodeHostFileShare)) + throw new Exception($"Unable to access file-share <{barcodeHostFileShare}>"); + int? rds; + int? slotNumber; + bool isWorkOrder; + long sequence = 0; + int? workOrderStep; + int? workOrderNumber; + int? workOrderCassette; + string psn = string.Empty; + string zone = string.Empty; + string layer = string.Empty; + int? reactor = !int.TryParse(input.MID.Substring(0, 2), out int reactorNumber) ? null : reactorNumber; + bool parsed = !string.IsNullOrEmpty(input.Sequence) && long.TryParse(input.Sequence, out sequence); + List files; + if (!parsed || string.IsNullOrEmpty(input.MID)) + files = new(); + else + files = GetFiles(input, barcodeHostFileShare); + string? text = GetText(sequence, files); + if (text is null || text.Length < 3) + { + rds = null; + (workOrderNumber, workOrderStep, workOrderCassette, slotNumber, isWorkOrder) = (null, null, null, null, false); + } + else if (!text.Contains('.')) + { + rds = !int.TryParse(text.Substring(2), out int rdsNumber) ? null : rdsNumber; + (workOrderNumber, workOrderStep, workOrderCassette, slotNumber, isWorkOrder) = (null, null, null, null, false); + } + else + { + rds = null; + (workOrderNumber, workOrderStep, workOrderCassette, slotNumber, isWorkOrder) = GetWorkOrder(new(input, text.Substring(2))); + } + Common common = new(layer, psn, rds, reactor, zone); + return new(common, workOrderNumber, workOrderStep, workOrderCassette, slotNumber, isWorkOrder); } #nullable disable diff --git a/Adaptation/_Tests/Static/Job.cs b/Adaptation/_Tests/Static/Job.cs index 1d64b0f..6571a25 100644 --- a/Adaptation/_Tests/Static/Job.cs +++ b/Adaptation/_Tests/Static/Job.cs @@ -43,7 +43,9 @@ public class Job : LoggingUnitTesting, IDisposable catch (Exception) { } } +#if true [Ignore] +#endif [TestMethod] public void TestJobA() { @@ -82,7 +84,9 @@ public class Job : LoggingUnitTesting, IDisposable NonThrowTryCatch(); } +#if true [Ignore] +#endif [TestMethod] public void TestJobB() { @@ -100,4 +104,24 @@ public class Job : LoggingUnitTesting, IDisposable NonThrowTryCatch(); } +#if true + [Ignore] +#endif + [TestMethod] + public void TestJobC() + { + MethodBase methodBase = new StackFrame().GetMethod(); + FileHandlers.TIBCO.Transport.Job job; + string barcodeHostFileShare = @"\\messv02ecc1.ec.local\EC_Metrology_Si\BarcodeHost\API"; + string metrologyFileShare = @"\\messv02ecc1.ec.local\EC_Metrology_Si\WorkMaterialOut\API"; + LoggingUnitTesting.Logger.LogInformation(string.Concat(methodBase.Name, " - Getting configuration")); + string lsl2SQLConnectionString = "Data Source=10.95.128.28\\PROD1,53959;Initial Catalog=LSL2SQL;Persist Security Info=True;User ID=srpadmin;Password=0okm9ijn;"; + job = new(lsl2SQLConnectionString, metrologyFileShare, barcodeHostFileShare, "{\"Area\": \"Si\", \"EquipmentType\": \"MET08RESIMAPCDE\", \"MesEntity\": \"BIORAD3\", \"Sequence\": \"638234699589174855\", \"MID\": \"33--\", \"Recipe\": \"Recipe\"}"); + Assert.IsTrue(!string.IsNullOrEmpty(job.ProcessType)); + Assert.IsTrue(!string.IsNullOrEmpty(job.LotName)); + Assert.IsTrue(!string.IsNullOrEmpty(job.ProductName)); + LoggingUnitTesting.Logger.LogInformation(string.Concat(methodBase.Name, " - Exit")); + NonThrowTryCatch(); + } + } \ No newline at end of file