diff --git a/AMESCoreStudio.Web/Controllers/PCSController.cs b/AMESCoreStudio.Web/Controllers/PCSController.cs index 71cf9364..c301c658 100644 --- a/AMESCoreStudio.Web/Controllers/PCSController.cs +++ b/AMESCoreStudio.Web/Controllers/PCSController.cs @@ -1,34 +1,29 @@ using AMESCoreStudio.CommonTools.Result; +using AMESCoreStudio.Web.Code; using AMESCoreStudio.Web.Models; -using AMESCoreStudio.Web.ViewModels; using AMESCoreStudio.Web.ViewModels.PCS; using AMESCoreStudio.WebApi.DTO.AMES; +using AMESCoreStudio.WebApi.Enum; using AMESCoreStudio.WebApi.Models.AMES; using AMESCoreStudio.WebApi.Models.BAS; +using AMESCoreStudio.WebApi.Models.SYS; +using ClosedXML.Excel; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Rendering; -using Microsoft.Extensions.Logging; using Microsoft.AspNetCore.StaticFiles; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.IO; using System.Linq; -using Newtonsoft.Json.Linq; using System.Threading.Tasks; -using AMESCoreStudio.WebApi.Enum; -using Microsoft.Extensions.Localization; -using Microsoft.Extensions.Configuration; -using ClosedXML.Excel; -using Microsoft.VisualBasic; -using AMESCoreStudio.WebApi.Models.SYS; -using System.IO.Pipes; -using System.Net; -using System.Net.Http; -using AMESCoreStudio.Web.Code; namespace AMESCoreStudio.Web.Controllers { @@ -270,6 +265,7 @@ namespace AMESCoreStudio.Web.Controllers { var result = await _pcsApi.GetLineInfo(); result = result.Where(w => w.StatusNo == "A").OrderBy(o => o.LineID).ToList(); + var LineInfo = new List(); for (int i = 0; i < result.Count; i++) { @@ -1790,7 +1786,7 @@ namespace AMESCoreStudio.Web.Controllers ModelState.AddModelError("error", Msg); return View("PCS001N", model); } - + model.wipInfo.CreateUserID = UserID; result = await _pcsApi.PostAddNewWipData(JsonConvert.SerializeObject(model)); @@ -2423,9 +2419,9 @@ namespace AMESCoreStudio.Web.Controllers var PowerMode_Desc = _pcsApi.GetPlmMeterialInfo(model.wipSystem.PowerMode).InvokeAsync().Result; model.wipSystem.PowerMode_Desc = PowerMode_Desc.Count() == 0 ? "" : PowerMode_Desc.FirstOrDefault().ProductionMemo; } - - var Memo = _pcsApi.GetPlmMeterialInfo(model.wipAtt.ItemNO).InvokeAsync().Result; - model.wipSystem.Memo = Memo.Count() == 0 ? "": Memo.FirstOrDefault().ProductionMemo; + + var Memo = _pcsApi.GetPlmMeterialInfo(model.wipAtt.ItemNO).InvokeAsync().Result; + model.wipSystem.Memo = Memo.Count() == 0 ? "" : Memo.FirstOrDefault().ProductionMemo; } model.wipMACs = await _pcsApi.GetWipMAC(model.wipInfo.WipNO); @@ -10187,7 +10183,7 @@ namespace AMESCoreStudio.Web.Controllers , desc: null , sdate: "*" , edate: "*" - , productionSID: productionSID) ; + , productionSID: productionSID); var storeProuctionNotice = result.Data.Select(d => (string)d.productionID).Where(ppid => !string.IsNullOrEmpty(ppid)).Distinct(); @@ -10494,6 +10490,468 @@ namespace AMESCoreStudio.Web.Controllers #endregion + #region PCS021_2025 條碼輸入作業 2025(新版) + + [ResponseCache(Duration = 0)] + [HttpGet] + public async Task PCS021_2025() + { + var model = new PCS021ViewModel(); + await GetFactoryUnit(false); + return View(model); + } + + [HttpPost] + public async Task PCS021_2025_GetWip(PCS021ViewModel model) + { + await GetFactoryUnit(false); + model.KpItemName += "null"; + if (string.IsNullOrWhiteSpace(model.WipNO)) + { + ModelState.AddModelError("error", "請輸入工單號碼"); + } + + if (string.IsNullOrWhiteSpace(model.UnitNO)) + { + ModelState.AddModelError("error", "請選擇生產單位"); + } + + if (model.LineID == 0) + { + ModelState.AddModelError("error", "請選擇線別"); + } + + var q = await _pcsApi.GetWipInfoByWipNO(model.WipNO); + var firstWipNo = q.Where(w => w.UnitNO == model.UnitNO).FirstOrDefault(); + + if (firstWipNo == null) + { + ModelState.AddModelError("error", "找不到該生產單位的工單號碼"); + } + + try + { + if (q.Count != 0) + { + model.WipID = firstWipNo.WipID; + model.PlanQTY = firstWipNo.PlanQTY; + model.UnitNO = firstWipNo.UnitNO; + model.FlowRuleID = firstWipNo.FlowRuleID; + model.ItemNO = (await _pcsApi.GetWipAtt(model.WipNO)).ItemNO ?? ""; + + // 判斷工單狀態 + var BarCodeWip = await _pcsApi.CheckBarCodeWip_2025(model.WipNO, model.UnitNO, model.LineID, model.FlowRuleID); + if (!BarCodeWip.Success) + { + ModelState.AddModelError("error", BarCodeWip.Msg); + return View("PCS021_2025", model); + } + + // 工單流程ID 取站別 + var ruleStations = await GetRuleStationByFlowRuleID(model.FlowRuleID, true); + if (!ruleStations.Any()) + { + ModelState.AddModelError("error", $"找不到該筆工單流程作業站設定 ID【{model.FlowRuleID}】"); + return View("PCS021_2025", model); + } + + // 作業站名稱代碼 提供不二過 + var StationNameSt = ""; + // 過站沒有作業站,就先帶預設 + if (model.Station == 0) + model.Station = ruleStations.FirstOrDefault().StationID; + + // 取作業站的生產製程 + var stationUnit = string.Empty; + var station = await _basApi.GetStations(model.Station); + if (station.Any()) + { + stationUnit = station.FirstOrDefault().UnitNo; + } + else + { + ModelState.AddModelError("error", "找不到該作業站的生產單位"); + } + + if (ruleStations.Any(a => a.StationID == model.Station)) + { + model.RuleStation = ruleStations.Where(w => w.StationID == model.Station).FirstOrDefault().RuleStationID; + model.StationTypeNo = ruleStations.Where(w => w.StationID == model.Station).FirstOrDefault().Station.TypeNo; + StationNameSt = ruleStations.Where(w => w.StationID == model.Station).FirstOrDefault().Station.StationNameSt; + } + else + { + model.RuleStation = ruleStations.FirstOrDefault().RuleStationID; + model.StationTypeNo = ruleStations.FirstOrDefault().Station.TypeNo; + model.Station = ruleStations.FirstOrDefault().StationID; + StationNameSt = ruleStations.FirstOrDefault().Station.StationNameSt; + } + + // 工單已刷數量 + model.InputQTY = await _pcsApi.GetBarcodeStationByInputQty(model.WipID, model.Station); + + // 工單KeyParts + model.WipKps = await _pcsApi.GetWipKpByWipNo(model.WipNO); + model.WipKps = model.WipKps.Where(w => w.UnitNo == stationUnit).OrderBy(o => o.KpSeq).ToList(); + + // 料號檔案 + model.MaterialItem = await _pcsApi.GetMaterialItemByItemNO(model.ItemNO); + if (model.MaterialItem != null) + { + model.MaterialStationsItems = await _pcsApi.GetMaterialStationsItemByItemID(model.MaterialItem.ItemID); + model.MaterialStationsItems = model.MaterialStationsItems.Where(w => w.StationID == model.Station).OrderBy(o => o.StationsItemSeq).ToList(); + if (model.MaterialStationsItems.Any()) + { + ModelState.AddModelError("error", "該站別有設定作業工項"); + } + + // 治具 + var q1 = await _pcsApi.GetWipOutfitByWipNo(model.WipNO); + q1 = q1.Where(w => (w.UnitNo == model.UnitNO && w.StationID == null) || + (w.UnitNo == model.UnitNO && w.StationID == model.Station)).ToList(); + model.wipOutfits.Clear(); + foreach (var item in q1) + { + model.wipOutfits.Add(new WipOutfitDtos + { + OutfitNo = item.OutfitNo, + PartNo = item.PartNo, + PartNoName = item.PartNoName, + StationName = item.StationName, + UnitNoName = item.UnitNoName + }); + } + } + + // 工程工單備註 + var wipsystem = await _pcsApi.GetWipSystem(model.WipNO); + if (wipsystem != null) + { + if (stationUnit == "B") + model.SystemMemo = wipsystem.BabMemo; + else if (stationUnit == "T") + model.SystemMemo = wipsystem.TestMemo; + else if (stationUnit == "P") + model.SystemMemo = wipsystem.PackingMemo; + } + + // KPSeq順序清除 + model.KpItemName = string.Empty; + + // 工單SOP + var wipSOP = await _pcsApi.GetWipSopByWipNo(model.WipNO); + // 標準SOP A + if (wipSOP.Any(a => a.UnitNo == stationUnit && a.SOPType == "A")) + { + var wipSOPTypeA = wipSOP.Where(w => w.UnitNo == stationUnit && w.SOPType == "A") + .OrderByDescending(w => w.UpdateTime).FirstOrDefault(); + var Esop = await _pcsApi.GetDocEsopViewByNo(wipSOPTypeA.SOPName); + if (Esop.Count != 0) + { + model.Sops.Add(new PCS021ViewModel_SOP + { + SopName = "SOP文件", + SopPath = $@"/DocEsop/{Esop.FirstOrDefault().file_path}" + }); + } + } + // 差異SOP F + if (wipSOP.Any(a => a.UnitNo == stationUnit && a.SOPType == "F")) + { + var wipSOPTypeF = wipSOP.Where(w => w.UnitNo == stationUnit && w.SOPType == "F") + .OrderByDescending(w => w.UpdateTime).FirstOrDefault(); + var Esop = await _pcsApi.GetDocEsopViewByNo(wipSOPTypeF.SOPName); + if (Esop.Count != 0) + { + model.Sops.Add(new PCS021ViewModel_SOP + { + SopName = "差異SOP", + SopPath = $@"/DocEsop/{Esop.FirstOrDefault().file_path}" + }); + } + } + // 暫行SOP D + if (wipSOP.Any(a => a.UnitNo == stationUnit && a.SOPType == "D")) + { + var wipSOPTypeD = wipSOP.Where(w => w.UnitNo == stationUnit && w.SOPType == "D") + .OrderByDescending(w => w.UpdateTime).FirstOrDefault(); + var Esop = await _pcsApi.GetEsopBySopName(wipSOPTypeD.SOPName); + if (Esop.Count != 0) + { + model.Sops.Add(new PCS021ViewModel_SOP + { + SopName = "暫行文件", + SopPath = $@"/e-sop/{Esop.FirstOrDefault().Process}/{Esop.FirstOrDefault().SopName}.pdf" + }); + } + } + // 不二過 + model.Sops.Add(new PCS021ViewModel_SOP + { + SopName = "不二過", + SopPath = Url.Action("PCS041V2", "PCS", new + { + material = model.ItemNO, + productionSID = model.Station + }) + }); + } + } + catch (Exception ex) + { + ModelState.AddModelError("error", $"系統錯誤:{ex.Message}"); + return View("PCS021_2025", model); + } + + return View("PCS021_2025", model); + } + + [HttpPost] + public async Task PCS021_2025_Input(PCS021ViewModel model) + { + // ResultModel + string Msg = string.Empty; + bool Success = true; + var input = model.Input.Trim().ToUpper(); + string Data = input; + + if (string.IsNullOrWhiteSpace(input)) + return Json(new Result1() { success = Success, msg = "", data = "", data1 = "" }); + + // 刷入條碼+異常欄位 + if (!string.IsNullOrWhiteSpace(model.InputNo)) + Data += "@" + model.InputNo; + + string ExtNo = string.Empty; + + try + { + #region 基本Input 輸入判斷 + if (model.WipID == 0) + Msg += "請確認是否有輸入工單相關訊息
"; + + // 當有作業站就必須要填治具編號 + if (model.wipOutfits.Any(a => !string.IsNullOrWhiteSpace(a.StationName) && string.IsNullOrWhiteSpace(a.Inputs))) + Msg += "請刷入治具編號
"; + + if (model.Station == 0) + { + Msg += "請選擇作業站
"; + } + + if (string.IsNullOrWhiteSpace(input)) + { + Msg += "請刷讀條碼
"; + } + + if (string.IsNullOrWhiteSpace(model.startTime)) + { + Msg += "請刷入開始時間START
"; + } + + if (!string.IsNullOrWhiteSpace(Msg)) + { + Success = false; + return Json(new Result() { success = Success, msg = Msg, data = Data }); + } + #endregion + + var q = await _pcsApi.CheckBarCodeByWipNo_2025(input, model.WipNO.Trim().ToUpper()); + // 判斷是否序號與工單號碼是否對應條碼區間值,沒對應到視為組件或不良代碼 + if (q.Success) + { + #region 確認序號的狀態 + + // 取作業站的生產製程 + var stationUnit = string.Empty; + var station = await _basApi.GetStations(model.Station); + if (station.Any()) + { + stationUnit = station.FirstOrDefault().UnitNo; + } + var keyParts = new List(); + + // 先查詢已綁定組件數量 By WipID + var BarCodeItems = await _pcsApi.GetBarcodeItemByBarCode(input); + BarCodeItems = BarCodeItems.Where(w => w.S.UnitNo == stationUnit && w.WipID == model.WipID).ToList(); + + // WipKps - BarCodeItem 剩下未綁定的KpNo + var ExceptWipKp = model.WipKps.ToList(); + foreach (var item in BarCodeItems) + { + var ByItemWipKp = ExceptWipKp.Where(w => w.KpNo.Trim().ToUpper() == item.ItemNo.Trim().ToUpper()).FirstOrDefault(); + if (ByItemWipKp != null) + ExceptWipKp.Remove(ByItemWipKp); + } + + // KeyParts代碼順序 + var SpecifyKeyPartsNo = model.KpItemName == null ? new List() : model.KpItemName.Split(',').ToList(); + int KpItemQty = BarCodeItems.Count(); + int i = 0; + + // 判斷指定KeyParts代碼是否有刷足夠數 + if (SpecifyKeyPartsNo.Count() > model.Inputs.Where(w => !w.Input.StartsWith("$")).Count()) + { + Msg = "有指定KeyParts代號 刷入數量不足,請在確認!"; + return Json(new Result() { success = false, msg = Msg, data = Data }); + } + + foreach (var KeyPartItem in model.Inputs) + { + // 判斷是組件先+1 + if (!KeyPartItem.Input.StartsWith("$")) + i += 1; + + // 當刷入組組件+已紀錄組件數量 大於 設定組件數量 + if (i + KpItemQty > model.WipKps.Count()) + { + Msg = "已刷超過組件數量"; + Success = false; + return Json(new Result() { success = Success, msg = Msg, data = Data }); + } + + // NG代碼 + if (KeyPartItem.Input.StartsWith("$")) + { + keyParts.Add(new BarCodeCheckDto.inputItem + { + inputType = "NG", + inputData = KeyPartItem.Input, + oldInputData = KeyPartItem.InputNo, + kpItemNo = "" + }); + } + else // KeaParts + { + // 判斷是否有輸入KeyParts代碼順序 + // 有指定KeyParts順序 + if (i <= SpecifyKeyPartsNo.Count()) + { + var WipKp = ExceptWipKp.Where(w => w.KpNoName.ToUpper() == SpecifyKeyPartsNo[i - 1].ToUpper()).FirstOrDefault(); + // 比對資料為空時 + if (WipKp == null) + { + Msg = $"請確認KeyParts代號【{SpecifyKeyPartsNo[i - 1].ToUpper()}】是否數量全數已綁定?"; + return Json(new Result() { success = false, msg = Msg, data = Data }); + } + + keyParts.Add(new BarCodeCheckDto.inputItem + { + inputType = WipKp.KpNo, + inputData = KeyPartItem.Input, + oldInputData = KeyPartItem.InputNo, + kpItemNo = WipKp.KpName + }); + } + else + { + var WipKp = ExceptWipKp.Where(w => !SpecifyKeyPartsNo.Any(w1 => w1.ToUpper().Contains(w.KpNoName.ToUpper()))).ToList(); + + // 排除有指定數量,其他按照WipKp順序取值 + var k = i - 1 - SpecifyKeyPartsNo.Count(); + keyParts.Add(new BarCodeCheckDto.inputItem + { + inputType = WipKp[k].KpNo, + inputData = KeyPartItem.Input, + oldInputData = KeyPartItem.InputNo, + kpItemNo = WipKp[k].KpName + }); + } + } + } + + // 判斷keyPart是否重複 + var duplicateKeyParts = keyParts.Where(item => item.inputType != "NG").GroupBy(item => item.inputData) + .Where(group => group.Count() > 1).Select(s => s.Key) + .Distinct().ToList(); + + if (duplicateKeyParts.Any()) + { + Msg = $"KeyParts有重複【{string.Join(",", duplicateKeyParts)}】,請在確認"; + return Json(new Result() { success = false, msg = Msg, data = Data }); + } + + // 治具 + var outfit = new List(); + foreach (var outfitItem in model.wipOutfits) + { + outfit.Add(new BarCodeCheckDto.Outfit + { + inputData = outfitItem.Inputs, + PartNo = outfitItem.PartNo + }); + } + + var x = new BarCodeCheckDto + { + wipNo = model.WipNO, + barcode = input, + barcodeType = "M", + stationID = model.Station, + line = model.LineID, + unitNo = model.UnitNO, + inputItems = keyParts, + outfits = outfit, + userID = GetLogInUserID(), + startTime = model.startTime + }; + + var barcode_result = await _pcsApi.PassIngByCheck_2025(JsonConvert.SerializeObject(x)); + // 過站失敗 + if (!barcode_result.Success) + return Json(new Result() { success = barcode_result.Success, msg = barcode_result.Msg, data = input }); + // 過站成功 + else + return Json(new Result1() { success = Success, msg = barcode_result.Msg, data = "", data1 = "" }); + + #endregion + } + else + { + // 組件資料 + var items = await _pcsApi.GetItems(); + items = items.Where(w => model.WipKps.Any(wi => wi.KpNo.Trim().ToUpper() == w.ItemNo.Trim().ToUpper())).ToList(); + // 判斷Input為指定KeyParts順序 + if (items.Any(a => a.ItemName.ToUpper() == input)) + { + if (model.KpItemName != null) + { + // 取得目前Input指定KP代碼的綁定數量 + var KpItemNameByCount = model.KpItemName.Split(",").Where(w => w.ToUpper() == input).Count(); + // WipKp的ByKpNo數量 + var WipKpByCount = model.WipKps.Where(w1 => w1.KpNo == items.Where(w => w.ItemName.ToUpper() == input) + .Select(s => s.ItemNo).FirstOrDefault()).Count(); + // 目前綁定KpNo 等於 WipKp ByKpNo 數量 + if (KpItemNameByCount == WipKpByCount) + { + Success = false; + Msg = $"指定KeyParts:{input} 已超過資料設定數量
"; + return Json(new Result() { success = Success, msg = Msg, data = Data }); + } + } + // 設定指定序號欄位 + return Json(new Result1() { success = Success, msg = Msg, data = "", data1 = Data }); + } + } + } + catch (Exception ex) + { + return Json(new Result() { success = false, msg = $"系統錯誤:{ex.Message}", data = Data }); + } + + return Json(new Result1() { success = Success, msg = Msg, data = Data, data1 = "" }); + } + + /// + /// 取得目前過站刷入時間 + /// + /// + public IActionResult UpdateStartTime() + { + return Json(new Result() { success = true, data = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") }); + } + + #endregion } public static class ObjectExtension diff --git a/AMESCoreStudio.Web/Controllers/QRSController.cs b/AMESCoreStudio.Web/Controllers/QRSController.cs index 9a271fa8..fe66d48e 100644 --- a/AMESCoreStudio.Web/Controllers/QRSController.cs +++ b/AMESCoreStudio.Web/Controllers/QRSController.cs @@ -11333,7 +11333,6 @@ namespace AMESCoreStudio.Web.Controllers } } } - return factoryNo; } @@ -11643,6 +11642,471 @@ namespace AMESCoreStudio.Web.Controllers return Json(new Table() { code = 0, msg = "", data = null, count = 0 }); } + + #region QRS021_2025 委外廠條碼輸入作業 2025(新版) + [ResponseCache(Duration = 0)] + [HttpGet] + public async Task QRS021_2025() + { + var model = new QRS021ViewModel(); + await GetUnitList(); + await GetLineInfoList(GetFactoryNo().Result); + return View(model); + } + + [HttpPost] + public async Task QRS021_2025_GetWip(QRS021ViewModel model) + { + await GetUnitList(); + await GetLineInfoList(GetFactoryNo().Result); + model.KpItemName += "null"; + if (string.IsNullOrWhiteSpace(model.WipNO)) + { + ModelState.AddModelError("error", "請輸入工單號碼"); + } + + if (string.IsNullOrWhiteSpace(model.UnitNO)) + { + ModelState.AddModelError("error", "請選擇生產單位"); + } + + if (model.LineID == 0) + { + ModelState.AddModelError("error", "請選擇線別"); + } + + var q = await _pcsApi.GetWipInfoByWipNO(model.WipNO); + var firstWipNo = q.Where(w => w.UnitNO == model.UnitNO).FirstOrDefault(); + + if (firstWipNo == null) + { + ModelState.AddModelError("error", "找不到該生產單位的工單號碼"); + } + + // 取作業站的生產製程 + var stationUnit = string.Empty; + var station = await _basApi.GetStations(model.Station); + if (station.Any()) + { + stationUnit = station.FirstOrDefault().UnitNo; + } + else + { + ModelState.AddModelError("error", "找不到該作業站的生產單位"); + } + + try + { + if (q.Count != 0) + { + model.WipID = firstWipNo.WipID; + model.PlanQTY = firstWipNo.PlanQTY; + model.UnitNO = firstWipNo.UnitNO; + model.FlowRuleID = firstWipNo.FlowRuleID; + model.ItemNO = (await _pcsApi.GetWipAtt(model.WipNO)).ItemNO ?? ""; + + // 判斷工單狀態 + var BarCodeWip = await _pcsApi.CheckBarCodeWip_2025(model.WipNO, model.UnitNO, model.LineID, model.FlowRuleID); + if (!BarCodeWip.Success) + { + ModelState.AddModelError("error", BarCodeWip.Msg); + return View("QRS021_2025", model); + } + + // 工單流程ID 取站別 + var ruleStations = await GetRuleStationByFlowRuleID(model.FlowRuleID, true); + if (!ruleStations.Any()) + { + ModelState.AddModelError("error", $"找不到該筆工單流程作業站設定 ID【{model.FlowRuleID}】"); + return View("QRS021_2025", model); + } + + // 作業站名稱代碼 提供不二過 + var StationNameSt = ""; + // 過站沒有作業站,就先帶預設 + if (model.Station == 0) + model.Station = ruleStations.FirstOrDefault().StationID; + + if (ruleStations.Any(a => a.StationID == model.Station)) + { + model.RuleStation = ruleStations.Where(w => w.StationID == model.Station).FirstOrDefault().RuleStationID; + model.StationTypeNo = ruleStations.Where(w => w.StationID == model.Station).FirstOrDefault().Station.TypeNo; + StationNameSt = ruleStations.Where(w => w.StationID == model.Station).FirstOrDefault().Station.StationNameSt; + } + else + { + model.RuleStation = ruleStations.FirstOrDefault().RuleStationID; + model.StationTypeNo = ruleStations.FirstOrDefault().Station.TypeNo; + model.Station = ruleStations.FirstOrDefault().StationID; + StationNameSt = ruleStations.FirstOrDefault().Station.StationNameSt; + } + + // 工單已刷數量 + model.InputQTY = await _pcsApi.GetBarcodeStationByInputQty(model.WipID, model.Station); + + // 工單KeyParts + model.WipKps = await _pcsApi.GetWipKpByWipNo(model.WipNO); + model.WipKps = model.WipKps.Where(w => w.UnitNo == stationUnit).OrderBy(o => o.KpSeq).ToList(); + + // 料號檔案 + model.MaterialItem = await _pcsApi.GetMaterialItemByItemNO(model.ItemNO); + if (model.MaterialItem != null) + { + model.MaterialStationsItems = await _pcsApi.GetMaterialStationsItemByItemID(model.MaterialItem.ItemID); + model.MaterialStationsItems = model.MaterialStationsItems.Where(w => w.StationID == model.Station).OrderBy(o => o.StationsItemSeq).ToList(); + if (model.MaterialStationsItems.Any()) + { + ModelState.AddModelError("error", "該站別有設定作業工項"); + } + + // 治具 + var q1 = await _pcsApi.GetWipOutfitByWipNo(model.WipNO); + q1 = q1.Where(w => (w.UnitNo == model.UnitNO && w.StationID == null) || + (w.UnitNo == model.UnitNO && w.StationID == model.Station)).ToList(); + model.wipOutfits.Clear(); + foreach (var item in q1) + { + model.wipOutfits.Add(new WipOutfitDtos + { + OutfitNo = item.OutfitNo, + PartNo = item.PartNo, + PartNoName = item.PartNoName, + StationName = item.StationName, + UnitNoName = item.UnitNoName + }); + + } + } + + // 工程工單備註 + var wipsystem = await _pcsApi.GetWipSystem(model.WipNO); + if (wipsystem != null) + { + if (stationUnit == "B") + model.SystemMemo = wipsystem.BabMemo; + else if (stationUnit == "T") + model.SystemMemo = wipsystem.TestMemo; + else if (stationUnit == "P") + model.SystemMemo = wipsystem.PackingMemo; + } + + // KPSeq順序清除 + model.KpItemName = string.Empty; + + // 工單SOP + var wipSOP = await _pcsApi.GetWipSopByWipNo(model.WipNO); + // 標準SOP A + if (wipSOP.Any(a => a.UnitNo == stationUnit && a.SOPType == "A")) + { + var wipSOPTypeA = wipSOP.Where(w => w.UnitNo == stationUnit && w.SOPType == "A") + .OrderByDescending(w => w.UpdateTime).FirstOrDefault(); + var Esop = await _pcsApi.GetDocEsopViewByNo(wipSOPTypeA.SOPName); + if (Esop.Count != 0) + { + model.Sops.Add(new QRS021ViewModel_SOP + { + SopName = "SOP文件", + SopPath = $@"/DocEsop/{Esop.FirstOrDefault().file_path}" + }); + } + } + // 差異SOP F + if (wipSOP.Any(a => a.UnitNo == stationUnit && a.SOPType == "F")) + { + var wipSOPTypeF = wipSOP.Where(w => w.UnitNo == stationUnit && w.SOPType == "F") + .OrderByDescending(w => w.UpdateTime).FirstOrDefault(); + var Esop = await _pcsApi.GetDocEsopViewByNo(wipSOPTypeF.SOPName); + if (Esop.Count != 0) + { + model.Sops.Add(new QRS021ViewModel_SOP + { + SopName = "差異SOP", + SopPath = $@"/DocEsop/{Esop.FirstOrDefault().file_path}" + }); + } + } + // 暫行SOP D + if (wipSOP.Any(a => a.UnitNo == stationUnit && a.SOPType == "D")) + { + var wipSOPTypeD = wipSOP.Where(w => w.UnitNo == stationUnit && w.SOPType == "D") + .OrderByDescending(w => w.UpdateTime).FirstOrDefault(); + var Esop = await _pcsApi.GetEsopBySopName(wipSOPTypeD.SOPName); + if (Esop.Count != 0) + { + model.Sops.Add(new QRS021ViewModel_SOP + { + SopName = "暫行文件", + SopPath = $@"/e-sop/{Esop.FirstOrDefault().Process}/{Esop.FirstOrDefault().SopName}.pdf" + }); + } + } + // 不二過 + model.Sops.Add(new QRS021ViewModel_SOP + { + SopName = "不二過", + SopPath = Url.Action("PCS041V2", "PCS", new + { + material = model.ItemNO, + productionSID = model.Station + }) + }); + } + } + catch (Exception ex) + { + ModelState.AddModelError("error", $"系統錯誤:{ex.Message}"); + return View("QRS021_2025", model); + } + + return View("QRS021_2025", model); + } + + [HttpPost] + public async Task QRS021_2025_Input(QRS021ViewModel model) + { + // ResultModel + string Msg = string.Empty; + bool Success = true; + var input = model.Input.Trim().ToUpper(); + string Data = input; + + if (string.IsNullOrWhiteSpace(input)) + return Json(new Result1() { success = Success, msg = Msg, data = "", data1 = "" }); + + // 刷入條碼+異常欄位 + if (!string.IsNullOrWhiteSpace(model.InputNo)) + Data += "@" + model.InputNo; + + string ExtNo = string.Empty; + + try + { + #region 基本Input 輸入判斷 + if (model.WipID == 0) + Msg += "請確認是否有輸入工單相關訊息
"; + + // 當有作業站就必須要填治具編號 + if (model.wipOutfits.Any(a => !string.IsNullOrWhiteSpace(a.StationName) && string.IsNullOrWhiteSpace(a.Inputs))) + Msg += "請刷入治具編號
"; + + if (model.Station == 0) + { + Msg += "請選擇作業站
"; + } + + if (string.IsNullOrWhiteSpace(input)) + { + Msg += "請刷讀條碼
"; + } + + if (string.IsNullOrWhiteSpace(model.startTime)) + { + Msg += "請刷入開始時間START
"; + } + + if (!string.IsNullOrWhiteSpace(Msg)) + { + Success = false; + return Json(new Result() { success = Success, msg = Msg, data = Data }); + } + #endregion + + var q = await _pcsApi.CheckBarCodeByWipNo_2025(input, model.WipNO.Trim().ToUpper()); + // 判斷是否序號與工單號碼是否對應條碼區間值,沒對應到視為組件或不良代碼 + if (q.Success) + { + #region 確認序號的狀態 + + // 取作業站的生產製程 + var stationUnit = string.Empty; + var station = await _basApi.GetStations(model.Station); + if (station.Any()) + { + stationUnit = station.FirstOrDefault().UnitNo; + } + var keyParts = new List(); + + // 先查詢已綁定組件數量 By WipID + var BarCodeItems = await _pcsApi.GetBarcodeItemByBarCode(input); + BarCodeItems = BarCodeItems.Where(w => w.S.UnitNo == stationUnit && w.WipID == model.WipID).ToList(); + + // WipKps - BarCodeItem 剩下未綁定的KpNo + var ExceptWipKp = model.WipKps.ToList(); + foreach (var item in BarCodeItems) + { + var ByItemWipKp = ExceptWipKp.Where(w => w.KpNo.Trim().ToUpper() == item.ItemNo.Trim().ToUpper()).FirstOrDefault(); + if (ByItemWipKp != null) + ExceptWipKp.Remove(ByItemWipKp); + } + + // KeyParts代碼順序 + var SpecifyKeyPartsNo = model.KpItemName == null ? new List() : model.KpItemName.Split(',').ToList(); + int KpItemQty = BarCodeItems.Count(); + int i = 0; + + // 判斷指定KeyParts代碼是否有刷足夠數 + if (SpecifyKeyPartsNo.Count() > model.Inputs.Where(w => !w.Input.StartsWith("$")).Count()) + { + Msg = "有指定KeyParts代號 刷入數量不足,請在確認!"; + return Json(new Result() { success = false, msg = Msg, data = Data }); + } + + foreach (var KeyPartItem in model.Inputs) + { + // 判斷是組件先+1 + if (!KeyPartItem.Input.StartsWith("$")) + i += 1; + + // 當刷入組組件+已紀錄組件數量 大於 設定組件數量 + if (i + KpItemQty > model.WipKps.Count()) + { + Msg = "已刷超過組件數量"; + Success = false; + return Json(new Result() { success = Success, msg = Msg, data = Data }); + } + + // NG代碼 + if (KeyPartItem.Input.StartsWith("$")) + { + keyParts.Add(new BarCodeCheckDto.inputItem + { + inputType = "NG", + inputData = KeyPartItem.Input, + oldInputData = KeyPartItem.InputNo, + kpItemNo = "" + }); + } + else // KeaParts + { + // 判斷是否有輸入KeyParts代碼順序 + // 有指定KeyParts順序 + if (i <= SpecifyKeyPartsNo.Count()) + { + var WipKp = ExceptWipKp.Where(w => w.KpNoName.ToUpper() == SpecifyKeyPartsNo[i - 1].ToUpper()).FirstOrDefault(); + // 比對資料為空時 + if (WipKp == null) + { + Msg = $"請確認KeyParts代號【{SpecifyKeyPartsNo[i - 1].ToUpper()}】是否數量全數已綁定?"; + return Json(new Result() { success = false, msg = Msg, data = Data }); + } + + keyParts.Add(new BarCodeCheckDto.inputItem + { + inputType = WipKp.KpNo, + inputData = KeyPartItem.Input, + oldInputData = KeyPartItem.InputNo, + kpItemNo = WipKp.KpName + }); + } + else + { + var WipKp = model.WipKps.Where(w => !SpecifyKeyPartsNo.Any(w1 => w1.ToUpper().Contains(w.KpNoName.ToUpper()))) + .ToList(); + // 排除有指定數量,其他按照WipKp順序取值 + var k = i - 1 - SpecifyKeyPartsNo.Count(); + keyParts.Add(new BarCodeCheckDto.inputItem + { + inputType = WipKp[k].KpNo, + inputData = KeyPartItem.Input, + oldInputData = KeyPartItem.InputNo, + kpItemNo = WipKp[k].KpName + }); + } + } + } + + // 判斷keyPart是否重複 + var duplicateKeyParts = keyParts.Where(item => item.inputType != "NG").GroupBy(item => item.inputData) + .Where(group => group.Count() > 1).Select(s => s.Key) + .Distinct().ToList(); + + if (duplicateKeyParts.Any()) + { + Msg = $"KeyParts有重複【{string.Join(",", duplicateKeyParts)}】,請在確認"; + return Json(new Result() { success = false, msg = Msg, data = Data }); + } + + // 治具 + var outfit = new List(); + foreach (var outfitItem in model.wipOutfits) + { + outfit.Add(new BarCodeCheckDto.Outfit + { + inputData = outfitItem.Inputs, + PartNo = outfitItem.PartNo + }); + } + + var x = new BarCodeCheckDto + { + wipNo = model.WipNO, + barcode = input, + barcodeType = "M", + stationID = model.Station, + line = model.LineID, + unitNo = model.UnitNO, + inputItems = keyParts, + outfits = outfit, + userID = GetLogInUserID(), + startTime = model.startTime + }; + + var barcode_result = await _pcsApi.PassIngByCheck_2025(JsonConvert.SerializeObject(x)); + // 過站失敗 + if (!barcode_result.Success) + return Json(new Result() { success = barcode_result.Success, msg = barcode_result.Msg, data = input }); + // 過站成功 + else + return Json(new Result1() { success = Success, msg = barcode_result.Msg, data = "", data1 = "" }); + + #endregion + } + else + { + // 組件資料 + var items = await _pcsApi.GetItems(); + items = items.Where(w => model.WipKps.Any(wi => wi.KpNo.Trim().ToUpper() == w.ItemNo.Trim().ToUpper())).ToList(); + // 判斷Input為指定KeyParts順序 + if (items.Any(a => a.ItemName.ToUpper() == input)) + { + if (model.KpItemName != null) + { + // 取得目前Input指定KP代碼的綁定數量 + var KpItemNameByCount = model.KpItemName.Split(",").Where(w => w.ToUpper() == input).Count(); + // WipKp的ByKpNo數量 + var WipKpByCount = model.WipKps.Where(w1 => w1.KpNo == items.Where(w => w.ItemName.ToUpper() == input) + .Select(s => s.ItemNo).FirstOrDefault()).Count(); + // 目前綁定KpNo 等於 WipKp ByKpNo 數量 + if (KpItemNameByCount == WipKpByCount) + { + Success = false; + Msg = $"指定KeyParts:{input} 已超過資料設定數量
"; + return Json(new Result() { success = Success, msg = Msg, data = Data }); + } + } + // 設定指定序號欄位 + return Json(new Result1() { success = Success, msg = Msg, data = "", data1 = Data }); + } + } + } + catch (Exception ex) + { + return Json(new Result() { success = false, msg = $"系統錯誤:{ex.Message}", data = Data }); + } + + return Json(new Result1() { success = Success, msg = Msg, data = Data, data1 = "" }); + } + + /// + /// 取得目前過站刷入時間 + /// + /// + public IActionResult UpdateStartTime() + { + return Json(new Result() { success = true, data = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") }); + } + + #endregion } diff --git a/AMESCoreStudio.Web/HttpApis/AMES/IPCS.cs b/AMESCoreStudio.Web/HttpApis/AMES/IPCS.cs index 4582252c..a81965ae 100644 --- a/AMESCoreStudio.Web/HttpApis/AMES/IPCS.cs +++ b/AMESCoreStudio.Web/HttpApis/AMES/IPCS.cs @@ -2062,6 +2062,30 @@ namespace AMESCoreStudio.Web #endregion + #region PCS021_2025 條碼輸入作業 2025(新版) + /// + /// 判斷工單狀態 + /// + /// 工單號碼 + /// 生產單位 + /// 線別 + /// 流程 + /// + [WebApiClient.Attributes.HttpGet("api/BarCodeCheck2025/CheckWipNoSation")] + ITask> CheckBarCodeWip_2025(string wipno, string unitno, int? line, int flowrule); + + /// + /// 查詢序號是否有在該工單 條碼區間內 + /// + /// 內部序號 + /// 工單號碼 + [WebApiClient.Attributes.HttpGet("api/BarCodeCheck2025/CheckBarCodeByWipNo")] + ITask> CheckBarCodeByWipNo_2025(string barcode, string wipNo); + + [WebApiClient.Attributes.HttpPost("api/BarCodeCheck2025/PassIngByCheck")] + ITask> PassIngByCheck_2025([FromBody, RawJsonContent] string model); + + #endregion } } diff --git a/AMESCoreStudio.Web/ViewModels/PCS/PCS021ViewModel.cs b/AMESCoreStudio.Web/ViewModels/PCS/PCS021ViewModel.cs index ad6bc9f6..04aecbf2 100644 --- a/AMESCoreStudio.Web/ViewModels/PCS/PCS021ViewModel.cs +++ b/AMESCoreStudio.Web/ViewModels/PCS/PCS021ViewModel.cs @@ -1,10 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; +using AMESCoreStudio.WebApi.DTO.AMES; using AMESCoreStudio.WebApi.Models.AMES; -using AMESCoreStudio.WebApi.Models.BAS; -using AMESCoreStudio.WebApi.DTO.AMES; +using System.Collections.Generic; namespace AMESCoreStudio.Web.ViewModels.PCS { @@ -136,7 +132,12 @@ namespace AMESCoreStudio.Web.ViewModels.PCS /// public List MaterialStationsItems { get; set; } = new List(); - public List Sops { get; set; } = new List(); + public List Sops { get; set; } = new List(); + + /// + /// 刷入時間 + /// + public string startTime { get; set; } } public class WipOutfitDtos : WipOutfitDto diff --git a/AMESCoreStudio.Web/ViewModels/QRS/QRS021ViewModel.cs b/AMESCoreStudio.Web/ViewModels/QRS/QRS021ViewModel.cs index 76df73c3..460d07ee 100644 --- a/AMESCoreStudio.Web/ViewModels/QRS/QRS021ViewModel.cs +++ b/AMESCoreStudio.Web/ViewModels/QRS/QRS021ViewModel.cs @@ -136,7 +136,12 @@ namespace AMESCoreStudio.Web.ViewModels.QRS /// public List MaterialStationsItems { get; set; } = new List(); - public List Sops { get; set; } = new List(); + public List Sops { get; set; } = new List(); + + /// + /// 刷入時間 + /// + public string startTime { get; set; } } public class WipOutfitDtos : WipOutfitDto diff --git a/AMESCoreStudio.Web/Views/PCS/PCS021_2025.cshtml b/AMESCoreStudio.Web/Views/PCS/PCS021_2025.cshtml new file mode 100644 index 00000000..cd56094a --- /dev/null +++ b/AMESCoreStudio.Web/Views/PCS/PCS021_2025.cshtml @@ -0,0 +1,631 @@ +@model AMESCoreStudio.Web.ViewModels.PCS.PCS021ViewModel +@{ + ViewData["Title"] = "過站作業"; + Layout = "~/Views/Shared/_AMESLayout.cshtml"; +} + + + + +
+
+
+
+
+
+
+
    +
  • 過站資料
  • +
  • 治具資料
  • +
