using Newtonsoft.Json; using Newtonsoft.Json.Converters; using NKC_SDK; using SteamWare; using System; using System.Collections.Generic; namespace AppData { /// /// Classe con metodi di supporto per COMUNICAZIONE /// public class ComLib { /// /// Wrapper traduzione termini /// /// /// public static string traduci(string lemma) { return user_std.UtSn.Traduci(lemma); } #region conf posizioni redis public static string redOutPath = "NKC:SERV:BREQ"; public static string redMsgCount = "NKC:SERV:BREQ:MCount"; public static string redMsgList = "NKC:SERV:BREQ:MList"; public static string redMLCurrStack = "NKC:SERV:TAKT:CurrStack"; public static string redNestAnsw = "NKC:NEST:BANSW"; public static string redProdReq = "NKC:SERV:BUNKS"; public static string redProdAnsw = "NKC:PROD:BUNKS"; #endregion #region definizione classi impiegate con PROD public static string PositionStatusDescr(object value) { string answ = ""; try { BatchPosition pStatus = (BatchPosition)Enum.Parse(typeof(BatchPosition), value.ToString()); switch (pStatus) { case BatchPosition.NotStarted: answ = traduci("NotStarted"); break; case BatchPosition.StackStarted: answ = traduci("Stacking"); break; case BatchPosition.StackDone: answ = traduci("StackDone"); break; default: break; } } catch { } return answ; } public static string BatchStatusDescr(object value) { string answ = ""; try { BatchStatus bStatus = (BatchStatus)Enum.Parse(typeof(BatchStatus), value.ToString()); switch (bStatus) { case BatchStatus.Imported: answ = "Imported"; break; case BatchStatus.EstimationRequested: answ = "Estimation Requested"; break; case BatchStatus.EstimationDone: answ = "Estimation Completed"; break; case BatchStatus.NestRequested: answ = "Nesting Requested"; break; case BatchStatus.NestDone: answ = "Nesting Completed"; break; case BatchStatus.Approved: answ = "Nesting Approved"; break; case BatchStatus.Discarded: answ = "Nesting Discarded"; break; case BatchStatus.Errors: answ = "Nesting Impossibile (data errors)"; break; case BatchStatus.PartEval: answ = "Part/Item under evaluation"; break; case BatchStatus.PartOk: answ = "Part/Item Validated"; break; case BatchStatus.PartKo: answ = "Part/Item NOT Validated"; break; default: break; } } catch { } return answ; } /// /// Oggetto globale TAKT /// public class Takt { /// /// Codice univoco oggetto TAKT (data.num) /// public string TaktId { get; set; } /// /// Stato del TAKT /// public CStatus Status { get; set; } /// /// Elenco degli Stack da lavorare /// public List StackList { get; set; } /// /// Numero di Stack da lavorare /// public int NumStack { get { int answ = 0; try { answ = StackList.Count; } catch { } return answ; } } } #endregion #region definizione classi impiegate con NEST public class Parte { public int PartId { get; set; } public string DataMatrix { get; set; } public string ExtCode { get; set; } public string Description { get; set; } public int MatId { get; set; } public string PostProc { get; set; } public string ProcessReq { get; set; } public string CadFilePath { get; set; } public int Qty { get; set; } } public class BatchData { /// /// ID del batch in esecuzione /// public int BatchId { get; set; } /// /// tempo amssimo eprmesso x nesting (minuti) /// public int maxTime { get; set; } /// /// Tipo di processing richiesto /// 1 = stima /// 2 = nesting /// [JsonConverter(typeof(StringEnumConverter))] public int procType { get; set; } /// /// Codice della amcchina x cui si effettua richeista /// [JsonConverter(typeof(StringEnumConverter))] public mType machineType { get; set; } /// /// Tipo di ordine richeisto /// [JsonConverter(typeof(StringEnumConverter))] public oType orderType { get; set; } } /// /// Salva su redis l'oggetto dei materiali serializzato /// /// public static bool sendMaterials() { bool answ = false; // leggo tab MNATERIALS da DB var table = DataLayer.man.taMat.GetData(); // serializzo string redVal = JsonConvert.SerializeObject(table); // salvo string redKey = $"NKC:SERV:CONF:MATERIALS"; // scrivo per ora solo su REDIS memLayer.ML.setRSV(redKey, redVal); return answ; } /// /// Restituisce il prossimo codice di envelope per comunicare con sistemi esterni /// /// Batch contenuto nell'envelope /// note opzionali (motivo envelope) /// public static string getNextEnv(int BatchID, string note) { // incremento counter long nextIndex = memLayer.ML.setRCntI(redMsgCount); // salvo contenuto della busta string answ = $"Z{nextIndex:000000000000}"; Dictionary lista = new Dictionary(); lista.Add(answ, $"{BatchID}|{note}"); memLayer.ML.redSaveHashDict(redMsgList, lista); // ritorno return answ; } /// /// Restituisce elenco KVP delle buste ancora "pending" (quando processate le elimina da elenco...) /// /// public static KeyValuePair[] getEnvList() { KeyValuePair[] answ = memLayer.ML.redGetHash(redMsgList); return answ; } /// /// resetta la richeista corrente in modo che non ce ne siano altre in coda /// /// public static bool resetBatchReq() { bool answ = false; try { currBatchReq = ""; answ = true; } catch { } return answ; } public static string currBatchReqKey { get { return $"{redOutPath}:CURR"; } } /// /// Valore della richiesta corrente di elaborazione batch /// public static string currBatchReq { get { return memLayer.ML.getRSV(currBatchReqKey); } set { // scrivo su REDIS memLayer.ML.setRSV(currBatchReqKey, value); } } public static bool sendFirstValidationBatch() { bool answ = false; // verifico se sia vuota la richeista corrente (= chiuso...) // ora verifico, se ci sono batch in stato 8 (da validare) --> metto in coda! var tabBatch = DataLayer.man.taBL.getByStatus(8); bool hasValReq = tabBatch.Count > 0; if (hasValReq) { // invia a redis una richiesta... ComLib.sendMaterials(); // recupero PRIMO batchID da validare int nextBatchId = 0; try { nextBatchId = tabBatch[0].BatchID; } catch { } if (nextBatchId > 0) { // richiedo! ComLib.sendBatchReq(nextBatchId, "Estimation", 1); // registro su DB nesting iniziato... QUANDO MI RISPONDE dovrò verificare che era un abtch x VALIDAZIONE DataLayer.man.taBL.updateStatus(nextBatchId, (int)BatchStatus.EstimationRequested, "", 0); answ = true; } } // resituisco return answ; } /// /// Invia una richiesta di esecuzione di Nesting x un Batch /// /// Batch di cui si chiede processing /// note opzionali /// Tipo processo: 1 = stima, 2 = nesting /// public static bool sendBatchReq(int BatchID, string note, int pType) { bool answ = false; // per prima cosa mi serve una "nuova busta" per inviare i messaggi string nextEnv = getNextEnv(BatchID, note); // preparo il contenuto della busta ed invio i messaggi... try { // in base allo stato del BATCH corrente determino il tempo e le opzioni da inviare... var batch = DataLayer.man.taBL.getByKey(BatchID); int mTime = 1; if (batch[0].STATUS < (int)BatchStatus.EstimationDone) { mTime = memLayer.ML.cdvi("estimMaxTime"); } else { mTime = memLayer.ML.cdvi("nestMaxTime"); } // init oggetti x fare cicli... Order currOrder = null; Kit currentKit = null; Part currPart = null; List listOrder = new List(); List listKit = new List(); List listPart = new List(); // leggo tab ORDINI da DB var tblOrd = DataLayer.man.taOL.getByBatch(BatchID); // leggo tab KIT da DB var tblKit = DataLayer.man.taKL.getByBatch(BatchID); // leggo tab ITEMS da DB var tblItm = DataLayer.man.taIL.getByBatch(BatchID); // ciclo per comporre oggetto con cicli annidiati ext --> int foreach (var rigaOrd in tblOrd) { listKit = new List(); // compongo kit var righeKit = (DS_App.KitListRow[])tblKit.Select($"OrdID = {rigaOrd.OrdID}"); foreach (var rigaKit in righeKit) { listPart = new List(); // elenco ITEMS var righeItems = (DS_App.ItemListRow[])tblItm.Select($"KitID = {rigaKit.KitID}"); foreach (var rigaItem in righeItems) { currPart = new Part() { PartId = rigaItem.ItemID, PartExtCode = rigaItem.ItemExtCode, PartQty = rigaItem.ItemQty, MatId = rigaItem.MatID, CadFilePath = rigaItem.CadFilePath }; listPart.Add(currPart); } // compongo KIT currentKit = new Kit() { KitId = rigaKit.KitID, KitExtCode = rigaKit.KitExtCode, PartList = listPart }; listKit.Add(currentKit); } // compongo ordine currOrder = new Order() { OrderId = rigaOrd.OrdID, OrderCod = rigaOrd.OrdCodOrig, OrderExtCode = rigaOrd.OrderExtCode, DestPlant = rigaOrd.DestPlant, KitList = listKit }; listOrder.Add(currOrder); } // oggetto complessivo batchRequest newBatchreq = new batchRequest() { BatchId = BatchID, EnvNum = nextEnv, MaxTime = mTime, ProcType = pType, MachineType = mType.Multiax, OrderType = oType.BatchRequest, OrderList = listOrder }; // serializzo string redVal = JsonConvert.SerializeObject(newBatchreq); // salvo string redKey = $"{redOutPath}:{nextEnv}"; // scrivo su REDIS memLayer.ML.setRSV(redKey, redVal); // invio notifica che c'è una busta da processare memLayer.ML.setRSV(currBatchReqKey, nextEnv); answ = true; } catch (Exception exc) { } // restituisco ok return answ; } /// /// Verifica lo stato di una richiesta di esecuzione BATCH x stima/nesting /// /// OfflineOrder di cui si chiede processing /// note opzionali /// public static bool checkBatchReq(int OffOrderID) { bool answ = false; #if false string typeSearch = "OffOrdCalculation"; string keyEnv = ""; // recupero lista dei vari task APERTI... KeyValuePair[] comAperte = getEnvList(); // processo x cercare ordine... foreach (var item in comAperte) { // cerco dove sia quello richiesto if (item.Value.Contains(typeSearch)) { // controllo SE sia quello richiesto if (item.Value == $"{OffOrderID}|{typeSearch}") { keyEnv = item.Key; break; } } } // controllo e se c'è risposta --> update DB string redKey = $"{redNestAnsw}:FULL:{keyEnv}"; string rawAnsw = memLayer.ML.getRSV(redKey); if (rawAnsw != "") { // cerco risposta come stack --> disegno... var offOrder = deserializeOfflineOrder(rawAnsw); // se ho in risposta 1 stack... if (offOrder.Stacks.Count == 1) { // se ho 1 solo sheet var sheets = offOrder.Stacks[0].SheetList; if (sheets.Count == 1) { // controllo se ho CNC prog answ = sheets[0].MachiningProgram != ""; if (answ) { // aggiorno su DB il disegno... string disegno = sheets[0].Drawing; DataLayer.man.taOffOL.updateDrawing(OffOrderID, disegno); } } } } #endif // restituisco ok return answ; } /// /// Invia una richiesta di esecuzione di CAM x un ordine offline /// /// OfflineOrder di cui si chiede processing /// note opzionali /// public static bool sendOfflineOrderReq(int OffOrderID, string note) { bool answ = false; // per prima cosa mi serve una "nuova busta" per inviare i messaggi string nextEnv = getNextEnv(OffOrderID, note); // preparo il contenuto della busta ed invio i messaggi... try { int mTime = 5; int pType = 1; // serializzo ordini come ARRAY VUOTO string redVal = "[]"; // salvo string redKey = $"{redOutPath}:{nextEnv}:ORDERS"; // scrivo su REDIS memLayer.ML.setRSV(redKey, redVal); // ora ITEMS var tblItm = DataLayer.man.taIL.getByOfflineOrder(OffOrderID); // serializzo redVal = JsonConvert.SerializeObject(tblItm); // salvo redKey = $"{redOutPath}:{nextEnv}:ITEMS"; // scrivo su REDIS memLayer.ML.setRSV(redKey, redVal); // ora versione gerarchica var currBatch = new BatchData() { BatchId = OffOrderID, maxTime = mTime, procType = pType, machineType = mType.Offline, orderType = oType.OfflineOrder }; // serializzo redVal = JsonConvert.SerializeObject(currBatch); // salvo redKey = $"{redOutPath}:{nextEnv}:DATA"; // scrivo su REDIS memLayer.ML.setRSV(redKey, redVal); // invio notifica che c'è una busta da processare memLayer.ML.setRSV(currBatchReqKey, nextEnv); answ = true; } catch (Exception exc) { logger.lg.scriviLog($"Eccezione in sendOfflineOrderReq:{Environment.NewLine}{exc}"); } // restituisco ok return answ; } /// /// Verifica lo stato di una richiesta di esecuzione /// /// OfflineOrder di cui si chiede processing /// note opzionali /// public static bool checkOfflineOrderReq(int OffOrderID) { bool answ = false; string typeSearch = "OffOrdCalculation"; string keyEnv = ""; // recupero lista dei vari task APERTI... KeyValuePair[] comAperte = getEnvList(); // processo x cercare ordine... foreach (var item in comAperte) { // cerco dove sia quello richiesto if (item.Value.Contains(typeSearch)) { // controllo SE sia quello richiesto if (item.Value == $"{OffOrderID}|{typeSearch}") { keyEnv = item.Key; break; } } } // controllo e se c'è risposta --> update DB string redKey = $"{redNestAnsw}:FULL:{keyEnv}"; string rawAnsw = memLayer.ML.getRSV(redKey); if (rawAnsw != "") { // cerco risposta come stack --> disegno... var offOrder = deserializeOfflineOrder(rawAnsw); // se ho in risposta 1+ sheets... if (offOrder.SheetList.Count > 0) { // se ho 1 solo sheet var sheets = offOrder.SheetList; // controllo se ho CNC prog answ = sheets[0].MachiningProgram != ""; if (answ) { // aggiorno su DB il disegno... string disegno = sheets[0].Drawing; DataLayer.man.taOffOL.updateDrawing(OffOrderID, disegno); } } } // restituisco ok return answ; } /// /// Salvo dati su PartList ricevuti da Nesting (COMPETATO) /// /// /// public static void updateBunksFromNesting(int BatchID, List BunkList) { // inizio a processare... bunks! if (BunkList != null) { foreach (var bunk in BunkList) { // creo il BUNK! var newBunk = DataLayer.man.taSTL.insertAndReturn(bunk.BunkIndex, BatchID); // se ho un bunk in risposta... if (newBunk.Count == 1) { var currBunk = newBunk[0]; // processo sheets if (bunk.SheetList != null) { foreach (var sheet in bunk.SheetList) { // creo lo sheet... var newSheet = DataLayer.man.taSHL.insertAndReturn(sheet.SheetIndex, sheet.MatId, (decimal)sheet.EstimatedWorktime, currBunk.StackID, sheet.PrintProgram, sheet.MachiningProgram, sheet.Drawing); // se ho 1 sheet in risposta if (newSheet.Count == 1) { var currSheet = newSheet[0]; // processo items! if (sheet.PartList != null) { foreach (var part in sheet.PartList) { // aggiungo part a sheet (in tab nesting) DataLayer.man.taNest.insertAndReturn(currSheet.SheetID, part.PartId); } } } } } } } } } /// /// Salvo dati su PartList ricevuti da Nesting (COMPETATO) /// /// /// public static void updateBinsFromNesting(int BatchID, List BinList) { // inizio a processare... bunks! if (BinList != null) { foreach (var item in BinList) { // creo il BIN! var newBin = DataLayer.man.taBN.insertAndReturn(item.BinIndex); // se ho un BIN in risposta... if (newBin.Count == 1) { var currBin = newBin[0]; // processo sheets if (item.PartList != null) { foreach (var part in item.PartList) { // creo lo sheet... var newB2I = DataLayer.man.taBNLS.insertAndReturn(currBin.BinID, part.PartId); } } } } } } /// /// Salvo dati su PartList ricevuti da Nesting (COMPETATO) /// /// /// public static void updateCartsFromNesting(int BatchID, List CartList) { // inizio a processare... bunks! if (CartList != null) { foreach (var item in CartList) { // creo il CART! var newCart = DataLayer.man.taCR.insertAndReturn(item.CartIndex); // se ho un CART in risposta... if (newCart.Count == 1) { var currCart = newCart[0]; // processo sheets if (item.KitList != null) { foreach (var kit in item.KitList) { // creo lo sheet... var updKit = DataLayer.man.taKL.updateCart(kit.KitId, currCart.CartID); } } } } } } /// /// Salvo dati su PartList ricevuti da Nesting (stima) /// /// public static void updatePartsFromNesting(List PartList) { string PostProcList = ""; string ProcessesReq = ""; string pdfFilePath = ""; // salvo elenco materiali x ogni item... foreach (Part currItem in PartList) { // calcolo parametri... PostProcList = ComLib.getPostProcList(currItem.OptParameters); ProcessesReq = ComLib.getProcessesReq(currItem.OptParameters); pdfFilePath = ComLib.getPdfFilePath(currItem.OptParameters); DataLayer.man.taIL.updateFromNesting(currItem.PartId, currItem.MatId, PostProcList, ProcessesReq, pdfFilePath); } } /// /// Recupera le operazioni di PostProcessing, esempio: /// - T-Nut /// - Round /// - Chop /// /// /// public static string getPostProcList(Dictionary optParameters) { string answ = ""; foreach (var currOpt in optParameters) { switch (currOpt.Key) { case "ChopAtTab": case "RoundEdge": case "TNutFlag": // se contiene YES aggiungo... if (currOpt.Value.ToLower() == "yes") { answ += $"{currOpt.Key}#"; } break; } } // se finisce per "#" trimmo... if (answ.EndsWith("#")) { answ = answ.Substring(0, answ.Length - 1); } return answ; } /// /// Recupera le operazioni RICHIESTE a valle /// - Paint /// - Assembly /// - SecOp /// /// /// public static string getProcessesReq(Dictionary optParameters) { string answ = ""; foreach (var currOpt in optParameters) { switch (currOpt.Key) { case "AssemblyCell": case "PaintFlag": case "RoundEdge": // se contiene YES aggiungo... if (currOpt.Value.ToLower() == "yes") { answ += $"{currOpt.Key}#"; } break; } } // se finisce per "#" trimmo... if (answ.EndsWith("#")) { answ = answ.Substring(0, answ.Length - 1); } return answ; } /// /// Recupera file pdf /// /// /// public static string getPdfFilePath(Dictionary optParameters) { string answ = ""; if (optParameters.ContainsKey("PdfLink")) { answ = optParameters["PdfLink"]; } return answ; } #endregion #region metodi helper di conversione /// /// Helper x serializzare l'oggetto /// /// /// public static string serializeTakt(Takt currData) { string answ = JsonConvert.SerializeObject(currData); return answ; } /// /// Helper x deserializzare l'oggetto /// /// /// public static Takt deserializeTakt(string rawData) { Takt answ = JsonConvert.DeserializeObject(rawData); return answ; } /// /// Deserializza un ordine offline /// /// /// public static nestReplyOffOrd deserializeOfflineOrder(string rawData) { nestReplyOffOrd answ = null; try { answ = JsonConvert.DeserializeObject(rawData); } catch { } return answ; } #endregion #region metodi x data persistence /// /// Salvo il Takt inviato /// /// Origine del dato: SERV / PROD / NEST /// /// public static bool saveTakt(string origin, Takt currData) { bool answ = false; try { // calcolo valori redis string redKey = $"NKC:{origin.ToUpper()}:TAKT:{currData.TaktId}"; string redVal = serializeTakt(currData); // scrivo per ora solo su REDIS memLayer.ML.setRSV(redKey, redVal); answ = true; } catch { } return answ; } /// /// Leggo il Takt inviato /// /// Origine del dato: SERV / PROD / NEST /// /// public static Takt readTakt(string origin, string TaktId) { Takt answ = null; try { string redKey = $"NKC:{origin.ToUpper()}:TAKT:{TaktId}"; string redVal = memLayer.ML.getRSV(redKey); answ = deserializeTakt(redVal); } catch { } return answ; } #endregion #region metodi per PROD /// /// Esegue richieste lettura da PROD /// public static void procProdReadReq() { // !!!FIXME!!! } /// /// Esegue richieste lettura da PROD /// public static void procProdWriteReq() { // !!!FIXME!!! } /// /// Fornisce il prossimo TAKT da elaborare oppure null se non ce ne fossero altri da elaborare per la data CORRENTE /// /// public Takt prodGetNextTakt() { return null; } /// /// Chiave primo bunk su redis /// protected static string redFirstBunkKey = $"{redProdReq}:FirstBunk"; /// /// Chiave primo bunk su redis /// protected static string redAllNextBunkKey = $"{redProdReq}:NextBunk"; /// /// TTL standard x dati da scambiare con PROD (30 gg) /// protected static int ttlProdData = 3600 * 24 * 30; /// /// Chiave primo bunk su redis /// protected static string redNextBunkKey(int BunkID) { return $"{redProdReq}:NextBunk:{BunkID}"; } /// /// Resetto in REDIS i dati di bunk (corrente e successivi) /// public static void resetRedisBunkData() { redisFirstBunk = null; } /// /// Cache redis del PRIMO bunk da lavorare /// private static ProdBunk redisFirstBunk { get { ProdBunk answ = null; string rawData = memLayer.ML.getRSV(redFirstBunkKey); if (rawData != "") { // provo a deserializzare try { answ = JsonConvert.DeserializeObject(rawData); } catch { } } return answ; } set { if (value != null) { string redVal = JsonConvert.SerializeObject(value); // default lascio x 5 minuti... memLayer.ML.setRSV(redFirstBunkKey, redVal, ttlProdData); } else // se null elimino da redis { memLayer.ML.setRSV(redFirstBunkKey, ""); // elimino TUTTI i next... memLayer.ML.redFlushKey(redAllNextBunkKey); } } } /// /// Recupero da Redis del SUCCESSIVO bunk da lavorare /// /// /// private static ProdBunk getRedisNextBunk(int currBunkId) { ProdBunk answ = null; string rawData = memLayer.ML.getRSV(redNextBunkKey(currBunkId)); if (rawData != "") { // provo a deserializzare try { answ = JsonConvert.DeserializeObject(rawData); } catch { } } return answ; } /// /// Salvo in Redis il SUCCESSIVO bunk da lavorare /// /// /// private static void setRedisNextBunk(int currBunkId, ProdBunk value) { if (value != null) { string redVal = JsonConvert.SerializeObject(value); // default lascio x 5 minuti... memLayer.ML.setRSV(redNextBunkKey(currBunkId), redVal, ttlProdData); } else // se null elimino da redis { memLayer.ML.setRSV(redNextBunkKey(currBunkId), ""); } } /// /// Restituisce il PRIMO bunk secondo criterio: /// - posizione = 5 (ho letto da webApp il BUNK e preso in carico) /// - NumSheet > NumSheetUnload /// - Ordinato per StackIndex (crescente) x avere il più VECCHIO /// /// public static ProdBunk prodGetFirstBunk() { // cerco prima su REDIS... ProdBunk answ = redisFirstBunk; if (answ == null) { // vado sul DB e leggo ... DS_App.StackListDataTable tabBunks = DataLayer.man.taSTL.getLoaded(); // controllo di averne almeno 1... if (tabBunks.Count > 0) { DS_App.StackListRow currBunk = tabBunks[0]; answ = getBunkFromDb(currBunk); // se ho qualcosa salvo su REDIS redisFirstBunk = answ; } } return answ; } /// /// Restituisce il PROSSIMO bunk secondo criterio: /// - posizione = 5 (ho letto da webApp il BUNK e preso in carico) /// - NumSheet > NumSheetUnload /// - Ordinato per StackIndex (crescente) x avere il più VECCHIO /// - SUCCESSIVO al BunkID(=StackID) ricevuto /// /// public static ProdBunk prodGetNextBunk(int BunkID) { ProdBunk answ = getRedisNextBunk(BunkID); if (answ == null) { // vado sul DB e leggo ... DS_App.StackListDataTable tabBunks = DataLayer.man.taSTL.getLoaded(); // controllo di averne almeno 1... if (tabBunks.Count > 0) { DS_App.StackListRow currBunk = null; bool trovato = false; // ciclo foreach (var item in tabBunks) { if (trovato) { currBunk = item; break; } // controllo se sia quello richiesto if (item.StackID == BunkID) { trovato = true; } } // se c'è un bunk trovato --> carico if (currBunk != null) { answ = getBunkFromDb(currBunk); // salvo su redis setRedisNextBunk(BunkID, answ); } } } return answ; } /// /// Recupera e transcodifica DA DB i dati di UN SINGOLO bunk /// /// /// private static ProdBunk getBunkFromDb(DS_App.StackListRow currBunk) { ProdBunk answ; // calcolo attributi oggetti CStatus currSt = CStatus.Programmed; if (currBunk.Position == 5) { currSt = CStatus.Running; } else { currSt = CStatus.Done; } List elSheet = new List(); // recupero gli sheets di questo stack... DS_App.SheetListDataTable tabSheets = DataLayer.man.taSHL.getByStack(currBunk.StackID); DateTime dataStart = DateTime.Now; ProdSheet currPanel; foreach (var item in tabSheets) { // converto i workData WorkData wdPrint = new WorkData() { DtStart = item.IsPrntStartNull() ? null : (DateTime?)item.PrntStart, DtEnd = item.IsPrntEndNull() ? null : (DateTime?)item.PrntEnd, ProgramPath = item.PrintFilePath }; WorkData wdMachining = new WorkData() { DtStart = item.IsWrkStartNull() ? null : (DateTime?)item.WrkStart, DtEnd = item.IsWrkEndNull() ? null : (DateTime?)item.WrkEnd, ProgramPath = item.CncFilePath }; WorkData wdUnload = new WorkData() { DtStart = item.IsUnlStartNull() ? null : (DateTime?)item.UnlStart, DtEnd = item.IsUnlEndNull() ? null : (DateTime?)item.UnlEnd }; MaterialData material = new MaterialData() { MaterialId = item.MatID, MaterialDescription = item.MatDesc, MaterialPN = item.MatExtCode.ToString() }; PStatus currPnlStatus = PStatus.Programmed; Enum.TryParse(item.ShStatus.ToString(), out currPnlStatus); currPanel = new ProdSheet() { Printing = wdPrint, Machining = wdMachining, Unloading = wdUnload, Material = material, SheetId = item.SheetID, Status = currPnlStatus }; elSheet.Add(currPanel); if (!item.IsPrntStartNull()) { dataStart = item.PrntStart < dataStart ? item.PrntStart : dataStart; } } // compongo il bunk... answ = new ProdBunk() { BunkId = currBunk.StackID, Status = currSt, DataMatrix = currBunk.StackDtmx, SheetList = elSheet, DtStart = dataStart }; return answ; } /// /// Recupera e transcodifica DA DB i dati di UN SINGOLO bunk /// /// /// public static ProdBunk prodGetBunk(int StackID) { ProdBunk answ = null; List elSheet = new List(); var tabBunks = DataLayer.man.taSTL.getByKey(StackID); if (tabBunks.Count == 1) { DS_App.StackListRow currBunk = tabBunks[0]; // calcolo attributi oggetti CStatus currSt = CStatus.Programmed; if (currBunk.Position == 5) { currSt = CStatus.Running; } else { currSt = CStatus.Done; } // recupero gli sheets di questo stack... DS_App.SheetListDataTable tabSheets = DataLayer.man.taSHL.getByStack(StackID); DateTime dataStart = DateTime.Now; ProdSheet currPanel; foreach (var item in tabSheets) { // converto i workData WorkData wdPrint = new WorkData() { DtStart = item.IsPrntStartNull() ? null : (DateTime?)item.PrntStart, DtEnd = item.IsPrntEndNull() ? null : (DateTime?)item.PrntEnd, ProgramPath = item.PrintFilePath }; WorkData wdMachining = new WorkData() { DtStart = item.IsWrkStartNull() ? null : (DateTime?)item.WrkStart, DtEnd = item.IsWrkEndNull() ? null : (DateTime?)item.WrkEnd, ProgramPath = item.CncFilePath }; WorkData wdUnload = new WorkData() { DtStart = item.IsUnlStartNull() ? null : (DateTime?)item.UnlStart, DtEnd = item.IsUnlEndNull() ? null : (DateTime?)item.UnlEnd }; MaterialData material = new MaterialData() { MaterialId = item.MatID, MaterialDescription = item.MatDesc, MaterialPN = item.MatExtCode.ToString() }; PStatus currPnlStatus = PStatus.Programmed; Enum.TryParse(item.ShStatus.ToString(), out currPnlStatus); currPanel = new ProdSheet() { Printing = wdPrint, Machining = wdMachining, Unloading = wdUnload, Material = material, SheetId = item.StackID, Status = currPnlStatus }; elSheet.Add(currPanel); if (!item.IsPrntStartNull()) { dataStart = item.PrntStart < dataStart ? item.PrntStart : dataStart; } } // compongo il bunk... answ = new ProdBunk() { BunkId = currBunk.StackID, Status = currSt, DataMatrix = currBunk.StackDtmx, SheetList = elSheet, DtStart = dataStart }; } return answ; } /// /// Valore dello Stack correntemente in processing per ML (MachineLoad) /// public static string taktMLCurrStack { get { return memLayer.ML.getRSV(redMLCurrStack); } set { memLayer.ML.setRSV(redMLCurrStack, value); } } #endregion } }