HH.WCS.Mobox3.HangYang/api/MoboxController.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
HH.WCS.Mobox3.HangYang/core/WCSCore.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
HH.WCS.Mobox3.HangYang/models/Container.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
HH.WCS.Mobox3.HangYang/models/wms/Algorit.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
HH.WCS.Mobox3.HangYang/process/TaskProcess.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
HH.WCS.Mobox3.HangYang/util/HttpHelper.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
HH.WCS.Mobox3.HangYang/wms/ContainerHelper.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
HH.WCS.Mobox3.HangYang/wms/LocationHelper.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
HH.WCS.Mobox3.HangYang/wms/WCSHelper.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
HH.WCS.Mobox3.HangYang/wms/WMSHelper.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
HH.WCS.Mobox3.HangYang/api/MoboxController.cs
@@ -144,7 +144,6 @@ #region 杭氧PDA接口 #endregion } HH.WCS.Mobox3.HangYang/core/WCSCore.cs
@@ -13,64 +13,91 @@ { public static void OperateAgvTaskStatus(AgvTaskState model) { var TN_Task = WCSHelper.GetTask(model.No); if (TN_Task != null) { if (model.State <= 7) { if (model == null) return; //有任务号请求 switch (model.State) var task = WCSHelper.GetTask(model.No); if (task == null) return; if (model.State > 7) return; // 状态与操作的映射字典 var stateActions = new Dictionary<int, Action> { case 1: WCSHelper.Begin(TN_Task); break; #region MyRegion case 3: WCSHelper.UpdateStatus(TN_Task, "开始取货"); break; case 4: WCSHelper.UpdateStatus(TN_Task, "取货完成"); TaskProcess.OperateStatus(TN_Task, 4); break; case 5: WCSHelper.UpdateStatus(TN_Task, "开始卸货"); break; case 6: WCSHelper.UpdateStatus(TN_Task, "卸货完成"); TaskProcess.OperateStatus(TN_Task, 6); break; #endregion case 2: WCSHelper.End(TN_Task); //根据任务类型更新作业状态和终点 var taskList = Settings.CompleteTasks; if (taskList.taskType.Contains(TN_Task.S_TYPE)) [1] = () => WCSHelper.Begin(task), [2] = () => HandleTaskCompletion(task), [3] = () => WCSHelper.UpdateStatus(task, "开始取货"), [4] = () => HandlePickCompletion(task), [5] = () => WCSHelper.UpdateStatus(task, "开始卸货"), [6] = () => HandleUnloadCompletion(task), [7] = () => HandleTaskFailure(task) }; if (stateActions.TryGetValue(model.State, out var action)) { //完成作业 WMSHelper.UpdateWmsTask(TN_Task, 2); WMSHelper.UpdateDistributionCntrState(2, 3, TN_Task.S_CNTR_CODE); } if (new List<string> { "料箱入库", "托盘入库" }.Contains(TN_Task.S_TYPE)) { ContainerHelper.UpdateCntrItem(TN_Task.S_CNTR_CODE); } //if (WMSHelper.DeleteChange(TN_Task)) //{ // WMSHelper.AddChange(TN_Task); //} break; case 7: TaskProcess.OperateStatus(TN_Task, 7); WCSHelper.Fail(TN_Task); break; } action.Invoke(); WCSHelper.AddActionRecord(model.No, model.State, model.ForkliftNo, model.ExtData); } } // 处理任务完成逻辑 private static void HandleTaskCompletion(WCSTask task) { WCSHelper.End(task); // 根据任务类型处理不同的完成逻辑 if (Settings.CompleteTasks.taskType.Contains(task.S_TYPE)) { WMSHelper.UpdateWmsTask(task, 2); WMSHelper.UpdateDistributionCntrState(2, 3, task.S_CNTR_CODE); } if (new List<string> { "料箱入库", "托盘入库" }.Contains(task.S_TYPE)) { ContainerHelper.UpdateCntrItem(task.S_CNTR_CODE); } // 处理区域变更 HandleAreaChange(task); } // 处理取货完成逻辑 private static void HandlePickCompletion(WCSTask task) { WCSHelper.UpdateStatus(task, "取货完成"); TaskProcess.OperateStatus(task, 4); } // 处理卸货完成逻辑 private static void HandleUnloadCompletion(WCSTask task) { WCSHelper.UpdateStatus(task, "卸货完成"); TaskProcess.OperateStatus(task, 6); } // 处理任务失败逻辑 private static void HandleTaskFailure(WCSTask task) { TaskProcess.OperateStatus(task, 7); WCSHelper.Fail(task); } // 处理区域变更逻辑 private static void HandleAreaChange(WCSTask task) { var areas = new List<string> { "TPLKQ", "LXLKQ" }; if (areas.Contains(task.S_START_AREA)) { WMSHelper.DeleteChange(task); } if (areas.Contains(task.S_END_AREA)) { WMSHelper.AddChange(task); } } /// <summary> /// 任务分发,根据调度类型发给不同的调度系统 @@ -104,11 +131,10 @@ var list = WMSHelper.GetWmsTaskListByState("等待"); if (list.Count > 0) { list.ForEach(task => list.ForEach(async task => { //生成入库任务 TaskProcess.CreateInTask(task); await TaskProcess.CreateInTask(task); }); } //查询任务 @@ -118,7 +144,7 @@ { exelist.ForEach(task => { //生成入库任务 //生成从分拣暂存区到集货托盘位的任务任务 TaskProcess.exeCreateInTask(task); }); } HH.WCS.Mobox3.HangYang/models/Container.cs
@@ -12,11 +12,11 @@ public string S_TYPE { get; set; } public string S_SPEC { get; set; } public float F_WEIGHT { get; set; } public float F_LOAD_WEIGHT { get; set; } //public float F_LOAD_WEIGHT { get; set; } public float F_MAX_WEIGHT { get; set; } public int N_LENGTH { get; set; } public int N_WIDTH { get; set; } public int N_HEIGHT { get; set; } //public int N_LENGTH { get; set; } //public int N_WIDTH { get; set; } //public int N_HEIGHT { get; set; } public string C_IS_VIRTUAL { get; set; } = "N"; public int N_TYPE { get; set; } public string C_ENABLE { get; set; } = "Y"; @@ -31,8 +31,8 @@ /// <summary> /// 码盘时候标记 /// </summary> public string S_SRC { get; internal set; } public string S_DEST { get; internal set; } //public string S_SRC { get; internal set; } //public string S_DEST { get; internal set; } [SugarColumn(IsIgnore = true)] HH.WCS.Mobox3.HangYang/models/wms/Algorit.cs
@@ -26,8 +26,6 @@ /// </summary> public class Outbound { /// <summary> /// 库区 /// </summary> @@ -57,6 +55,11 @@ /// 作业任务号 /// </summary> public string opCode { get; set; } /// <summary> /// 呼叫空托数 /// </summary> public int requiredCount { get; set; } } public class LocationParams HH.WCS.Mobox3.HangYang/process/TaskProcess.cs
@@ -924,12 +924,12 @@ /// </summary> /// <param name="mst"></param> /// <returns></returns> internal static bool CreateInTask(WMSTask mst) internal static async Task<bool> CreateInTask(WMSTask mst) { try { if (mst.S_B_STATE.Trim() != "等待") return true; if (string.IsNullOrEmpty(mst.S_START_LOC)) return false; //if (string.IsNullOrEmpty(mst.S_START_LOC)) return false; var reservoirs = Settings.ReservoirAreas?.ToList(); if (reservoirs == null || !reservoirs.Any()) @@ -947,7 +947,13 @@ case "合托回库": return HandleMergeReturn(mst, reservoirs); case "分拣回库": return HandleMergeReturn(mst, reservoirs); return await SortingReturn(mst, reservoirs); case "解绑回库": return await UnbindReturn(mst, reservoirs); case "空托回库": return await EmptyPalletReturn(mst, reservoirs); case "空托出库": return EmptyPalletOutbound(mst); case "料箱出库": return HandleBoxOutbound(mst, reservoirs); case "发货暂存": @@ -1135,7 +1141,7 @@ } /// <summary> /// 合托回库 || 分拣回库 /// 合托回库 /// </summary> /// <param name="mst"></param> /// <param name="reservoirs"></param> @@ -1237,6 +1243,218 @@ } } return true; } /// <summary> /// 分拣回库 /// </summary> /// <param name="mst"></param> /// <param name="reservoirs"></param> /// <returns></returns> private static async Task<bool> SortingReturn(WMSTask mst, List<ReservoirArea> reservoirs) { var trayLst = ContainerHelper.GetCntr(mst.S_CNTR_CODE); if (trayLst != null && trayLst.S_TYPE.Equals("托盘")) { //托盘分拣回库 var area = reservoirs.Where(s => s.areaName == "入库接驳位").FirstOrDefault(); if (area == null) { LogHelper.Info("Settings出现错误未查询到入库接驳位!", "杭氧"); return false; } //(2.1)先查询入库接驳位是否为空,如果为空直接生成到入库的任务 var anyLoc = LocationHelper.GetLocAreaList(area.areaCode); if (anyLoc.Any()) { //生成到接驳位的任务 var res = TaskProcess.HYCreateTransport(mst.S_START_LOC, anyLoc.FirstOrDefault().S_CODE, "托盘分拣回库", mst.S_CNTR_CODE, mst.S_CODE); if (!res) { LogHelper.Info("托盘分拣回库任务创建失败!", "杭氧"); return false; } WMSHelper.UpdateStatus(mst, 1); } } else { //料箱回库 var inbound = new Inbound() { areaCode = "LXLKQ" }; var wh = new Warehouse(inbound); var stored = await wh.StoreItemAsync(); if (stored == null) { LogHelper.Info($"未查询到{inbound.areaCode}可用货位!", "杭氧"); return false; } var res = TaskProcess.HYCreateTransport(mst.S_START_LOC, stored.loationCode, "料箱分拣回库" , mst.S_CNTR_CODE, mst.S_CODE); if (!res) { LogHelper.Info("料箱分拣回库任务创建失败!", "杭氧"); return false; } WMSHelper.UpdateStatus(mst, 1); } return true; } /// <summary> /// 解绑回库 /// </summary> /// <param name="mst"></param> /// <param name="reservoirs"></param> /// <returns></returns> private static async Task<bool> UnbindReturn(WMSTask mst, List<ReservoirArea> reservoirs) { var trayLst = ContainerHelper.GetCntr(mst.S_CNTR_CODE); if (trayLst != null && trayLst.S_TYPE.Equals("托盘")) { //托盘分拣回库 var area = reservoirs.Where(s => s.areaName == "入库接驳位").FirstOrDefault(); if (area == null) { LogHelper.Info("Settings出现错误未查询到入库接驳位!", "杭氧"); return false; } //(2.1)先查询入库接驳位是否为空,如果为空直接生成到入库的任务 var anyLoc = LocationHelper.GetLocAreaList(area.areaCode); if (anyLoc.Any()) { //生成到接驳位的任务 var res = TaskProcess.HYCreateTransport(mst.S_START_LOC, anyLoc.FirstOrDefault().S_CODE, "托盘解绑回库", mst.S_CNTR_CODE, mst.S_CODE); if (!res) { LogHelper.Info("托盘解绑回库任务创建失败!", "杭氧"); return false; } WMSHelper.UpdateStatus(mst, 1); } } else { //料箱回库 var inbound = new Inbound() { areaCode = "LXLKQ" }; var wh = new Warehouse(inbound); var stored = await wh.StoreItemAsync(); if (stored == null) { LogHelper.Info($"未查询到{inbound.areaCode}可用货位!", "杭氧"); return false; } var res = TaskProcess.HYCreateTransport(mst.S_START_LOC, stored.loationCode, "料箱解绑回库", mst.S_CNTR_CODE, mst.S_CODE); if (!res) { LogHelper.Info("料箱解绑回库任务创建失败!", "杭氧"); return false; } WMSHelper.UpdateStatus(mst, 1); } return true; } /// <summary> /// 空托回库 /// </summary> /// <param name="mst"></param> /// <param name="reservoirs"></param> /// <returns></returns> private static async Task<bool> EmptyPalletReturn(WMSTask mst, List<ReservoirArea> reservoirs) { var trayLst = ContainerHelper.GetCntr(mst.S_CNTR_CODE); if (trayLst != null && trayLst.S_TYPE.Equals("托盘")) { //托盘空托回库 var area = reservoirs.Where(s => s.areaName == "入库接驳位").FirstOrDefault(); if (area == null) { LogHelper.Info("Settings出现错误未查询到入库接驳位!", "杭氧"); return false; } //(2.1)先查询入库接驳位是否为空,如果为空直接生成到入库的任务 var anyLoc = LocationHelper.GetLocAreaList(area.areaCode); if (anyLoc.Any()) { //生成到接驳位的任务 var res = TaskProcess.HYCreateTransport(mst.S_START_LOC, anyLoc.FirstOrDefault().S_CODE, "托盘空托回库", mst.S_CNTR_CODE, mst.S_CODE); if (!res) { LogHelper.Info("托盘空托回库任务创建失败!", "杭氧"); return false; } WMSHelper.UpdateStatus(mst, 1); } } else { //料箱空托回库 var inbound = new Inbound() { areaCode = "LXLKQ" }; var wh = new Warehouse(inbound); var stored = await wh.StoreItemAsync(); if (stored == null) { LogHelper.Info($"未查询到{inbound.areaCode}可用货位!", "杭氧"); return false; } var res = TaskProcess.HYCreateTransport(mst.S_START_LOC, stored.loationCode, "料箱空托回库", mst.S_CNTR_CODE, mst.S_CODE); if (!res) { LogHelper.Info("料箱空托回库任务创建失败!", "杭氧"); return false; } WMSHelper.UpdateStatus(mst, 1); } return true; } /// <summary> /// 空托出库 /// </summary> /// <param name="mst"></param> /// <param name="reservoirs"></param> /// <returns></returns> private static bool EmptyPalletOutbound(WMSTask mst) { var result = true; var scheduler = new EmptyPalletOutboundScheduler(mst.S_START_AREA); var outbound = new Outbound { endArea = mst.S_END_AREA, endBit = mst.S_END_LOC, requiredCount = 1, taskType = "空托出库" }; // 请求出库 var tasks = scheduler.GenerateEmptyPalletTasks(outbound); foreach (var item in tasks) { // 创建出库任务 var res = TaskProcess.HYCreateTransport(item.S_START_LOC, item.S_END_LOC, item.S_TYPE, item.S_CNTR_CODE, mst.S_CODE); mst.S_START_LOC = item.S_START_LOC; mst.S_CNTR_CODE = item.S_CNTR_CODE; //修改空托出库起点和托盘码 UpdateTask(mst,1); if (!res) { LogHelper.Info($"根据配盘单生成出库任务创建出库任务失败!!"); return false; } } return result; } /// <summary> @@ -1370,6 +1588,8 @@ if (locList.Any()) { var startLoc = WMSHelper.GetCntrLoc(mst.S_CNTR_CODE); if (startLoc != null) { // 创建出库任务 var res = TaskProcess.HYCreateTransport(startLoc.S_LOC_CODE, locList.FirstOrDefault().S_CODE, mst.S_TYPE, mst.S_CNTR_CODE, mst.S_CODE); if (!res) @@ -1377,6 +1597,8 @@ LogHelper.Info($"根据配盘单生成出库任务创建出库任务失败!!"); return false; } } } return true; @@ -1595,6 +1817,10 @@ if (list == null) { list = WMSHelper.GetWmsTaskList("执行", item.cntrNo); if (list != null && list.S_TYPE.Contains("回库")) { list.S_END_AREA = "TPLKQ"; } } if (list == null) { HH.WCS.Mobox3.HangYang/util/HttpHelper.cs
@@ -55,7 +55,7 @@ #endregion #region WebHelper public string WebPost(string url, string postData, string cotentType = "application/json") public string WebHttpPost(string url, string postData, string cotentType = "application/json") { Console.WriteLine(url); WebRequest request = WebRequest.Create(url); HH.WCS.Mobox3.HangYang/wms/ContainerHelper.cs
@@ -21,160 +21,7 @@ var date = DateTime.Now.ToString("yyMMdd"); return $"TP{date}{id.ToString().PadLeft(4, '0')}"; } /// <summary> /// 根据容器类型、目的地、状态查询容器 /// </summary> /// <param name="dest"></param> /// <param name="cntrType"></param> /// <param name="state"></param> /// <returns></returns> internal static List<Container> GetCntrListByPurpose(string dest, string cntrType, int state) { //1.0 查货位容器表 var db = new SqlHelper<object>().GetInstance(); var list = db.Queryable<Container>().Where(a => a.S_DEST == dest && a.S_TYPE == cntrType && a.N_B_STATE == state).ToList(); return list; } /// <summary> /// 创建托盘物料绑定关系 /// </summary> /// <param name="loc"></param> /// <param name="cntr"></param> /// <param name="itemcode"></param> /// <returns></returns> internal static bool CreateCntrItem(string loc, string cntr, string itemcode, string itemname, string itemtype, string cntrtype, string batch, int weight, string unit) { var res = false; var db = new SqlHelper<object>().GetInstance(); try { var location = db.Queryable<Location>().Where(a => a.S_CODE == loc).First(); if (location != null) { LogHelper.Info($"托盘{cntr}:添加货位{loc}绑定关系,添加容器货品表"); db.BeginTran(); var con = db.Queryable<Container>().Where(a => a.S_CODE.Trim() == cntr).First(); if (con == null) { var container = new Container { S_CODE = cntr, S_TYPE = cntrtype }; db.Insertable<Container>(container).ExecuteCommand(); } var cntritem = db.Queryable<CntrItemDetail>().Where(a => a.S_CNTR_CODE.Trim() == cntr).First(); if (cntritem == null) { var cir = new CntrItemDetail { S_CNTR_CODE = cntr, S_ITEM_CODE = itemcode, S_ITEM_NAME = itemname, S_ITEM_SPEC = itemtype, S_WU = unit, F_NET_WEIGHT = weight, S_BATCH_NO = batch }; db.Insertable<CntrItemDetail>(cir).ExecuteCommand(); } var loctp = new LocCntrRel { S_LOC_CODE = loc, S_CNTR_CODE = cntr }; db.Insertable<LocCntrRel>(loctp).ExecuteCommand(); location.N_CURRENT_NUM = location.N_CURRENT_NUM + 1; db.Updateable(location).UpdateColumns(it => new { it.N_CURRENT_NUM }).ExecuteCommand(); db.Ado.CommitTran(); res = true; } } catch (Exception ex) { LogHelper.Info($"CreateCntrItem => erro:托盘{cntr}添加失败" + ex.Message.ToString()); db.Ado.RollbackTran(); } return res; } /// <summary> /// 创建托盘物料绑定关系 /// </summary> /// <param name="loc"></param> /// <param name="cntr"></param> /// <param name="itemcode"></param> /// <returns></returns> internal static bool CreateCntrItem(string cntr, string itemcode, string itemname, string batch, string weight) { var res = false; var db = new SqlHelper<object>().GetInstance(); try { LogHelper.Info($"托盘{cntr}:添加物料{itemcode}绑定关系"); db.BeginTran(); var cntritem = db.Queryable<CntrItemDetail>().Where(a => a.S_CNTR_CODE.Trim() == cntr).First(); if (cntritem == null) { var cir = new CntrItemDetail { S_CNTR_CODE = cntr, S_ITEM_CODE = itemcode, S_ITEM_NAME = itemname, F_NET_WEIGHT = float.Parse(weight), S_BATCH_NO = batch }; db.Insertable<CntrItemDetail>(cir).ExecuteCommand(); } else { cntritem.S_ITEM_CODE = itemcode; cntritem.S_ITEM_NAME = itemname; cntritem.F_NET_WEIGHT = float.Parse(weight); cntritem.S_BATCH_NO = batch; db.Updateable<CntrItemDetail>(cntritem).ExecuteCommand(); } var con = db.Queryable<Container>().Where(a => a.S_CODE.Trim() == cntr).First(); if (con == null) { var container = new Container { S_CODE = cntr }; db.Insertable<Container>(container).ExecuteCommand(); } db.Ado.CommitTran(); res = true; } catch (Exception ex) { LogHelper.Info($"CreateCntrItem => erro:托盘{cntr}添加失败" + ex.Message.ToString()); db.Ado.RollbackTran(); } return res; } /// <summary> /// 判断容器是否有物料信息 /// </summary> /// <param name="cntr"></param> /// <returns></returns> internal static bool CheckEmpty(string cntr) { //1.0 查货位容器表 var db = new SqlHelper<object>().GetInstance(); return db.Queryable<LocCntrRel>().Count(a => a.S_LOC_CODE.Trim() == cntr) == 0; } internal static bool AddCntr(string cntrCode, string itemCode) { var res = false; var db = new SqlHelper<object>().GetInstance(); var TN_Container = new Container { S_CODE = cntrCode }; var cntrItemRel = new CntrItemDetail { S_CNTR_CODE = cntrCode, S_ITEM_CODE = itemCode }; try { db.BeginTran(); db.Insertable<Container>(TN_Container).ExecuteCommand(); db.Insertable<CntrItemDetail>(cntrItemRel).ExecuteCommand(); db.CommitTran(); res = true; } catch (Exception ex) { db.RollbackTran(); } return res; } /// <summary> /// 根据容器号获取容器信息 @@ -208,335 +55,6 @@ var db = new SqlHelper<object>().GetInstance(); var list = db.Queryable<CntrItemDetail>().Where(a => a.S_CNTR_CODE.Trim() == cntr).ToList(); return list; } /// <summary> /// 根据物料获取容器信息 /// </summary> /// <param name="cntr"></param> /// <returns></returns> internal static List<CntrItemDetail> GetItemCntrRel(string itemcode) { var db = new SqlHelper<object>().GetInstance(); var list = db.Queryable<CntrItemDetail>().Where(a => a.S_ITEM_CODE.Trim() == itemcode.Trim()).ToList(); return list; } /// <summary> /// 物料信息绑定到满容器上 /// </summary> /// <param name="cntrCode"></param> /// <param name="itemCode"></param> /// <param name="batchNo"></param> /// <param name="qty"></param> /// <param name="purpose">容器用途,用于哪个线边还是目的点</param> /// <returns></returns> internal static bool BindCntrItemSingle(Container cntr, string itemCode, string batchNo, float qty) { var res = false; var db = new SqlHelper<object>().GetInstance(); try { db.BeginTran(); db.Updateable(cntr).UpdateColumns(it => new { it.S_DEST }).ExecuteCommand(); //1.将原有容器物料信息删除 db.Deleteable<CntrItemDetail>().Where(it => it.S_CNTR_CODE == cntr.S_CODE.Trim()).ExecuteCommand(); //2.插入新的容器物料信息(容器号不变) var cir = new CntrItemDetail { S_CNTR_CODE = cntr.S_CODE.Trim(), S_BATCH_NO = batchNo, F_QTY = qty, S_ITEM_CODE = itemCode }; db.Insertable<CntrItemDetail>(cir).ExecuteCommand(); db.CommitTran(); res = true; } catch (Exception ex) { db.RollbackTran(); } return res; } /// <summary> /// 根据容器来源和状态获取托盘 /// </summary> /// <param name="src"></param> /// <param name="state"></param> /// <returns></returns> internal static List<Container> GetCntr(string dest, int state, string cntrType = "") { var db = new SqlHelper<object>().GetInstance(); if (cntrType == "") { return db.Queryable<Container>().Where(a => a.S_DEST == dest && a.N_B_STATE == state).ToList(); } else { return db.Queryable<Container>().Where(a => a.S_DEST == dest && a.N_B_STATE == state && a.S_TYPE == cntrType).ToList(); } } internal static bool UpdateCntr(List<string> cntrs, string dest, int state) { var res = false; var db = new SqlHelper<object>().GetInstance(); var models = db.Queryable<Container>().Where(a => cntrs.Contains(a.S_CODE)).ToList(); if (models.Count > 0) { models.ForEach(a => { a.S_DEST = dest; a.N_B_STATE = state; db.Updateable(a).UpdateColumns(it => new { it.S_DEST, it.N_B_STATE }).ExecuteCommand(); }); res = true; } return res; } internal static bool UpdateCntrDest(List<string> cntrs, string dest) { var res = false; var db = new SqlHelper<object>().GetInstance(); var models = db.Queryable<Container>().Where(a => cntrs.Contains(a.S_CODE)).ToList(); if (models.Count > 0) { models.ForEach(a => { a.S_DEST = dest; db.Updateable(a).UpdateColumns(it => new { it.S_DEST }).ExecuteCommand(); }); res = true; } return res; } /// <summary> /// 更新托盘来源 /// </summary> /// <param name="cntr"></param> /// <param name="src"></param> /// <returns></returns> internal static bool UpdateCntrSrc(string cntr, string src) { var res = false; var db = new SqlHelper<object>().GetInstance(); var model = db.Queryable<Container>().Where(a => a.S_CODE == cntr).First(); if (model != null) { model.S_SRC = src; model.T_MODIFY = DateTime.Now; res = db.Updateable(model).UpdateColumns(it => new { it.S_SRC, it.T_MODIFY }).ExecuteCommand() > 0; } return res; } internal static bool UpdateCntrState(List<string> cntrs, int state) { var res = false; var db = new SqlHelper<object>().GetInstance(); var models = db.Queryable<Container>().Where(a => cntrs.Contains(a.S_CODE)).ToList(); if (models.Count > 0) { models.ForEach(a => { a.N_B_STATE = state; db.Updateable(a).UpdateColumns(it => new { it.N_B_STATE }).ExecuteCommand(); }); res = true; } return res; } internal static bool UpdateCntr(List<string> cntrs, string src, string dest, int state) { var res = false; var db = new SqlHelper<object>().GetInstance(); var models = db.Queryable<Container>().Where(a => cntrs.Contains(a.S_CODE)).ToList(); if (models.Count > 0) { models.ForEach(a => { a.S_DEST = dest; a.N_B_STATE = state; a.S_SRC = src; db.Updateable(a).UpdateColumns(it => new { it.S_DEST, it.N_B_STATE, it.S_SRC }).ExecuteCommand(); }); res = true; } return res; } public static bool ClearCntrInfo(string cntr) { var db = new SqlHelper<object>().GetInstance(); var model = db.Queryable<Container>().Where(a => a.S_CODE == cntr).First(); if (model != null) { model.S_SRC = ""; model.S_DEST = ""; model.N_B_STATE = 0; model.T_MODIFY = DateTime.Now; } db.Updateable(model).UpdateColumns(it => new { it.S_SRC, it.S_DEST, it.N_B_STATE, it.T_MODIFY }).ExecuteCommand(); return db.Deleteable<CntrItemDetail>().Where(a => a.S_CNTR_CODE.Trim() == cntr.Trim()).ExecuteCommand() > 0; } internal static List<Container> GetCntrBySrc(string src, int state, string cntrType = "") { var db = new SqlHelper<object>().GetInstance(); if (cntrType == "") { return db.Queryable<Container>().Where(a => a.S_SRC == src && a.N_B_STATE == state).ToList(); } else { return db.Queryable<Container>().Where(a => a.S_SRC == src && a.N_B_STATE == state && a.S_TYPE == cntrType).ToList(); } } /// <summary> /// enable 让托盘允许被出库计算到,同时增加量表数据 /// </summary> /// <param name="cntr"></param> internal static void Enable(string cntr, string loc) { var db = new SqlHelper<object>().GetInstance(); var cntrInfo = db.Queryable<Container>().Where(a => a.S_CODE == cntr).First(); //获取仓库量表 //获取物理库区 //获取逻辑库区 if (cntrInfo != null) { try { db.BeginTran(); //防止接口重复调用,量表重复增加 if (cntrInfo.C_ENABLE == "N") { cntrInfo.C_ENABLE = "Y"; db.Updateable(cntrInfo).UpdateColumns(a => new { a.C_ENABLE, a.T_MODIFY }).ExecuteCommand(); var cirList = db.Queryable<CntrItemDetail>().Where(a => a.S_CNTR_CODE == cntr).ToList(); if (cirList.Count > 0) { cirList.ForEach(a => { var wh = db.Queryable<WHInventory>().Where(b => b.S_ITEM_CODE == a.S_ITEM_CODE).First(); if (wh != null) { //更新仓库量表 wh.F_QTY += a.F_QTY; wh.T_MODIFY = DateTime.Now; db.Updateable(wh).UpdateColumns(it => new { it.F_QTY, it.T_MODIFY }).ExecuteCommand(); } else { //新增仓库量表 wh = new WHInventory { F_QTY = a.F_QTY, S_ITEM_CODE = a.S_ITEM_CODE }; db.Insertable(wh).ExecuteCommand(); } //写入第三方中间表 //如果要统计分拣中,分拣回的量,无法跟踪托盘,除非对托盘加标识,属于哪个库区。 //另外分拣回可能去别的巷道,别的逻辑库区,逻辑库区的量控制更复杂,不能计算分拣中和分拣回。所以库区量表本项目暂不考虑 /* //获取货位的物理库区和所有逻辑库区 var location = db.Queryable<Location>().Where(l => l.S_CODE == loc).First(); if (location != null) { var az = db.Queryable<AZInventory>().Where(b => b.S_ITEM_CODE == a.S_ITEM_CODE && b.S_AREA_CODE == location.S_AREA_CODE).First(); if (az != null) { //更新库区量表 az.F_QTY += a.F_QTY; az.T_MODIFY = DateTime.Now; db.Updateable(az).UpdateColumns(it => new { it.F_QTY, it.T_MODIFY }).ExecuteCommand(); } else { //新增库区量表 az = new AZInventory { F_QTY = a.F_QTY, S_ITEM_CODE = a.S_ITEM_CODE, S_AREA_CODE = location.S_AREA_CODE }; db.Insertable(az).ExecuteCommand(); } } //逻辑库区的量表 var zoneList = db.Queryable<ZoneLoc>().Where(l => l.S_LOC_CODE == loc).ToList(); if (zoneList.Count > 0) { zoneList.ForEach(z => { var az = db.Queryable<AZInventory>().Where(b => b.S_ITEM_CODE == a.S_ITEM_CODE && b.S_AREA_CODE == z.S_ZONE_CODE).First(); if (az != null) { //更新库区量表 az.F_QTY += a.F_QTY; az.T_MODIFY = DateTime.Now; db.Updateable(az).UpdateColumns(it => new { it.F_QTY, it.T_MODIFY }).ExecuteCommand(); } else { //新增库区量表 az = new AZInventory { F_QTY = a.F_QTY, S_ITEM_CODE = a.S_ITEM_CODE, S_AREA_CODE = z.S_ZONE_CODE, C_IS_LOGIC_AREA = "Y" }; db.Insertable(az).ExecuteCommand(); } }); } */ }); } } db.CommitTran(); } catch (Exception ex) { Console.WriteLine(ex.Message); db.RollbackTran(); } } } /// <summary> /// 绑定货位容器表 /// </summary> /// <param name="cntr"></param> /// <returns></returns> internal static bool BindLocCntrs(string loc, string cntr, string itemCode, string itemName) { bool result = true; List<string> list = new List<string>(cntr.Split(',')); var db = new SqlHelper<object>().GetInstance(); for (int i = 0; i < list.Count; i++) { if (!string.IsNullOrEmpty(list[i])) { string cntrCode = list[i]; if (db.Queryable<LocCntrRel>().Count(a => a.S_CNTR_CODE.Trim() == cntrCode) == 0) { var cir = new LocCntrRel { S_LOC_CODE = loc, S_CNTR_CODE = cntrCode }; var con = new Container { S_CODE = cntrCode,N_DETAIL_COUNT = 1 }; db.Insertable<LocCntrRel>(cir).ExecuteCommand(); db.Insertable<Container>(con).ExecuteCommand(); if (!string.IsNullOrEmpty(itemCode)) { ContainerHelper.BindCntrItem(cntrCode, itemCode, itemName); } } } } //1.0 查货位容器表 return result; } /// <summary> /// 绑定容器物料表 /// </summary> /// <param name="itemCode"></param> /// <param name="batchNo"></param> /// <param name="qty"></param> /// <returns></returns> internal static bool BindCntrItem(string trayCode, string itemCode, string itemName) { var res = false; var db = new SqlHelper<object>().GetInstance(); try { db.BeginTran(); var cir = new CntrItemDetail { S_CNTR_CODE = trayCode, S_ITEM_CODE = itemCode, S_ITEM_NAME = itemName }; db.Insertable<CntrItemDetail>(cir).ExecuteCommand(); db.Ado.CommitTran(); res = true; } catch (Exception ex) { db.Ado.RollbackTran(); } return res; } #region 杭氧货位容器物料帮助方法 @@ -607,6 +125,26 @@ return model; } internal static LocCntrRel GetLocCntr(string loc) { var db = new SqlHelper<object>().GetInstance(); var model = db.Queryable<LocCntrRel>().Where(s => s.S_LOC_CODE == loc).First(); return model; } internal static bool GetLocItemRel(string loc) { bool result = false; var db = new SqlHelper<object>().GetInstance(); var model = db.Queryable<LocCntrRel>().Where(s => s.S_LOC_CODE == loc).First(); if (model != null) { var list = db.Queryable<CntrItemDetail>().Where(a => a.S_CNTR_CODE.Trim() == model.S_CNTR_CODE).ToList(); result = list.Any() ? false : true; } return result; } #endregion HH.WCS.Mobox3.HangYang/wms/LocationHelper.cs
@@ -460,15 +460,6 @@ return db.Queryable<ZoneLoc>().Where(a => a.S_LOC_CODE == loc).ToList(); } internal static void Test() { //多查询一次也是可以的,先查出可用的货位组,然后选择货位组中列比较大的,或者列比较小的 var availableRowGroups = new List<Location>().GroupBy(l => l.N_ROW_GROUP).Where(g => !g.Any(l => l.N_LOCK_STATE != 0)).Select(g => g.Key); var db = new SqlHelper<object>().GetInstance(); //db.Queryable<Location>().Where(a => a.S_AREA_CODE == "11").Where(a => SqlFunc.Subqueryable<Location>().Where(b => b.)).GroupBy(z => z.N_ROW_GROUP).ToList(); } #region 杭氧货位帮助Helper HH.WCS.Mobox3.HangYang/wms/WCSHelper.cs
@@ -44,16 +44,7 @@ db.Updateable(task).UpdateColumns(it => new { it.S_EQ_TASK_CODE, it.T_MODIFY }).ExecuteCommand(); return res; } internal static bool UpdateInfo(WCSTask task, string sourceNo, string endBit, string status) { var res = false; var db = new SqlHelper<WCSTask>().GetInstance(); task.S_B_STATE = status; task.S_OP_CODE = sourceNo; task.S_END_LOC = endBit; db.Updateable(task).UpdateColumns(it => new { it.S_B_STATE, it.S_OP_CODE, it.S_END_LOC }).ExecuteCommand(); return res; } internal static WCSTask GetTask(string no) { var db = new SqlHelper<WCSTask>().GetInstance(); @@ -62,35 +53,8 @@ } internal static List<WCSTask> GetTaskBycntrcode(string no) { var db = new SqlHelper<WCSTask>().GetInstance(); var task = db.Queryable<WCSTask>().Where(a => a.S_CNTR_CODE.Trim() == no && a.S_B_STATE.Trim() == "完成").ToList(); return task; } internal static WCSTask GetTaskBySrcNo(string no) { var db = new SqlHelper<WCSTask>().GetInstance(); var task = db.Queryable<WCSTask>().Where(a => a.S_OP_CODE == no).First(); return task; } internal static List<WCSTask> GetTaskByStart(string bit) { var db = new SqlHelper<WCSTask>().GetInstance(); var task = db.Queryable<WCSTask>().Where(a => a.S_START_LOC == bit).ToList(); return task; } internal static List<WCSTask> GetTaskByEnd(string bit) { var db = new SqlHelper<WCSTask>().GetInstance(); var task = db.Queryable<WCSTask>().Where(a => a.S_END_LOC == bit).ToList(); return task; } internal static List<WCSTask> GetTaskByType(string taskType) { var db = new SqlHelper<WCSTask>().GetInstance(); return db.Queryable<WCSTask>().Where(a => a.S_TYPE == taskType).ToList(); } internal static bool CreateTask(string no, string from, string to, string taskType, int pri, string cntrInfo, int cntrCount = 1, int startLayer = 1, int endLayer = 1) { var whCode = Settings.WHCode; @@ -142,10 +106,7 @@ }; return CreateTask(TN_Task); } internal static bool CheckExist(string no) { return GetTask(no) != null; } internal static bool UpdateStatus(string no, int state) { var res = false; @@ -237,20 +198,5 @@ return db.Queryable<WCSTask>().Where(a => a.S_B_STATE.Trim() == status).OrderBy(s => s.T_CREATE).ToList(); } internal static List<WCSTask> GetTaskListByState(int state) { var db = new SqlHelper<object>().GetInstance(); return db.Queryable<WCSTask>().Where(a => a.N_B_STATE == state).ToList(); } internal static List<WCSTask> GetWaitingTaskList() { var db = new SqlHelper<object>().GetInstance(); return db.Queryable<WCSTask>().Where(a => a.N_B_STATE == 0).ToList(); } } } HH.WCS.Mobox3.HangYang/wms/WMSHelper.cs
@@ -42,63 +42,10 @@ var date = DateTime.Now.ToString("yyMMdd"); return $"SO{date}{id.ToString().PadLeft(4, '0')}"; } internal static List<WMSTask> GetOperationListByState(string state) { var db = new SqlHelper<object>().GetInstance(); return db.Queryable<WMSTask>().Where(a => a.S_B_STATE == state).ToList(); } internal static List<WMSTask> GetOperationListByState(int state) { var db = new SqlHelper<object>().GetInstance(); return db.Queryable<WMSTask>().Where(a => a.N_B_STATE == state).ToList(); } internal static List<WMSTask> GetWaitingOperationList() { var db = new SqlHelper<object>().GetInstance(); return db.Queryable<WMSTask>().Where(a => a.N_B_STATE == 0 || a.N_B_STATE == 3).ToList(); } internal static PutawayOrder GetPutawayOrder(string no) { var db = new SqlHelper<object>().GetInstance(); return db.Queryable<PutawayOrder>().Where(a => a.S_NO == no).First(); } internal static bool CreatePutawayOrder(PutawayOrder model) { var db = new SqlHelper<object>().GetInstance(); var result = db.Insertable<PutawayOrder>(model).ExecuteCommand() > 0; db.Insertable<PutawayDetail>(model.Details).ExecuteCommand(); return result; } internal static PutawayDetail GetPutawayOrderDetail(string no, string item_code) { var db = new SqlHelper<object>().GetInstance(); return db.Queryable<PutawayDetail>().Where(a => a.S_PUTAWAY_NO == no && a.S_ITEM_CODE == item_code).First(); } internal static PutawayDetail GetPutawayOrderDetail(string item_code) { var db = new SqlHelper<object>().GetInstance(); return db.Queryable<PutawayDetail>().Where(a => a.S_ITEM_CODE == item_code && a.F_QTY - a.F_ACC_B_QTY > 0).OrderByDescending(a => a.T_CREATE).First(); } internal static void UpdatePutawayOrderDetailQty(PutawayDetail model) { var db = new SqlHelper<object>().GetInstance(); db.Updateable(model).UpdateColumns(it => new { it.F_ACC_B_QTY }).ExecuteCommand(); } internal static ShippingOrder GetShippingOrder(string no) { var db = new SqlHelper<object>().GetInstance(); return db.Queryable<ShippingOrder>().Includes(a => a.Details).Where(a => a.S_NO == no).First(); } internal static bool CreateShippingOrder(ShippingOrder model) { var db = new SqlHelper<object>().GetInstance(); var result = db.Insertable<ShippingOrder>(model).ExecuteCommand() > 0; db.Insertable<ShippingDetail>(model.Details).ExecuteCommand(); return result; } internal static bool CreateSortingOrder(List<string> list) @@ -273,11 +220,6 @@ throw new NotImplementedException(); } internal static Location GetStart(WMSTask a) { throw new NotImplementedException(); } internal static void UpdateTaskState(WMSTask task) { var db = new SqlHelper<object>().GetInstance(); @@ -293,11 +235,8 @@ return db.Updateable<WMSTask>(a).UpdateColumns(it => new { it.S_END_LOC, it.T_MODIFY }).ExecuteCommand() > 0; } internal static WMSTask GetWmsTask(string code) { var db = new SqlHelper<object>().GetInstance(); return db.Queryable<WMSTask>().Where(a => a.S_CODE == code).First(); } internal static void CreateSortingOrderDetail(string so_no) { @@ -372,15 +311,6 @@ } } /// <summary> /// 获取开始配货的分拣单,一次性生成分拣明细,避免生成一半再生成,所以创建分拣明细的时候加上事务 /// </summary> /// <returns></returns> internal static List<SortingOrder> GetWaitingSortingOrderList() { var db = new SqlHelper<object>().GetInstance(); return db.Queryable<SortingOrder>().Includes(a => a.Composes).Where(a => a.N_B_STATE == 1 || a.N_B_STATE == 20).ToList(); } /// <summary> /// 获取配货完成的分拣单,每个分拣单单独创建分拣作业 /// </summary> @@ -917,6 +847,14 @@ return res; } internal static bool UpdateTask(WMSTask a, int state) { var db = new SqlHelper<object>().GetInstance(); a.T_MODIFY = DateTime.Now; a.N_B_STATE = state; a.S_B_STATE = GetStateStr(state); return db.Updateable<WMSTask>(a).UpdateColumns(it => new { it.N_B_STATE, it.S_B_STATE, it.S_CNTR_CODE, it.S_START_LOC, it.T_MODIFY }).ExecuteCommand() > 0; } #endregion @@ -1099,7 +1037,7 @@ } /// <summary> /// 立库出库封装算法 /// 配盘出库封装算法 /// </summary> public class DoubleDeepOutboundScheduler { @@ -1117,7 +1055,7 @@ // 生成出库任务队列(含移库任务) /// <summary> /// 立库WMS货位出库算法(运用于配盘单出库、空托出库) /// 立库WMS货位出库算法(运用于配盘单出库) /// </summary> /// <param name="outbound">出库参数</param> /// <returns></returns> @@ -1134,7 +1072,7 @@ var wmsTask = WMSHelper.GetWmsTaskList("执行", outboundItem.trayCode); if (wmsTask == null) { LogHelper.Info($"未查询到在执行中的作业:{outboundItem.trayCode}!", "杭氧"); //LogHelper.Info($"未查询到在执行中的作业:{outboundItem.trayCode}!", "杭氧"); outboundItem.opCode = ""; } @@ -1158,6 +1096,7 @@ .Where(x => x.S_CODE == outerLoc.S_CODE) .ToList() .ForEach(x => x.N_LOCK_STATE = 3); var trayCode = ContainerHelper.GetLocCntr(outerLoc.S_CODE); tasks.Add(new WCSTask { S_CODE = GenerateTaskNo(), @@ -1171,20 +1110,14 @@ N_SCHEDULE_TYPE = 1, N_B_STATE = 0, S_B_STATE = WCSTask.GetStateStr(0), S_CNTR_CODE = outboundItem.trayCode, S_CNTR_CODE = trayCode.S_CNTR_CODE, N_START_LAYER = 1, N_END_LAYER = 1, N_CNTR_COUNT = 1 }); } else continue; } //else //{ // //货位为空直接生成出库任务 // tasks.Add(CreateOutboundTask(targetLoc, outboundItem)); //} } else { @@ -1245,7 +1178,7 @@ S_END_LOC = outbound.endBit, S_TYPE = outbound.taskType, S_OP_CODE = outbound.opCode, N_PRIORITY = 1, N_PRIORITY = 0, N_SCHEDULE_TYPE = 1, N_B_STATE = 0, S_B_STATE = WCSTask.GetStateStr(0), @@ -1294,6 +1227,182 @@ } } public class EmptyPalletOutboundScheduler { private readonly List<Location> _allLocations; public EmptyPalletOutboundScheduler(string areaCode) { var db = new SqlHelper<object>().GetInstance(); _allLocations = db.Queryable<Location>() .Where(a => a.S_AREA_CODE == areaCode) .ToList(); } /// <summary> /// 空托盘出库算法(自动寻找可用空托并生成任务) /// </summary> public List<WCSTask> GenerateEmptyPalletTasks(Outbound outbound) { var tasks = new List<WCSTask>(); var foundPallets = 0; if (foundPallets < outbound.requiredCount) { var doubleDeepPallets = FindDoubleDeepEmptyPallets(); foreach (var palletLoc in doubleDeepPallets) { if (IsDoubleDeepRow(palletLoc.N_ROW)) { var outerLoc = FindOuterLocation(palletLoc); if (outerLoc != null) { if (outerLoc.N_CURRENT_NUM == outerLoc.N_CAPACITY) { // 优先移到深位,其次外侧 var bestTarget = FindBestRelocationTarget(outerLoc); if (bestTarget != null) { //计算到了外侧把外侧的货位锁定 _allLocations .Where(x => x.S_CODE == outerLoc.S_CODE) .ToList() .ForEach(x => x.N_LOCK_STATE = 3); var trayCode = ContainerHelper.GetLocCntr(outerLoc.S_CODE); tasks.Add(new WCSTask { S_CODE = GenerateTaskNo(), S_START_AREA = outerLoc.S_AREA_CODE, S_END_AREA = bestTarget.S_AREA_CODE, S_START_LOC = outerLoc.S_CODE, S_END_LOC = bestTarget.S_CODE, S_TYPE = "深位移库", S_OP_CODE = outbound.opCode, N_PRIORITY = 1, N_SCHEDULE_TYPE = 1, N_B_STATE = 0, S_B_STATE = WCSTask.GetStateStr(0), S_CNTR_CODE = trayCode.S_CNTR_CODE, N_START_LAYER = 1, N_END_LAYER = 1, N_CNTR_COUNT = 1 }); } else continue; } } } var tray = ContainerHelper.GetLocCntr(palletLoc.S_CODE); outbound.trayCode = tray.S_CNTR_CODE; tasks.Add(CreateEmptyPalletTask(palletLoc, outbound)); foundPallets++; if (foundPallets >= outbound.requiredCount) break; } } return tasks; } // 关键辅助方法 private List<Location> FindDoubleDeepEmptyPallets() => _allLocations.Where(loc => loc.N_LOCK_STATE == 0 && loc.N_CURRENT_NUM == loc.N_CAPACITY && ContainerHelper.GetLocItemRel(loc.S_CODE) ).OrderBy(loc => loc.N_ROW) // 按排排序 .ThenBy(loc => loc.N_COL) .ToList(); private WCSTask CreateEmptyPalletTask(Location loc, Outbound outbound) => new WCSTask { S_CODE = GenerateTaskNo(), S_START_AREA = loc.S_AREA_CODE, S_END_AREA = outbound.endArea, S_START_LOC = loc.S_CODE, S_END_LOC = outbound.endBit, S_TYPE = outbound.taskType, S_OP_CODE = outbound.opCode, N_PRIORITY = 0, N_SCHEDULE_TYPE = 1, N_B_STATE = 0, S_B_STATE = WCSTask.GetStateStr(0), S_CNTR_CODE = outbound.trayCode, N_START_LAYER = 1, N_END_LAYER = 1, N_CNTR_COUNT = 1 }; // 复用原有双深位方法 private bool IsDoubleDeepRow(int row) => row == 1 || row == 4; private Location FindTargetLocation(string code) => _allLocations.FirstOrDefault(loc => loc.S_CODE == code && loc.N_LOCK_STATE == 0); //查询深位外侧的货位 private Location FindOuterLocation(Location deepLoc) => _allLocations.FirstOrDefault(loc => loc.N_ROW != deepLoc.N_ROW && loc.N_ROADWAY == deepLoc.N_ROADWAY && loc.N_COL == deepLoc.N_COL && loc.N_LAYER == deepLoc.N_LAYER && loc.N_LOCK_STATE == 0 || loc.N_LOCK_STATE == 5 ); private Location FindBestRelocationTarget(Location outerLoc) { return _allLocations .Where(loc => loc.N_ROADWAY == outerLoc.N_ROADWAY && loc.N_LOCK_STATE == 0 && loc.N_CURRENT_NUM == 0 && loc.S_CODE != outerLoc.S_CODE) .OrderBy(loc => loc.N_ROW == outerLoc.N_ROW ? 1 : 0) .ThenBy(loc => loc.N_COL) .ThenBy(loc => Math.Abs(loc.N_LAYER - outerLoc.N_LAYER)) .FirstOrDefault(); } private void MarkReservedLocations(List<Outbound> outbound) { //查询已经被锁住的货位 var lockLoc = _allLocations .Where(loc => loc.N_LOCK_STATE != 0) .ToList(); //把锁住的货位标记为占用 foreach (var item in lockLoc) { if (IsDoubleDeepRow(item.N_ROW)) { _allLocations .Where(x => x.S_CODE == item.S_CODE) .ToList() .ForEach(x => x.N_LOCK_STATE = 3); } } foreach (var item in outbound) { var loc = FindTargetLocation(item.locCode); if (loc != null && IsDoubleDeepRow(loc.N_ROW)) { // 标记该深位对应的外侧货位(如果存在) var outerLoc = FindOuterLocation(loc); if (outerLoc != null) { // 标记深位的外侧货位(避免被移库占用) _allLocations .Where(x => x.S_CODE == outerLoc.S_CODE) .ToList() .ForEach(x => x.N_LOCK_STATE = 5); //标记深位的外侧货位为5 } } } } } #endregion #region 杭氧升降量表帮助方法