| | |
| | | using Tiger.IBusiness; |
| | | using Tiger.Model.Entitys.MES.Position; |
| | | using Tiger.Business.MES; |
| | | using static Microsoft.CodeAnalysis.CSharp.SyntaxTokenParser; |
| | | using Org.BouncyCastle.Ocsp; |
| | | |
| | | namespace Tiger.Business |
| | | { |
| | |
| | | public WorkBatch Init(string lineCode) |
| | | { |
| | | LineCode = lineCode; |
| | | WO = Biz.Db.Queryable<BIZ_MES_WO>().Where(q => q.ORDER_NO == OrderNo).IncludesAllFirstLayer().First(); |
| | | Batch = Biz.Db.Queryable<BIZ_MES_WO_BATCH>().Where(q => q.ORDER_NO == OrderNo && q.ACT_LINE == LineCode && |
| | | (q.STATUS == BIZ_MES_WO_BATCH.STATUSs.Release.GetValue() || q.STATUS == BIZ_MES_WO_BATCH.STATUSs.Working.GetValue())).First(); |
| | | GetBatchInfo(); |
| | | return this; |
| | | } |
| | | |
| | | public void Update() |
| | | public void Update(bool updateAll = false) |
| | | { |
| | | if (!WoContext.WoBatchDic.ContainsKey(Batch.BATCH_NO)) |
| | | var wo = Biz.Db.Queryable<BIZ_MES_WO>().Where(q => q.ORDER_NO == OrderNo).IncludesAllFirstLayer().First(); |
| | | var batch = Biz.Db.Queryable<BIZ_MES_WO_BATCH>().Where(q => q.BATCH_NO == Batch.BATCH_NO).First(); |
| | | if (WoContext.WoBatchDic.ContainsKey(batch.BATCH_NO)) |
| | | { |
| | | if (wo.STATUS < BIZ_MES_WO.STATUSs.Release.GetValue() || batch.STATUS > BIZ_MES_WO_BATCH.STATUSs.Working.GetValue()) |
| | | { |
| | | WoContext.WoBatchDic.Remove(Batch.BATCH_NO); |
| | | } |
| | | else if(updateAll || wo.UPDATE_TIME > WO.UPDATE_TIME || batch.UPDATE_TIME > Batch.UPDATE_TIME) |
| | | { |
| | | GetBatchInfo(); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | GetBatchInfo(); |
| | | WoContext.WoBatchDic.Add(Batch.BATCH_NO, this); |
| | | WoContext.WoBatchDic.Add(batch.BATCH_NO, this); |
| | | } |
| | | WO = wo; |
| | | Batch = batch; |
| | | } |
| | | |
| | | private void GetBatchInfo() |
| | | { |
| | | WO = Biz.Db.Queryable<BIZ_MES_WO>().Where(q => q.ORDER_NO == OrderNo).IncludesAllFirstLayer().First(); |
| | | Product = Biz.Db.Queryable<BAS_ITEM>().Where(q => q.ITEM_CODE == WO.ITEM_CODE && q.AUTH_ORG == WO.AUTH_ORG).IncludesAllFirstLayer().First(); |
| | | Batch = Biz.Db.Queryable<BIZ_MES_WO_BATCH>().Where(q => q.ORDER_NO == OrderNo && q.ACT_LINE == LineCode && |
| | | (q.STATUS == BIZ_MES_WO_BATCH.STATUSs.Release.GetValue() || q.STATUS == BIZ_MES_WO_BATCH.STATUSs.Working.GetValue())).First(); |
| | | Customer = Biz.Db.Queryable<BAS_CUSTOMER>().Where(q => q.CUST_CODE == WO.CUST_CODE).First(); |
| | | WoSNs = Biz.Db.Queryable<BIZ_MES_WO_SN>().Where(q => q.WORK_ORDER == OrderNo).ToList(); |
| | | Edges = Biz.Db.Queryable<MES_WO_EDGE>().Where(q => q.WORK_ORDER == OrderNo).ToList(); |
| | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 添加节点的下一个行为到工步列表 |
| | | /// 递归遍历工序节点,给下级工序节点排序和整理前置工序 |
| | | /// </summary> |
| | | /// <param name="parent"></param> |
| | | private void NodeSorting(MES_WO_NODE parent) |
| | |
| | | /// </summary> |
| | | /// <param name="curNode"></param> |
| | | /// <returns></returns> |
| | | public ApiAction<SubmitOutput> CheckCanProduce(MES_WO_NODE curNode) |
| | | public ApiAction<SubmitOutput> CheckCanProduce(MES_WO_NODE curNode, MES_WO_OPER curNodeSetting) |
| | | { |
| | | var action = new ApiAction<SubmitOutput>(new SubmitOutput(), true); |
| | | |
| | | WO = Biz.Db.Queryable<BIZ_MES_WO>().Where(q => q.ORDER_NO == OrderNo).IncludesAllFirstLayer().First(); |
| | | Batch = Biz.Db.Queryable<BIZ_MES_WO_BATCH>().Where(q => q.ORDER_NO == OrderNo && q.ACT_LINE == LineCode).First(); |
| | | Update(); |
| | | |
| | | //工单批次状态不是已下发或者生产中,则不允许生产 |
| | | if (Batch.STATUS != BIZ_MES_WO_BATCH.STATUSs.Release.GetValue() && Batch.STATUS != BIZ_MES_WO_BATCH.STATUSs.Working.GetValue()) |
| | | { |
| | | action.IsSuccessed = false; |
| | | action.Data.SetValue(this, null); |
| | | //action.LocaleMsg = new($"工单批次[{Batch.BATCH_NO}]状态[{Batch.STATUS.GetEnum<BIZ_MES_WO_BATCH.STATUSs>().GetName()}]不是允许生产的状态,请扫描允许生产的产品条码"); |
| | | action.LocaleMsg = new("MES.WorkBatch.WoBatchStatusCanNotWork", Batch.BATCH_NO, Batch.STATUS.GetEnum<BIZ_MES_WO_BATCH.STATUSs>().GetName()); |
| | | action.LocaleMsg = new("MES.WorkBatch.WoBatchStatusCanNotWork", Batch.BATCH_NO, Batch.STATUS.GetEnumDesc<BIZ_MES_WO_BATCH.STATUSs>()); |
| | | } |
| | | //工单状态不是已下发或者生产中,则不允许生产 |
| | | if (WO.STATUS != BIZ_MES_WO.STATUSs.Release.GetValue() && WO.STATUS != BIZ_MES_WO.STATUSs.Working.GetValue()) |
| | |
| | | action.IsSuccessed = false; |
| | | action.Data.SetValue(this, null); |
| | | //action.LocaleMsg = new($"工单[{WO.ORDER_NO}]状态[{Batch.STATUS.GetEnum<BIZ_MES_WO.STATUSs>().GetName()}]不是允许生产的状态,请扫描允许生产的产品条码"); |
| | | action.LocaleMsg = new("MES.WorkBatch.WoStatusCanNotWork", WO.ORDER_NO, Batch.STATUS.GetEnum<BIZ_MES_WO.STATUSs>().GetName()); |
| | | action.LocaleMsg = new("MES.WorkBatch.WoStatusCanNotWork", WO.ORDER_NO, Batch.STATUS.GetEnumDesc<BIZ_MES_WO.STATUSs>()); |
| | | } |
| | | //工单批次投入数量减去报废数量如果大于等于计划数量,则不允许生产 |
| | | //if (curNode.IS_INPUT == "Y" && Batch.INPUT_QTY - Batch.SCRAP_QTY >= Batch.PLAN_QTY) |
| | | if (curNode.IS_INPUT == "Y" && WoSNs.Count(q => q.STATUS > BIZ_MES_WO_SN.STATUSs.NotInput.GetValue() && q.BATCH_NO == Batch.BATCH_NO) - Batch.SCRAP_QTY >= Batch.PLAN_QTY) |
| | | if (curNode.IS_FIRST_NODE == "Y" && WoSNs.Count(q => q.BATCH_NO == Batch.BATCH_NO && BIZ_MES_WO_SN.STATUSs.NotInput.GetValue() < q.STATUS && q.STATUS <= BIZ_MES_WO_SN.STATUSs.Finished.GetValue()) >= Batch.PLAN_QTY) |
| | | { |
| | | action.IsSuccessed = false; |
| | | action.Data.SetValue(this, null); |
| | | //action.LocaleMsg = new($"工单批次[{0}]已投入 {1},其中报废 {2},以满足计划数量[{3}],无需继续投入"); |
| | | action.LocaleMsg = new("MES.WorkBatch.BatchInputEnough", Batch.BATCH_NO, WoSNs.Count(q => q.BATCH_NO == Batch.BATCH_NO), Batch.SCRAP_QTY, Batch.PLAN_QTY); |
| | | action.LocaleMsg = new("MES.WorkBatch.BatchInputEnough", Batch.BATCH_NO, WoSNs.Count(q => q.BATCH_NO == Batch.BATCH_NO), WoSNs.Count(q => q.BATCH_NO == Batch.BATCH_NO && q.STATUS > BIZ_MES_WO_SN.STATUSs.Finished.GetValue()), Batch.PLAN_QTY); |
| | | } |
| | | //工单投入数量减去报废数量如果大于等于计划数量,则不允许生产 |
| | | if (curNode.IS_INPUT == "Y" && WoSNs.Count(q => q.STATUS > BIZ_MES_WO_SN.STATUSs.NotInput.GetValue() && q.WORK_ORDER == WO.ORDER_NO) - WO.SCRAP_QTY >= WO.PLAN_QTY) |
| | | if (curNode.IS_FIRST_NODE == "Y" && WoSNs.Count(q =>q.WORK_ORDER == WO.ORDER_NO && BIZ_MES_WO_SN.STATUSs.NotInput.GetValue() < q.STATUS && q.STATUS <= BIZ_MES_WO_SN.STATUSs.Finished.GetValue()) >= WO.PLAN_QTY) |
| | | { |
| | | action.IsSuccessed = false; |
| | | action.Data.SetValue(this, null); |
| | | //action.LocaleMsg = new($"工单[{0}]已投入 {1},其中报废 {2},以满足计划数量[{3}],无需继续投入"); |
| | | action.LocaleMsg = new("MES.WorkBatch.WoInputEnough", WO.ORDER_NO, WoSNs.Count(q => q.WORK_ORDER == WO.ORDER_NO), WO.SCRAP_QTY, WO.PLAN_QTY); |
| | | action.LocaleMsg = new("MES.WorkBatch.WoInputEnough", WO.ORDER_NO, WoSNs.Count(q => q.WORK_ORDER == WO.ORDER_NO), WoSNs.Count(q => q.WORK_ORDER == WO.ORDER_NO && q.STATUS > BIZ_MES_WO_SN.STATUSs.Finished.GetValue()), WO.PLAN_QTY); |
| | | } |
| | | |
| | | return action; |
| | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 检查工单是否完工,已完工则修改相应状态并记录到数据库 |
| | | /// </summary> |
| | | /// <param name="user"></param> |
| | | /// <returns></returns> |
| | | public async Task<bool> CheckIsComplete(string user) |
| | | { |
| | | var woSNs = Biz.Db.Queryable<BIZ_MES_WO_SN>().Where(q => q.WORK_ORDER == OrderNo).ToList(); |
| | | |
| | | //判断当前工单批次是否已完工 |
| | | if (!woSNs.Any(q => q.BATCH_NO == Batch.BATCH_NO && q.STATUS < BIZ_MES_WO_SN.STATUSs.Finished.GetValue()) && |
| | | woSNs.Count(q => q.BATCH_NO == Batch.BATCH_NO && q.STATUS == BIZ_MES_WO_SN.STATUSs.Finished.GetValue()) == Batch.PLAN_QTY) |
| | | { |
| | | Batch.STATUS = BIZ_MES_WO_BATCH.STATUSs.Closed.GetValue(); |
| | | Batch.ACT_END_TIME = DateTime.Now; |
| | | } |
| | | |
| | | //判断当前工单是否已完工 |
| | | if (!woSNs.Any(q => q.STATUS < BIZ_MES_WO_SN.STATUSs.Finished.GetValue()) && |
| | | woSNs.Count(q => q.STATUS == BIZ_MES_WO_SN.STATUSs.Finished.GetValue()) == WO.PLAN_QTY) |
| | | { |
| | | WO.STATUS = BIZ_MES_WO.STATUSs.Closed.GetValue(); |
| | | WO.ACT_END_TIME = DateTime.Now; |
| | | } |
| | | |
| | | //保存数据库 |
| | | var db = Biz.Db; |
| | | var dbTran = db.UseTran(() => |
| | | { |
| | | db.Updateable(WO, user).UpdateColumns(q => new { q.UPDATE_TIME, q.UPDATE_USER, q.STATUS, q.ACT_END_TIME }).ExecuteCommand(); |
| | | db.Updateable(Batch, user).UpdateColumns(q => new { q.UPDATE_TIME, q.UPDATE_USER, q.STATUS, q.ACT_END_TIME }).ExecuteCommand(); |
| | | }); |
| | | if (!dbTran.IsSuccess) |
| | | { |
| | | //throw dbTran.ErrorException; |
| | | Logger.Default.Fatal(dbTran.ErrorException, $"检查工单批次[{Batch.BATCH_NO}]是否完工异常"); |
| | | return false; |
| | | } |
| | | //删除缓存 |
| | | if (Batch.STATUS == BIZ_MES_WO_BATCH.STATUSs.Closed.GetValue()) |
| | | { |
| | | WoContext.WoBatchDic.Remove(Batch.BATCH_NO); |
| | | } |
| | | if (WO.STATUS == BIZ_MES_WO.STATUSs.Closed.GetValue()) |
| | | { |
| | | var list = WoContext.WoBatchDic.Where(q => q.Value.WO.ORDER_NO == OrderNo).Select(q => q.Key); |
| | | foreach (var item in list) |
| | | { |
| | | WoContext.WoBatchDic.Remove(item); |
| | | } |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 根据岗位编码判断是不是首站 |
| | | /// </summary> |
| | | /// <param name="postCode"></param> |
| | |
| | | public MES_WO_NODE GetNode(string postCode) |
| | | { |
| | | return Nodes.FirstOrDefault(q => NodePosts.Any(p => p.NODE_ID == q.ID && p.POST_CODE == postCode)); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 根据工序节点返回工序节点设置 |
| | | /// </summary> |
| | | /// <param name="postCode"></param> |
| | | /// <returns></returns> |
| | | public MES_WO_OPER GetNodeSetting(MES_WO_NODE node) |
| | | { |
| | | return NodeSets.FirstOrDefault(q => q.NODE_ID == node?.ID); |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | action.IsSuccessed = false; |
| | | action.Data.SetValue(this, null); |
| | | var nextList = Nodes.Where(q => q.IS_FIRST_NODE == "Y"); |
| | | action.LocaleMsg = new("MES.WorkBatch.GotoNextNodeException", input.SN, nextNode.NODE_NAME, string.Join(", ", nextList.Select(q => q.NODE_NAME + (q.CAN_SKIP == "Y" ? $"({Biz.T(Biz.L("MES.WorkBatch.Optional"), input.Locale)})" : "")))); |
| | | action.LocaleMsg = new("MES.WorkBatch.GotoNextNodeException", input.SN, nextNode.NODE_NAME, string.Join(", ", nextList.Select(q => q.NODE_NAME + (GetNodeSetting(q)?.CAN_SKIP == "Y" ? $"({Biz.T(Biz.L("MES.WorkBatch.Optional"), input.Locale)})" : "")))); |
| | | return action; |
| | | } |
| | | } |
| | |
| | | action.IsSuccessed = false; |
| | | action.Data.SetValue(this, null); |
| | | var nextList = reflowNodes.Where(q => wipSN.REFLOW_NODE.IsNullOrEmpty() || wipSN.REFLOW_NODE == q.NODE_NAME); |
| | | action.LocaleMsg = new("MES.WorkBatch.ReflowToNodeException", nextNode.NODE_NAME, input.SN, curNode.NODE_NAME, string.Join(", ", nextList.Select(q => q.NODE_NAME + (q.CAN_SKIP == "Y" ? $"({Biz.T(Biz.L("MES.WorkBatch.Optional"), input.Locale)})" : "")))); |
| | | action.LocaleMsg = new("MES.WorkBatch.ReflowToNodeException", nextNode.NODE_NAME, input.SN, curNode.NODE_NAME, string.Join(", ", nextList.Select(q => q.NODE_NAME + (GetNodeSetting(q)?.CAN_SKIP == "Y" ? $"({Biz.T(Biz.L("MES.WorkBatch.Optional"), input.Locale)})" : "")))); |
| | | return action; |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | //如果当前工序有必须执行的后续工序,则报错 |
| | | if (nextNodes.Any(q => NodeSets.Any(s => s.NODE_ID == q.ID && s.IS_ACTIVE == "Y" && s.CAN_SKIP != "Y"))) |
| | | if (nextNodes.Any(q => q.OPER_CODE != "EndNode" && NodeSets.Any(s => s.NODE_ID == q.ID && s.IS_ACTIVE == "Y" && s.CAN_SKIP != "Y"))) |
| | | { |
| | | action.IsSuccessed = false; |
| | | action.Data.SetValue(this, null); |
| | | var nextList = nextNodes.Where(q => NodeSets.Any(s => s.NODE_ID == q.ID && s.IS_ACTIVE == "Y" && s.CAN_SKIP != "Y")); |
| | | action.LocaleMsg = new("MES.WorkBatch.GotoNextNodeException", input.SN, nextNode.NODE_NAME, string.Join(", ", nextList.Select(q => q.NODE_NAME + (q.CAN_SKIP == "Y" ? $"({Biz.T(Biz.L("MES.WorkBatch.Optional"), input.Locale)})" : "")))); |
| | | action.LocaleMsg = new("MES.WorkBatch.GotoNextNodeException", input.SN, nextNode.NODE_NAME, string.Join(", ", nextList.Select(q => q.NODE_NAME + (GetNodeSetting(q)?.CAN_SKIP == "Y" ? $"({Biz.T(Biz.L("MES.WorkBatch.Optional"), input.Locale)})" : "")))); |
| | | return action; |
| | | } |
| | | //如果当前工序没有必须执行的后续工序,则在前置工序查找还有没有后续工序没完成的工序,有则尝试执行 |
| | |
| | | { |
| | | //在前置工序查找还有没有后续工序没完成的前置工序 |
| | | var prepIDs = curNode.PrepNodeIDs.Where(id => |
| | | Edges.Any(e => e.SRC_NODE == id && !wipSN.History.Any(h => h.WORK_ORDER == WO.ORDER_NO && h.NODE_ID == e.TGT_NODE && h.IsFinished)) |
| | | Edges.Any(e => e.SRC_NODE == id && !wipSN.History.Any(h => h.WORK_ORDER == WO.ORDER_NO && h.UNBIND_FLAG != "Y" && h.NODE_ID == e.TGT_NODE && h.IsFinished)) |
| | | ).ToList(); |
| | | foreach (var prepID in prepIDs) |
| | | { |
| | |
| | | action.IsSuccessed = false; |
| | | action.Data.SetValue(this, null); |
| | | var nextList = nextNodes.Where(q => NodeSets.Any(s => s.NODE_ID == q.ID && s.IS_ACTIVE == "Y")); |
| | | action.LocaleMsg = new("MES.WorkBatch.GotoNextNodeException", input.SN, nextNode.NODE_NAME, string.Join(", ", nextList.Select(q => q.NODE_NAME + (q.CAN_SKIP == "Y" ? $"({Biz.T(Biz.L("MES.WorkBatch.Optional"), input.Locale)})" : "")))); |
| | | action.LocaleMsg = new("MES.WorkBatch.GotoNextNodeException", input.SN, nextNode.NODE_NAME, string.Join(", ", nextList.Select(q => q.NODE_NAME + (GetNodeSetting(q)?.CAN_SKIP == "Y" ? $"({Biz.T(Biz.L("MES.WorkBatch.Optional"), input.Locale)})" : "")))); |
| | | return action; |
| | | } |
| | | } |
| | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 添加节点的下一个可执行节点 |
| | | /// 获取节点的下一个可执行节点(排除有前置工序未完成的节点) |
| | | /// </summary> |
| | | /// <param name="parent"></param> |
| | | /// <param name="wipSN">当前的条码过站记录,需要导航查询生产过程记录信息</param> |
| | |
| | | var result = new List<MES_WO_NODE>(); |
| | | var nextNodes = Nodes.Where(q => q.Operation.OPER_TYPE != MES_OPERATION.OPER_TYPEs.Repair.GetValue() |
| | | && Edges.Any(e => e.SRC_NODE == parent.ID && e.TGT_NODE == q.ID) |
| | | && !wipSN.History.Any(h => h.WORK_ORDER == WO.ORDER_NO && h.NODE_ID == q.ID && h.IsFinished) |
| | | && !wipSN.History.Any(h => h.WORK_ORDER == WO.ORDER_NO && h.UNBIND_FLAG != "Y" && h.NODE_ID == q.ID && h.IsFinished) |
| | | ).ToList(); |
| | | //尝试将当前工序的后续工序添加到可以执行的工序列表 |
| | | foreach (var next in nextNodes) |
| | | { |
| | | //查找有没有前置工序找不到已良品过站的历史记录,若有则不允许继续执行 |
| | | if (!next.PrepNodeIDs.Any(id => !wipSN.History.Any(h => h.WORK_ORDER == WO.ORDER_NO && h.NODE_ID == id && h.IsFinished)) || parent.IS_FIRST_NODE == "Y") |
| | | if (!next.PrepNodeIDs.Any(id => !wipSN.History.Any(h => h.WORK_ORDER == WO.ORDER_NO && h.UNBIND_FLAG != "Y" && h.NODE_ID == id && h.IsFinished)) || parent.IS_FIRST_NODE == "Y") |
| | | { |
| | | var setting = NodeSets.FirstOrDefault(q => q.NODE_ID == next.ID); |
| | | //后续工序是启用的,则添加 |
| | |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 根据传入的条码返回下一站可进入进入的目标工序 |
| | | /// 根据传入的条码返回下一站可进入的目标工序 |
| | | /// </summary> |
| | | /// <param name="wipSN">当前的条码过站记录,需要导航查询生产过程记录和生产不良记录信息</param> |
| | | /// <returns></returns> |
| | |
| | | { |
| | | //在前置工序查找还有没有后续工序没完成的前置工序 |
| | | var prepIDs = curNode.PrepNodeIDs.Where(id => |
| | | Edges.Any(e => e.SRC_NODE == id && !wipSN.History.Any(h => h.WORK_ORDER == WO.ORDER_NO && h.NODE_ID == e.TGT_NODE && h.IsFinished)) |
| | | Edges.Any(e => e.SRC_NODE == id && !wipSN.History.Any(h => h.WORK_ORDER == WO.ORDER_NO && h.UNBIND_FLAG != "Y" && h.NODE_ID == e.TGT_NODE && h.IsFinished)) |
| | | ).ToList(); |
| | | foreach (var prepID in prepIDs) |
| | | { |
| | |
| | | return result; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 从工单中移除正在生产的条码 |
| | | /// </summary> |
| | | /// <param name="wipList"></param> |
| | | /// <returns></returns> |
| | | public ApiAction RemoveWipSn(List<MES_WIP_DATA> wipList, string user) |
| | | { |
| | | var action = UnbindWipSnFromWO(WO, wipList, user); |
| | | //移除成功则处理工单缓存中的数据 |
| | | if (action.IsSuccessed) |
| | | { |
| | | Update(true); |
| | | } |
| | | |
| | | return action; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 从工单中解绑正在生产的条码 |
| | | /// </summary> |
| | | /// <param name="wo"></param> |
| | | /// <param name="wipList"></param> |
| | | /// <returns></returns> |
| | | public static ApiAction UnbindWipSnFromWO(BIZ_MES_WO wo, List<MES_WIP_DATA> wipList, string user) |
| | | { |
| | | var action = new ApiAction(); |
| | | |
| | | var wipIDs = wipList.Select(q => q.ID); |
| | | var batchs = wipList.Where(q => !q.BATCH_NO.IsNullOrEmpty()).GroupBy(q => new { q.BATCH_NO }).Select(g => new { |
| | | g.Key.BATCH_NO, |
| | | Qty = g.Count(), |
| | | FinishQty = g.Count(q => q.STATUS == MES_WIP_DATA.STATUSs.Finished.GetValue()), |
| | | }); |
| | | var db = Biz.Db; |
| | | var dbTran = db.UseTran(() => |
| | | { |
| | | //BIZ_MES_WO |
| | | wo.INPUT_QTY -= wipList.Count; |
| | | wo.OUTPUT_QTY -= wipList.Count(q => q.STATUS == MES_WIP_DATA.STATUSs.Finished.GetValue()); |
| | | wo.SCRAP_QTY += wipList.Count; |
| | | db.Updateable(wo, user).UpdateColumns(q => new { q.INPUT_QTY, q.OUTPUT_QTY, q.SCRAP_QTY, q.UPDATE_USER, q.UPDATE_TIME }).ExecuteCommand(); |
| | | //BIZ_MES_WO_BATCH |
| | | foreach (var batch in batchs) |
| | | { |
| | | db.Updateable<BIZ_MES_WO_BATCH>(user) |
| | | .SetColumns(q => q.INPUT_QTY == q.INPUT_QTY - batch.Qty) |
| | | .SetColumns(q => q.OUTPUT_QTY == q.OUTPUT_QTY - batch.FinishQty) |
| | | .SetColumns(q => q.SCRAP_QTY == q.SCRAP_QTY + batch.Qty) |
| | | .Where(q => q.BATCH_NO == q.BATCH_NO) |
| | | .ExecuteCommand(); |
| | | } |
| | | //BIZ_MES_WO_SN |
| | | db.Updateable<BIZ_MES_WO_SN>(user) |
| | | .SetColumns(q => q.STATUS == BIZ_MES_WO_SN.STATUSs.Offline.GetValue()) |
| | | .Where(q => q.WORK_ORDER == wo.ORDER_NO && wipIDs.Contains(q.WIP_ID)) |
| | | .ExecuteCommand(); |
| | | //MES_WIP_DATA & MES_WIP_HIS |
| | | var wipHiss = new List<MES_WIP_HIS>(); |
| | | foreach (var wipSN in wipList.Where(q => q.STATUS != MES_WIP_DATA.STATUSs.Offline.GetValue())) |
| | | { |
| | | wipSN.STATUS = MES_WIP_DATA.STATUSs.Offline.GetValue(); |
| | | wipSN.UNBIND_FLAG = "Y"; |
| | | wipSN.NODE_ID = ""; |
| | | wipSN.NODE_NAME = "下线退库"; |
| | | wipSN.OPERATION_TIME = DateTime.Now; |
| | | var his = new MES_WIP_HIS(wipSN, $"工单[{wipSN.WORK_ORDER}]条码[{wipSN.SN}]下线"); |
| | | wipHiss.Add(his); |
| | | } |
| | | db.Storageable(wipList, user).ExecuteCommand(); |
| | | db.Storageable(wipHiss, user).ExecuteCommand(); |
| | | db.Updateable<MES_WIP_HIS>(user) |
| | | .SetColumns(q => q.UNBIND_FLAG == "Y") |
| | | .Where(q => q.WORK_ORDER == wo.ORDER_NO && wipIDs.Contains(q.WIP_ID)) |
| | | .ExecuteCommand(); |
| | | //MES_WIP_PKG |
| | | var curpkg = db.Queryable<MES_WIP_PKG>().Where(q => wipIDs.Contains(q.WIP_ID)).ToList(); |
| | | db.Deleteable(curpkg).ExecuteCommand(); |
| | | var pkgs = new List<MES_WIP_PKG>(); |
| | | do |
| | | { |
| | | var parentSns = curpkg.Where(q => !q.PARENT_SN.IsNullOrEmpty()).Select(q => q.PARENT_SN).Distinct(); |
| | | curpkg = db.Queryable<MES_WIP_PKG>().Where(q => parentSns.Contains(q.SN)).ToList(); |
| | | foreach (var pkg in curpkg) |
| | | { |
| | | pkg.QTY = db.Queryable<MES_WIP_PKG>().Where(q => q.PARENT_SN == pkg.SN).Sum(q => q.QTY); |
| | | pkgs.Add(pkg); |
| | | } |
| | | } |
| | | while (curpkg.Any()); |
| | | db.Updateable(curpkg, user).ExecuteCommand(); |
| | | //MES_WIP_DFT,在上仓库装配和维修之前,先把不良记录标记为已处理 |
| | | db.Updateable<MES_WIP_DFT>(user) |
| | | .SetColumns(q => q.STATUS == MES_WIP_DFT.STATUSs.Resolved.GetValue()) |
| | | .Where(q => q.WORK_ORDER == wo.ORDER_NO && wipIDs.Contains(q.WIP_ID)) |
| | | .ExecuteCommand(); |
| | | }); |
| | | if (!dbTran.IsSuccess) |
| | | { |
| | | //抛出异常 |
| | | throw dbTran.ErrorException; |
| | | } |
| | | |
| | | return action; |
| | | } |
| | | #endregion |
| | | |
| | | /// <summary> |