+
+
+
+
+
+ +
+ +
+ +
+ +
+
+
+
+
+ +
+
+ +
+ + + + + +
+ +
+ +
+
+
+
+
+
+
+ + +
+
+
+
+ + + +
+
+
+
+ + +
+
+
+ 刷讀條碼 +
+
+
+ +
+ +
+
+ +
+
+
+
+
+ 刷入資料 + + + +
+
+
+ 檢查項目 + + @{ + int i = 0; + } + + + + + + + + + @foreach (var index in Model.MaterialStationsItems) + { + + + + + + i++; + } + +
+ 工項順序 + + 工項名稱 + + 工項描述 +
+ @index.StationsItemSeq + + @index.StationsItemNo + + +
+
+
+ 指定KeyPart + +
+
+ 工程備註 +
+ +
+
+
+ KeyParts +
+
+
+ + @{ + int j = 0; + } + + + + + + + + + + + + @foreach (var index in Model.WipKps) + { + + + + + + + + + j++; + } + +
+ KP料號名稱 + + KP料號NO + + 順序 + + 前置碼 + + 長度 + + 生產單位 +
+ + + + + + + + + + + + + @index.UnitNoName +
+
+
+
+
+ + @{ + int k = 0; + } + + + + + + + + + + @foreach (var index in Model.wipOutfits) + { + + + + + + + k++; + } + +
+ 治具種類 + + 生產單位 + + 作業站 + + 刷入治具條碼 +
+ + + + + + + + +
+
+
+
+
+
+ @if (Model.Sops.Count != 0) + { + bool sopfirst = true; +
+
    + @foreach (var index in Model.Sops) + { + if (sopfirst) + { +
  • @index.SopName
  • + sopfirst = false; + } + else + { +
  • @index.SopName
  • + } + } +
+ +
+ @foreach (var index in Model.Sops) + { + if (!sopfirst) + { +
+ +
+ sopfirst = true; + } + else + { +
+ +
+ } + } +
+
+ } +
+
+
+
+
+ +@section Scripts { + @{ + await Html.RenderPartialAsync("_ValidationScriptsPartial"); + await Html.RenderPartialAsync("_FileinputScriptsPartial"); + } + + +} diff --git a/AMESCoreStudio.Web/Views/QRS/QRS021_2025.cshtml b/AMESCoreStudio.Web/Views/QRS/QRS021_2025.cshtml new file mode 100644 index 00000000..aab9f0bc --- /dev/null +++ b/AMESCoreStudio.Web/Views/QRS/QRS021_2025.cshtml @@ -0,0 +1,630 @@ +@model AMESCoreStudio.Web.ViewModels.QRS.QRS021ViewModel +@{ + ViewData["Title"] = "過站作業"; + Layout = "~/Views/Shared/_AMESLayout.cshtml"; +} + + + + + +
+
+
+
+
+
+
+
    +
  • 過站資料
  • +
  • 治具資料
  • +
