服务端的TigerApi 框架,基于.NET6 2024 版本
Rodney Chen
2024-08-15 cf2d2398c62f5e13049d3ee92ffc12aa79cbfee5
WoContext增加获取SN的下一个工序节点列表方法
已修改4个文件
138 ■■■■■ 文件已修改
Tiger.Api/Language.db 补丁 | 查看 | 原始文档 | blame | 历史
Tiger.Business/MES/Biz.WorkBatch.cs 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tiger.Business/MES/WoContext.cs 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tiger.Model.Net/Entitys/MES/BIZ_MES_WO_SN.cs 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tiger.Api/Language.db
Binary files differ
Tiger.Business/MES/Biz.WorkBatch.cs
@@ -6,7 +6,6 @@
using System.Text;
using System.Threading.Tasks;
using Rhea.Common;
using System.Net;
using System.Linq;
using Tiger.IBusiness;
using Tiger.Business.MES;
@@ -225,7 +224,7 @@
            /// 根据传入的条码过站信息和下一站的目标工序,判断条码是否能进入下一站
            /// </summary>
            /// <param name="input">本次提交的数据</param>
            /// <param name="wipSN">当前的条码过站记录</param>
            /// <param name="wipSN">当前的条码过站记录,需要导航查询生产过程记录信息</param>
            /// <param name="nextNode">要进入的目标工序</param>
            /// <returns></returns>
            public ApiAction<SubmitOutput> CanGotoNext(SubmitInput input, MES_WIP_DATA wipSN, MES_WO_NODE nextNode)
@@ -254,6 +253,7 @@
                {
                    var curNode = Nodes.First(q => q.ID == wipSN.NODE_ID);
                    var curSetting = NodeSets.FirstOrDefault(q => q.NODE_ID == curNode.ID);
                    var nextSetting = NodeSets.FirstOrDefault(q => q.NODE_ID == nextNode.ID);
                    //进入维修:如果目标工序是维修工序则判断当前条码在本工单有未维修的不良记录且当前工序节点有连线到维修工序,则允许进入维修工序
                    if (nextNode.Operation.OPER_TYPE == MES_OPERATION.OPER_TYPEs.Repair.GetValue()
                        && wipSN.Defects.Any(q => q.WORK_ORDER == WO.ORDER_NO && q.STATUS < MES_WIP_DFT.STATUSs.Resolved.GetValue())
@@ -286,7 +286,7 @@
                    }
                    //不良品入站:如果产品有不良记录且目标工序不是维修工序且不允许不良品入站,则报错
                    else if (wipSN.Defects.Any(q => q.WORK_ORDER == WO.ORDER_NO && q.STATUS < MES_WIP_DFT.STATUSs.Resolved.GetValue()) 
                         && curSetting.ALLOW_DFT_IN != "Y" && nextNode.Operation.OPER_TYPE != MES_OPERATION.OPER_TYPEs.Repair.GetValue())
                         && nextSetting.ALLOW_DFT_IN != "Y" && nextNode.Operation.OPER_TYPE != MES_OPERATION.OPER_TYPEs.Repair.GetValue())
                    {
                        action.IsSuccessed = false;
                        action.Data.SetValue(this, null);
@@ -354,7 +354,7 @@
            /// 添加节点的下一个可执行节点
            /// </summary>
            /// <param name="parent"></param>
            /// <param name="wipSN"></param>
            /// <param name="wipSN">当前的条码过站记录,需要导航查询生产过程记录信息</param>
            private List<MES_WO_NODE> GetNextNodes(MES_WO_NODE parent, MES_WIP_DATA wipSN)
            {
                var result = new List<MES_WO_NODE>();
@@ -386,6 +386,66 @@
            }
            /// <summary>
            /// 根据传入的条码返回下一站可进入进入的目标工序
            /// </summary>
            /// <param name="wipSN">当前的条码过站记录,需要导航查询生产过程记录和生产不良记录信息</param>
            /// <returns></returns>
            public List<MES_WO_NODE> GetNextNodes(MES_WIP_DATA wipSN)
            {
                var result = new List<MES_WO_NODE>();
                //条码在本工单第一次过站
                if (wipSN.NODE_ID.IsNullOrEmpty())
                {
                    result.AddRange(Nodes.Where(q => q.IS_FIRST_NODE == "Y"));
                }
                //条码已有过站记录
                else
                {
                    var curNode = Nodes.First(q => q.ID == wipSN.NODE_ID);
                    //条码在维修工序,返回可回流工序
                    if (curNode.Operation.OPER_TYPE == MES_OPERATION.OPER_TYPEs.Repair.GetValue())
                    {
                        //查找所有可以回流的工序
                        var reflowNodes = Nodes.Where(q => Edges.Any(e => e.SRC_NODE == curNode.ID && e.TGT_NODE == q.ID)
                                                                    && NodeSets.Any(s => s.NODE_ID == q.ID && s.IS_ACTIVE == "Y")).ToList();
                        result.AddRange(reflowNodes.Where(q => wipSN.REFLOW_NODE.IsNullOrEmpty() || wipSN.REFLOW_NODE == q.NODE_NAME));
                    }
                    else
                    {
                        //往下查找条码当前工序的下一个可执行工序
                        var nextNodes = GetNextNodes(curNode, wipSN);
                        //如果当前工序没有必须执行的后续工序,则尝试在前置工序查找还有没有后续工序没完成的工序,有则加入
                        if (!nextNodes.Any(q => NodeSets.Any(s => s.NODE_ID == q.ID && s.IS_ACTIVE == "Y" && s.CAN_SKIP != "Y")))
                        {
                            //在前置工序查找还有没有后续工序没完成的前置工序
                            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))
                                                                 ).ToList();
                            foreach (var prepID in prepIDs)
                            {
                                //如果连线的目标工序的前置工序都已完成,则把连线的目标工序添加到可执行工序列表
                                var prep = Nodes.First(q => q.ID == prepID);
                                var next = GetNextNodes(prep, wipSN);
                                nextNodes.AddRange(next);
                            }
                        }
                        result.AddRange(nextNodes);
                        //如果当前条码是不良则只返回允许不良进站的工序和工序连接的维修工序
                        if (wipSN.Defects.Any(q => q.WORK_ORDER == WO.ORDER_NO && q.STATUS < MES_WIP_DFT.STATUSs.Resolved.GetValue()))
                        {
                            result.RemoveAll(q => NodeSets.Any(s => s.NODE_ID == q.ID && s.ALLOW_DFT_IN != "Y"));
                            //加入工序连接的维修工序
                            var repairNodes = Nodes.Where(q => Edges.Any(e => e.SRC_NODE == curNode.ID && e.TGT_NODE == q.ID) && q.Operation.OPER_TYPE == MES_OPERATION.OPER_TYPEs.Repair.GetValue());
                            result.AddRange(repairNodes);
                        }
                    }
                }
                return result;
            }
            /// <summary>
            /// 根据岗位编码返回工序不良代码
            /// </summary>
            /// <param name="postCode"></param>
