| | |
| | | /// </summary> |
| | | /// <param name="input"></param> |
| | | /// <returns></returns> |
| | | public async Task<ApiAction> Submit(SubmitInput input) |
| | | public async Task<ApiAction<SubmitOutput>> Submit(SubmitInput input) |
| | | { |
| | | var action = new ApiAction(); |
| | | var action = new ApiAction<SubmitOutput>(new SubmitOutput()); |
| | | try |
| | | { |
| | | //工步列表为空时,认为需要先扫描过站条码 |
| | | if (Steps.IsNullOrEmpty()) |
| | | //工步列表为空或者工序节点工步有未完成时,优先完成工序节点工步 |
| | | if (Steps.IsNullOrEmpty() || !IsFinishNodeSteps) |
| | | { |
| | | //先判断当前工单不为空且当前岗位在当前工单是不是首站,如果是则不允许变更当前工单,尝试把条码绑定到当前工单 |
| | | if (!CurBatch.IsNullOrEmpty() && CurBatch.IsFirstNode(PostCode)) |
| | | { |
| | | action = ScanSn(action, input); |
| | | action = NodeSubmit(action, input); |
| | | return action; |
| | | } |
| | | //当前岗位在当前工单不是首站,则查找条码已绑定的工单当作当前工单 |
| | | else |
| | | { |
| | | var wosn = Biz.Db.Queryable<BIZ_MES_WO_BATCH, BIZ_MES_WO_SN>((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(); |
| | | var wosn = Biz.Db.Queryable<BIZ_MES_WO_BATCH, BIZ_MES_WO_SN>((q, s) => new JoinQueryInfos(JoinType.Inner, q.ORDER_NO == s.WORK_ORDER)) |
| | | .ByAuth(input.AuthOption) |
| | | .Where((q, s) => s.SN == input.SN && q.ACT_LINE == CurLine.LINE_CODE && (q.STATUS == BIZ_MES_WO_BATCH.STATUSs.Release.GetValue() || q.STATUS == BIZ_MES_WO_BATCH.STATUSs.Working.GetValue())) |
| | | .Select((q, s) => new { Batch = q, SN = s }).First(); |
| | | //查找到条码已绑定的工单 |
| | | if (!wosn.IsNullOrEmpty()) |
| | | { |
| | |
| | | var result = await SelectOrder(new() { AuthOption = input.AuthOption, OrderNo = wosn.Batch.ORDER_NO }); |
| | | if (!result.IsSuccessed) |
| | | { |
| | | action = result; |
| | | action.IsSuccessed = result.IsSuccessed; |
| | | action.LocaleMsg = result.LocaleMsg; |
| | | return action; |
| | | } |
| | | } |
| | | //条码过站 |
| | | action = ScanSn(action, input); |
| | | action = NodeSubmit(action, input); |
| | | return action; |
| | | } |
| | | //查找不到条码已绑定的工单 |
| | |
| | | } |
| | | } |
| | | //完成第一步,后开始执行当前工序的行为列表 |
| | | else if (Steps.First().IsFinished && !IsFinishAllSteps) |
| | | //完成工序节点工步后,后开始执行当前工序的行为工步 |
| | | else if (IsFinishNodeSteps && !IsFinishAllSteps) |
| | | { |
| | | var curStep = Steps.Where(q => q.ID == input.StepID).FirstOrDefault(); |
| | | if (!curStep.IsNullOrEmpty()) |
| | | var submitStep = Steps.Where(q => q.ID == input.CurStepID && !q.IsFinished).FirstOrDefault(); |
| | | if (submitStep.IsNullOrEmpty()) |
| | | { |
| | | var result = curStep.Submit(input); |
| | | result.Data.StepID = curStep.ID; |
| | | result.Data.IsFinished = IsFinishAllSteps; |
| | | result.Data.CurStep = CurStep; |
| | | action = BeginNextActionStep(input); |
| | | return action; |
| | | } |
| | | else |
| | | { |
| | | var result = submitStep.Submit(input); |
| | | //如果当前工步已完成,开始执行下一工步 |
| | | if (result.IsSuccessed && submitStep.IsFinished) |
| | | { |
| | | result = BeginNextActionStep(input); |
| | | } |
| | | //如果当前工步未完成 |
| | | else |
| | | { |
| | | //行为执行出错,工步被重置 |
| | | if (Steps.IsNullOrEmpty()) |
| | | { |
| | | result.LocaleMsg = new(Biz.T(result.LocaleMsg, input.Locale) + Biz.T(Biz.L("MES.Transaction.Position.RescanSN"), input.Locale)); |
| | | } |
| | | else |
| | | { |
| | | result.Data.IsFinished = IsFinishAllSteps; |
| | | result.Data.CurWO = CurBatch.WO.ORDER_NO; |
| | | result.Data.CurBatch = CurBatch.Batch.BATCH_NO; |
| | | result.Data.CurNode = CurStep?.NodeAct.ACT_NAME; |
| | | result.Data.StepActCode = CurStep?.NodeAct.ACT_CODE; |
| | | result.Data.NextStepID = CurStep?.ID; |
| | | } |
| | | } |
| | | //如果所有工步都完成 |
| | | if (IsFinishAllSteps) |
| | | { |
| | | return DoIfFinishAllSteps(result.ToApiAction()); |
| | | return DoIfFinishAllSteps(result); |
| | | } |
| | | return result.ToApiAction(); |
| | | return result; |
| | | } |
| | | } |
| | | //没有可执行的工步 |
| | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 扫描过站条码 |
| | | /// 工序节点工步提交数据 |
| | | /// </summary> |
| | | /// <param name="action"></param> |
| | | /// <param name="input"></param> |
| | | /// <returns></returns> |
| | | public ApiAction ScanSn(ApiAction action, SubmitInput input) |
| | | public ApiAction<SubmitOutput> NodeSubmit(ApiAction<SubmitOutput> 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<MES_WIP_DATA>().First(q => q.SN == input.SN && q.BATCH_NO == CurBatch.Batch.BATCH_NO) ?? new MES_WIP_DATA() |
| | | //判断工单实时状态判断 |
| | | var woStatus = CurBatch.CheckStatus(); |
| | | if (!woStatus.IsSuccessed) |
| | | { |
| | | return woStatus; |
| | | } |
| | | //非法过站防呆:进入工序时要增加判断条码是否按流程过站 |
| | | var wipSN = Biz.Db.Queryable<MES_WIP_DATA>().IncludesAllFirstLayer().First(q => q.SN == input.SN && q.WORK_ORDER == CurBatch.WO.ORDER_NO) ?? new MES_WIP_DATA() |
| | | { |
| | | SN = input.SN, |
| | | STATUS = MES_WIP_DATA.STATUSs.Init.GetValue(), |
| | |
| | | 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") |
| | | var canGotoNext = CurBatch.CanGotoNext(input, wipSN, curNode); |
| | | if (!canGotoNext.IsSuccessed) |
| | | { |
| | | 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; |
| | | return canGotoNext; |
| | | } |
| | | |
| | | 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) |
| | | //当工步列表为空,则执行当前工序的必要逻辑当作第一个工序节点,完成后按需求创建后续的工步列表 |
| | | if (Steps.IsNullOrEmpty()) |
| | | { |
| | | Sequence = Steps.Count + 1, |
| | | Node = curNode, |
| | | DBSubmitAction = () => |
| | | //绑定条码到工单 |
| | | if (!CurBatch.WoSNs.Any(q => q.SN == input.SN)) |
| | | { |
| | | var db = GetCommitDB(); |
| | | db.Storageable(woSN, UserCode).ExecuteCommand(); |
| | | db.Storageable(wipSN, UserCode).ExecuteCommand(); |
| | | db.Storageable(wipSnHis, UserCode).ExecuteCommand(); |
| | | CurBatch.WoSNs.Add(new() |
| | | { |
| | | WORK_ORDER = CurBatch.Batch.ORDER_NO, |
| | | SN = input.SN, |
| | | STATUS = BIZ_MES_WO_SN.STATUSs.NotInput.GetValue(), |
| | | }); |
| | | } |
| | | }; |
| | | Steps.Add(curStep); |
| | | var woSN = CurBatch.WoSNs.First(q => q.SN == input.SN); |
| | | woSN.AUTH_ORG = CurBatch.WO.AUTH_ORG; |
| | | woSN.AUTH_PROD = CurLine.LINE_CODE; |
| | | woSN.BATCH_NO = CurBatch.Batch.BATCH_NO; |
| | | |
| | | //如果当前工序节点有行为则添加到工步列表 |
| | | 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) |
| | | //条码过站 |
| | | wipSN.AUTH_ORG = CurBatch.WO.AUTH_ORG; |
| | | 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; |
| | | var curShiftPeriod = GetShiftPeriodForNow(); |
| | | if (!curShiftPeriod.IsNullOrEmpty()) |
| | | { |
| | | wipSN.SFTS_CODE = curShiftPeriod.ShiftSys.SFTS_CODE; |
| | | wipSN.SFT_CODE = curShiftPeriod.Shift.SFT_CODE; |
| | | wipSN.PRD_CODE = curShiftPeriod.Period.PRD_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; |
| | | } |
| | | |
| | | CurWipSNHis = new MES_WIP_HIS(CurWipSN = wipSN, $"工单[{wipSN.WORK_ORDER}]条码[{wipSN.SN}]在岗位[{wipSN.POST_CODE}]过站工序[{wipSN.NODE_NAME}]成功"); |
| | | |
| | | //初始化工步列表 |
| | | Steps.Clear(); |
| | | var curStep = new Biz.WorkStep(IWorkStep.Types.Node, this) |
| | | { |
| | | NodeID = curNode.ID, |
| | | Sequence = Steps.Count + 1, |
| | | Node = curNode, |
| | | NodeAct = act, |
| | | Setting = CurBatch.ActionSets.FirstOrDefault(q => q.ACT_ID == act.ID), |
| | | }); |
| | | DBSubmitAction = () => |
| | | { |
| | | var db = GetCommitDB(); |
| | | db.Storageable(woSN, UserCode).ExecuteCommand(); |
| | | db.Storageable(wipSN, UserCode).ExecuteCommand(); |
| | | db.Storageable(CurWipSNHis, UserCode).ExecuteCommand(); |
| | | } |
| | | }; |
| | | Steps.Add(curStep); |
| | | |
| | | //有需要用户提交信息则添加工序节点的其他工步 |
| | | |
| | | //最后添加当前工序的行为工步 |
| | | GenerateSteps(curStep); |
| | | |
| | | //完成第一个工序节点工步 |
| | | curStep.IsFinished = true; |
| | | CurStep = curStep; |
| | | } |
| | | else if (!IsFinishNodeSteps) |
| | | { |
| | | var curStep = Steps.Where(q => q.Type == IWorkStep.Types.Node && !q.IsFinished).OrderBy(q => q.Sequence).First(); |
| | | |
| | | //完成当前工序节点工步 |
| | | curStep.IsFinished = true; |
| | | CurStep = curStep; |
| | | } |
| | | |
| | | //未完成所有工步 |
| | | 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(); |
| | | var result = new ApiAction<SubmitOutput>(new SubmitOutput()); |
| | | //未完成所有工序节点工步 |
| | | if (!IsFinishNodeSteps) |
| | | { |
| | | var next = Steps.Where(q => q.Type == IWorkStep.Types.Node && !q.IsFinished).OrderBy(q => q.Sequence).First(); |
| | | //设置后续可执行的工步列表 |
| | | NextSteps.Clear(); |
| | | NextSteps.Add(next); |
| | | //根据后续工步返回ApiAction |
| | | result.Data.IsFinished = IsFinishAllSteps; |
| | | result.Data.CurWO = CurBatch.WO.ORDER_NO; |
| | | result.Data.CurBatch = CurBatch.Batch.BATCH_NO; |
| | | result.Data.CurNode = CurStep?.Node.NODE_NAME; |
| | | result.Data.NextStepID = next.ID; |
| | | |
| | | //根据工序节点工步的序号返回相应的操作提示 |
| | | switch (next.Sequence) |
| | | { |
| | | case 2: |
| | | //action.LocaleMsg = new($"请执行第二步"); |
| | | result.LocaleMsg = new("MES.Transaction.TestNode.第二步操作提示"); |
| | | break; |
| | | default: |
| | | break; |
| | | } |
| | | } |
| | | //已完成所有工序节点工步,开始执行行为工步 |
| | | else |
| | | { |
| | | result = BeginNextActionStep(input); |
| | | } |
| | | return result; |
| | | } |
| | | //已完成所有工步 |
| | | else |
| | | { |
| | | action.Data.IsFinished = IsFinishAllSteps; |
| | | action.Data.CurWO = CurBatch.WO.ORDER_NO; |
| | | action.Data.CurBatch = CurBatch.Batch.BATCH_NO; |
| | | action.Data.CurNode = CurStep?.Node.NODE_NAME; |
| | | action.Data.NextStepID = ""; |
| | | action = DoIfFinishAllSteps(action); |
| | | } |
| | | } |
| | |
| | | /// </summary> |
| | | /// <param name="action"></param> |
| | | /// <returns></returns> |
| | | public ApiAction DoIfFinishAllSteps(ApiAction action) |
| | | public ApiAction<SubmitOutput> DoIfFinishAllSteps(ApiAction<SubmitOutput> action) |
| | | { |
| | | //保存数据库 |
| | | var dbTran = GetCommitDB().UseTran(() => |