+
+
+
+
+
+ +
+ +
+ +
+ +
+
+
+
+
+ +
+
+ +
+ + + + + +
+ +
+ +
+
+
+
+
+
+
+ + +
+
+
+
+ + + +
+
+
+
+ + +
+
+
+ 刷讀條碼 +
+
+
+ +
+ +
+
+ +
+
+
+
+
+ 刷入資料 + + + +
+
+
+ 檢查項目 + + @{ + int i = 0; + } + + + + + + + + + @foreach (var index in Model.MaterialStationsItems) + { + + + + + + i++; + } + + +
+ 工項順序 + + 工項名稱 + + 工項描述 +
+ @index.StationsItemSeq + + @index.StationsItemNo + + +
+
+
+ 指定KeyPart + +
+
+ 工程備註 +
+ +
+
+
+ KeyParts +
+
+
+ + @{ + int j = 0; + } + + + + + + + + + + + + @foreach (var index in Model.WipKps) + { + + + + + + + + + j++; + } + +
+ KP料號名稱 + + KP料號NO + + 順序 + + 前置碼 + + 長度 + + 生產單位 +
+ + + + + + + + + + + + + @index.UnitNoName +
+
+
+
+
+ + @{ + int k = 0; + } + + + + + + + + + + @foreach (var index in Model.wipOutfits) + { + + + + + + + k++; + } + +
+ 治具種類 + + 生產單位 + + 作業站 + + 刷入治具條碼 +
+ + + + + + + + +
+
+
+
+
+
+ @if (Model.Sops.Count != 0) + { + bool sopfirst = true; +
+
    + @foreach (var index in Model.Sops) + { + if (sopfirst) + { +
  • @index.SopName
  • + sopfirst = false; + } + else + { +
  • @index.SopName
  • + } + } +
+ +
+ @foreach (var index in Model.Sops) + { + if (!sopfirst) + { +
+ +
+ sopfirst = true; + } + else + { +
+ +
+ } + } +
+
+ } +
+
+
+
+
+ +@section Scripts { + @{ + await Html.RenderPartialAsync("_ValidationScriptsPartial"); + await Html.RenderPartialAsync("_FileinputScriptsPartial"); + } + + +} diff --git a/AMESCoreStudio.WebApi/Controllers/BLL/BarCodeCheck2025Controller.cs b/AMESCoreStudio.WebApi/Controllers/BLL/BarCodeCheck2025Controller.cs new file mode 100644 index 00000000..85896463 --- /dev/null +++ b/AMESCoreStudio.WebApi/Controllers/BLL/BarCodeCheck2025Controller.cs @@ -0,0 +1,3081 @@ +using AMESCoreStudio.CommonTools.Result; +using AMESCoreStudio.WebApi.Controllers.BLL; +using AMESCoreStudio.WebApi.DTO.AMES; +using AMESCoreStudio.WebApi.Enum; +using AMESCoreStudio.WebApi.Models.AMES; +using AMESCoreStudio.WebApi.Models.BAS; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Threading.Tasks; +using Dapper; +using AMESCoreStudio.WebApi.Extensions; + +namespace AMESCoreStudio.WebApi.Controllers.AMES +{ + /// + /// 過站判斷 + /// + [Route("api/[controller]")] + [ApiController] + public class BarCodeCheck2025Controller : ControllerBase + { + private readonly AMESContext _context; + private readonly IConfiguration _config; + + /// + /// + /// + /// + public BarCodeCheck2025Controller(AMESContext context, IConfiguration config) + { + _config = config; + _context = context; + } + + #region -- 過站判斷 -- + /// + /// 過站判斷 + /// + /// + /// + [HttpPost("PassIngByCheck")] + public async Task>> CheckBarCodeCheck([FromBody] BarCodeCheckDto barCodeCheckDto) + { + ResultModel resultModel = new ResultModel { Success = false }; + try + { + // 確認過站欄位是否填寫 + resultModel.Msg = CheckBarCodeInputData(barCodeCheckDto); + if (!string.IsNullOrWhiteSpace(resultModel.Msg)) + return resultModel; + + // 抓取過站需要訊息及資料轉換 + var data = await PassIngDataTuck(barCodeCheckDto); + + // 確認資料正確 + resultModel.Msg = await CheckPassIngDataCorrect(data); + if (!string.IsNullOrWhiteSpace(resultModel.Msg)) + return resultModel; + + #region 宣告參數 + // 存放要更新BarCodeItem + var update_BarCodeItem = new List(); + var insert_BarCodeItemChange = new List(); + #endregion + + #region 判斷工單狀態 + + resultModel = await CheckWipNoSationAsync(wipNo: data.wipNo, unitNo: data.unitNo + , flowRuleID: data.flowRule, line: data.line, stationID: data.stationID, barCodeNo: data.barcode); + if (!resultModel.Success) + return resultModel; + + #endregion + + #region 判斷序號區間 + + resultModel = await CheckBarCodeByWipNo(wipNo: data.wipNo, barcode: data.barcode); + if (!resultModel.Success) + return resultModel; + + #endregion + + #region 判斷序號狀態 + + resultModel = await GetCheckBarCodeStation(barCode: data.barcodeID, barCodeNo: data.barcode); + if (!resultModel.Success) + return resultModel; + + #endregion + + #region 判斷序號流程 + + resultModel = await CheckBarCodeFlowAsync(wipId: data.wipID, barCode: data.barcodeID, barCodeNo: data.barcode, + stationID: data.stationID, ruleStatus: data.ruleStatus); + if (!resultModel.Success) + return resultModel; + + #endregion + + #region 燒機判斷 + + // Station_Type = B 燒機站 + if (data.stations_TypeNo == "B") + { + resultModel = await GetCheckBurn(data.wipNo, data.barcodeID, data.stationID, data.ruleStatus); + if (!resultModel.Success) + return resultModel; + else if (resultModel.Msg == "BurnIn") + data.burnIn = true; + } + #endregion + + #region 治具判斷 + + if (data.outfits.Count != 0) + { + resultModel = CheckBarCodeOutfitAsync(data.outfits); + if (!resultModel.Success) + return resultModel; + } + + #endregion + + #region 判斷T3掃毒 + + if (data.stations_Name.ToUpper() == "T3") + { + resultModel = await CheckAntivirus(data.wipNo, data.itemNo); + if (!resultModel.Success) + return resultModel; + } + + #endregion + + #region KeyParts 判斷 + + // 排除刷不良代碼 + if (data.inputItems.Where(w => !w.inputType.ToUpper().StartsWith("NG")).Any()) + { + // + var WipKps = _context.WipKps.Where(w => w.WipNo == data.wipNo).OrderBy(o => o.KpSeq).ToList(); + if (WipKps.Count == 0) + { + resultModel.Msg = "工單號碼【" + data.wipNo + "】找不到相關Key Parts設定"; + resultModel.Success = false; + return resultModel; + } + + // 一般過站 + if (data.barcodeType != "S") + { + var barcodeItemKPDto = new BarcodeItemKPDto + { + wipNo = data.wipNo, + wipId = data.wipID, + barCode = data.barcodeID, + barCodeNo = data.barcode, + unitNo = data.unitNo, + ststionUnitNo = data.stations_UnitNo, + inputKP = data.inputItems.Where(w => !w.inputType.ToUpper().StartsWith("NG")).ToList() + }; + + var resultModelKeyParts = await CheckBarCodeKeyPartsData(barcodeItemKPDto); + if (!resultModelKeyParts.Success) + { + resultModel.Success = false; + resultModel.Msg = resultModelKeyParts.Msg; + return resultModel; + } + + } + // 維修過站 + else if (data.barcodeType == "S") + { + // 用BarCodeID And WipID 取BarCodeItem + var q_BarCodeItem = await _context.BarcodeItems.Where(w => w.BarcodeID == data.barcodeID).ToListAsync(); + + foreach (var KPs in data.inputItems) + { + // 用舊組件序號比對 + var barCodeItem = q_BarCodeItem.Where(w => w.PartNo == KPs.oldInputData).FirstOrDefault(); + + if (barCodeItem != null) + { + var q_Kp = WipKps.Where(w => w.KpNo.ToUpper() == barCodeItem.ItemNo.ToUpper()).FirstOrDefault(); + if (q_Kp != null) + { + resultModel.Msg += await CheckKeyPartsCorrect(q_Kp, KPs); + } + + barCodeItem.WipID = data.wipID; + barCodeItem.PartNo = KPs.inputData; + barCodeItem.UpdateDate = DateTime.Now; + update_BarCodeItem.Add(barCodeItem); + + insert_BarCodeItemChange.Add(new BarcodeItemChange + { + WipID = data.wipID, + StationID = data.stationID, + BarcodeID = data.barcodeID, + ItemNo = barCodeItem.ItemNo, + PartNoOld = KPs.oldInputData, + ChangeType = "RP", + KpItemNo = KPs.inputData, + CreateUserID = data.userID + }); + } + else + { + resultModel.Msg = $"內部條碼【{data.barcode}】找不到已綁定Kp序號【{KPs.oldInputData}】"; + } + } + + if (!string.IsNullOrWhiteSpace(resultModel.Msg)) + { + resultModel.Success = false; + return resultModel; + } + + // 將InputItem清空 + data.inputItems = new List(); + } + } + #endregion + + #region 判斷為CHECK站.組件是否都有資料 + + // 判斷作業站是否為CHECK站 Station_Type == C + if (data.stations_TypeNo == "C") + { + // 過站輸入組件數量 + var inputKPQty = data.inputItems.Where(w => !w.inputData.Contains("$")).Count(); + + // 已記錄組件數量 + var BarCodeItems = _context.BarcodeItems.Where(w => w.BarcodeID == data.barcodeID && w.WipID == data.wipID); + var Stations = _context.Stationses.Where(w => w.UnitNo == data.stations_UnitNo); + var BarCodeItemsQty = BarCodeItems.Where(w => Stations.Any(s => s.StationID == w.StationID)).Count(); + + // WipKp DB 設定綁定組件數量 + 製程判斷 + var wipKpQty = _context.WipKps.Where(w => w.WipNo == data.wipNo + && w.UnitNo == data.stations_UnitNo + ).Count(); + + if (wipKpQty != inputKPQty + BarCodeItemsQty) + { + resultModel.Success = false; + resultModel.Msg = "組件資料筆數不符,請確認"; + return resultModel; + } + } + + #endregion + + #region 內部序號輸入後新增 or 更新 + + var result_CUTableMsg = await CU_Tables(data); + if (!string.IsNullOrWhiteSpace(result_CUTableMsg)) + { + resultModel.Msg = "內部序號【" + barCodeCheckDto.barcode + "】 過站失敗,錯誤訊息:
"; + resultModel.Msg += result_CUTableMsg; + resultModel.Success = false; + return resultModel; + } + + #endregion + + #region 維修組件更換 + + if (update_BarCodeItem.Count() != 0) + { + await UpdateBarCodeItemChange(update_BarCodeItem, insert_BarCodeItemChange); + } + + #endregion + + #region 燒機In 修改狀態 + if (data.burnIn) + { + resultModel.Msg = $"內部序號【{data.barcode}】 燒機In 完成!"; + } + else + { + resultModel.Msg = $"內部序號【{data.barcode}】 過站完成!"; + } + #endregion + + // IPQC 任務性 + IPQCTaskNoticeController iPQCTaskNoticeController = new IPQCTaskNoticeController(_context, _config); + await iPQCTaskNoticeController.CheckIPQCTaskNotice(barCodeCheckDto.wipNo, data.itemNo, barCodeCheckDto.stationID); + + resultModel.Success = true; + return resultModel; + + } + catch (Exception ex) + { + resultModel.Success = false; + resultModel.Msg = ex.Message; + return resultModel; + } + } + #endregion + + #region -- FQC抽驗過站 -- + /// + /// FQC抽驗過站 + /// + /// 入庫單號 + /// 順序 + /// UserID + /// + [HttpGet("PassIngByFQC")] + [Obsolete("請切換到PassingByFQCV1")] + public async Task>> PassingByFQC(string inhouseNo, int seqID, int userID) + { + ResultModel resultModel = new ResultModel { Success = false }; + var InhouseMaster = _context.FqcInhouseMasters.Where(w => w.InhouseNo == inhouseNo && w.SeqID == seqID) + .FirstOrDefault(); + try + { + if (InhouseMaster != null) + { + // 判斷是否有設定FQC站 Station_Type == F + var WipInfo = _context.WipInfos.Where(w => w.WipNO == InhouseMaster.WipNo).FirstOrDefault(); + var RuleStations = _context.RuleStations.Where(w => w.FlowRuleID == WipInfo.FlowRuleID && + w.Station.TypeNo == "F").ToList(); + // 有設定FQC站別 + if (RuleStations.Any()) + { + var RuleStation = RuleStations.FirstOrDefault(); + // 取FQC抽驗單號 + var InhouseDetail = await _context.FqcInhouseDetails.Where(w => w.InhouseNo == inhouseNo && w.SeqID == seqID) + .ToListAsync(); + BarCodeCheckDtoForDBData data = new BarCodeCheckDtoForDBData(); + data.line = -1; + data.ruleStatus = "P"; + data.stationID = RuleStation.Station.StationID; + data.userID = userID; + data.barcodeType = "M"; + // 生產單位_簡碼 + data.factoryUnit_UnitCode = _context.FactoryUnits.Where(w => w.UnitNo == WipInfo.UnitNO).FirstOrDefault().UnitCode ?? ""; + foreach (var item in InhouseDetail.Select(s => s.SerialNo).Distinct()) + { + var BarcodeNo = await _context.BarcodeInfoes.Where(w => w.BoxNo == item).ToListAsync(); + foreach (var barcode in BarcodeNo) + { + data.unitNo = WipInfo.UnitNO; + data.wipID = barcode.WipID; + data.barcode = barcode.BarcodeNo; + data.barcodeID = barcode.BarcodeID; + data.extNo = barcode.ExtraBarcodeNo; + data.flowRule = WipInfo.FlowRuleID; + data.wipNo = WipInfo.WipNO; + + var result_CUTableMsg = await CU_Tables(data); + if (string.IsNullOrWhiteSpace(result_CUTableMsg)) + { + resultModel.Success = true; + resultModel.Msg = "FQC過站完成"; + } + else + { + resultModel.Msg = result_CUTableMsg; + } + } + } + } + else + { + resultModel.Msg = $"該筆工單號碼【{InhouseMaster.WipNo}】,無設定FQC站別"; + } + } + else + { + resultModel.Msg = "找不到該筆FQC單號"; + } + return resultModel; + } + catch (Exception ex) + { + resultModel.Msg = ex.Message; + resultModel.Success = false; + return resultModel; + } + } + #endregion + + #region -- FQC抽驗過站 新版 -- + /// + /// FQC抽驗過站 + /// + /// 入庫單號 + /// 順序 + /// UserID + /// + [HttpGet("PassIngByFQCV1")] + public async Task>> PassingByFQCV1(string inhouseNo, int seqID, int userID) + { + ResultModel resultModel = new ResultModel { Success = false }; + var InhouseMaster = _context.FqcInhouseMasters.Where(w => w.InhouseNo == inhouseNo && w.SeqID == seqID) + .FirstOrDefault(); + try + { + if (InhouseMaster != null) + { + // 判斷是否有設定FQC站 Station_Type == F + var WipInfo = _context.WipInfos.Where(w => w.WipNO == InhouseMaster.WipNo).FirstOrDefault(); + var RuleStations = _context.RuleStations.Where(w => w.FlowRuleID == WipInfo.FlowRuleID && + w.Station.TypeNo == "F").ToList(); + // 有設定FQC站別 + if (RuleStations.Any()) + { + var RuleStation = RuleStations.FirstOrDefault(); + var datas = new List(); + var BarcodeNo = new List(); + + // 取FQC抽驗單號 + var InhouseDetail = await _context.FqcInhouseDetails.Where(w => w.InhouseNo == inhouseNo && w.SeqID == seqID) + .ToListAsync(); + + foreach (var item in InhouseDetail.Select(s => s.SerialNo).Distinct()) + { + BarcodeNo = await _context.BarcodeInfoes.Where(w => w.BoxNo == item).ToListAsync(); + + foreach (var barcode in BarcodeNo) + { + var dataItem = new BarCodeCheckDtoForDBData(); + dataItem.line = (int)WipInfo.LineID; + dataItem.ruleStatus = "P"; + dataItem.stationID = RuleStation.Station.StationID; + dataItem.userID = userID; + dataItem.barcodeType = "M"; + dataItem.unitNo = WipInfo.UnitNO; + dataItem.wipID = barcode.WipID; + dataItem.barcode = barcode.BarcodeNo; + dataItem.barcodeID = barcode.BarcodeID; + dataItem.extNo = barcode.ExtraBarcodeNo; + dataItem.flowRule = WipInfo.FlowRuleID; + dataItem.wipNo = WipInfo.WipNO; + datas.Add(dataItem); + } + } + + if (datas.Any()) + { + var result_CUTableMsg = await CU_TablesByFQC(datas); + if (string.IsNullOrWhiteSpace(result_CUTableMsg)) + { + resultModel.Success = true; + resultModel.Msg = "FQC過站完成"; + } + else + { + resultModel.Msg = result_CUTableMsg; + } + } + } + else + resultModel.Msg = $"該筆工單號碼【{InhouseMaster.WipNo}】,無設定FQC站別"; + } + else + resultModel.Msg = "找不到該筆FQC單號"; + } + catch (Exception ex) + { + resultModel.Msg = ex.Message; + resultModel.Success = false; + } + return resultModel; + } + #endregion + + #region -- 判斷過站完成新增or更新 Table -- + /// + /// 判斷過站完成新增or更新 Table + /// + /// + /// + private async Task CU_Tables(BarCodeCheckDtoForDBData data) + { + #region 先取得各個Table ID + + Helper helper = new Helper(_context); + int BarCodeId = 0; + List BarCodeItemId = new List(); + List BarCodeOutfitId = new List(); + int NgId = 0; + List ComponentId = new List(); + + // BarCodeInfo ID + if (data.barcodeID == 0) + { + BarCodeId = helper.GetIDKey("BARCODE_ID").Result; + data.barcodeID = BarCodeId; + } + + // 組件料號 + foreach (var item in data.inputItems.Where(w => !w.inputData.Contains("$"))) + { + BarCodeItemId.Add(helper.GetIDKey("BARCODEITEM_ID").Result); + } + + // 治具編號 + foreach (var item in data.outfits) + { + BarCodeOutfitId.Add(helper.GetIDKey("BARCODE_OUTFIT_ID").Result); + } + + // 不良代碼 + if (data.inputItems.Where(w => w.inputData.Contains("$")).Any()) + { + NgId = helper.GetIDKey("NG_ID").Result; + foreach (var item in data.inputItems.Where(w => w.inputData.Contains("$"))) + { + ComponentId.Add(helper.GetIDKey("COMPONENT_ID").Result); + } + } + + #endregion + + string Msg = string.Empty; + + using (var tran = _context.Database.BeginTransaction()) + { + try + { + if (!data.burnIn) + { + // 條碼主檔 + Msg = Table_BarcodeInfo(data, BarCodeId); + if (!string.IsNullOrWhiteSpace(Msg)) + { + throw new Exception($"BarcodeInfo_Error:{Msg}"); + } + + // 條碼紀錄 + Msg = Table_BarcodeWip(data); + if (!string.IsNullOrWhiteSpace(Msg)) + { + throw new Exception($"BarcodeWip_Error:{Msg}"); + } + + // 工單各站數量資料檔 + Msg = Table_WipStation(data); + if (!string.IsNullOrWhiteSpace(Msg)) + { + throw new Exception($"WipStation_Error:{Msg}"); + } + + // 各班別數量資料檔 + Msg = Table_WipClass(data); + if (!string.IsNullOrWhiteSpace(Msg)) + { + throw new Exception($"WipClass_Error:{Msg}"); + } + + // 工單各站數量資料檔 – By TIME + Msg = Table_WipTime(data); + if (!string.IsNullOrWhiteSpace(Msg)) + { + throw new Exception($"WipTime_Error:{Msg}"); + } + + // 條碼過站資料檔 + Msg = Table_BarcodeStation(data); + if (!string.IsNullOrWhiteSpace(Msg)) + { + throw new Exception($"BarcodeStation_Error:{Msg}"); + } + + // 組件資料 + Msg = Table_BarcodeItem(data, BarCodeItemId); + if (!string.IsNullOrWhiteSpace(Msg)) + { + throw new Exception($"BarcodeItem_Error:{Msg}"); + } + + // 條碼治具 + Msg = Table_BarcodeOutfit(data, BarCodeOutfitId); + if (!string.IsNullOrWhiteSpace(Msg)) + { + throw new Exception($"BarcodeOutfit_Error:{Msg}"); + } + + // 設備資料檔 使用次數 + Msg = await Table_OutfitInfo(data); + if (!string.IsNullOrWhiteSpace(Msg)) + { + throw new Exception($"OutfitInfo_Error:{Msg}"); + } + + // 不良資料檔 + Msg = Table_NgInfo(data, NgId, ComponentId); + if (!string.IsNullOrWhiteSpace(Msg)) + { + throw new Exception($"NgInfo_Error:{Msg}"); + } + + // 判斷是否為第一站 + if (await CheckNowFirstStation(data.wipID, data.stationID) == "Y") + { + // 在BarStation 確認該筆工單ID只有一筆當第一次投入 + var CheckBarcodeStation = await _context.BarcodeStation.Where(w => w.BarcodeID == data.barcodeID && + w.WipID == data.wipID) + .ToListAsync(); + if (CheckBarcodeStation.Count() == 1) + { + // 有資料加1 後續判斷第一次過站 + string updateSql = $@" UPDATE JHAMES.WIP_INFO SET COMPLETE_QTY = COMPLETE_QTY + 1 + WHERE WIP_ID = {data.wipID}"; + // 執行原生 SQL + _context.Database.ExecuteSqlRaw(updateSql); + } + } + + // 判斷下一站為完工站 + if (CheckNextStopCloseStation(data.flowRule, data.stationID, data.ruleStatus).Result.Success) + { + await CheckWipNoBarCodeAllClost(data.wipID); + } + } + + // 燒入資料檔 + Msg = await Table_BurnInfo(data); + if (!string.IsNullOrWhiteSpace(Msg)) + { + throw new Exception($"BurnInfo_Error:{Msg}"); + } + + // 判斷是否有DB更新錯誤 + if (string.IsNullOrWhiteSpace(Msg)) + { + _context.SaveChanges(); + await tran.CommitAsync(); + } + else + { + await tran.RollbackAsync(); + } + } + + catch (Exception ex) + { + Msg = "過站新增系統錯誤:" + ex.Message; + await tran.RollbackAsync(); + } + } + + return Msg; + } + + /// + /// BarcodeInfo-條碼資料檔 + /// + /// model資料 + /// BarCodeId 0=(修改) !=0(新增) + /// + private string Table_BarcodeInfo(BarCodeCheckDtoForDBData data, int id) + { + // 查看是否有資料 + var barcodeInfo = _context.BarcodeInfoes.Where(w => w.BarcodeID == data.barcodeID).FirstOrDefault(); + + // 新增 + if (barcodeInfo == null) + { + barcodeInfo = new BarcodeInfo + { + BarcodeID = id, + BarcodeNo = data.barcode, + StationID = data.stationID, + LocationID = -1, + WipID = data.wipID, + RuleStatus = data.ruleStatus, + StatusID = 1, + SysType = "S", + StatusNo = data.factoryUnit_UnitCode, + CreateUserID = data.userID + }; + } + // 更新 + else + { + barcodeInfo.StationID = data.stationID; + barcodeInfo.RuleStatus = data.ruleStatus; + barcodeInfo.StatusNo = data.factoryUnit_UnitCode; + barcodeInfo.WipID = data.wipID; + barcodeInfo.StatusID = 1; + barcodeInfo.UpdateDate = DateTime.Now; + if (!string.IsNullOrWhiteSpace(data.extNo)) + barcodeInfo.ExtraBarcodeNo = data.extNo; + } + + // 判斷該站別是否為最後一站 + if (CheckNextStopCloseStation(data.flowRule, data.stationID, data.ruleStatus).Result.Success) + { + barcodeInfo.StatusID = -1; + } + + try + { + // 新增 + if (id != 0) + { + _context.BarcodeInfoes.Add(barcodeInfo); + } + // 更新 + else + { + _context.Entry(barcodeInfo).State = EntityState.Modified; + //設置容器空間某一個模型的某一個欄位 不提交到資料庫 + _context.Entry(barcodeInfo).Property("CreateDate").IsModified = false; + _context.Entry(barcodeInfo).Property("CreateUserID").IsModified = false; + } + } + catch (Exception ex) + { + return ex.InnerException.Message + "
"; + } + + return ""; + } + + /// + /// BarcodeStation-條碼過站資料檔 + /// + /// + /// + private string Table_BarcodeStation(BarCodeCheckDtoForDBData data) + { + // 新增 BarCodeStation + BarcodeStation barcodeStation = new BarcodeStation + { + BarcodeID = data.barcodeID, + WipID = data.wipID, + StationID = data.stationID, + RuleStatus = data.ruleStatus, //F 不良 + InputDate = DateTime.Now, + LineId = data.line, + CreateUserID = data.userID, + FlowRuleID = data.flowRule, + StartDate = data.start_Time + }; + + try + { + _context.BarcodeStation.Add(barcodeStation); + } + catch (Exception ex) + { + return ex.InnerException.Message; + } + return ""; + } + + /// + /// BarcodeItem-組件资料 + /// + /// + /// BarcodeItemID 陣列 + /// + private string Table_BarcodeItem(BarCodeCheckDtoForDBData data, List id) + { + var KeyPartsItem = data.inputItems.Where(w => !w.inputData.Contains("$")).ToList(); + var barcodeItem = new List(); + // 新增 BarCodeStation + for (int i = 0; i < KeyPartsItem.Count; i++) + { + barcodeItem.Add(new BarcodeItem + { + BarcodeItemID = id[i], + BarcodeID = data.barcodeID, + WipID = data.wipID, + StationID = data.stationID, + ItemNo = KeyPartsItem[i].inputType, + PartNo = KeyPartsItem[i].inputData, + SysType = "S", + CreateUserID = data.userID, + CreateDate = DateTime.Now, + UpdateDate = DateTime.Now, + KpItemNo = KeyPartsItem[i].kpItemNo + }); + } + + if (barcodeItem.Count != 0) + { + try + { + _context.BarcodeItems.AddRange(barcodeItem); + } + catch (Exception ex) + { + return ex.InnerException.Message; + } + } + + return ""; + } + + /// + /// BarCodeOutfit-治具資料 + /// + /// + /// BarCodeOutfit ID List + /// + private string Table_BarcodeOutfit(BarCodeCheckDtoForDBData data, List id) + { + var OutfitsItem = data.outfits; + var barcodeOutfit = new List(); + // 新增 BarCodeStation + for (int i = 0; i < OutfitsItem.Count; i++) + { + barcodeOutfit.Add(new BarcodeOutfit + { + BarcodeOutfitID = id[i], + BarcodeNo = data.barcode, + WipNo = data.wipNo, + OutfitNo = OutfitsItem[i].inputData, + StationID = data.stationID, + CreateUserID = data.userID, + CreateDate = DateTime.Now, + UpdateUserID = data.userID, + UpdateDate = DateTime.Now + }); + } + + if (barcodeOutfit.Count != 0) + { + try + { + _context.BarcodeOutfits.AddRange(barcodeOutfit); + } + catch (Exception ex) + { + return ex.InnerException.Message; + } + } + return ""; + } + + /// + /// OutfitInfo-設備資料檔 使用次數 + /// + /// + /// + private async Task Table_OutfitInfo(BarCodeCheckDtoForDBData data) + { + OutfitInfoesController outfitInfoesController = new OutfitInfoesController(_context); + var OutfitsItem = data.outfits.Where(w => !string.IsNullOrWhiteSpace(w.inputData)).ToList(); + foreach (var item in OutfitsItem) + { + var outfitInfo = _context.OutfitInfoes.Where(w => w.OutfitNo == item.inputData.ToUpper()).FirstOrDefault(); + #region 治具 + if (outfitInfo != null) + { + outfitInfo.UseTimes += 1; + outfitInfo.TotalTimes += 1; + outfitInfo.UpdateDate = DateTime.Now; + + try + { + _context.Entry(outfitInfo).State = EntityState.Modified; + } + catch (Exception ex) + { + return ex.InnerException.Message; + } + WipAlarmsController wipAlarmsController = new WipAlarmsController(_context); + var wipAlarms = await wipAlarmsController.GetWipAlarmByOutfit(data.wipNo, item.inputData.Trim().ToUpper()); + // 判斷確認治具編號是否已到預警提醒 + if (outfitInfoesController.GetOutfitInfoByAlertTimes(item.inputData.Trim().ToUpper()).Result.Value == "Y") + { + if (!wipAlarms.Value.Where(w => w.AlarmTypeID == (int)EnumWipAlarm.EnumTypeId.OutfitAlert).Any()) + { + string MailGroup = "OUTFIT_ALARM"; + string Subject = $"[AMES系統通知] 治具編號:{item.inputData.Trim().ToUpper()},預警提前通知"; + string Body = ""; + + await new MailController(_context, _config).PostMail(Subject, Body, MailGroup, "", false); + + WipAlarm wipAlarm = new WipAlarm(); + wipAlarm.AlarmTypeID = (int)EnumWipAlarm.EnumTypeId.OutfitAlert; + wipAlarm.WipNO = data.wipNo; + wipAlarm.AlarmParam = item.inputData.ToUpper(); + wipAlarm.AlarmValue = "1"; + wipAlarm.AlarmDesc = Subject; + wipAlarm.AlarmDateTime = DateTime.Now; + + await wipAlarmsController.PostWipAlarm(wipAlarm); + } + } + } + #endregion + //// 確認治具編號使用次數已經超過預計次數 + //if (outfitInfoesController.GetOutfitInfoByOverUseTimes("").Result.Value == "Y") + //{ + + //} + } + return ""; + } + + /// + /// BurnInfo-燒入資料檔 + /// + /// + /// + private async Task Table_BurnInfo(BarCodeCheckDtoForDBData data) + { + // 判斷作業站是否為燒機站 Station_Type == B + if (data.stations_TypeNo == "B") + { + // 判斷是否有燒機時間 + WipBoardController wipBoardController = new WipBoardController(_context); + var wipBoardTime = await wipBoardController.GetWipBoardToBITime(data.wipNo); + WipSystemController wipSystemController = new WipSystemController(_context); + var wipSystemTime = await wipSystemController.GetWipSystemToBITime(data.wipNo); + decimal PlanHour = 0; + if (wipBoardTime.Value > 0) + PlanHour = (decimal)wipBoardTime.Value; + else + PlanHour = (decimal)wipSystemTime.Value; + + // 確認有燒機資訊 + var burnInfos = await _context.BurnInfos.Where(w => w.BarcodeID == data.barcodeID && + w.FinishTime == null) + .FirstOrDefaultAsync(); + try + { + // 新增 + if (burnInfos == null) + { + Helper helper = new Helper(_context); + // 新增 BarCodeStation + var burnInfo = new BurnInfo + { + BurnID = await helper.GetIDKey("BURN_ID"), + BarcodeID = data.barcodeID, + WipNo = data.wipNo, + BurnPlanHour = PlanHour, + StartTime = DateTime.Now, + ScheduleFinishTime = DateTime.Now.AddMinutes((double)PlanHour * 60), + InUserID = data.userID, + Status = 0, + CreateUserID = data.userID, + UpdateUserID = data.userID + }; + _context.BurnInfos.Add(burnInfo); + } + else + { + burnInfos.Status = 1; + burnInfos.FinishTime = DateTime.Now; + burnInfos.OutUserID = data.userID; + burnInfos.UpdateDate = DateTime.Now; + burnInfos.UpdateUserID = data.userID; + + _context.Entry(burnInfos).State = EntityState.Modified; + //設置容器空間某一個模型的某一個欄位 不提交到資料庫 + _context.Entry(burnInfos).Property("CreateDate").IsModified = false; + _context.Entry(burnInfos).Property("CreateUserID").IsModified = false; + } + } + catch (Exception ex) + { + return ex.InnerException.Message; + } + } + return ""; + } + + /// + /// NgInfo-測試不良基本資料檔 + /// + /// + /// Db ID + /// Db ID + /// + private string Table_NgInfo(BarCodeCheckDtoForDBData data, int ngId, List componentId) + { + var NgItem = data.inputItems.Where(w => w.inputData.Contains("$")).ToList(); + + try + { + // 新增 NgInfo + if (NgItem.Count != 0) + { + NgInfo ngInfo = new NgInfo + { + NgID = ngId, + TypeNo = data.stations_TestType, + OperatorID = 0, + FixtureNo = "NA", + BarcodeID = data.barcodeID, + ReasonNo = NgItem[0].inputData.Replace("$", "").Trim().ToUpper(), + ProgramNo = "N/A", + MachineNo = "N/A", + StationId = data.stationID, + WipId = data.wipID, + CreateUserID = data.userID, + UpdateUserID = data.userID + }; + _context.NgInfos.Add(ngInfo); + + var ngComponent = new List(); + for (int i = 0; i < NgItem.Count; i++) + { + ngComponent.Add(new NgComponent + { + NgID = ngId, + ComponentID = componentId[i], + LocationNo = string.IsNullOrWhiteSpace(NgItem[i].oldInputData) ? "N/A" : NgItem[i].oldInputData, + NgNo = NgItem[i].inputData.Replace("$", "").Trim().ToUpper(), + CreateUserID = data.userID, + UpdateUserID = data.userID + }); + + + // 累計預警 + WipAlarmsController wipAlarmsController = new WipAlarmsController(_context); + wipAlarmsController.PostWipAlarm4ErrorCode(data.wipNo, NgItem[i].inputData.Replace("$", "")).Wait(); + } + _context.NgComponents.AddRange(ngComponent); + } + } + catch (Exception ex) + { + return ex.InnerException.Message; + } + return ""; + } + + /// + /// BarcodeWip-檔案用途 條碼工單資料檔 + /// + /// + /// + private string Table_BarcodeWip(BarCodeCheckDtoForDBData data) + { + var barcodeWip = _context.BarcodeWips.Where(w => w.BarcodeID == data.barcodeID && + w.WipID == data.wipID).FirstOrDefault(); + try + { + // 新增 + if (barcodeWip == null) + { + barcodeWip = new BarcodeWip + { + BarcodeID = data.barcodeID, + WipID = data.wipID, + CreateUserID = data.userID + }; + _context.BarcodeWips.Add(barcodeWip); + } + // 更新 + else + { + barcodeWip.UpdateDate = DateTime.Now; + _context.Attach(barcodeWip); + _context.Entry(barcodeWip).Property(p => p.UpdateDate).IsModified = true; + } + } + catch (Exception ex) + { + return ex.InnerException.Message + "
"; + } + return ""; + } + + /// + /// WipStation + /// + /// + private string Table_WipStation(BarCodeCheckDtoForDBData data) + { + var BarcodeStation = _context.BarcodeStation.Where(w => w.BarcodeID == data.barcodeID && + w.WipID == data.wipID && w.StationID == data.stationID && + w.FlowRuleID == data.flowRule).Any(); + var today = DateTime.Now.ToString("yyyy/MM/dd"); + // 判斷是否有資料 + var wipStations = _context.WipStations.Where(w => w.WipID == data.wipID && w.StationID == data.stationID && + w.RuleStatus == data.ruleStatus).ToList(); + wipStations = wipStations.Where(w => w.CreateDate.ToString("yyyy/MM/dd") == today).ToList(); + try + { + // 新增 + if (wipStations.Count() == 0) + { + var firstCnt = 1; + // 有過站資料不能第一次 + if (BarcodeStation) + firstCnt = 0; + + _context.WipStations.Add(new WipStation + { + WipID = data.wipID, + RuleStatus = data.ruleStatus, + StationID = data.stationID, + FirstCnt = firstCnt, + PassCnt = 1, + CreateUserID = data.userID + }); + } + // 更新 + else + { + + // 有資料加1 後續判斷第一次過站 + string updateSql = @" UPDATE JHAMES.WIP_STATION SET PASS_CNT = PASS_CNT + 1 , + UPDATE_DATE = SYSDATE"; + if (!BarcodeStation) + { + updateSql += " , FIRST_CNT = FIRST_CNT + 1 "; + } + updateSql += $@" WHERE WIP_ID = '{data.wipID}' + AND STATION_ID = '{data.stationID}' + AND RULE_STATUS = '{data.ruleStatus}' + AND TO_CHAR(CREATE_DATE , 'YYYY/MM/DD') = '{today}' "; + // 執行原生 SQL + _context.Database.ExecuteSqlRaw(updateSql); + } + } + catch (Exception ex) + { + return ex.InnerException.Message + "
"; + } + return ""; + } + + /// + /// WipClass-各班別數量資料檔 + /// + /// + private string Table_WipClass(BarCodeCheckDtoForDBData data) + { + var BarcodeStation = _context.BarcodeStation.Where(w => w.BarcodeID == data.barcodeID && + w.WipID == data.wipID && w.StationID == data.stationID && + w.FlowRuleID == data.flowRule).Any(); + var today = DateTime.Now.ToString("yyyy/MM/dd"); + // 取ClassID + int ClassID = -1; + var ClassInfo = _context.ClassInfoes.Where(w => w.UnitNo == data.unitNo).ToList(); + + ClassInfo = ClassInfo.Where(w => DateTime.Parse(today + " " + w.BeginTime) <= DateTime.Now && + DateTime.Now <= DateTime.Parse(today + " " + w.EndTime)).ToList(); + if (ClassInfo.Count() != 0) + { + ClassID = ClassInfo.FirstOrDefault().ClassID; + } + + // 判斷是否有資料 + var wipClasses = _context.WipClass.Where(w => w.WipID == data.wipID && w.StationID == data.stationID && + w.RuleStatus == data.ruleStatus && w.ClassID == ClassID).ToList(); + + wipClasses = wipClasses.Where(w => w.CreateDate.ToString("yyyy/MM/dd") == today).ToList(); + + try + { + // 新增 + if (wipClasses.Count() == 0) + { + var firstCnt = 1; + // 有過站資料不能第一次 + if (BarcodeStation) + firstCnt = 0; + _context.WipClass.Add(new WipClass + { + WipID = data.wipID, + RuleStatus = data.ruleStatus, + StationID = data.stationID, + ClassID = ClassID, + FirstCnt = firstCnt, + PassCnt = 1, + CreateUserID = data.userID + }); + } + // 更新 + else + { + // 有資料加1 後續判斷第一次過站 + string updateSql = @" UPDATE JHAMES.WIP_CLASS SET PASS_CNT = PASS_CNT + 1 , + UPDATE_DATE = SYSDATE"; + if (!BarcodeStation) + { + updateSql += " , FIRST_CNT = FIRST_CNT + 1 "; + } + updateSql += $@" WHERE WIP_ID = '{data.wipID}' + AND STATION_ID = '{data.stationID}' + AND RULE_STATUS = '{data.ruleStatus}' + AND CLASS_ID = {ClassID} + AND TO_CHAR(CREATE_DATE , 'YYYY/MM/DD') = '{today}' "; + // 執行原生 SQL + _context.Database.ExecuteSqlRaw(updateSql); + } + } + catch (Exception ex) + { + return ex.InnerException.Message + "
"; + } + return ""; + } + + /// + /// WipTime-工單各站數量資料檔 – By TIME + /// + /// + private string Table_WipTime(BarCodeCheckDtoForDBData data) + { + // 有資料加1 後續判斷第一次過站 + var BarcodeStation = _context.BarcodeStation.Where(w => w.BarcodeID == data.barcodeID && + w.WipID == data.wipID && w.StationID == data.stationID && + w.FlowRuleID == data.flowRule).Any(); + + var today = DateTime.Now.ToString("yyyy/MM/dd"); + // 取SegmentID + int SegmentID = -1; + var timeSegment = _context.TimeSegments.ToList(); + + timeSegment = timeSegment.Where(w => DateTime.Parse(today + " " + w.StartTime) <= DateTime.Now && + DateTime.Now <= DateTime.Parse(today + " " + w.EndTime)).ToList(); + if (timeSegment.Count() != 0) + { + SegmentID = timeSegment.FirstOrDefault().SegmentID; + } + + // 判斷是否有資料 + var wipTimes = _context.WipTimes.Where(w => w.WipID == data.wipID && w.StationID == data.stationID && + w.RuleStatus == data.ruleStatus && w.SegmentID == SegmentID).ToList(); + + + wipTimes = wipTimes.Where(w => w.CreateDate.ToString("yyyy/MM/dd") == today).ToList(); + try + { + // 新增 + if (wipTimes.Count() == 0) + { + var firstCnt = 1; + // 有過站資料不能第一次 + if (BarcodeStation) + firstCnt = 0; + + _context.WipTimes.Add(new WipTime + { + WipID = data.wipID, + RuleStatus = data.ruleStatus, + StationID = data.stationID, + SegmentID = SegmentID, + FirstCnt = firstCnt, + PassCnt = 1, + CreateUserID = data.userID + }); + } + // 更新 + else + { + // 有資料加1 後續判斷第一次過站 + string updateSql = @" UPDATE JHAMES.WIP_TIME SET PASS_CNT = PASS_CNT + 1 , + UPDATE_DATE = SYSDATE"; + if (!BarcodeStation) + { + updateSql += " , FIRST_CNT = FIRST_CNT + 1 "; + } + updateSql += $@" WHERE WIP_ID = '{data.wipID}' + AND STATION_ID = '{data.stationID}' + AND RULE_STATUS = '{data.ruleStatus}' + AND SEGMENT_ID = {SegmentID} + AND TO_CHAR(CREATE_DATE , 'YYYY/MM/DD') = '{today}' "; + // 執行原生 SQL + _context.Database.ExecuteSqlRaw(updateSql); + } + + } + catch (Exception ex) + { + return ex.InnerException.Message + "
"; + } + return ""; + } + + /// + /// WipKp-工單keyParts 長度更新 + /// + /// + /// + private string Table_WipKps(List data, int userId) + { + try + { + // 查看是否有資料 + foreach (var item in data) + { + var wipKp = _context.WipKps.Where(w => w.WipKpID == item.WipKpID).FirstOrDefault(); + if (wipKp != null) + { + wipKp.Length = item.Length; + wipKp.UpdateUserID = userId; + wipKp.UpdateDate = DateTime.Now; + _context.Entry(wipKp).State = EntityState.Modified; + //設置容器空間某一個模型的某一個欄位 不提交到資料庫 + _context.Entry(wipKp).Property("CreateDate").IsModified = false; + _context.Entry(wipKp).Property("CreateUserID").IsModified = false; + _context.SaveChangesAsync(); + } + } + } + catch (Exception ex) + { + return ex.InnerException.Message; + } + return ""; + } + + #endregion + + #region -- 判斷過站完成新增or更新 By FQC -- + /// + /// 判斷過站完成新增or更新 Table + /// + /// + /// + private async Task CU_TablesByFQC(List data) + { + using (var tran = _context.Database.BeginTransaction()) + { + try + { + // T-SQL 查詢資料 + int wipId = data.FirstOrDefault().wipID; + int stationId = data.FirstOrDefault().stationID; + int flowRule = data.FirstOrDefault().flowRule; + int createUserId = data.FirstOrDefault().userID; + int dataQty = data.Count(); + string unitNo = data.FirstOrDefault().unitNo; + string ruleStatus = "P"; + DynamicParameters p = new DynamicParameters(); + + #region -- 條碼主檔 -- + var upBarCodeInfo = @" UPDATE JHAMES.BARCODE_INFO SET + STATION_ID =:stationID , + RULE_STATUS = 'P' , + UPDATE_DATE = SYSDATE + WHERE BARCODE_ID = :barcodeID + AND WIP_ID = :wipID "; + _context.Database.DapperExecute(upBarCodeInfo, data); + + // 判斷該站別是否為最後一站 + if (CheckNextStopCloseStation(flowRule, stationId, ruleStatus).Result.Success) + { + upBarCodeInfo = @" UPDATE JHAMES.BARCODE_INFO SET + STATUS_ID ='-1' , + LOCATION_ID = '-1' + WHERE BARCODE_ID = :barcodeID + AND WIP_ID = :wipID "; + _context.Database.DapperExecute(upBarCodeInfo, data); + } + + #endregion + + #region -- 條碼紀錄 -- + + var upBarCodeWip = @" UPDATE JHAMES.BARCODE_WIP + SET UPDATE_DATE = SYSDATE + WHERE BARCODE_ID = :barcodeID + AND WIP_ID = :wipID "; + _context.Database.DapperExecute(upBarCodeWip, data); + + #endregion + + #region -- 條碼過站資料檔 -- + + var inBarCodeStation = @" BEGIN INSERT INTO JHAMES.BARCODE_STATION + ( + BARCODE_ID, + WIP_ID, + FLOW_RULE_ID, + STATION_ID, + RULE_STATUS, + INPUT_DATE, + SYSTYPE, + LINE_ID, + STATION_FLAG, + STATION_TIMES, + CREATE_USERID, + CREATE_DATE + ) VALUES ( + :barcodeID, + :wipID, + :flowRule, + :stationID, + 'P', + SYSDATE, + 'S', + :line, + '1', + '1', + :userID, + SYSDATE + ); + EXCEPTION + WHEN DUP_VAL_ON_INDEX THEN + NULL; + END; "; + _context.Database.DapperExecute(inBarCodeStation, data); + + #endregion + + #region -- 工單各站數量資料檔 -- + + var queryWipStation = @"SELECT * FROM JHAMES.WIP_STATION WHERE WIP_ID = :WipId + AND STATION_ID = :StationId + AND RULE_STATUS ='P' + AND TRUNC(CREATE_DATE) = TRUNC(SYSDATE) "; + + p = new DynamicParameters(); + p.Add("WipId", wipId); + p.Add("StationId", stationId); + var reautWipStation = _context.Database.DapperQuery(queryWipStation, p); + + // 新增 + if (!reautWipStation.Any()) + { + var insertSql = @" BEGIN INSERT INTO JHAMES.WIP_STATION + ( + WIP_ID, + STATION_ID, + RULE_STATUS, + FIRST_CNT, + PASS_CNT, + CREATE_USERID, + CREATE_DATE, + UPDATE_DATE + ) VALUES ( + :WipId, + :StationId, + 'P', + :FirstCnt, + :PassCnt, + :UserID, + SYSDATE, + SYSDATE + ); + EXCEPTION + WHEN DUP_VAL_ON_INDEX THEN + NULL; + END; "; + p = new DynamicParameters(); + p.Add("WipId", wipId); + p.Add("StationId", stationId); + p.Add("UserID", createUserId); + p.Add("FirstCnt", dataQty); + p.Add("PassCnt", dataQty); + _context.Database.DapperExecute(insertSql, p); + } + // 更新 + else + { + // 有資料加1 後續判斷第一次過站 + var updateSql = @" UPDATE JHAMES.WIP_STATION SET PASS_CNT = PASS_CNT + :PassCnt , + UPDATE_DATE = SYSDATE , + FIRST_CNT = FIRST_CNT + :FirstCnt + WHERE WIP_ID = :WipId + AND STATION_ID = :StationId + AND RULE_STATUS = 'P' + AND TRUNC(CREATE_DATE) = TRUNC(SYSDATE) "; + p = new DynamicParameters(); + p.Add("WipId", wipId); + p.Add("StationId", stationId); + p.Add("FirstCnt", dataQty); + p.Add("PassCnt", dataQty); + _context.Database.DapperExecute(updateSql, p); + } + + #endregion + + #region -- 各班別數量資料檔 -- + + // 取ClassID + int ClassID = -1; + var queryClassInfo = @" SELECT * FROM JHAMES.CLASS_INFO + WHERE UNIT_NO = :UnitNo + AND SYSTIMESTAMP BETWEEN + TO_TIMESTAMP(TO_CHAR(SYSDATE, 'YYYY-MM-DD') || ' ' || BEGIN_TIME, 'YYYY-MM-DD HH24:MI') + AND TO_TIMESTAMP(TO_CHAR(SYSDATE, 'YYYY-MM-DD') || ' ' || END_TIME, 'YYYY-MM-DD HH24:MI')"; + + p = new DynamicParameters(); + p.Add("UnitNo", unitNo); + var reautClassInfo = _context.Database.DapperQuery(queryClassInfo, p); + + if (reautClassInfo.Any()) + { + ClassID = (int)reautClassInfo.FirstOrDefault().CLASS_ID; + } + + // 判斷是否有資料 + var queryWipClass = @" SELECT * FROM JHAMES.WIP_CLASS WHERE WIP_ID = :WipId + AND STATION_ID = :StationId + AND RULE_STATUS ='P' + AND CLASS_ID = :ClassId + AND TRUNC(CREATE_DATE) = TRUNC(SYSDATE) "; + + p = new DynamicParameters(); + p.Add("WipId", wipId); + p.Add("StationId", stationId); + p.Add("ClassId", ClassID); + var reautWipClass = _context.Database.DapperQuery(queryWipClass, p); + + // 新增 + if (!reautWipClass.Any()) + { + var insertSql = @" BEGIN INSERT INTO JHAMES.WIP_CLASS + ( + WIP_ID, + STATION_ID, + RULE_STATUS, + CLASS_ID, + FIRST_CNT, + PASS_CNT, + CREATE_USERID, + CREATE_DATE, + UPDATE_DATE + ) VALUES ( + :WipId, + :StationId, + 'P', + :ClassId, + :FirstCnt, + :PassCnt, + :UserID, + SYSDATE, + SYSDATE + ); + EXCEPTION + WHEN DUP_VAL_ON_INDEX THEN + NULL; + END; "; + p = new DynamicParameters(); + p.Add("WipId", wipId); + p.Add("StationId", stationId); + p.Add("UserID", createUserId); + p.Add("ClassId", ClassID); + p.Add("FirstCnt", dataQty); + p.Add("PassCnt", dataQty); + _context.Database.DapperExecute(insertSql, p); + } + // 更新 + else + { + // 有資料加1 後續判斷第一次過站 + string updateSql = @" UPDATE JHAMES.WIP_CLASS SET PASS_CNT = PASS_CNT + :PassCnt , + UPDATE_DATE = SYSDATE , + FIRST_CNT = FIRST_CNT + :FirstCnt + WHERE WIP_ID = :WipId + AND STATION_ID = :StationId + AND RULE_STATUS = 'P' + AND CLASS_ID = :ClassId + AND TRUNC(CREATE_DATE) = TRUNC(SYSDATE) "; + p = new DynamicParameters(); + p.Add("WipId", wipId); + p.Add("StationId", stationId); + p.Add("ClassId", ClassID); + p.Add("FirstCnt", dataQty); + p.Add("PassCnt", dataQty); + _context.Database.DapperExecute(updateSql, p); + } + + #endregion + + #region -- 工單各站數量資料檔 – By TIME -- + + // 取SegmentID + int SegmentID = -1; + var queryTimeSegment = @" SELECT * FROM JHAMES.TIME_SEGMENT + WHERE SYSTIMESTAMP BETWEEN + TO_TIMESTAMP(TO_CHAR(SYSDATE, 'YYYY-MM-DD') || ' ' || START_TIME, 'YYYY-MM-DD HH24:MI') + AND TO_TIMESTAMP(TO_CHAR(SYSDATE, 'YYYY-MM-DD') || ' ' || END_TIME, 'YYYY-MM-DD HH24:MI')"; + + p = new DynamicParameters(); + var reautTimeSegment = _context.Database.DapperQuery(queryTimeSegment, p); + + if (reautTimeSegment.Any()) + { + SegmentID = (int)reautTimeSegment.FirstOrDefault().SEGMENT_ID; + } + + // 判斷是否有資料 + var queryWipTime = @" SELECT * FROM JHAMES.WIP_TIME + WHERE WIP_ID = :WipId + AND STATION_ID = :StationId + AND RULE_STATUS ='P' + AND SEGMENT_ID = :SegmentID "; + p = new DynamicParameters(); + p.Add("WipId", wipId); + p.Add("StationId", stationId); + p.Add("SegmentID", SegmentID); + var reautWipTime = _context.Database.DapperQuery(queryWipTime, p); + + // 新增 + if (!reautWipTime.Any()) + { + var insertSql = @" BEGIN INSERT INTO JHAMES.WIP_TIME + ( + WIP_ID, + STATION_ID, + RULE_STATUS, + SEGMENT_ID, + FIRST_CNT, + PASS_CNT, + CREATE_USERID, + CREATE_DATE, + UPDATE_DATE + ) VALUES ( + :WipId, + :StationId, + 'P', + :SegmentID, + :FirstCnt, + :PassCnt, + :UserID, + SYSDATE, + SYSDATE + ); + EXCEPTION + WHEN DUP_VAL_ON_INDEX THEN + NULL; + END; "; + p = new DynamicParameters(); + p.Add("WipId", wipId); + p.Add("StationId", stationId); + p.Add("UserID", createUserId); + p.Add("SegmentID", SegmentID); + p.Add("FirstCnt", dataQty); + p.Add("PassCnt", dataQty); + _context.Database.DapperExecute(insertSql, p); + } + // 更新 + else + { + // 有資料加1 後續判斷第一次過站 + string updateSql = @" UPDATE JHAMES.WIP_TIME SET PASS_CNT = PASS_CNT + :PassCnt , + UPDATE_DATE = SYSDATE , + FIRST_CNT = FIRST_CNT + :FirstCnt + WHERE WIP_ID = :WipId + AND STATION_ID = :StationId + AND RULE_STATUS = 'P' + AND SEGMENT_ID = :SegmentID + AND TRUNC(CREATE_DATE) = TRUNC(SYSDATE) "; + p = new DynamicParameters(); + p.Add("WipId", wipId); + p.Add("StationId", stationId); + p.Add("SegmentID", SegmentID); + p.Add("FirstCnt", dataQty); + p.Add("PassCnt", dataQty); + _context.Database.DapperExecute(updateSql, p); + } + + #endregion + + // 判斷下一站為完工站 + if (CheckNextStopCloseStation(flowRule, stationId, "P").Result.Success) + { + await CheckWipNoBarCodeAllClost(wipId); + } + + await tran.CommitAsync(); + return ""; + } + catch (Exception ex) + { + await tran.RollbackAsync(); + return "FQC新增系統錯誤:" + ex.Message; + } + } + } + #endregion + + /// + /// 判斷工單狀態 + /// + /// 工單號碼 + /// 生產單位 + /// 線別 + /// 流程 + /// 作業站ID + /// + [HttpGet("CheckWipNoSation")] + public IActionResult GetCheckWipNoSation(string wipno, string unitno, int line, int flowrule, int stationID) + { + var result = CheckWipNoSationAsync(wipNo: wipno, unitNo: unitno, flowRuleID: flowrule, line: line, stationID: stationID); + return Ok(result.Result); + } + + /// + /// 內部序號查詢工單號碼 + /// + /// 內部序號 + /// Success:true or false + [HttpGet("BarCodeFromWip")] + public async Task CheckBarCodeFromWip(string barcode) + { + ResultModel resultModel = new ResultModel { Success = false }; + if (barcode.Length <= 4) + { + resultModel.Msg = "內部序號小於4個字數"; + return resultModel; + } + + // 內部序號扣除流水號 查詢 + var SerialNumber = await GetWipNoSerialNumber(""); + IQueryable q = _context.WipBarcodes.Where(w => w.StartNO.Substring(0, (barcode.Length - SerialNumber)) == (barcode.Substring(0, (barcode.Length - SerialNumber)))); + if (!q.Any()) + { + resultModel.Msg = "找不到內部序號【" + barcode + "】 對應相關工單號碼"; + return resultModel; + } + else + { + try + { + var No = int.Parse(barcode.Substring(barcode.Length - SerialNumber, SerialNumber)); + foreach (var item in q) + { + int StartNo = int.Parse(item.StartNO.Substring(item.StartNO.Length - SerialNumber, SerialNumber)); + int EndNo = int.Parse(item.EndNO.Substring(item.EndNO.Length - SerialNumber, SerialNumber)); + if (StartNo <= No && No <= EndNo) + { + resultModel.Success = true; + resultModel.Msg = q.Select(s => s.WipNO).FirstOrDefault(); + return resultModel; + } + } + resultModel.Msg = "工單號碼【" + q.Select(s => s.WipNO).FirstOrDefault() + "】 找不到範圍內的內部序號"; + } + catch (Exception ex) + { + resultModel.Msg = ex.Message; + } + } + + return resultModel; + } + + /// + /// 查詢序號是否有在該工單 條碼區間內(過站使用) + /// + /// 內部序號 + /// 工單號碼 + [HttpGet("CheckBarCodeByWipNo")] + public async Task> CheckBarCodeByWipNo(string barcode, string wipNo) + { + ResultModel resultModel = new ResultModel { Success = false }; + if (barcode.Length <= 4) + { + resultModel.Msg = "內部序號小於4個字數"; + return resultModel; + } + + // 內部序號扣除流水號 查詢 + var q = await _context.WipBarcodes.Where(w => w.WipNO == wipNo).ToListAsync(); + if (!q.Any()) + { + resultModel.Msg = "找不到工單號碼【" + wipNo + "】 有設定條碼區間"; + return resultModel; + } + else + { + try + { + // 刷入資料 = 條碼起始 或 條碼結束 都符合條碼區間 + if (q.Where(w => w.StartNO == barcode || w.EndNO == barcode).Any()) + { + resultModel.Success = true; + return resultModel; + } + + var query = @$" SELECT * FROM JHAMES.WIP_BARCODE + WHERE WIP_NO =:WipNo -- 工單號碼 + AND :BarCode BETWEEN START_NO AND END_NO -- 判斷區間 + AND LENGTH(:BarCode) = LENGTH(START_NO) -- 判斷長度 "; + + DynamicParameters p = new DynamicParameters(); + p.Add("WipNo", wipNo); + p.Add("BarCode", barcode); + + var q1 = await _context.Database.DapperQueryAsync(query, p); + if (q1.Any()) + { + resultModel.Success = true; + return resultModel; + } + else + resultModel.Msg = $"工單號碼【{wipNo}】 找不到範圍內的內部序號【{barcode}】"; + } + catch (Exception ex) + { + resultModel.Msg = ex.Message; + } + } + return resultModel; + } + + /// + /// 內部序號是否鎖定 + /// + /// 內部序號ID + /// 內部序號 + /// Success:true or false + [HttpGet("BarCodeLock")] + public async Task> CheckBarCodeLockAsync(int barCode, string barCodeNo) + { + ResultModel resultModel = new ResultModel { Success = false }; + if (barCodeNo.Length <= 4) + { + resultModel.Msg = "內部序號小於4個字數"; + return resultModel; + } + + // 第一次投入 沒有資料 不用判斷 + if (barCode == 0) + { + resultModel.Success = true; + return resultModel; + } + + var BarCodeLock = _context.BarcodeLocks.Where(w => w.BarcodeID == barCode && w.LockStatus == 0).FirstOrDefaultAsync(); + if (await BarCodeLock != null) + { + resultModel.Msg = $"內部序號【{barCodeNo}】在當前站別被鎖定,不可過站"; + return resultModel; + } + + resultModel.Success = true; + return resultModel; + } + + /// + /// 內部序號是否報廢 + /// + /// 內部序號ID + /// 內部序號 + /// Success:true or false + [HttpGet("BarCodeScrapped")] + public async Task> CheckBarCodeScrappedAsync(int barCode, string barCodeNo) + { + ResultModel resultModel = new ResultModel { Success = false }; + if (barCodeNo.Length <= 4) + { + resultModel.Msg = "內部序號小於4個字數"; + return resultModel; + } + + var BarCodeInfo = await _context.BarcodeInfoes.Where(w => w.BarcodeID == barCode).FirstOrDefaultAsync(); + if (BarCodeInfo != null) + { + if (BarCodeInfo.RuleStatus == "S") + { + resultModel.Msg = $"內部序號【{barCodeNo}】已報廢, 不可繼續過站!"; + return resultModel; + } + if (BarCodeInfo.RuleStatus == "C") + { + resultModel.Msg = $"內部序號【{barCodeNo}】已轉出, 不可繼續過站!"; + return resultModel; + } + } + + resultModel.Success = true; + return resultModel; + } + + /// + /// 確認內部條碼流動 + /// + /// 工單號碼ID + /// 內部條碼ID + /// 內部條碼 + /// 作業站編號 + /// 過站狀態 P/F + /// + [HttpGet("BarCodeFlow")] + private async Task> CheckBarCodeFlowAsync(int wipId, int barCode, string barCodeNo, int stationID, string ruleStatus = "P") + { + ResultModel resultModel = new ResultModel { Success = false }; + var WipInfo = await _context.WipInfos.Where(w => w.WipID == wipId).FirstOrDefaultAsync(); + + // 取工單號碼開立的 WipID、生產單位 + var WipInfos = await _context.WipInfos.Where(w => w.WipNO == WipInfo.WipNO).Select(s => new { s.WipID, s.UnitNO }).ToListAsync(); + + // 取內部序號過站紀錄 + var BarCodeStations = await _context.BarcodeStation.Where(w => w.BarcodeID == barCode).ToListAsync(); + + // 判斷需要前製程是否已經投入 + if (WipInfo.InputFlag == "Y") + { + // 有BarCodeID + if (barCode != 0) + { + // 判斷是否有前製程過站資料 + // SMT(S)->DIP(D) + if (WipInfo.UnitNO == "D") + { + int? WipID = WipInfos.Where(w => w.UnitNO == "S").Select(s => s.WipID).FirstOrDefault(); + if (WipID == null) + { + resultModel.Msg = $"該工單號碼【{WipInfo.WipNO}】的前製程生產單位尚未建立工單基本資料"; + return resultModel; + } + + if (!BarCodeStations.Where(w => w.BarcodeID == barCode && w.WipID == WipID && w.RuleStatus == "P").Any()) + { + resultModel.Msg = $"該內部序號【{barCodeNo}】前製程生產單位尚未有過站紀錄"; + return resultModel; + } + } + // 組裝(B)->系統測試(T)->成品包裝(P) + else if (WipInfo.UnitNO == "T") + { + int? WipID = WipInfos.Where(w => w.UnitNO == "B").Select(s => s.WipID).FirstOrDefault(); + if (WipID == null) + { + resultModel.Msg = $"該工單號碼【{WipInfo.WipNO}】的前製程生產單位尚未建立工單基本資料"; + return resultModel; + } + + if (!BarCodeStations.Where(w => w.BarcodeID == barCode && w.WipID == WipID && w.RuleStatus == "P").Any()) + { + resultModel.Msg = $"該內部序號【{barCodeNo}】前製程生產單位尚未有過站紀錄"; + return resultModel; + } + } + else if (WipInfo.UnitNO == "P") + { + int? WipID = WipInfos.Where(w => w.UnitNO == "T").Select(s => s.WipID).FirstOrDefault(); + if (WipID == null) + { + resultModel.Msg = $"該工單號碼【{WipInfo.WipNO}】的前製程生產單位尚未建立工單基本資料"; + return resultModel; + } + + if (!BarCodeStations.Where(w => w.BarcodeID == barCode && w.WipID == WipID && w.RuleStatus == "P").Any()) + { + resultModel.Msg = $"該內部序號【{barCodeNo}】前製程生產單位尚未有過站紀錄"; + return resultModel; + } + } + } + // 沒有BarCodeID + else + { + if (WipInfo.UnitNO != "S" && WipInfo.UnitNO != "B") + { + resultModel.Msg = $"該工單號碼【{WipInfo.WipNO}】前製程式尚未投產"; + return resultModel; + } + } + } + #region 判斷作業站順序 + + // 判斷序號目前是否有重複過站 + var BarcodeInfo = await _context.BarcodeInfoes.Where(w => w.BarcodeID == barCode && w.StationID == stationID && w.WipID == wipId).FirstOrDefaultAsync(); + if (BarcodeInfo != null) + { + resultModel.Msg = $"該內部序號【{barCodeNo}】已刷過此站"; + return resultModel; + } + + resultModel = (ResultModel)await GetBarCodeLastStopRuleStationID(wipId, barCode, stationID, WipInfo.FlowRuleID, ruleStatus); + if (!resultModel.Success) + return resultModel; + + #endregion + resultModel.Success = true; + return resultModel; + } + + /// + /// 確認工單狀態 + /// + /// 工單號碼 + /// 生產單位 + /// 流程 + /// 線別 + /// 作業站 + /// 生產條碼 + /// + private async Task> CheckWipNoSationAsync(string wipNo, string unitNo, int flowRuleID, int line, int stationID = 0, string barCodeNo = "") + { + ResultModel resultModel = new ResultModel() { Success = false }; + var WipInfo = await _context.WipInfos.Where(w => w.WipNO == wipNo).ToListAsync(); + + try + { + if (WipInfo.Count() == 0) + { + resultModel.Msg = "找不到工單號碼【" + wipNo + "】"; + return resultModel; + } + + if (!WipInfo.Where(w => w.UnitNO == unitNo).Any()) + { + resultModel.Msg = "工單號碼【" + wipNo + ",尚未設定此生產單位"; + return resultModel; + } + + if (!WipInfo.Where(w => w.UnitNO == unitNo && w.LineID == line).Any()) + { + resultModel.Msg = "工單號碼【" + wipNo + "】,尚未設定此線別"; + return resultModel; + } + + if (!WipInfo.Where(w => w.UnitNO == unitNo && w.LineID == line && w.FlowRuleID == flowRuleID).Any()) + { + resultModel.Msg = "工單號碼【" + wipNo + "】,尚未設定此流程站"; + return resultModel; + } + + // 抓單筆資料 + var item = WipInfo.Where(w => w.UnitNO == unitNo && w.LineID == line).FirstOrDefault(); + + if (item.StatusNO == "E") + { + resultModel.Msg = $"工單號碼【{item.WipNO}】,該工單已經投入完工,請切換工單"; + return resultModel; + } + + if (item.StatusNO == "C") + { + resultModel.Msg = $"工單號碼【{item.WipNO}】,該工單已刪除,請切換工單"; + return resultModel; + } + + // 判斷是否是投入站 + var RuleStation = await _context.RuleStations.Where(w => w.FlowRuleID == flowRuleID && w.StationID == stationID) + .FirstOrDefaultAsync(); + if (RuleStation != null) + { + if (RuleStation.Sequence == 1) + { + var LineInfo = await _context.LineInfoes.Where(w => w.WipNo == item.WipID && w.LineID == item.LineID).FirstOrDefaultAsync(); + if (LineInfo == null) + { + //因維修後投入站 不須重開線 + if (!await _context.BarcodeInfoes.Where(w => w.WipID == item.WipID && w.BarcodeNo == barCodeNo).AnyAsync()) + { + resultModel.Msg = $"工單號碼【{item.WipNO}】,工單尚未開線,不可過站"; + return resultModel; + } + } + } + } + + // 已投入數量>=工單數量+領退量 + if (await CheckNowFirstStation(item.WipID, stationID) == "Y") + { + if (item.CompleteQTY >= item.PlanQTY + item.ReceivedQty) + { + //因維修後投入站 不須判斷投入數量 + if (!await _context.BarcodeInfoes.Where(w => w.WipID == item.WipID && w.BarcodeNo == barCodeNo).AnyAsync()) + { + resultModel.Msg = $"工單號碼【{item.WipNO}】,已投入數量 >= (工單數量+序號領退量),請在確認"; + return resultModel; + } + } + } + + // 該筆工單號碼鎖定 + var WipLock = await _context.WipLocks.Where(w => w.WipNO == item.WipNO && w.LockStatus == "0").ToListAsync(); + if (WipLock.Where(w => w.StationID == 0).Any()) + { + resultModel.Msg = $"工單號碼【{item.WipNO}】,已被鎖定,不可過站"; + return resultModel; + } + + // StationID = 0 代表批次鎖定 + else if (WipLock.Where(w => w.StationID == stationID).Any()) + { + resultModel.Msg = $"工單號碼【{item.WipNO}】,工單在當前站別被鎖定,不可過站"; + return resultModel; + } + + resultModel.Success = true; + return resultModel; + } + catch (Exception ex) + { + resultModel.Msg += ex.Message; + resultModel.Success = false; + return resultModel; + } + } + + /// + /// 判斷序號狀態 + /// + /// 內部序號ID + /// 內部序號 + /// + [HttpGet("CheckBarCodeStation")] + public async Task> GetCheckBarCodeStation(int barCode, string barCodeNo) + { + ResultModel resultModel = new ResultModel(); + + #region 內部序號是否被鎖定 + resultModel = await CheckBarCodeLockAsync(barCode, barCodeNo); + if (!resultModel.Success) + return resultModel; + #endregion + + #region 內部序號是否被報廢 + resultModel = await CheckBarCodeScrappedAsync(barCode, barCodeNo); + if (!resultModel.Success) + return resultModel; + #endregion + + return resultModel; + } + + /// + /// 燒機判斷 + /// + /// 工單號碼 + /// 內部序號ID + /// 作業站ID + /// 過站狀態Pass Fail + /// + private async Task> GetCheckBurn(string wipNo, int barcodeID, int stationID, string ruleStatus) + { + ResultModel resultModel = new ResultModel() { Success = false }; + // 判斷是否有燒機時間 + var wipBoard = await _context.WipBoards.Where(w => w.WipNo == wipNo).FirstOrDefaultAsync(); + var wipSystem = await _context.WipSystems.Where(w => w.WipNo == wipNo).FirstOrDefaultAsync(); + var wipBoardTime = 0.0; + var wipSystemTime = 0.0; + + if (wipBoard != null) + { + try + { + if (!string.IsNullOrWhiteSpace(wipBoard.BiTime)) + wipBoardTime = double.Parse(wipBoard.BiTime); + + } + catch + { + wipBoardTime = -1; + } + } + + if (wipSystem != null) + { + try + { + if (!string.IsNullOrWhiteSpace(wipSystem.BiTime)) + wipSystemTime = double.Parse(wipSystem.BiTime); + + } + catch + { + wipSystemTime = -1; + } + } + + if (wipBoardTime <= 0 && wipSystemTime <= 0) + { + resultModel.Msg = "請確認燒機時間是否有填寫或者格式有誤"; + return resultModel; + } + + // 判斷燒機時間是否足夠 + var burnInfo = await _context.BurnInfos.Where(w => w.BarcodeID == barcodeID).ToListAsync(); + if (burnInfo.Count() != 0) + { + // 取實際燒機完成時間 空白資料 + var item = burnInfo.Where(w => string.IsNullOrWhiteSpace(w.FinishTime.ToString())).FirstOrDefault(); + if (item != null) + { + // 現在時間 < 預計排程時間 + if (DateTime.Now < item.ScheduleFinishTime) + { + resultModel.Msg = "燒機排程完成時間【" + item.ScheduleFinishTime + "】尚未到達"; + return resultModel; + } + } + else // 燒機資料都有填入實際燒機時間 + { + resultModel.Msg = "BurnIn"; + } + } + else + // 沒有BurnInfo = Burn In + { + resultModel.Msg = "BurnIn"; + } + resultModel.Success = true; + return resultModel; + } + + /// + /// 確認組件狀態 + /// + /// + [HttpGet("BarCodeKP")] + private async Task> CheckBarCodeKeyPartsData([FromQuery] BarcodeItemKPDto data) + { + ResultModel resultModel = new ResultModel { Success = false }; + // 更新WipKp字元長度 + var UpdateWipKpLength = new List(); + try + { + // 抓 工單key Parts資料 + var wipKps = _context.WipKps.Where(w => w.WipNo == data.wipNo && w.UnitNo == data.ststionUnitNo) + .OrderBy(o => o.KpSeq).ToList(); + if (wipKps.Count != 0) + { + // 取料號組件資料 + var BarCodeItems = _context.BarcodeItems.Where(w => w.BarcodeID == data.barCode && + w.S.UnitNo == data.ststionUnitNo && + w.WipID == data.wipId).ToList(); + + // 當前組件數量+已存料號組件數量 > 工單綁定組件數量 + if (data.inputKP.Count + BarCodeItems.Count > wipKps.Count) + { + resultModel.Msg = "組件數量已刷超過設定數量,請確認"; + return resultModel; + } + + #region 比對組件資料 + + var CheckMsg = string.Empty; + int x = BarCodeItems.Count; + + // 紀錄刷入KP不可重複序號,後續判斷刷入KP有重複 + var CheckInputKp = new List(); + + for (int i = 0; i < data.inputKP.Count; i++) + { + // 按照順序 + var wipKpsItem = wipKps[x + i]; + var dataItem = data.inputKP[i]; + // 有KpNo以KpNo為主 + if (!string.IsNullOrWhiteSpace(dataItem.inputType)) + { + wipKpsItem = wipKps.Where(w => w.KpNo.ToUpper() == dataItem.inputType.ToUpper()).FirstOrDefault(); + + if (wipKpsItem == null) + { + wipKpsItem = wipKps[x + i]; + } + } + + CheckMsg += await CheckKeyPartsCorrect(wipKpsItem, dataItem); + } + + // 有錯誤訊息 + if (!string.IsNullOrWhiteSpace(CheckMsg)) + { + resultModel.Msg = CheckMsg; + return resultModel; + } + + // 刷入KP有重複 + var RepeatKp = CheckInputKp + .GroupBy(g => g.inputData) + .Where(group => group.Count() > 1) + .Select(group => group.Key); + + if (RepeatKp.Count() != 0) + { + resultModel.Msg = $"刷入組件序號有重複【{string.Join(',', RepeatKp)}】
"; + return resultModel; + } + + #endregion + } + + // 確認沒問題後 + resultModel.Data = UpdateWipKpLength; + resultModel.Success = true; + return resultModel; + } + catch (Exception ex) + { + resultModel.Success = false; + resultModel.Msg = ex.Message; + return resultModel; + } + } + + /// + /// 確認治具狀態 + /// + /// + private ResultModel CheckBarCodeOutfitAsync([FromQuery] List outfit) + { + ResultModel resultModel = new ResultModel { Success = false }; + + #region 判斷是否有治具編號 + + OutfitInfoesController outfitInfoesController = new OutfitInfoesController(_context); + OutfitCommodityInfoesController outfitCommodityInfoesController = new OutfitCommodityInfoesController(_context); + foreach (var outfitNo in outfit) + { + var q = outfitInfoesController.GetOutfitInfoByOutfitNo(outfitNo.inputData.ToUpper()).Result; + + if (q.Value == null) + { + resultModel.Msg = "中央治具找不到該治具編號【" + outfitNo.inputData + "】"; + return resultModel; + } + + // 判斷治具種類 + var q1 = outfitCommodityInfoesController.GetOutfitCommodityInfo().Result; + if (!q1.Value.Where(w => w.CommodityID == q.Value.CommodityID && w.CommodityNo == outfitNo.PartNo).Any()) + { + resultModel.Msg = "刷入治具編號【" + outfitNo.inputData + "】總類不一致,請確認"; + return resultModel; + } + } + + #endregion + + resultModel.Success = true; + return resultModel; + } + + /// + /// 取得上一個作業站RuleStationID + /// + /// 工單ID + /// BarCodeID + /// 目前作業站ID + /// 工單流程ID + /// 過站狀態 P/F + /// true:false + private async Task GetBarCodeLastStopRuleStationID(int wipID, int barCodeID, int stationID, int flowRuleID, string ruleStatus) + { + ResultModel resultModel = new ResultModel { Success = false }; + + // 用作業站抓 有設定下一站為該站的資料 + var Rules = await _context.Ruleses.Where(w => w.FlowRuleID == flowRuleID).ToListAsync(); + // 取得目前BarCodeInfo 站別 + var BarCodeInfo = await _context.BarcodeInfoes.Where(w => w.BarcodeID == barCodeID).FirstOrDefaultAsync(); + + if (!Rules.Any()) + { + resultModel.Msg = "找不到該筆工單流程之流程設定相關資料,請確認"; + return resultModel; + } + else + { + // 確認是否有設定該站 + if (!Rules.Any(a => a.StationID == stationID && a.RuleStatus == ruleStatus)) + { + resultModel.Msg = "找不到該站別或無設定FAIL流程,請確認"; + return resultModel; + } + + // 有過站紀錄 + if (BarCodeInfo != null) + { + // 如果BarCodeInfo 結案,判斷當下作業站是否第一站 + if (BarCodeInfo.StatusID == -1) + { + if (BarCodeInfo.WipID == wipID) + { + resultModel.Msg = "該內部序號在目前生產製程已完工,請確認"; + return resultModel; + } + + if (!Rules.Where(w => w.StationID == stationID && w.RuleSeq == 1 && w.RuleStatus == "P").Any()) + { + resultModel.Msg = "目前作業站不是第一站,請確認"; + return resultModel; + } + resultModel.Success = true; + return resultModel; + } + + if (BarCodeInfo.WipID != wipID) + { + resultModel.Msg = $"前一製程還未結束,請確認"; + return resultModel; + } + + // 目前BarCodeInfo StationID 取得相對應下個流程StationID + var rulesByBarCodeInfoStationID = Rules.Where(w => w.StationID == BarCodeInfo.StationID).ToList(); + + // 當下個流程 != 目前過站流程 + if (rulesByBarCodeInfoStationID.Where(w => w.NextStationID == stationID && w.RuleStatus == BarCodeInfo.RuleStatus).Count() == 0) + { + var Nextstation = rulesByBarCodeInfoStationID.Where(w => w.RuleStatus == BarCodeInfo.RuleStatus).ToList(); + var StationName = Nextstation.Select(s => s.NextStation.StationName).ToArray(); + resultModel.Msg = "該內部序號下一個作業站應該是:" + string.Join('、', StationName) + " ,請確認"; + return resultModel; + } + } + // 沒有過站紀錄 判斷是否為投入站 + else + { + if (!Rules.Where(w => w.StationID == stationID && w.RuleSeq == 1 && w.RuleStatus == "P").Any()) + { + resultModel.Msg = "該內部序號尚未投入,請確認"; + return resultModel; + } + } + } + resultModel.Success = true; + return resultModel; + } + + /// + /// 確認下一站為完工 + /// + /// 流程ID + /// 作業站ID + /// 過站狀態 Pass or Fail + /// Success(true)是 (false)不是 + [HttpGet("CheckNextStopCloseStation")] + public async Task> CheckNextStopCloseStation(int flowRuleId, int stationID, string ruleStatus) + { + ResultModel resultModel = new ResultModel { Success = false }; + + // 取得流程 + var ruleStations = await _context.RuleStations.Where(w => w.FlowRuleID == flowRuleId).ToListAsync(); + if (ruleStations.Any()) + { + // 在RuleStation 找不到該作業站 + if (!ruleStations.Where(w => w.StationID == stationID).Any()) + return resultModel; + + var rules = await _context.Ruleses.Where(w => w.FlowRuleID == flowRuleId).ToListAsync(); + + // 當下一站SatationID= 1000 代表完工站 + if (rules.Where(w => w.StationID == stationID && w.NextStationID == 1000 && w.RuleStatus == ruleStatus).Any()) + { + resultModel.Success = true; + return resultModel; + } + } + return resultModel; + } + + /// + /// 確認目前該站是否為第一站 + /// + /// 工單號碼ID + /// 作業站ID + /// Y:是 N:不是 + private async Task CheckNowFirstStation(int wipId, int stationID) + { + var WipInfo = await _context.WipInfos.Where(w => w.WipID == wipId).FirstOrDefaultAsync(); + + if (WipInfo != null) + { + // 取得流程 + var ruleStations = await _context.RuleStations.Where(w => w.FlowRuleID == WipInfo.FlowRuleID).ToListAsync(); + if (ruleStations.Count() != 0) + { + // 用目前站別判斷順序是不是 1 + if (ruleStations.Where(w => w.StationID == stationID && w.Sequence == 1 && w.StationType == "M").Any()) + return "Y"; + } + } + return "N"; + } + + /// + /// 判斷生產中工單是否已經全部完工 自動更新 + /// + /// 工單ID + /// + [HttpGet("CheckWipNoBarCodeAllClost")] + public async Task CheckWipNoBarCodeAllClost(int wipId) + { + var wipInfo = await _context.WipInfos.Where(w => w.WipID == wipId).FirstOrDefaultAsync(); + + if (wipInfo != null) + { + // 取Rules 最後一站為完工站的Station及狀態 + var rules = await _context.Ruleses.Where(w => w.FlowRuleID == wipInfo.FlowRuleID).ToListAsync(); + var lastStation = rules.Where(w => w.NextStationID == 1000).Select(s => new { s.StationID, s.RuleStatus }).ToList(); + + var barcodeStations = await _context.BarcodeStation.Where(w => w.WipID == wipId).ToListAsync(); + + // ByLastStation Count = 工單數 (完工) + var closeWipQty = 0; + foreach (var item in lastStation) + { + closeWipQty += barcodeStations.Where(w => item.StationID == w.StationID && item.RuleStatus == w.RuleStatus) + .Select(s => s.BarcodeID).Distinct().Count(); + } + + if (wipInfo.PlanQTY == closeWipQty) + { + WipInfosController wipInfosController = new WipInfosController(_context); + var result = await wipInfosController.PutWipinfoToStatusNO(wipId, "E"); + // 呼叫CTO + await WipEndCallCtoUrl(wipInfo.WipNO); + } + } + return ""; + } + + /// + /// 無序號工單批次作業 + /// + /// + /// + [HttpGet("CreateBarcodeInfobyPCS038")] + public async Task CreateBarcodeInfobyPCS038(int WipID) + { + ResultModel resultModel = new ResultModel { Success = true }; + + var wipinfo = await _context.WipInfos.Where(w => w.WipID == WipID).FirstOrDefaultAsync(); + if (wipinfo != null) + { + var wipbarcode = await _context.WipBarcodes.Where(w => w.WipNO == wipinfo.WipNO).ToListAsync(); + string resultMsg = ""; + if (wipbarcode.Count() != 0) + { + // 取BarCodeID + Helper helper = new Helper(_context); + foreach (var item in wipbarcode) + { + string start = item.StartNO; + string end = item.EndNO; + + // 取得流水號的長度 + int serialLength = start.Length - 4; + + // 將起始跟結束序號的流水號轉換為數字 + int startSerial = int.Parse(start.Substring(start.Length - 4)); + int endSerial = int.Parse(end.Substring(end.Length - 4)); + + // 進行序號展開 + for (int i = startSerial; i <= endSerial; i++) + { + string serial = i.ToString().PadLeft(4, '0'); + string code = start.Substring(0, start.Length - 4); + + string barcode = code + serial; + BarCodeCheckDtoForDBData data = new BarCodeCheckDtoForDBData(); + data.unitNo = wipinfo.UnitNO; + data.wipID = WipID; + data.barcode = barcode; + data.barcodeID = 0; + data.extNo = ""; + data.flowRule = wipinfo.FlowRuleID; + data.wipNo = wipinfo.WipNO; + var Msg = Table_BarcodeInfo(data, await helper.GetIDKey("BARCODE_ID")); + + if (string.IsNullOrWhiteSpace(Msg)) + { + resultMsg += $"{code + serial} 內部條碼:產生成功!!!" + "
"; + } + else + { + resultMsg += $"{code + serial} 內部條碼:產生失敗!!!原因:" + Msg + "
"; + } + } + + resultModel.Success = true; + } + } + else + { + resultModel.Success = false; + resultModel.Msg = "工單資料沒有設定生產序號區間"; + } + } + else + { + resultModel.Success = false; + resultModel.Msg = "查無工單"; + } + return resultModel; + } + + /// + /// 確認過站基本欄位是否填寫 + /// + /// + /// + private string CheckBarCodeInputData(BarCodeCheckDto barCodeCheckDto) + { + string Msg = string.Empty; + if (string.IsNullOrWhiteSpace(barCodeCheckDto.wipNo)) + Msg += "請輸入工單號碼,"; + + if (string.IsNullOrWhiteSpace(barCodeCheckDto.barcode)) + Msg += "請輸入內部條碼,"; + + if (string.IsNullOrWhiteSpace(barCodeCheckDto.unitNo)) + Msg += "請輸入生產單位,"; + + if (barCodeCheckDto.stationID == 0) + Msg += "請輸入作業站代碼,"; + + if (barCodeCheckDto.line == 0) + Msg += "請輸入線別代碼,"; + + // 判斷User存在 + if (barCodeCheckDto.userID != 0) + { + if (_context.UserInfoes.Where(w => w.UserID == barCodeCheckDto.userID).Count() == 0) + Msg += $"找不到UserID【{barCodeCheckDto.userID}】資料,"; + } + + // 判斷是否有刷入時間 + if (!DateTime.TryParse(barCodeCheckDto.startTime, out _)) + { + Msg += $"請刷入開始時間或時間格式錯誤【{barCodeCheckDto.startTime}】"; + } + + if (!string.IsNullOrWhiteSpace(Msg)) + Msg = Msg.Substring(0, Msg.Length - 1); + + return Msg; + } + + /// + /// 過站相關資訊 寫入 + /// + /// + /// + private async Task PassIngDataTuck(BarCodeCheckDto barCodeCheckDto) + { + var result = new BarCodeCheckDtoForDBData(); + + result.wipNo = barCodeCheckDto.wipNo.Trim().ToUpper(); + result.barcode = barCodeCheckDto.barcode.Trim().ToUpper(); + result.barcodeType = barCodeCheckDto.barcodeType; + result.unitNo = barCodeCheckDto.unitNo; + result.stationID = barCodeCheckDto.stationID; + result.line = barCodeCheckDto.line; + result.userID = barCodeCheckDto.userID; + result.start_Time = DateTime.Parse(barCodeCheckDto.startTime); + + #region 相關資料 Null給空白 + // KP||NG Input + if (barCodeCheckDto.inputItems == null) + result.inputItems = new List(); + else + { + result.inputItems = barCodeCheckDto.inputItems.Where(w => !string.IsNullOrWhiteSpace(w.inputType)).ToList(); + result.inputItems = result.inputItems.Select(s => + { + s.inputData = s.inputData.Trim().ToUpper(); + return s; + }).ToList(); + } + + // 治具 Input + if (barCodeCheckDto.outfits == null) + result.outfits = new List(); + else + { + result.outfits = barCodeCheckDto.outfits.Where(w => !string.IsNullOrWhiteSpace(w.inputData)).ToList(); + result.outfits = result.outfits.Select(s => + { + s.inputData = s.inputData.Trim().ToUpper(); + return s; + }).ToList(); + } + + #endregion + + // 工單資料 + var WipInfo = await _context.WipInfos.Where(w => w.WipNO == barCodeCheckDto.wipNo && + w.UnitNO == barCodeCheckDto.unitNo && + w.LineID == barCodeCheckDto.line).FirstOrDefaultAsync(); + if (WipInfo != null) + { + result.wipID = WipInfo.WipID; + result.flowRule = WipInfo.FlowRuleID; + } + + // 料號 + var WipAtt = await _context.WipAtts.Where(w => w.WipNO == barCodeCheckDto.wipNo.Trim().ToUpper()).FirstOrDefaultAsync(); + if (WipAtt != null) + { + result.itemNo = WipAtt.ItemNO; + var MaterialItem = await _context.MaterialItems.Where(w => w.ItemNo == result.itemNo).FirstOrDefaultAsync(); + if (MaterialItem != null) + { + // 料號ID + result.item = MaterialItem.ItemID; + } + } + + // 工作站 + var Station = await _context.Stationses.Where(w => w.StationID == result.stationID).FirstOrDefaultAsync(); + if (Station != null) + { + result.stations_TestType = Station.TestType; + result.stations_TypeNo = Station.TypeNo; + result.stations_UnitNo = Station.UnitNo; + result.stations_Name = Station.StationName; + } + + // 生產單位_簡碼 + var FactoryUnit = await _context.FactoryUnits.Where(w => w.UnitNo == result.unitNo).FirstOrDefaultAsync(); + if (FactoryUnit != null) + { + result.factoryUnit_UnitCode = FactoryUnit.UnitCode; + } + + // 判斷序號為出貨條碼,並轉成內部條碼 + var BarCodeInfo = await _context.BarcodeInfoes.Where(w => w.ExtraBarcodeNo.Trim().ToUpper() == barCodeCheckDto.barcode.Trim().ToUpper()).FirstOrDefaultAsync(); + if (BarCodeInfo != null) + { + result.extNo = BarCodeInfo.ExtraBarcodeNo; + result.barcode = BarCodeInfo.BarcodeNo; + } + + // 抓BarCode ID + BarCodeInfo = await _context.BarcodeInfoes.Where(w => w.BarcodeNo == result.barcode).FirstOrDefaultAsync(); + if (BarCodeInfo != null) + { + result.barcodeID = BarCodeInfo.BarcodeID; + } + + // 過站狀態 + if (result.inputItems.Where(w => w.inputData.Contains("$")).Any()) + result.ruleStatus = "F"; + else + result.ruleStatus = "P"; + + return result; + } + + /// + /// 確認過站資料是否正確 + /// + /// + /// + private async Task CheckPassIngDataCorrect(BarCodeCheckDtoForDBData data) + { + string Msg = string.Empty; + + if (data.wipID == 0) + Msg += $"找不到工單號碼【{data.wipNo}】相關工單資料,請確認,"; + + if (data.flowRule == 0) + Msg += $"工單號碼【{data.wipNo}】尚未設定流程,請確認,"; + + // 抓流程順序資料 + var ruleStations = await _context.RuleStations.Where(w => w.FlowRuleID == data.flowRule).ToListAsync(); + if (!ruleStations.Any()) + { + Msg += $"該工單號碼【{data.wipNo}】的流程編號尚未設定流程"; + } + else + { + if (!ruleStations.Where(w => w.StationID == data.stationID).Any()) + { + Msg += $"該工單號碼【{data.wipNo}】的流程未設定此作業站"; + } + } + + // 判斷有無不良代碼 + if (data.inputItems.Any(a => a.inputData.Contains("$"))) + { + var NgItem = data.inputItems.Where(w => w.inputData.Contains("$")).ToList(); + IQueryable q = _context.NGReasons; + foreach (var item in NgItem.Select(s => s.inputData)) + { + if (!q.Where(w => w.NGReasonNo.Trim().ToUpper() == item.Replace("$", "").Trim().ToUpper() + && w.Status == "A").Any()) + { + Msg += $"查無不良代碼【{item.Replace("$", "").Trim().ToUpper()}】,請確認,"; + } + } + } + + // 維修過站資料判斷 + if (data.barcodeType == "S") + { + // 確認新舊組件序號是否都有值 + if (data.inputItems.Any(a => a.inputType.ToUpper() != "NG" && + (string.IsNullOrWhiteSpace(a.inputData) || string.IsNullOrWhiteSpace(a.oldInputData)))) + { + Msg += "工單號碼【" + data.wipNo + "】維修過站資料有缺新舊組件序號,請確認,"; + } + } + + // 判斷有無重複序號 + if (data.inputItems.Any()) + { + // 判斷keyPart是否重複 + var duplicateKeyParts = data.inputItems.Where(item => item.inputType != "NG").GroupBy(item => item.inputData) + .Where(group => group.Count() > 1).Select(s => s.Key) + .Distinct().ToList(); + + // 判斷keyPart是否重複 + if (duplicateKeyParts.Any()) + { + Msg += $"KeyParts有重複【{string.Join(",", duplicateKeyParts)}】,請在確認,"; + } + } + + if (!string.IsNullOrWhiteSpace(Msg)) + Msg = Msg.Substring(0, Msg.Length - 1); + + return Msg; + } + + /// + /// KeyPart 細項判斷確認 + /// + /// 工單組件資料 + /// 過站刷入組件資料 + /// + private async Task CheckKeyPartsCorrect(WipKp wipKp, BarCodeCheckDto.inputItem inputItem) + { + string CheckMsg = string.Empty; + #region 比對序號長度是否正確 + + if (wipKp.Length != null) + { + if (wipKp.Length != inputItem.inputData.Length && wipKp.Length != 0) + CheckMsg += "組件序號【" + inputItem.inputData + "】 與組件名稱【" + wipKp.KpName + "】長度不符合
"; + } + + #endregion + + #region 前置碼正確 + + if (!string.IsNullOrWhiteSpace(wipKp.Title)) + { + if (!inputItem.inputData.ToUpper().StartsWith(wipKp.Title.ToUpper())) + CheckMsg += "組件序號【" + inputItem.inputData + "】 與組件名稱【" + wipKp.Title + "】前置碼不符合
"; + } + #endregion + + #region 組件代碼-組件序號是否重複 + + // 抓C_SFIS_KEYPARTS (安勤轉拋) + if (await _context.CSfisKeyparts.Where(w => w.Partbarcode.ToUpper() == inputItem.inputData).AnyAsync()) + { + CheckMsg += "組件名稱【" + wipKp.KpName + "】已有相同組件序號【" + inputItem.inputData + "】安勤轉拋KeyParts紀錄
"; + } + + if (await _context.BarcodeItems.AsNoTracking().Where(w => w.PartNo.Trim().ToUpper() == inputItem.inputData).AnyAsync()) + { + CheckMsg += "組件名稱【" + wipKp.KpName + "】已有相同組件序號【" + inputItem.inputData + "】紀錄
"; + } + + #endregion + + #region 判斷組件序號是否在製狀態 + + if (wipKp.KpNo.ToUpper() == "04") + { + if (await _context.BarcodeInfoes.Where(w => w.BarcodeNo == inputItem.inputData.ToUpper().Trim() && w.StatusID != -1).AnyAsync()) + { + CheckMsg += "組件序號【" + inputItem.inputData + "】 目前是在製狀態
"; + } + } + + #endregion + + #region 安勤不需要判斷MAC區間 + //if (wipKp.KpNo.ToUpper().StartsWith("MAC")) + //{ + // var wipMAC = await _context.WipMACs.Where(w => w.WipNO == wipKp.WipNo).ToListAsync(); + // if (wipMAC.Count() == 0) + // { + // CheckMsg += "工單號碼【" + wipKp.WipNo + "】 找不到綁定MAC區間
"; + // } + // else + // { + // // 判斷是否符合區間 + // if (inputItem.inputData.Length != 12 && inputItem.inputData.Length != 6) + // { + // CheckMsg += "組件序號【" + inputItem.inputData + "】 綁定MAC不足12碼或6碼
"; + // } + // else + // { + // // 長度12碼 判斷前置碼 + // if (inputItem.inputData.Length == 12) + // { + // if (!wipMAC.Where(w => inputItem.inputData.StartsWith(w.Title)).Any()) + // { + // CheckMsg += $"組件序號【{inputItem.inputData}】與MAC【{string.Join('、', wipMAC.Select(s => s.Title).ToList())}】前置碼不符合
"; + // } + // } + // // 長度6碼 抓WIPMAC 前6碼補足 12碼 + // else if (inputItem.inputData.Length == 6) + // { + // var wipMacItem = wipMAC.FirstOrDefault(); + // inputItem.inputData = wipMacItem.Title + inputItem.inputData; + // } + + // var InputMacTitle = inputItem.inputData.Substring(0, 6).ToUpper(); + // var InputMacNo = Convert.ToInt32(inputItem.inputData.Substring(6, 6), 16); + // if (!wipMAC.Where(w => Convert.ToInt32(w.StartNO, 16) <= InputMacNo && + // InputMacNo <= Convert.ToInt32(w.EndNO, 16) && + // w.Title == InputMacTitle).Any()) + // { + // CheckMsg += "組件序號【" + inputItem.inputData + "】 與工單設定MAC區間不符合
"; + // } + // } + // } + //} + + #endregion + + #region 判斷出貨序號 + + // 當KP_NAME是 EXT_NO 判斷組件-出貨序號 是否有在區間 + if (wipKp.KpNo.ToUpper() == "95") + { + WipBarcodeOtherController wipBarcodeOtherController = new WipBarcodeOtherController(_context); + var WipBarCodeOther = await wipBarcodeOtherController.CheckWipBarcodeOtherByNo(wipKp.WipNo, inputItem.inputData); + if (WipBarCodeOther.Value.Count() == 0) + { + CheckMsg += "組件序號【" + inputItem.inputData + "】 與工單設定出貨序號區間不符合
"; + } + } + + #endregion + + return CheckMsg; + } + + /// + /// 更新 組件替換資料 + /// + /// 料號組件資料 + /// 料號組件更換資料 + /// + private async Task UpdateBarCodeItemChange(List barcodeItems, List barcodeItemChanges) + { + string Msg = string.Empty; + using (var tran = _context.Database.BeginTransaction()) + { + try + { + // 更新料號組件 + foreach (var item in barcodeItems) + { + _context.Entry(item).State = EntityState.Modified; + await _context.SaveChangesAsync(); + } + + // 新增料號組件更換資料 + foreach (var item in barcodeItemChanges) + { + Helper helper = new Helper(_context); + item.BarcodeItemChangeID = await helper.GetIDKey("BARCODE_ITEM_CHANGE"); + _context.BarcodeItemChanges.Add(item); + + await _context.SaveChangesAsync(); + } + await tran.CommitAsync(); + } + catch (Exception ex) + { + Msg = $"過站新增系統錯誤:{ex.Message}"; + await tran.RollbackAsync(); + } + } + return Msg; + } + + /// + /// 取該筆工單流水碼 + /// + /// 工單號碼 + /// + private async Task GetWipNoSerialNumber(string wipNo) + { + int snLen = 4; + try + { + var result_WipInfo = await _context.WipInfos.Where(w => w.WipNO == wipNo.Trim().ToUpper()).ToListAsync(); + // 取工單號碼最大工單數量 + snLen = result_WipInfo.Max(m => m.PlanQTY).ToString().Length; + // 長度最小取4碼 + if (snLen <= 4) snLen = 4; + } + catch + { + return snLen; + } + return snLen; + } + + /// + /// 確認是否有掃毒 + /// + /// 工單號碼 + /// 工單料號 + /// + private async Task> CheckAntivirus(string wipNo, string itemNo) + { + ResultModel resultModel = new ResultModel { Success = false }; + + var wipSystem = _context.WipSystems.Where(w => w.WipNo == wipNo).FirstOrDefault(); + // 找不到工程資料 不須判斷 + if (wipSystem == null) + { + resultModel.Success = true; + return resultModel; + } + + // 是否掃毒 != Y + if (wipSystem.Antivirus != "Y") + { + resultModel.Success = true; + return resultModel; + } + else + { + TestLogController testLogController = new TestLogController(_context, _config); + var resultAntivirus = testLogController.GetSacnvirus(wipNo).Result; + if (resultAntivirus.Count() != 0) + { + resultModel.Success = true; + return resultModel; + } + else + { + string MailGroup = "PE_SCANV"; + string Subject = $"[AMES系統通知] 工單號碼【{wipNo}】,未執行掃毒,請確認"; + string Body = $"工單號碼【{wipNo}】,未執行掃毒,請確認"; + await new MailController(_context, _config).PostMail(Subject, Body, MailGroup, "", false); + + WipAlarm wipAlarm = new WipAlarm(); + wipAlarm.AlarmTypeID = (int)EnumWipAlarm.EnumTypeId.Antivirus; + wipAlarm.WipNO = wipNo; + wipAlarm.AlarmParam = itemNo; + wipAlarm.AlarmValue = "1"; + wipAlarm.AlarmDesc = Subject; + wipAlarm.AlarmDateTime = DateTime.Now; + + Helper helper = new Helper(_context); + wipAlarm.WipAlarmID = helper.GetIDKey("WIP_ALARMID").Result; + + _context.WipAlarms.Add(wipAlarm); + _context.SaveChanges(); + + resultModel.Success = false; + resultModel.Msg = "未執行掃毒,請確認"; + return resultModel; + } + } + } + + /// + /// 工單完工時呼叫CTO + /// + /// 工單號碼 + /// + private async Task WipEndCallCtoUrl(string WipNo) + { + // 呼叫CTO + string getUrl = $"https://nportal.avalue.com.tw/avaluecto/ctoamesmodone.aspx?orderno={WipNo}"; + await MakeGetRequest(getUrl); + } + + /// + /// 執行Get Https網址 + /// + /// 呼叫網址 + /// + private async Task MakeGetRequest(string targetUrl) + { + using (HttpClient httpClient = new HttpClient()) + { + // 執行GET請求 + HttpResponseMessage response = await httpClient.GetAsync(targetUrl); + } + } + } +} + diff --git a/AMESCoreStudio.WebApi/DTO/BLL/BarCodeCheckDto.cs b/AMESCoreStudio.WebApi/DTO/BLL/BarCodeCheckDto.cs index 552369e1..0801c47c 100644 --- a/AMESCoreStudio.WebApi/DTO/BLL/BarCodeCheckDto.cs +++ b/AMESCoreStudio.WebApi/DTO/BLL/BarCodeCheckDto.cs @@ -104,7 +104,6 @@ namespace AMESCoreStudio.WebApi.DTO.AMES [DataMember] public int userID { get; set; } = 0; - /// /// 紀錄組件或不良代碼 /// @@ -156,6 +155,12 @@ namespace AMESCoreStudio.WebApi.DTO.AMES /// public string PartNo { get; set; } = string.Empty; } + + [DataMember] + /// + /// 刷入時間 + /// + public string startTime { get; set; } } public class BarCodeCheckDtoForDBData : BarCodeCheckDto @@ -207,5 +212,10 @@ namespace AMESCoreStudio.WebApi.DTO.AMES /// [DataMember] public string factoryUnit_UnitCode { get; set; } = string.Empty; + + /// + /// 刷入時間 + /// + public DateTime? start_Time { get; set; } } } diff --git a/AMESCoreStudio.WebApi/Models/AMES/BarcodeStation.cs b/AMESCoreStudio.WebApi/Models/AMES/BarcodeStation.cs index a2349108..d1c3a0fe 100644 --- a/AMESCoreStudio.WebApi/Models/AMES/BarcodeStation.cs +++ b/AMESCoreStudio.WebApi/Models/AMES/BarcodeStation.cs @@ -123,6 +123,14 @@ namespace AMESCoreStudio.WebApi.Models.AMES [Display(Name = "建立時間")] public DateTime CreateDate { get; set; } = DateTime.Now; + /// + /// 過站刷入時間 + /// + [Column("START_DATE")] + [DataMember] + [Display(Name = "過站刷入時間")] + public DateTime? StartDate { get; set; } + /// /// 工單-基本資料 ///