Tiger.Business/MES/WoContext.cs
@@ -1,11 +1,14 @@
using Microsoft.AspNetCore.Http;
using Rhea.Common;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tiger.IBusiness;
using Tiger.Model;
using Tiger.Model.Entitys.MES.Position;
using static Tiger.Business.Biz;
namespace Tiger.Business.MES
@@ -87,6 +90,68 @@
                return false;
            }
        }
        /// <summary>
        /// 获取SN的下一个工序节点列表
        /// </summary>
        /// <param name="sn"></param>
        /// <returns></returns>
        public static ApiAction<List<MES_WO_NODE>> GetSnNextNodes(string sn)
        {
            var action = new ApiAction<List<MES_WO_NODE>>(new List<MES_WO_NODE>());
            try
            {
                var wipSNs = Biz.Db.Queryable<MES_WIP_DATA>().IncludesAllFirstLayer().Where(q => (q.SN == sn || q.FLOW_SN == sn || q.TRAY_SN == sn || q.INNER_SN == sn || q.CARTON_SN == sn || q.PALLET_SN == sn)).ToList();
                if (wipSNs.IsNullOrEmpty())
                {
                    var woSNs = Biz.Db.Queryable<BIZ_MES_WO_SN>().Where(q => (q.SN == sn || q.TRAY_SN == sn || q.OUTER_SN == sn)).ToList();
                    //查找到条码已绑定的工单
                    if (!woSNs.IsNullOrEmpty())
                    {
                        foreach (var woSN in woSNs)
                        {
                            var wipSN = new MES_WIP_DATA()
                            {
                                SN = sn,
                                FLOW_SN = sn,
                                STATUS = MES_WIP_DATA.STATUSs.Init.GetValue(),
                                ITEM_CODE = woSN.ITEM_CODE,
                                WORK_ORDER = woSN.WORK_ORDER,
                                BATCH_NO = woSN.BATCH_NO,
                                HOLD_FLAG = "N",
                                FINISHED_FLAG = "N",
                                INV_FLAG = "N",
                                DFT_FLAG = "N",
                                DFT_COUNT = 0,
                            };
                            wipSNs.Add(wipSN);
                        }
                    }
                }
                if (wipSNs.IsNullOrEmpty())
                {
                    action.IsSuccessed = false;
                    //action.LocaleMsg = new($"找不到条码[{sn}]的生产信息", sn);
                    action.LocaleMsg = new("MES.WoContext.SnNotFound", sn);
                }
                else
                {
                    if (!WoBatchDic.Any(q => q.Value.WO.ORDER_NO == wipSNs.First().WORK_ORDER))
                    {
                        var wb = new WorkBatch(wipSNs.First().WORK_ORDER).Init("");
                        WoBatchDic.Add(wb.Batch.BATCH_NO, wb);
                    }
                    var wo = WoBatchDic.FirstOrDefault(q => q.Value.WO.ORDER_NO == wipSNs.First().WORK_ORDER).Value;
                    action.Data = wo.GetNextNodes(wipSNs.First());
                }
            }
            catch (Exception ex)
            {
                //action.CatchExceptionWithLog(ex, $"获取条码[{sn}]的下一个工序节点列表异常");
                action.CatchExceptionWithLog(ex, Biz.L("MES.WoContext.GetSnNextNodesException"));
            }
            return action;
        }
        #endregion
    }
}
Tiger.Model.Net/Entitys/MES/BIZ_MES_WO_SN.cs
@@ -54,6 +54,11 @@
        [DisplayName("最外层包装条码")]
        public string OUTER_SN { get; set; }
        /// <summary>
        /// 物料编码
        /// </summary>
        [DisplayName("物料编码")]
        public string ITEM_CODE { get; set; }
        /// <summary>
        /// 状态(0NotInput未投入|1Inputed已投入|2Finished已完工)
        /// </summary>
        [DisplayName("状态(0NotInput未投入|1Inputed已投入|2Finished已完工)")]