using Rhea.Common; using Tiger.IBusiness; using SqlSugar; using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Text; using System.Threading; using System.Threading.Tasks; using Tiger.Model; using Tiger.Model.Entitys.MES.Position; namespace Tiger.Business.MES.Transaction { /// /// 采集工序事务 /// public class CollectNode : Position, ICollectNode { public new ICollectNode Init(string id, string apiHost, string userCode, string postCode) { base.Init(id, apiHost, userCode, postCode); Logger.Console.Info($"User[{userCode}] start a {this.GetType().Name}[{postCode}] Transaction[ID: {TransID}]"); return this; } #region Propertys & Variables #endregion Propertys & Variables #region Functions /// /// 采集工序:提交操作数据 /// /// /// public async Task Submit(SubmitInput input) { var action = new ApiAction(); try { //工步列表为空时,认为需要先扫描过站条码 if (Steps.IsNullOrEmpty()) { //先判断当前工单不为空且当前岗位在当前工单是不是首站,如果是则不允许变更当前工单,尝试把条码绑定到当前工单 if (!CurBatch.IsNullOrEmpty() && CurBatch.IsFirstNode(PostCode)) { action = ScanSn(action, input); return action; } //当前岗位在当前工单不是首站,则查找条码已绑定的工单当作当前工单 else { var wosn = Biz.Db.Queryable((b, s) => new JoinQueryInfos(JoinType.Inner, b.ORDER_NO == s.WORK_ORDER)).ByAuth(input.AuthOption) .Where((b, s) => s.SN == input.SN && b.ACT_LINE == CurLine.LINE_CODE && (b.STATUS == BIZ_MES_WO_BATCH.STATUSs.Release.GetValue() || b.STATUS == BIZ_MES_WO_BATCH.STATUSs.Working.GetValue())) .Select((b, s) => new { Batch = b, SN = s }).First(); //查找到条码已绑定的工单 if (!wosn.IsNullOrEmpty()) { if (CurBatch?.Batch?.ORDER_NO != wosn.Batch.ORDER_NO) { //条码已绑定的工单不等于当前工单则重新选择工单 var result = await SelectOrder(new() { AuthOption = input.AuthOption, OrderNo = wosn.Batch.ORDER_NO }); if (!result.IsSuccessed) { action = result; return action; } } //条码过站 action = ScanSn(action, input); return action; } //查找不到条码已绑定的工单 else { //没有当前工单,则先选择工单后再扫描条码 if (CurBatch.IsNullOrEmpty()) { action.IsSuccessed = false; //action.LocaleMsg = new($"未选择工单,请先选择要生产的工单"); action.LocaleMsg = new("MES.Transaction.CollectNode.Submit.NotSelectOrderException"); return action; } //有当前工单且不是投入,则提示条码未投入生产,请先去首站扫描 else { action.IsSuccessed = false; //action.LocaleMsg = new($"条码[{input.SN}]尚未投入生产,请先去首站扫描", input.SN); action.LocaleMsg = new("MES.Transaction.CollectNode.Submit.NotInputException", input.SN); return action; } } } } //完成第一步,后开始执行当前工序的行为列表 else if (Steps.First().IsFinished && !IsFinishAllSteps) { //var curStep = Steps.Where(q => !q.IsFinished).OrderBy(q => q.Sequence).First(); var curStep = Steps.Where(q => q.ID == input.StepID).FirstOrDefault(); if (!curStep.IsNullOrEmpty()) { var result = curStep.Submit(input); result.Data.StepID = curStep.ID; result.Data.IsFinished = IsFinishAllSteps; result.Data.CurStep = CurStep; if (IsFinishAllSteps) { return DoIfFinishAllSteps(result.ToApiAction()); } return result.ToApiAction(); } } //没有可执行的工步 ResetSteps(); action.IsSuccessed = false; //action.LocaleMsg = new($"岗位[{CurPosition.POST_CODE}]工步执行异常,请重新扫描产品条码", CurPosition.POST_CODE); action.LocaleMsg = new("MES.Transaction.CollectNode.Submit.WorkStepException", CurPosition.POST_CODE); } catch (Exception ex) { action.CatchExceptionWithLog(ex, $"采集工序:扫描产品条码异常"); } return action; } /// /// 扫描过站条码 /// /// /// /// public ApiAction ScanSn(ApiAction action, SubmitInput input) { try { //绑定条码到工单 if (!CurBatch.WoSNs.Any(q => q.SN == input.SN)) { CurBatch.WoSNs.Add(new() { WORK_ORDER = CurBatch.Batch.ORDER_NO, SN = input.SN, STATUS = BIZ_MES_WO_SN.STATUSs.NotInput.GetValue(), BATCH_NO = CurBatch.Batch.BATCH_NO, }); } var woSN = CurBatch.WoSNs.FirstOrDefault(q => q.SN == input.SN); var curNode = CurBatch.GetNode(PostCode); //条码过站 var wipSN = Biz.Db.Queryable().First(q => q.SN == input.SN && q.BATCH_NO == CurBatch.Batch.BATCH_NO) ?? new MES_WIP_DATA() { SN = input.SN, STATUS = MES_WIP_DATA.STATUSs.Init.GetValue(), ITEM_CODE = CurBatch.WO.ITEM_CODE, WORK_ORDER = CurBatch.Batch.ORDER_NO, BATCH_NO = CurBatch.Batch.BATCH_NO, HOLD_FLAG = "N", REWORK_FLAG = CurBatch.WO.ORDER_TYPE == BIZ_MES_WO.ORDER_TYPEs.Rework.GetValue() ? "Y" : "N", FINISHED_FLAG = "N", INV_FLAG = "N", DFT_FLAG = "N", DFT_COUNT = 0, }; wipSN.AUTH_PROD = CurLine.LINE_CODE; wipSN.STATUS = wipSN.STATUS > 0 ? MES_WIP_DATA.STATUSs.OK.GetValue() : wipSN.STATUS; wipSN.ROT_CODE = CurBatch.WO.ROUTE_CODE; wipSN.NODE_ID = curNode.ID; wipSN.NODE_NAME = curNode.NODE_NAME; wipSN.FTY_CODE = CurFactory.FTY_CODE; wipSN.WS_CODE = CurWorkshop.WS_CODE; wipSN.LINE_CODE = CurLine.LINE_CODE; wipSN.POST_CODE = CurPosition.POST_CODE; wipSN.OPER_CODE = curNode.OPER_CODE; wipSN.SEGMENT = curNode.SEGMENT; wipSN.OPERATION_TIME = DateTime.Now; wipSN.SFTS_CODE = CurLine.SFTS_CODE; //wipSN.SFT_CODE = CurBatch.WO.ROUTE_CODE; //wipSN.PRD_CODE = CurBatch.WO.ROUTE_CODE; CurBatch.StartWorking(UserCode); //如果是投入站 if (curNode.IS_INPUT == "Y") { woSN.STATUS = BIZ_MES_WO_SN.STATUSs.Inputed.GetValue(); wipSN.STATUS = MES_WIP_DATA.STATUSs.Input.GetValue(); wipSN.INLINE_DATE = DateTime.Now; } //如果是产出站 if (curNode.IS_OUTPUT == "Y") { woSN.STATUS = BIZ_MES_WO_SN.STATUSs.Finished.GetValue(); wipSN.STATUS = MES_WIP_DATA.STATUSs.Finished.GetValue(); wipSN.OUTLINE_DATE = DateTime.Now; } //如果有提交不良 if (!input.DFT_CODE.IsNullOrEmpty()) { wipSN.STATUS = MES_WIP_DATA.STATUSs.NG.GetValue(); wipSN.DFT_FLAG = "Y"; wipSN.DFT_COUNT++; wipSN.DFT_CODE = input.DFT_CODE; } var wipSnHis = new MES_WIP_HIS(CurWipSN = wipSN, $"工单[{wipSN.WORK_ORDER}]条码[{wipSN.SN}]在岗位[{wipSN.POST_CODE}]过站工序[{wipSN.NODE_NAME}]成功"); //初始化工步列表 Steps.Clear(); var curStep = new Biz.WorkStep(curNode.ID, Biz.WorkStep.Types.Node) { Sequence = Steps.Count + 1, Node = curNode, DBSubmitAction = () => { var db = GetCommitDB(); db.Storageable(woSN, UserCode).ExecuteCommand(); db.Storageable(wipSN, UserCode).ExecuteCommand(); db.Storageable(wipSnHis, UserCode).ExecuteCommand(); } }; Steps.Add(curStep); //如果当前工序节点有行为则添加到工步列表 var acts = CurBatch.NodeActs.Where(q => q.NODE_ID == curNode.ID).ToList(); foreach (var act in acts) { Steps.Add(new Biz.WorkStep(act.ID, Biz.WorkStep.Types.Action) { Sequence = Steps.Count + 1, Node = curNode, NodeAct = act, Setting = CurBatch.ActionSets.FirstOrDefault(q => q.ACT_ID == act.ID), }); } //未完成所有工步 if (!IsFinishAllSteps) { var next = Steps.Where(q => !q.IsFinished).OrderBy(q => q.Sequence).First(); var result = next.Begin(this); result.Data.StepID = next.ID; result.Data.IsFinished = IsFinishAllSteps; result.Data.CurStep = CurStep; return result.ToApiAction(); } //已完成所有工步 else { action = DoIfFinishAllSteps(action); } } catch (Exception ex) { ResetSteps(); action.CatchExceptionWithLog(ex, $"采集工序:扫描产品条码异常"); } return action; } /// /// 完成所有工步后执行 /// /// /// public ApiAction DoIfFinishAllSteps(ApiAction action) { //保存数据库 var dbTran = GetCommitDB().UseTran(() => { //在同一个事务中保存所有工步的数据 foreach (var step in Steps.OrderBy(q => q.Sequence)) { step.DBSubmitAction.Invoke(); } }); if (!dbTran.IsSuccess) { throw dbTran.ErrorException; } //保存成功,返回过站消息 //action.LocaleMsg = new($"工单[{CurWipSN.WORK_ORDER}]的条码[{CurWipSN.SN}]在岗位[{CurWipSN.POST_CODE}]工序[{CurWipSN.NODE_NAME}]过站成功,状态[{CurWipSN.STATUS.GetEnumDesc()}]", CurWipSN.WORK_ORDER, CurWipSN.SN, CurWipSN.POST_CODE, CurWipSN.NODE_NAME, CurWipSN.STATUS.GetEnumDesc()); action.LocaleMsg = new("MES.Transaction.CollectNode.ScanSn.PassSuccess", CurWipSN.WORK_ORDER, CurWipSN.SN, CurWipSN.POST_CODE, CurWipSN.NODE_NAME,CurWipSN.STATUS.GetEnumDesc()); return action; } #endregion Functions public override bool Close(bool needSaveHistoryLog = false) { //needSaveHistoryLog = true; //保存操作日志 this.IsFinished = true; return IsFinished ? base.Close(needSaveHistoryLog) : IsFinished; } }//endClass }