杨前锦
2025-07-01 a93b0e99036c24b9bd58c79bf5e7364b1ba28bae
HH.WCS.Mobox3/HH.WCS.Mobox3.YNJT_PT/api/ApiHelper.cs
@@ -4,6 +4,7 @@
using HH.WCS.Mobox3.YNJT_PT.process;
using HH.WCS.Mobox3.YNJT_PT.util;
using HH.WCS.Mobox3.YNJT_PT.wms;
using MySqlX.XDevAPI.Common;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using SqlSugar;
@@ -14,9 +15,11 @@
using System.Reflection;
using System.Text.RegularExpressions;
using System.Threading;
using Ubiety.Dns.Core;
using static HH.WCS.Mobox3.YNJT_PT.api.ApiModel;
using static HH.WCS.Mobox3.YNJT_PT.api.OtherModel;
using static HH.WCS.Mobox3.YNJT_PT.api.WmsController;
using static HH.WCS.Mobox3.YNJT_PT.dispatch.WCSDispatch;
using static HH.WCS.Mobox3.YNJT_PT.util.Settings;
using static HH.WCS.Mobox3.YNJT_PT.wms.WMSHelper;
using static System.Net.Mime.MediaTypeNames;
@@ -34,25 +37,27 @@
        /// 成型机下线记录
        /// </summary>
        /// <param name="model"></param>
        public static ResponseResult cxjOffLineRecord(OffLineModel model)
        public static ResponseResult cxjOffLineRecord(NotifyDeviceSignalModel model)
        {
            ResponseResult response = new ResponseResult();
            var container = ContainerHelper.GetCntr(model.rfid);
            var container = ContainerHelper.GetCntr(model.cntrNo);
            if (container == null)
            {
                ContainerHelper.AddCntr(model.rfid);
                ContainerHelper.AddCntr(model.cntrNo);
            }
            try
            {
                OffLineModel extData1 = JsonConvert.DeserializeObject<OffLineModel>(model.extData.ToString());
                OffLineRecord record = new OffLineRecord()
                {
                    S_RFID = model.rfid,
                    S_RFID = model.cntrNo,
                    S_DEVICE_NO = model.deviceNo,
                    N_IS_URGENT = model.isUrgent,
                    N_IS_URGENT = extData1.isUrgent,
                    T_OFF_TIME = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                    N_IS_FULL = model.isFull,
                    N_IS_FULL = extData1.isFull,
                    N_NEED_PAIR = extData1.needPair,
                    S_LOC = model.loc
                };
                WMSHelper.addOffLineRecord(record);
            }
@@ -75,7 +80,7 @@
            var startLoc = LocationHelper.GetLoc(model.loc);
            if (startLoc != null)
            {
                List<BarcodeModel> extData = model.extData;
                List<BarcodeModel> extData = JsonConvert.DeserializeObject<List<BarcodeModel>>(model.extData.ToString());
                int dataCount = extData.Count;
                if (dataCount > 0)
                {
@@ -105,7 +110,7 @@
                                    var offLineRecord = WMSHelper.getOffLineRecord(rfid);
                                    if (offLineRecord != null)
                                    {
                                        if (offLineRecord.N_IS_FULL == 1)
                                        if (offLineRecord.N_IS_FULL == 1)
                                        {
                                            if (ext.barcode.Contains("99999999"))
                                            {
@@ -118,11 +123,31 @@
                                                var itemBarcodeInfo = WMSHelper.GetGreenTireInformation(ext.barcode);
                                                if (itemBarcodeInfo != null)
                                                {
                                                    itemBarcodeInfo.N_URGENT_FLAG = offLineRecord.N_IS_URGENT;
                                                    // 计算生效时间、失效时间
                                                    var overage = WMSHelper.getOverage(itemBarcodeInfo.BARCODE);
                                                    LogHelper.Info($"计算生效时间、失效时间,返回值:{JsonConvert.SerializeObject(overage)}", "WMS");
                                                    if (overage != null)
                                                    {
                                                        DateTime txndate = DateTime.Parse(itemBarcodeInfo.TXNDATE);
                                                        DateTime minTime = txndate.AddHours(overage.MINHOUR);
                                                        DateTime maxTime = txndate.AddDays(overage.OVERAGE);
                                                        itemBarcodeInfo.S_EFFECTIVE_TIME = minTime.ToString("yyyy-MM-dd HH:mm:ss");
                                                        itemBarcodeInfo.S_EXPIRATION_TIME = maxTime.ToString("yyyy-MM-dd HH:mm:ss");
                                                    }
                                                    else
                                                    {
                                                        response.code = 1;
                                                        response.msg = $"未查询到物料存放时间配置信息,条形码:{itemBarcodeInfo.BARCODE}";
                                                        return response;
                                                    }
                                                    ContainerHelper.addCntrItemRel(rfid, itemBarcodeInfo);
                                                    barcodeList.Add(ext);
                                                }
                                                else
                                                {
                                                   // 记录查询条码信息异常
                                                    // 记录查询条码信息异常
                                                }
                                            }
@@ -134,7 +159,13 @@
                            EndLocGroup endLocGroup = null;
                            if (barcodeList.Count > 0) 
                            {
                               endLocGroup = WMSHelper.getInStockEndLoc(barcodeList.Count);
                               string itemCode = null;
                               var cntrItemRels = ContainerHelper.GetCntrItemRel(barcodeList[0].rfid);
                               if (cntrItemRels.Count > 0)
                               {
                                    itemCode = cntrItemRels[0].S_ITEM_CODE;
                               }
                               endLocGroup = WMSHelper.getInStockEndLoc(barcodeList.Count, itemCode);
                            }
                            foreach (var ext in extData)
@@ -197,9 +228,9 @@
                                                wmsTask.N_B_STATE = 1;
                                                WMSHelper.UpdateTaskState(wmsTask);
                                                // 绑定容器物料信息
                                                /*// 绑定容器物料信息
                                                var itemBarcodeInfo = WMSHelper.GetGreenTireInformation(ext.barcode);
                                                WMSHelper.bindBarcodeItemInfo(wmsTask.S_CNTR_CODE, itemBarcodeInfo);
                                                WMSHelper.bindBarcodeItemInfo(wmsTask.S_CNTR_CODE, itemBarcodeInfo);*/
                                            }
                                        }
                                    }
@@ -207,8 +238,8 @@
                                else
                                {
                                    // 异常托盘排除
                                    var middleLoc = WMSHelper.getMinTaskMiddleLoc(1);  // 1.异常排出位
                                    endLoc = WMSHelper.getAbnormalAreaEmptyLoc(Settings.abnormalArea);
                                    var middleLoc = WMSHelper.getMinTaskMiddleLoc(1);  // 1.排出位
                                    endLoc = WMSHelper.getOnlneLoc(2);  // 2.空托上线位(排出的托盘都出库到空托上线位进行处理)
                                    if (endLoc != null && middleLoc != null)
                                    {
                                        var wmsTask = new WMSTask()
@@ -281,6 +312,7 @@
        /// <summary>
        /// 读码请求
        /// 场景:1.
        /// </summary>
        public static ResponseResult readCodeRequest(NotifyDeviceSignalModel model) 
        {
@@ -289,62 +321,51 @@
            {
                verifyResult = true
            };
            var wmsTask = WMSHelper.GetWmsTask(model.taskNo);
            if (wmsTask != null)
            var wcsTask = WCSHelper.GetTask(model.taskNo);
            var wmsTask = WMSHelper.GetWmsTask(wcsTask.S_OP_CODE);
            if (wcsTask != null && wmsTask != null)
            {
                if (wmsTask.S_TYPE != "异常托盘出库任务")
                Location endLoc = LocationHelper.GetLoc(wmsTask.S_END_LOC);   // 原终点
                if (wcsTask.S_TYPE == "满料下线入库任务")
                {
                    Location endLoc = null;
                    Location middleLoc = null;
                    // 判断rfid是否异常
                    if (model.cntrNo != wmsTask.S_CNTR_CODE)
                    if (model.cntrNo != wcsTask.S_CNTR_CODE)
                    {
                        endLoc = LocationHelper.GetLoc(wmsTask.S_END_LOC);
                        var connectLoc = Settings.connectLocList.Where(a => a.roadway == endLoc.N_ROADWAY && a.type == 1).FirstOrDefault();
                        middleLoc = LocationHelper.GetLoc(connectLoc.locCode);
                        endLoc = WMSHelper.getAbnormalAreaEmptyLoc(Settings.abnormalArea);
                        // 查询排出口
                        Location middleLoc = WMSHelper.getMinTaskMiddleLoc(1, 0, endLoc.N_ROADWAY);
                        // 查询新终点
                        endLoc = WMSHelper.getOnlneLoc(2);
                        wcsTask.S_END_LOC = middleLoc.S_CODE;
                        wcsTask.S_END_AREA = middleLoc.S_AREA_CODE;
                        WCSHelper.updateTaskEnd(wcsTask);
                        wmsTask.S_END_LOC = endLoc.S_CODE;
                        wmsTask.S_END_AREA = endLoc.S_AREA_CODE;
                        WMSHelper.UpdateTaskEnd(wmsTask);
                        var wcsTask = WCSHelper.GetTaskBySrcNo(wmsTask.S_CODE);
                        if (wcsTask != null)
                        {
                            wcsTask.S_END_LOC = middleLoc.S_CODE;
                            wcsTask.S_END_AREA = middleLoc.S_AREA_CODE;
                            WCSHelper.updateTaskEnd(wcsTask);
                        }
                        readCodeFeedbackResponse.verifyResult = false;
                        readCodeFeedbackResponse.endLoc = middleLoc.S_CODE;
                        response.data = readCodeFeedbackResponse;
                    }
                    else
                }
                else if (wcsTask.S_TYPE == "胚胎叫料出库任务")
                {
                    var cntrItemRels = ContainerHelper.GetCntrItemRel(wcsTask.S_CNTR_CODE);
                    if (model.cntrNo != wcsTask.S_CNTR_CODE || cntrItemRels.Count == 0 || cntrItemRels.Count > 0 && cntrItemRels[0].S_ITEM_STATE != "OK")
                    {
                        var cntrItemRels = ContainerHelper.GetCntrItemRel(wmsTask.S_CNTR_CODE);
                        if (cntrItemRels.Count > 0)
                        {
                            if (cntrItemRels[0].S_ITEM_STATE != "OK")
                            {
                                middleLoc = WMSHelper.getMinTaskMiddleLoc(1);  // 1.异常排出位
                                endLoc = WMSHelper.getAbnormalAreaEmptyLoc(Settings.abnormalArea);
                                wmsTask.S_END_LOC = endLoc.S_CODE;
                                wmsTask.S_END_AREA = endLoc.S_AREA_CODE;
                                WMSHelper.UpdateTaskEnd(wmsTask);
                        // 计算排出口
                        endLoc = WMSHelper.getCallOutLoc(endLoc.N_ROW);
                                var wcsTask = WCSHelper.GetTaskBySrcNo(wmsTask.S_CODE);
                                if (wcsTask != null)
                                {
                                    wcsTask.S_END_LOC = middleLoc.S_CODE;
                                    wcsTask.S_END_AREA = middleLoc.S_AREA_CODE;
                                    WCSHelper.updateTaskEnd(wcsTask);
                                }
                        wcsTask.S_END_LOC = endLoc.S_CODE;
                        wcsTask.S_END_AREA = endLoc.S_AREA_CODE;
                        WCSHelper.updateTaskEnd(wcsTask);
                                readCodeFeedbackResponse.verifyResult = false;
                                readCodeFeedbackResponse.endLoc = middleLoc.S_CODE;
                                response.data = readCodeFeedbackResponse;
                            }
                        }
                        wmsTask.S_END_LOC = endLoc.S_CODE;
                        wmsTask.S_END_AREA = endLoc.S_AREA_CODE;
                        WMSHelper.UpdateTaskEnd(wmsTask);
                        readCodeFeedbackResponse.verifyResult = false;
                        readCodeFeedbackResponse.endLoc = endLoc.S_CODE;
                    }
                }
            }
@@ -358,133 +379,239 @@
        }
        /// <summary>
        /// 硫化机呼叫胚胎出库
        /// 异常申请(取消任务)
        /// </summary>
        /// <param name="model"></param>
        public static ResponseResult callItemOutStock(CallItemModel model)
        /// <returns></returns>
        public static ResponseResult anomalyRequest(NotifyDeviceSignalModel model)
        {
            ResponseResult response = new ResponseResult();
            //参数校验
            if (model.locCodes.Count == 0)
            readCodeFeedbackResponse readCodeFeedbackResponse = new readCodeFeedbackResponse()
            {
                string msg = $"硫化机:{model.mcn}呼叫胚胎出库,参数校验失败,缺少货位信息";
                LogHelper.Info(msg, "WMS");
                response.code = 1;
                response.msg = msg;
                return response;
            }
            // 1.一个硫化机工位只能同时存在一个正在执行中的任务
            WCSTask existTask = WCSHelper.GetTaskByEqNo(model.mcn);
            if (existTask == null)
                verifyResult = true
            };
            var wcsTask = WCSHelper.GetTask(model.taskNo);
            var wmsTask = WMSHelper.GetWmsTask(wcsTask.S_OP_CODE);
            if (wcsTask != null && wmsTask != null)
            {
                // 2.根据当前时间,判断班次日期和班次
                var currentTime = DateTime.Now;
                var shift = getShift(currentTime.TimeOfDay);
                var dateShift = DateTime.Now.ToString("dd/MM/yyyy");
                TimeSpan shiftIII_Start = new TimeSpan(7, 00, 0); // 7:00:00
                if (shift == "III" && currentTime.TimeOfDay < shiftIII_Start)
                Location endLoc = LocationHelper.GetLoc(wmsTask.S_END_LOC);   // 原终点
                if (wcsTask.S_TYPE == "满料下线入库任务")
                {
                    dateShift = DateTime.Now.AddDays(-1).ToString("dd/MM/yyyy");
                    // 查询排出口
                    var middleLoc = WMSHelper.getMinTaskMiddleLoc(1, 0, endLoc.N_ROADWAY);
                    wcsTask.S_END_LOC = middleLoc.S_CODE;
                    wcsTask.S_END_AREA = middleLoc.S_AREA_CODE;
                    WCSHelper.updateTaskEnd(wcsTask);
                    readCodeFeedbackResponse.verifyResult = false;
                    readCodeFeedbackResponse.endLoc = middleLoc.S_CODE;
                    // 查询新终点
                    endLoc = WMSHelper.getOnlneLoc(2);
                }
                // 3.根据班次日期+班次+硫化机工位号查询呼叫的物料编码、预计生产数量
                var productionShedule = WMSHelper.getProductionShedule(dateShift, model.mcn, shift);
                if (productionShedule != null && productionShedule.QTY != 0)
                else if (wcsTask.S_TYPE == "胚胎叫料出库任务")
                {
                    // 4.查询【胚胎已完成的条码中间表】并计算当前班次的已完成数量
                    int finishNum = WMSHelper.getEmbryoFinishNum(dateShift, model.mcn, shift);
                    endLoc = WMSHelper.getCallOutLoc(endLoc.N_ROW);
                    readCodeFeedbackResponse.verifyResult = false;
                    readCodeFeedbackResponse.endLoc = endLoc.S_CODE;
                }
                wmsTask.S_END_LOC = endLoc.S_CODE;
                wmsTask.S_END_AREA = endLoc.S_AREA_CODE;
                WMSHelper.UpdateTaskEnd(wmsTask);
            }
            else
            {
                response.code = 1;
                response.msg = $"任务号:{model.taskNo},未查询到执行中的任务";
            }
            response.data = readCodeFeedbackResponse;
            return response;
        }
                    if (productionShedule.QTY > finishNum)
        /// <summary>
        /// 申请新终点
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public static ResponseResult applyDest(ApplyDestModel model)
        {
            ResponseResult response = new ResponseResult();
            ApplyDest applyDest = new ApplyDest();
            var wcsTask = WCSHelper.GetTask(model.taskNo);
            if (wcsTask != null)
            {
                var wmsTask = WMSHelper.GetWmsTask(wcsTask.S_OP_CODE);
                if (wcsTask != null)
                {
                    string itemCode = null;
                    var endLoc = LocationHelper.GetLoc(wcsTask.S_END_LOC);
                    var cntrItemRels = ContainerHelper.GetCntrItemRel(wcsTask.S_CNTR_CODE);
                    if (cntrItemRels.Count > 0)
                    {
                        // 5.计算(1.巷道不报警、2.物料状态OK、3.小于失效时间 大于等于生效时间 4.加急料先出、5.先入先出(生产时间))出库物料,生成任务
                        int locNum = model.locCodes.Count;
                        var startLocData = WMSHelper.getOutStockStartLoc(productionShedule.ITEMCODE,locNum);
                        if (startLocData.startLocList != null && startLocData.startLocList.Count == locNum)
                        {
                            var startLocList = startLocData.startLocList;
                            for (int i = 0; i < locNum; i++)
                            {
                                Location startLoc = startLocList[i];
                                Location endLoc =  LocationHelper.GetLoc(model.locCodes[i]);
                                if (endLoc != null)
                                {
                                    var locCntrRels = LocationHelper.GetLocCntr(startLoc.S_CODE);
                                    if (locCntrRels != null && locCntrRels.Count > 0)
                                    {
                                        var wmsTask = new WMSTask()
                                        {
                                            S_CNTR_CODE = locCntrRels[0].S_CNTR_CODE,
                                            S_CODE = WMSHelper.GenerateTaskNo(),
                                            S_START_LOC = startLoc.S_CODE,
                                            S_START_AREA = startLoc.S_AREA_CODE,
                                            S_END_LOC = endLoc.S_CODE,
                                            S_END_AREA = endLoc.S_AREA_CODE,
                                            S_TYPE = "满料下线入库任务",
                                            S_OP_DEF_CODE = model.reqId,
                                            S_OP_DEF_NAME = "成型机满料下线入库",
                                            N_PRIORITY = 1,
                                            T_START_TIME = DateTime.Now,
                                            S_GROUP_NO = startLocData.groupNo,
                                        };
                                        if (WMSHelper.CreateWmsTask(wmsTask))
                                        {
                                            // 创建一段入库任务
                                            WCSTask wcsTask = new WCSTask()
                                            {
                                                S_OP_NAME = wmsTask.S_OP_DEF_NAME,
                                                S_OP_CODE = wmsTask.S_CODE,
                                                S_CODE = WCSHelper.GenerateTaskNo(),
                                                S_CNTR_CODE = wmsTask.S_CNTR_CODE,
                                                S_TYPE = wmsTask.S_TYPE,
                                                S_START_LOC = startLoc.S_CODE,
                                                S_START_AREA = startLoc.S_AREA_CODE,
                                                S_END_LOC = endLoc.S_CODE,
                                                S_END_AREA = endLoc.S_AREA_CODE,
                                                S_SCHEDULE_TYPE = "WCS",
                                                N_PRIORITY = 1,
                                                T_START_TIME = DateTime.Now,
                                            };
                        itemCode = cntrItemRels[0].S_ITEM_CODE;
                    }
                                            if (WCSHelper.CreateTask(wcsTask))
                                            {
                                                // 起点、接驳点、终点加锁
                                                LocationHelper.LockLoc(wcsTask.S_START_LOC, 2);
                                                LocationHelper.LockLoc(wcsTask.S_END_LOC, 1);
                                                // 更新作业任务状态
                                                wmsTask.N_B_STATE = 1;
                                                WMSHelper.UpdateTaskState(wmsTask);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        else
                    if (model.applyType == 1)
                    {
                        LocationHelper.LockLoc(wcsTask.S_END_LOC, 3);  // 将原货位锁定(其他锁)
                        var endLocGroup = WMSHelper.getInStockEndLoc(1, itemCode, endLoc.N_ROADWAY);
                        if (endLocGroup.endLocList.Count > 0)
                        {
                            string msg = $"库内没有满足条件的物料";
                            LogHelper.Info(msg, "WMS");
                            response.code = 1;
                            response.msg = msg;
                            endLoc = endLocGroup.endLocList[0];
                            applyDest.endLoc = endLoc.S_CODE;
                        }
                    }
                    else
                    else if (model.applyType == 2)
                    {
                        string msg = $"硫化机:{model.mcn}的当前班次任务已完成,停止叫料";
                        LogHelper.Info(msg, "WMS");
                        response.code = 1;
                        response.msg = msg;
                        var endLocGroup = WMSHelper.getInStockEndLoc(1, cntrItemRels[0].S_ITEM_CODE, 0, endLoc.N_ROADWAY);
                        if (endLocGroup.endLocList.Count > 0)
                        {
                            endLoc = endLocGroup.endLocList[0];
                            applyDest.endLoc = endLoc.S_CODE;
                        }
                    }
                }
            }
            else 
            {
                string msg = $"硫化机:{model.mcn}的存在正在执行中的任务,请勿重复叫料";
                LogHelper.Info(msg, "WMS");
                response.code = 1;
                response.msg = msg;
                response.msg = $"任务:{model.taskNo}不存在";
            }
            return response;
        }
        public class ApplyDest
        {
            public string endLoc { get; set; }
        }
        /// <summary>
        /// 4.硫化机呼叫胚胎出库
        /// 逻辑:
        /// 1.根据机台号查询【硫化机工单表】、【胚胎已完成的条码中间表】筛选当前班次的生产计划数量是否满足,当预计生产数量 = 实际数+在途数量 ,则停止叫料
        /// 2.查询机台号在【硫化机工单表】对应的物料编码,
        ///   开始计算(1.巷道不报警、2.物料状态OK、3.小于失效时间 大于等于生效时间 4.加急料先出、5.先入先出(生产时间))出库物料,生成任务
        /// </summary>
        /// <param name="model"></param>
        public static ResponseResult callItemOutStock(NotifyDeviceSignalModel model)
        {
            ResponseResult response = new ResponseResult();
            var locCodes = model.loc.Split(',').ToList();
            int locNum = locCodes.Count;
            if (locNum > 0)
            {
                Location prevLoc = null;
                Dictionary<string,Location> outLocDic = new Dictionary<string,Location>();
                foreach (var mcn in locCodes)
                {
                    // 1.一个硫化机工位只能同时存在一个正在执行中的任务
                    var existTask = WCSHelper.GetTaskByEnd(mcn);
                    if (existTask.Count == 0)
                    {
                        // 2.根据当前时间,判断班次日期和班次
                        var currentTime = DateTime.Now;
                        var shift = getShift(currentTime.TimeOfDay);  // 班次
                        var dateShift = currentTime.ToString("dd/MM/yyyy");
                        TimeSpan shiftIII_Start = new TimeSpan(7, 00, 0); // 7:00:00
                        if (shift == "III" && currentTime.TimeOfDay < shiftIII_Start)
                        {
                            dateShift = DateTime.Now.AddDays(-1).ToString("dd/MM/yyyy");
                        }
                        // 3.根据班次日期+班次+硫化机工位号查询 硫化机工单 中的物料编码、预计生产数量
                        var productionShedule = WMSHelper.getProductionShedule(dateShift, mcn, shift);
                        if (productionShedule != null && productionShedule.QTY != 0)
                        {
                            // 4查询【胚胎已完成的条码中间表】并计算当前班次的已完成数量
                            int finishNum = WMSHelper.getEmbryoFinishNum(dateShift, mcn, shift);
                            if (productionShedule.QTY > finishNum)
                            {
                                // 5.出库策略 1.优先查询前一拖货位的左右两边是否满足条件  2.计算(1.巷道不报警、2.物料状态OK、3.小于失效时间 大于等于生效时间 4.加急料先出、5.先入先出(生产时间))出库物料,生成任务
                                var startLoc = WMSHelper.getOutStockStartLoc(productionShedule.ITEMCODE, prevLoc);
                                if (startLoc != null)
                                {
                                    outLocDic.Add(mcn, startLoc);
                                    prevLoc = startLoc;
                                }
                            }
                        }
                    }
                }
                // 6.判断出库货位是否是同一巷道,同一巷道生成任务组号
                string groupNo = null;
                if (outLocDic.Count > 1)
                {
                    var groupNum = outLocDic.Select(a => a.Value).ToList().GroupBy(a => a.N_ROADWAY).Count();
                    if (groupNum == 1)
                    {
                        groupNo = GenerateTaskGroupNo();
                    }
                }
                // 7.生成出库任务
                if (outLocDic.Count > 0)
                {
                    foreach (var item in outLocDic)
                    {
                        Location endLoc = LocationHelper.GetLoc(item.Key);
                        Location startLoc = item.Value;
                        if (endLoc != null)
                        {
                            var locCntrRels = LocationHelper.GetLocCntr(startLoc.S_CODE);
                            if (locCntrRels != null && locCntrRels.Count > 0)
                            {
                                var wmsTask = new WMSTask()
                                {
                                    S_CNTR_CODE = locCntrRels[0].S_CNTR_CODE,
                                    S_CODE = WMSHelper.GenerateTaskNo(),
                                    S_START_LOC = startLoc.S_CODE,
                                    S_START_AREA = startLoc.S_AREA_CODE,
                                    S_END_LOC = endLoc.S_CODE,
                                    S_END_AREA = endLoc.S_AREA_CODE,
                                    S_TYPE = "胚胎叫料出库任务",
                                    S_OP_DEF_CODE = model.reqId,
                                    S_OP_DEF_NAME = "硫化机呼叫胚胎出库",
                                    N_PRIORITY = 1,
                                    T_START_TIME = DateTime.Now,
                                    S_GROUP_NO = groupNo,
                                };
                                if (WMSHelper.CreateWmsTask(wmsTask))
                                {
                                    // 创建一段入库任务
                                    WCSTask wcsTask = new WCSTask()
                                    {
                                        S_OP_NAME = wmsTask.S_OP_DEF_NAME,
                                        S_OP_CODE = wmsTask.S_CODE,
                                        S_CODE = WCSHelper.GenerateTaskNo(),
                                        S_CNTR_CODE = wmsTask.S_CNTR_CODE,
                                        S_TYPE = wmsTask.S_TYPE,
                                        S_START_LOC = startLoc.S_CODE,
                                        S_START_AREA = startLoc.S_AREA_CODE,
                                        S_END_LOC = endLoc.S_CODE,
                                        S_END_AREA = endLoc.S_AREA_CODE,
                                        S_SCHEDULE_TYPE = "WCS",
                                        N_PRIORITY = 1,
                                        T_START_TIME = DateTime.Now,
                                    };
                                    if (WCSHelper.CreateTask(wcsTask))
                                    {
                                        // 起点、接驳点、终点加锁
                                        LocationHelper.LockLoc(wcsTask.S_START_LOC, 2);
                                        LocationHelper.LockLoc(wcsTask.S_END_LOC, 1);
                                        // 更新作业任务状态
                                        wmsTask.N_B_STATE = 1;
                                        WMSHelper.UpdateTaskState(wmsTask);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return response;
        }
@@ -494,98 +621,33 @@
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public static ResponseResult emptyTrayInStock(EmptyTrayInStockModel model)
        public static ResponseResult emptyTrayInStock(NotifyDeviceSignalModel model)
        {
            ResponseResult response = new ResponseResult();
            Location startLoc = LocationHelper.GetLoc(model.startLoc);
            var endLocGroup = WMSHelper.getInStockEndLoc(1);
            if (endLocGroup.endLocList.Count == 1)
            {
                Location endLoc = endLocGroup.endLocList[0];
                var wmsTask = new WMSTask()
                {
                    S_CNTR_CODE = model.trayCode,
                    S_CODE = WMSHelper.GenerateTaskNo(),
                    S_START_LOC = startLoc.S_CODE,
                    S_START_AREA = startLoc.S_AREA_CODE,
                    S_END_LOC = endLoc.S_CODE,
                    S_END_AREA = endLoc.S_AREA_CODE,
                    S_TYPE = "空托入库任务",
                    S_OP_DEF_CODE = model.reqId,
                    S_OP_DEF_NAME = "空托盘回库任务",
                    N_PRIORITY = 1,
                    T_START_TIME = DateTime.Now,
                };
                if (WMSHelper.CreateWmsTask(wmsTask))
                {
                    // 创建一段入库任务
                    WCSTask wcsTask = new WCSTask()
                    {
                        S_OP_NAME = wmsTask.S_OP_DEF_NAME,
                        S_OP_CODE = wmsTask.S_CODE,
                        S_CODE = WCSHelper.GenerateTaskNo(),
                        S_CNTR_CODE = wmsTask.S_CNTR_CODE,
                        S_TYPE = wmsTask.S_TYPE,
                        S_START_LOC = startLoc.S_CODE,
                        S_START_AREA = startLoc.S_AREA_CODE,
                        S_END_LOC = endLoc.S_CODE,
                        S_END_AREA = endLoc.S_AREA_CODE,
                        S_SCHEDULE_TYPE = "WCS",
                        N_PRIORITY = 1,
                        T_START_TIME = DateTime.Now,
                    };
            Location startLoc = LocationHelper.GetLoc(model.loc);
                    if (WCSHelper.CreateTask(wcsTask))
                    {
                        // 起点、接驳点、终点加锁
                        LocationHelper.LockLoc(wcsTask.S_START_LOC, 2);
                        LocationHelper.LockLoc(wcsTask.S_END_LOC, 1);
                        // 更新作业任务状态
                        wmsTask.N_B_STATE = 1;
                        WMSHelper.UpdateTaskState(wmsTask);
                    }
                }
            }
            else
            var cntrCodeList = model.loc.Split(',').ToList();
            if (cntrCodeList.Count > 0)
            {
                response.code = 1;
                response.msg = "库区没有可入的空货位";
            }
            return response;
        }
        /// <summary>
        /// 呼叫空托出库
        /// </summary>
        /// <returns></returns>
        public static ResponseResult callEmptyTrayOutStock(CallEmptyTrayOutStockModel model)
        {
            ResponseResult responseResult = new ResponseResult();
            Location endLoc = LocationHelper.GetLoc(model.endLoc);
            var startLocData = WMSHelper.getOutStockStartLoc(null, 1);
            if (startLocData.startLocList != null && startLocData.startLocList.Count == 1)
            {
                Location startLoc = startLocData.startLocList[0];
                if (endLoc != null)
                var endLocGroup = WMSHelper.getInStockEndLoc(cntrCodeList.Count, null);
                if (endLocGroup.endLocList.Count > 0)
                {
                    var locCntrRels = LocationHelper.GetLocCntr(startLoc.S_CODE);
                    if (locCntrRels != null && locCntrRels.Count > 0)
                    foreach (var endLoc in endLocGroup.endLocList)
                    {
                        var wmsTask = new WMSTask()
                        {
                            S_CNTR_CODE = locCntrRels[0].S_CNTR_CODE,
                            S_CNTR_CODE = model.cntrNo,
                            S_CODE = WMSHelper.GenerateTaskNo(),
                            S_START_LOC = startLoc.S_CODE,
                            S_START_AREA = startLoc.S_AREA_CODE,
                            S_END_LOC = endLoc.S_CODE,
                            S_END_AREA = endLoc.S_AREA_CODE,
                            S_TYPE = "呼叫空托出库",
                            S_TYPE = "空托入库任务",
                            S_OP_DEF_CODE = model.reqId,
                            S_OP_DEF_NAME = "呼叫空托出库",
                            S_OP_DEF_NAME = "空托盘回库任务",
                            N_PRIORITY = 1,
                            T_START_TIME = DateTime.Now,
                            S_GROUP_NO = startLocData.groupNo,
                            S_GROUP_NO = endLocGroup.groupNo,
                        };
                        if (WMSHelper.CreateWmsTask(wmsTask))
                        {
@@ -619,13 +681,92 @@
                        }
                    }
                }
                else
                {
                    response.code = 1;
                    response.msg = "库区没有可入的空货位";
                }
            }
            else
            return response;
        }
        /// <summary>
        /// 呼叫空托出库
        /// </summary>
        /// <returns></returns>
        public static ResponseResult callEmptyTrayOutStock(NotifyDeviceSignalModel model)
        {
            ResponseResult responseResult = new ResponseResult();
            int executeNum = 0;
            string startLocCode = null;
            for (int i = 1; i <= 2; i++)
            {
                string msg = $"库内没有满足条件的物料";
                LogHelper.Info(msg, "WMS");
                Location startLoc = WMSHelper.getOutStockStartLoc(startLocCode);
                if (startLoc != null)
                {
                    startLocCode = startLoc.S_CODE;
                    Location endLoc = WMSHelper.getMinTaskMiddleLoc(1, 0, startLoc.N_ROADWAY);
                    if (endLoc != null)
                    {
                        var locCntrRels = LocationHelper.GetLocCntr(startLoc.S_CODE);
                        if (locCntrRels != null && locCntrRels.Count > 0)
                        {
                            var wmsTask = new WMSTask()
                            {
                                S_CNTR_CODE = locCntrRels[0].S_CNTR_CODE,
                                S_CODE = WMSHelper.GenerateTaskNo(),
                                S_START_LOC = startLoc.S_CODE,
                                S_START_AREA = startLoc.S_AREA_CODE,
                                S_END_LOC = endLoc.S_CODE,
                                S_END_AREA = endLoc.S_AREA_CODE,
                                S_TYPE = "呼叫空托出库",
                                S_OP_DEF_CODE = model.reqId,
                                S_OP_DEF_NAME = "呼叫空托出库",
                                N_PRIORITY = 1,
                                T_START_TIME = DateTime.Now
                            };
                            if (WMSHelper.CreateWmsTask(wmsTask))
                            {
                                // 创建一段入库任务
                                WCSTask wcsTask = new WCSTask()
                                {
                                    S_OP_NAME = wmsTask.S_OP_DEF_NAME,
                                    S_OP_CODE = wmsTask.S_CODE,
                                    S_CODE = WCSHelper.GenerateTaskNo(),
                                    S_CNTR_CODE = wmsTask.S_CNTR_CODE,
                                    S_TYPE = wmsTask.S_TYPE,
                                    S_START_LOC = startLoc.S_CODE,
                                    S_START_AREA = startLoc.S_AREA_CODE,
                                    S_END_LOC = endLoc.S_CODE,
                                    S_END_AREA = endLoc.S_AREA_CODE,
                                    S_SCHEDULE_TYPE = "WCS",
                                    N_PRIORITY = 1,
                                    T_START_TIME = DateTime.Now,
                                };
                                if (WCSHelper.CreateTask(wcsTask))
                                {
                                    // 起点、接驳点、终点加锁
                                    LocationHelper.LockLoc(wcsTask.S_START_LOC, 2);
                                    LocationHelper.LockLoc(wcsTask.S_END_LOC, 1);
                                    // 更新作业任务状态
                                    wmsTask.N_B_STATE = 1;
                                    WMSHelper.UpdateTaskState(wmsTask);
                                    executeNum += 1;
                                }
                            }
                        }
                    }
                }
            }
            if (executeNum < 1)
            {
                responseResult.code = 1;
                responseResult.msg = msg;
                responseResult.msg = "立库内空托盘数量不足";
            }
            return responseResult;
        }
@@ -634,14 +775,14 @@
        /// 胚胎抽检出库
        /// </summary>
        /// <returns></returns>
        public static ResponseResult embryoCheckOutStock(EmbryoCheckOutStockModel model)
        public static SimpleResult embryoCheckOutStock(EmbryoCheckOutStockModel model)
        {
            ResponseResult responseResult = new ResponseResult();
            SimpleResult result = new SimpleResult();
            var locCntrs = LocationHelper.GetLocCntrRelByCntr(model.trayCode);
            if (locCntrs.Count == 1)
            {
                Location startLoc = LocationHelper.GetLoc(locCntrs[0].S_LOC_CODE);
                var connectLoc = Settings.connectLocList.Where(a => a.roadway == startLoc.N_ROADWAY && a.type == 1).First();
                var connectLoc = Settings.connectLocList.Where(a => a.roadway == startLoc.N_ROADWAY).First();
                Location middleLoc = LocationHelper.GetLoc(connectLoc.locCode);
                Location endLoc = LocationHelper.GetLoc("");
                if (endLoc != null)
@@ -692,7 +833,7 @@
                    }
                }
            }
            return responseResult;
            return result;
        }
        /// <summary>
@@ -700,11 +841,11 @@
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public static ResponseResult anomalyTrayInStock(AnomalyTrayInStockModel model)
        public static ResponseResult anomalyTrayInStock(NotifyDeviceSignalModel model)
        {
            ResponseResult responseResult = new ResponseResult();
            LocationHelper.UnBindingLoc(model.startLoc, new List<string>() { model.trayCode });
            ContainerHelper.deleteCntrItemRelByCntr(model.trayCode);
            LocationHelper.UnBindingLoc(model.loc, new List<string>() { model.cntrNo });
            ContainerHelper.deleteCntrItemRelByCntr(model.cntrNo);
            return responseResult;
        }
@@ -766,11 +907,21 @@
                        if (model.status == 2 || model.status == 8)
                        {
                            if (mst != null)
                            if (mst != null && mst.N_B_STATE != 2)
                            {
                                if (mst.N_B_STATE != 2)
                                if (mst.S_END_LOC != cst.S_END_LOC)
                                {
                                    WCSCore.createLastTask(cst.S_END_LOC, mst);
                                }
                                else
                                {
                                    mst.N_B_STATE = 2;
                                    WMSHelper.UpdateTaskState(mst);
                                }
                                if (mst.S_TYPE == "呼叫空托出库")
                                {
                                    LocationHelper.UnBindingLoc(mst.S_END_LOC, new List<string>() { mst.S_CNTR_CODE });
                                }
                            }
                        }
@@ -808,6 +959,16 @@
                return "III";
            else
                return "No shift"; // 理论上不会触发
        }
        /// <summary>
        /// 空托解绑
        /// </summary>
        public static ReturnResult emptyTrayUnBind(EmptyTrayUnBindModel model)
        {
            ReturnResult responseResult = new ReturnResult();
            ContainerHelper.deleteCntrItemRelByCntr(model.rfid);
            return responseResult;
        }
        public class readCodeFeedbackResponse
@@ -947,10 +1108,9 @@
        public class OffLineModel
        {
            public string rfid { get; set; } // 托盘号
            public string deviceNo { get; set; } // 机台号
            public int isUrgent { get; set; } // N_IS_URGENT 是否加急(0.否 1.是)
            public int isFull { get; set; } // 是否满拖 0.否 1.是
            public int needPair { get; set; } // 0.否  1.是(当前空托盘为配对托盘)
        }
        public class AddTaskModel {
            public string From { get; set; }