using HH.WCS.Mobox3.YNJT_BZP.api; using HH.WCS.Mobox3.YNJT_BZP.dispatch; using HH.WCS.Mobox3.YNJT_BZP.models; using HH.WCS.Mobox3.YNJT_BZP.models.other; using HH.WCS.Mobox3.YNJT_BZP.util; using Newtonsoft.Json; using NLog.Fluent; using SqlSugar; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Runtime.Remoting.Messaging; using System.Text; using System.Threading.Tasks; using static HH.WCS.Mobox3.YNJT_BZP.api.ApiModel; using static HH.WCS.Mobox3.YNJT_BZP.api.WmsController; namespace HH.WCS.Mobox3.YNJT_BZP.wms { /// /// wms管到作业 /// internal class WMSHelper { internal static string GenerateTaskNo() { var id = SYSHelper.GetSerialNumber("作业号", "OP"); var date = DateTime.Now.ToString("yyMMdd"); return $"OP{date}{id.ToString().PadLeft(4, '0')}"; } internal static string GenerateSortingNo() { var id = SYSHelper.GetSerialNumber("分拣单", "SO"); var date = DateTime.Now.ToString("yyMMdd"); return $"SO{date}{id.ToString().PadLeft(4, '0')}"; } internal static List GetOperationListByState(string state) { var db = new SqlHelper().GetInstance(); return db.Queryable().Where(a => a.S_B_STATE == state).ToList(); } internal static List GetOperationListByState(int state) { var db = new SqlHelper().GetInstance(); return db.Queryable().Where(a => a.N_B_STATE == state).ToList(); } internal static List GetWaitingOperationList() { var db = new SqlHelper().GetInstance(); return db.Queryable().Where(a => a.N_B_STATE == 0 || a.N_B_STATE == 3).ToList(); } internal static PutawayOrder GetPutawayOrder(string no) { var db = new SqlHelper().GetInstance(); return db.Queryable().Where(a => a.S_NO == no).First(); } internal static bool CreatePutawayOrder(PutawayOrder model) { var db = new SqlHelper().GetInstance(); var result = db.Insertable(model).ExecuteCommand() > 0; db.Insertable(model.Details).ExecuteCommand(); return result; } internal static PutawayDetail GetPutawayOrderDetail(string no, string item_code) { var db = new SqlHelper().GetInstance(); return db.Queryable().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().GetInstance(); return db.Queryable().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().GetInstance(); db.Updateable(model).UpdateColumns(it => new { it.F_ACC_B_QTY }).ExecuteCommand(); } internal static ShippingOrder GetShippingOrder(string no) { var db = new SqlHelper().GetInstance(); return db.Queryable().Includes(a => a.Details).Where(a => a.S_NO == no).First(); } internal static bool CreateShippingOrder(ShippingOrder model) { var db = new SqlHelper().GetInstance(); var result = db.Insertable(model).ExecuteCommand() > 0; db.Insertable(model.Details).ExecuteCommand(); return result; } internal static bool CreateSortingOrder(List list) { var res = false; //遍历获取发货单,然后判断库存,如果全都没库存,则不生成分拣单,如果有生成分拣单 //更新波次单,即使只有一个发货单也更新波次单 var db = new SqlHelper().GetInstance(); var sortingOrderNo = ""; SortingOrder sortingOrder = null; try { db.BeginTran(); list.ForEach(a => { var so = db.Queryable().Includes(s => s.Details).Where(s => s.S_NO == a).First(); //判断库存,只有已经入库的才可以计算,码盘的不算,入库后出库途中的也要计算,码盘后默认叫待入库,入库后叫正常 //生成出库任务,只有托盘位置在立库才需要创建出库任务(先写死立库) //只有全部分拣完成才允许回库(一个托盘可能对应多个分拣明细) //查找仓库量表和库区量表,出库单需要定位仓库和库区了,出库定位物理库区就行,入库可能物料库区还要区分逻辑库区 //暂时只查仓库量表(量表如何重置,查找所有查找C_ENABLE=N的,判断如果在仓库中,改成Y,然后统计) //生成分拣单时候增加仓库量表分配量,生成分拣单明细时候,增加库区量表分配量 if (so != null && so.Details.Count > 0) { var fail = true; for (int i = 0; i < so.Details.Count; i++) { var whi = db.Queryable().Where(w => w.S_ITEM_CODE == so.Details[i].S_ITEM_CODE).First(); if (whi != null && whi.F_QTY - whi.F_ALLOC_QTY > 0) { //有货就出 float qty = whi.F_QTY - whi.F_ALLOC_QTY > so.Details[i].F_QTY ? so.Details[i].F_QTY : whi.F_QTY - whi.F_ALLOC_QTY; fail = false; //有可用库存,生成分拣单 if (sortingOrderNo == "") { sortingOrderNo = GenerateSortingNo(); sortingOrder = new SortingOrder { S_NO = sortingOrderNo, S_SHIPPING_NO = so.S_NO, Composes = new List() }; //创建分拣单 db.Insertable(sortingOrder).ExecuteCommand(); } else { //获取最新分拣单 sortingOrder = db.Queryable().Includes(s => s.Composes).Where(s => s.S_NO == sortingOrderNo).First(); //更新分拣单中的发货单单号 sortingOrder.S_SHIPPING_NO = sortingOrder.S_SHIPPING_NO + ";" + so.S_NO; sortingOrder.T_MODIFY = DateTime.Now; db.Updateable(sortingOrder).UpdateColumns(it => new { it.S_SHIPPING_NO, it.T_MODIFY }).ExecuteCommand(); } //查询分拣单子表(正常情况还需要增加批次判断) var soc = db.Queryable().Where(s => s.S_ITEM_CODE == so.Details[i].S_ITEM_CODE && s.S_SORTING_NO == sortingOrder.S_NO).First(); if (soc == null) { soc = new SortingCompose { S_ITEM_CODE = so.Details[i].S_ITEM_CODE, S_SORTING_NO = sortingOrder.S_NO, F_QTY = qty, N_ROW_NO = sortingOrder.Composes.Count() + 1, S_BATCH_NO = so.Details[i].S_BATCH_NO }; //创建分拣单子表 db.Insertable(soc).ExecuteCommand(); } else { soc.F_QTY += qty; soc.T_MODIFY = DateTime.Now; //更新分拣单子表 db.Updateable(soc).UpdateColumns(it => new { it.F_QTY, it.T_MODIFY }).ExecuteCommand(); } //更新仓库量表分配量 whi.F_ALLOC_QTY += qty; whi.T_MODIFY = DateTime.Now; db.Updateable(whi).UpdateColumns(it => new { it.F_ALLOC_QTY, it.T_MODIFY }).ExecuteCommand(); //跟新发货单子表配货数量 so.Details[i].F_ACC_D_QTY += qty; so.Details[i].T_MODIFY = DateTime.Now; db.Updateable(so.Details[i]).UpdateColumns(it => new { it.F_ACC_D_QTY, it.T_MODIFY }).ExecuteCommand(); } } //更新发货单状态 so.N_B_STATE = fail ? 5 : 1; if (fail) { so.S_NOTE = "没有库存"; } so.S_WAVE_CODE = sortingOrderNo; so.T_MODIFY = DateTime.Now; db.Updateable(so).UpdateColumns(it => new { it.N_B_STATE, it.T_MODIFY, it.S_WAVE_CODE, it.S_NOTE }).ExecuteCommand(); } //查找库区内托盘生成托盘明细(包括分拣中)怎么判断库内?查找货位绑定?还是托盘上加标识比较好,如果是整托出的,分拣确认后去掉分拣标识。 //1、只有码盘入库后的才需要加标识,分拣回的不用,分拣回的标识还在,没有变。写死码盘入的完成后加标识,整托分拣的去掉标识,防止后面重新码盘脏数据 //2、或者关联查询库内的,只给分拣出的加标识,每次分拣回再把标识清除了(如果不清除带标识的会很多,还不如全部加标识),整托的清除。 //综合选择还是方案1,这样创建分拣明细,只需要托盘物料两表查询就能定位托盘(如果信息不准,可以重置),方案2需要货位、托盘、物料三表联查 //暂时不计库区,标识用容器表 C_ENABLE 来判断,表示能不能出库 //执行分拣创建任务,遍历分拣明细中的托盘,如果在仓库就出库,如果不在就不用出库 }); //全部分拣单生成之后将分拣单状态设置为开始配货,波次号为发货单 sortingOrder = db.Queryable().Where(s => s.S_NO == sortingOrderNo).First(); sortingOrder.N_B_STATE = 1; sortingOrder.T_MODIFY = DateTime.Now; db.Updateable(sortingOrder).UpdateColumns(it => new { it.N_B_STATE, it.T_MODIFY }).ExecuteCommand(); db.CommitTran(); res = true; } catch (Exception ex) { Console.WriteLine(ex.Message); db.RollbackTran(); } return res; } internal static List GetSortingDetailByCntr(string cntr) { var db = new SqlHelper().GetInstance(); var result = db.Queryable().Where(a => a.S_CNTR_CODE == cntr && a.N_B_STATE != 2).ToList(); return result; } internal static bool CreateWmsTask(WMSTask wmsTask) { try { var db = new SqlHelper().GetInstance(); return db.Insertable(wmsTask).ExecuteCommand() > 0; } catch (Exception ex) { Console.WriteLine(ex.Message); throw; } } internal static WMSTask GetWmsTaskByCntr(string cntr, bool active = true) { WMSTask result = null; var db = new SqlHelper().GetInstance(); if (active) { result = db.Queryable().Where(a => a.S_CNTR_CODE.Contains(cntr) && a.N_B_STATE < 2).OrderByDescending(a =>a.T_CREATE).First(); } else { result = db.Queryable().Where(a => a.S_CNTR_CODE.Contains(cntr)).OrderByDescending(a => a.T_CREATE).First(); } return result; } internal static Location GetEnd(WMSTask a) { throw new NotImplementedException(); } internal static Location GetStart(WMSTask a) { throw new NotImplementedException(); } internal static void UpdateTaskState(WMSTask task) { var db = new SqlHelper().GetInstance(); task.T_MODIFY = DateTime.Now; task.S_B_STATE = WMSTask.GetStateStr(task.N_B_STATE); db.Updateable(task).UpdateColumns(a => new { a.N_B_STATE, a.S_B_STATE, a.T_MODIFY }).ExecuteCommand(); } internal static bool UpdateTaskEnd(WMSTask a) { var db = new SqlHelper().GetInstance(); a.T_MODIFY = DateTime.Now; return db.Updateable(a).UpdateColumns(it => new { it.S_END_LOC,it.S_END_AREA, it.T_MODIFY }).ExecuteCommand() > 0; } internal static WMSTask GetWmsTask(string code) { var db = new SqlHelper().GetInstance(); return db.Queryable().Where(a => a.S_CODE == code).First(); } /// /// 类似农夫堆叠 /// /// /// /// /// internal static Location GetInstockEnd(string item, string endArea) { Location end = null; end = GetLocation4InAnySrc(endArea, item); if (end == null) { end = GetLocation4InEmptyRow(endArea); } return end; } public static Location GetLocation4InAnySrc(string area, string itemCode) { Location result = null; try { Console.WriteLine("成品满托入库 GetLocation4InAnySrc:" + area); //1.0 获取每一排最大的列 //1.1 判断当前数量是不是满的,如果是满的并且是最大列,需要排除 var listMaxCol = new SqlHelper().GetInstance().Queryable().Where(a => a.S_AREA_CODE == area ).OrderByDescending(a => a.N_COL).Take(1).PartitionBy(a => a.N_ROW).ToList(); //1.1 查到所有有托盘的排 Console.WriteLine("查到所有有托盘的排 "); var db = new SqlHelper().GetInstance(); var list = db.Queryable().Where(a => a.N_CURRENT_NUM > 0 && a.S_AREA_CODE == area ).Includes(a => a.LocCntrRel, a => a.CntrItemRel).OrderByDescending(a => a.N_COL).Take(1).PartitionBy(a => a.N_ROW).ToList(); if (list.Count > 0) { //1.2 查找其它尺寸有托盘或者锁定的排 for (int i = list.Count - 1; i >= 0; i--) { //排除已经锁定的货位 和 放满了且是最大列的货位 if (list[i].N_LOCK_STATE != 0 || (list[i].N_CURRENT_NUM == list[i].N_CAPACITY && listMaxCol.Count(a => a.S_CODE == list[i].S_CODE) > 0)) { Console.WriteLine($"排除已经锁定的货位 和 放满了且是最大列的货位 排{list[i].N_ROW}"); list.Remove(list[i]); } else { //排有锁也排除 var other = db.Queryable().Where(a => a.S_AREA_CODE == area && a.N_ROW == list[i].N_ROW && a.S_LOCK_STATE != "无" && a.N_LOCK_STATE != 0).First(); if (other != null) { Console.WriteLine($"排除有锁的排{list[i].N_ROW}"); list.Remove(list[i]); } } } Console.WriteLine($"有托盘排数为{list.Count}"); if (list.Count > 0) { //1.3 遍历判断物料类型是否相同 Console.WriteLine("遍历判断物料类型是否相同"); for (int i = 0; i < list.Count; i++) { //todo 还需要判断锁 if (list[i].LocCntrRel != null && list[i].LocCntrRel.CntrItemRel != null) { Console.WriteLine($"货位{list[i].S_CODE} 物料{list[i].LocCntrRel.CntrItemRel.S_ITEM_CODE}"); if (list[i].LocCntrRel.CntrItemRel.S_ITEM_CODE == itemCode) { if (list[i].N_CURRENT_NUM < list[i].N_CAPACITY) { result = list[i]; } else { Console.WriteLine("选择后面空位"); result = db.Queryable().Where(a => a.S_AREA_CODE == area && a.N_ROW == list[i].N_ROW && a.N_COL > list[i].N_COL && a.C_ENABLE == "Y").OrderBy(a => a.N_COL).First(); } if (result != null) { break; } } } } } } if (result != null && (!string.IsNullOrEmpty(result.C_ENABLE) && (result.C_ENABLE == "禁用" || result.C_ENABLE == "N"))) { //禁用了选择后面一个货位 //Console.WriteLine("禁用了选择后面一个货位"); result = db.Queryable().OrderBy(a => a.N_COL).Where(a => a.S_AREA_CODE == area && a.N_ROW == result.N_ROW && (string.IsNullOrEmpty(a.C_ENABLE) || (a.C_ENABLE != "禁用" && a.C_ENABLE != "N")) && a.N_COL > result.N_COL).First(); } } catch (Exception ex) { LogHelper.Error("GetLocation4InFinish:" + ex.Message, ex); } return result; } public static Location GetLocation4InEmptyRow(string area) { Location result = null; try { var db = new SqlHelper().GetInstance(); #region 查找所有数量是空的排 //Console.WriteLine("查找所有数量是空的排"); //2.0 简化查询只查每一排第一列 var list = db.Queryable().Where(a => a.S_AREA_CODE == area).OrderBy(a => a.N_COL).Take(1).PartitionBy(a => a.N_ROW).ToList().Where(a => a.N_CURRENT_NUM == 0 ).ToList(); //2.1 选一个空排 for (int i = 0; i < list.Count; i++) { var other = db.Queryable().Where(a => a.S_AREA_CODE == area && a.N_ROW == list[i].N_ROW && a.S_LOCK_STATE != "无").First(); if (list[i].N_LOCK_STATE == 0 && other == null) { //二次校验当前排所有货位都是空的,防止系统数据错乱 var rowSumInfo = db.Queryable().Where(l => l.S_AREA_CODE == area && l.N_ROW == list[i].N_ROW && l.N_CURRENT_NUM != 0).Count(); if (rowSumInfo == 0) { result = list[i]; break; } } } #endregion if (result != null && (!string.IsNullOrEmpty(result.C_ENABLE) && (result.C_ENABLE == "禁用" || result.C_ENABLE == "N"))) { //禁用了选择后面一个货位 Console.WriteLine("禁用了选择后面一个货位"); result = db.Queryable().OrderBy(a => a.N_COL).Where(a => a.S_AREA_CODE == area && a.N_ROW == result.N_ROW && (string.IsNullOrEmpty(a.C_ENABLE) || (a.C_ENABLE != "禁用" && a.C_ENABLE != "N")) && a.N_COL > result.N_COL).First(); } } catch (Exception ex) { LogHelper.Error("GetLocation4InEmptyRow:" + ex.Message, ex); } return result; } public static Location GetLocation4InEmptyRow() { Location result = null; try { var db = new SqlHelper().GetInstance(); #region 查找所有数量是空的排 //Console.WriteLine("查找所有数量是空的排"); //2.0 简化查询只查每一排第一列 var list = db.Queryable().OrderBy(a => a.N_COL).Take(1).PartitionBy(a => a.N_ROW).ToList().Where(a => a.N_CURRENT_NUM == 0).ToList(); //2.1 选一个空排 for (int i = 0; i < list.Count; i++) { var other = db.Queryable().Where(a => a.S_AREA_CODE == list[i].S_AREA_CODE && a.N_ROW == list[i].N_ROW && a.S_LOCK_STATE != "无").First(); if (list[i].N_LOCK_STATE == 0 && other == null) { //二次校验当前排所有货位都是空的,防止系统数据错乱 var rowSumInfo = db.Queryable().Where(l => l.S_AREA_CODE == list[i].S_AREA_CODE && l.N_ROW == list[i].N_ROW && l.N_CURRENT_NUM != 0).Count(); if (rowSumInfo == 0) { result = list[i]; break; } } } #endregion if (result != null && (!string.IsNullOrEmpty(result.C_ENABLE) && (result.C_ENABLE == "禁用" || result.C_ENABLE == "N"))) { //禁用了选择后面一个货位 Console.WriteLine("禁用了选择后面一个货位"); result = db.Queryable().OrderBy(a => a.N_COL).Where(a => a.S_AREA_CODE == result.S_AREA_CODE && a.N_ROW == result.N_ROW && (string.IsNullOrEmpty(a.C_ENABLE) || (a.C_ENABLE != "禁用" && a.C_ENABLE != "N")) && a.N_COL > result.N_COL).First(); } } catch (Exception ex) { LogHelper.Error("GetLocation4InEmptyRow:" + ex.Message, ex); } return result; } /// /// 获取空托开始货位 /// /// /// 是否排除母拖缓存位 0.不排除 1.排除 /// public static Location GetEmptyTrayStartLoc(int trayType ,int exclude = 1) { Location result = null; try { // 1、查询当前库区-排-物料 有托盘的货位 var db = new SqlHelper().GetInstance(); var query = db.Queryable() .LeftJoin((a, b) => a.S_CODE == b.S_LOC_CODE) .LeftJoin((a, b, c) => b.S_CNTR_CODE == c.S_CODE) .LeftJoin((a, b, c, d) => c.S_CODE == d.S_CNTR_CODE) .Where((a, b, c, d) => a.S_AREA_CODE == Settings.storeAreaCode && (trayType == 0 && a.N_CURRENT_NUM == 1 || trayType > 0 && a.N_CURRENT_NUM > 0) && a.N_LOCK_STATE == 0 && (a.C_ENABLE != "禁用" && a.C_ENABLE != "N") && c.N_TYPE == trayType && d.S_ITEM_CODE == null); if (exclude == 1) { List bufferInLocs = Settings.baseTrayBufferLocList.Select(a => a.bufferInLoc).ToList(); query = query.Where((a, b, c, d) => !bufferInLocs.Contains(a.S_CODE)); } else { List bufferInLocs = Settings.baseTrayBufferLocList.Select(a => a.bufferInLoc).ToList(); query = query.OrderByDescending((a, b, c, d) => bufferInLocs.Contains(a.S_CODE)); } result = query.OrderByDescending((a, b, c, d) => a.N_LAYER).First(); } catch (Exception ex) { LogHelper.Info("获取空托开始货位错误:" + ex.Message, "WMS"); } return result; } /// /// 入库前检查母拖数量是否满足 /// /// public static bool CheckBaseTrayNum() { bool result = false; try { // 1、查询当前库区-排-物料 有托盘的货位 var db = new SqlHelper().GetInstance(); // 查询库内母拖数量 var baseTrayNum = db.Queryable() .LeftJoin((a, b) => a.S_CODE == b.S_LOC_CODE) .LeftJoin((a, b, c) => b.S_CNTR_CODE == c.S_CODE) .Where((a, b, c) => a.N_CURRENT_NUM == 1 && a.N_LOCK_STATE == 0 && (a.C_ENABLE != "禁用" && a.C_ENABLE != "N") && c.N_TYPE == 0) .Count(); var taskTrayNum = db.Queryable() .LeftJoin((a, b) => a.S_CNTR_CODE == b.S_CODE) .Where((a, b) => a.N_B_STATE < 2 && b.N_TYPE == 0) .Count(); if (baseTrayNum - taskTrayNum > 0) { result = true; } } catch (Exception ex) { LogHelper.Info("检查母拖数量错误:" + ex.Message, "WMS"); } return result; } /// /// 获取出库开始货位 /// 出库策略: /// 1.先入先出 /// 2.不合格、未生效 、失效 物料不允许出库 /// /// /// /// /// public static Location GetoutStockStartLoc(string itemCode ,string trayCode = null ,string jbLoc = null) { LogHelper.Info("【获取出库开始货位】", "WMS"); var db = new SqlHelper().GetInstance(); Location loc = null; try { var query = db.Queryable() .LeftJoin((a, b) => a.S_CODE == b.S_LOC_CODE) .LeftJoin((a, b, c) => b.S_CNTR_CODE == c.S_CNTR_CODE) .Where((a, b, c) => a.S_AREA_CODE == Settings.storeAreaCode && a.N_CURRENT_NUM > 0 && a.N_LOCK_STATE == 0 && c.S_ITEM_CODE == itemCode && c.S_FOVRAGE != "Y" && c.S_ITEM_STATE == "OK" && SqlFunc.ToDate(c.S_EFFECTIVE_TIME) <= SqlFunc.GetDate() // 生效时间早于当前时间 && SqlFunc.ToDate(c.S_EXPIRATION_TIME) >= SqlFunc.GetDate() // 失效时间晚于当前时间 && c.S_EFFECTIVE_TIME != null && c.S_EXPIRATION_TIME != null ); if (trayCode != null) { query = query.Where((a, b, c) => c.S_CNTR_CODE == trayCode); } if (jbLoc != null) { List roadwayList = new List(); var agvJBLoc = Settings.getAgvJBLoc(jbLoc); if (agvJBLoc != null) { roadwayList = agvJBLoc.roadway; query = query.Where((a, b, c) => roadwayList.Contains(a.N_ROADWAY)); } } // 先入先出 loc = query.OrderBy((a, b, c) => c.T_CREATE) .OrderByDescending((a, b, c) => a.N_LAYER).First(); } catch (Exception ex) { LogHelper.Info($"【获取出库开始货位】内部错误,错误原因:{ex.Message}","WMS"); } return loc; } /// /// 获取入库终点货位 /// 入库策略 /// 1.巷道均衡 /// 2.物料均衡 /// /// /// /// 入库方式 1.自动入库 2.人工入库 /// 物料编码 /// public static Location GetInstockEndLoc(int trayType , string locCode = null , int inWay = 1 ,string itemCode = null) { LogHelper.Info("【获取入库终点货位】开始获取入库终点货位", "WMS"); var db = new SqlHelper().GetInstance(); Location loc = null; try { // 托盘 1.带束 2.胎侧 3.BEC 入巷道 1-5 进行混放 ; 4.内衬 5.帘布 6.胎圈 入巷道 6-7 ;其中内衬、帘布放5-8层 胎圈放 1-4 层 List roadwayList = null; List layerList = null; if (locCode != null) { var agvJBLoc = Settings.getAgvJBLoc(locCode); if (agvJBLoc != null) { roadwayList = agvJBLoc.roadway; } } else { if (trayType > 0 && trayType <= 3) { roadwayList = new List() { 1, 2, 3, 4, 5 }; } else { roadwayList = new List() { 6,7 }; } } // 确定物料的入库层数 if (trayType > 0 && trayType <= 3) { layerList = new List() { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; } else if (trayType > 3 && trayType <= 5) { layerList = new List() { 5, 6, 7, 8 }; } else { layerList = new List() { 1, 2, 3, 4 }; } LogHelper.Info("【获取入库终点货位】查询是否有满足条件的空货位", "WMS"); var locList = db.Queryable() .Where(a => a.S_AREA_CODE == Settings.storeAreaCode && a.N_CURRENT_NUM == 0 && a.N_LOCK_STATE == 0 && a.C_ENABLE == "Y" && roadwayList.Contains(a.N_ROADWAY) && layerList.Contains(a.N_LAYER) ) .OrderBy(l => l.N_LAYER) .ToList(); if (locList.Count == 0) { LogHelper.Info("【获取入库终点货位】没有满足条件的空货位", "WMS"); return loc; } else { LogHelper.Info($"【获取入库终点货位】满足条件的空货位数量:{locList.Count}", "WMS"); } LogHelper.Info($"【获取入库终点货位】开始查询巷道的容积率", "WMS"); var roadwayVolumeList = db.Queryable() .Where(a => a.N_CURRENT_NUM == 0 && a.S_AREA_CODE == Settings.storeAreaCode && a.N_LOCK_STATE == 0 && a.C_ENABLE == "Y" && roadwayList.Contains(a.N_ROADWAY) && layerList.Contains(a.N_LAYER)) .GroupBy(a => a.N_ROADWAY) .Select(a => new { roadway = a.N_ROADWAY , num = SqlFunc.AggregateDistinctCount(a.S_CODE)}) .OrderBy(a => a.num) .ToList(); LogHelper.Info($"【获取入库终点货位】查询巷道的容积率,并按从小到大排序:{JsonConvert.SerializeObject(roadwayVolumeList)}", "WMS"); Dictionary roadwayDic = new Dictionary(); foreach (var item in roadwayVolumeList) { roadwayDic.Add(item.roadway, item.num); } LogHelper.Info($"【获取入库终点货位】开始查询巷道的同物料数量", "WMS"); var roadwayItemNumList = db.Queryable() .LeftJoin((a,b) => a.S_CODE == b.S_LOC_CODE) .LeftJoin((a,b,c) => b.S_CNTR_CODE == c.S_CNTR_CODE ) .Where((a, b, c) => a.S_AREA_CODE == Settings.storeAreaCode && a.N_LOCK_STATE == 0 && a.C_ENABLE == "Y" && roadwayList.Contains(a.N_ROADWAY) && layerList.Contains(a.N_LAYER)) .GroupBy((a, b, c) => a.N_ROADWAY) .Select((a, b, c) => new { roadway = a.N_ROADWAY, volumNum = SqlFunc.AggregateDistinctCount(c.S_ITEM_CODE == itemCode) }) .ToList(); LogHelper.Info($"【获取入库终点货位】查询巷道的同物料数量,并按从小到到排序:{JsonConvert.SerializeObject(roadwayItemNumList)}", "WMS"); roadwayItemNumList = roadwayItemNumList.OrderBy(a => a.volumNum).ThenBy(a => roadwayDic[a.roadway]).ToList(); if (inWay == 1) { LogHelper.Info($"【获取入库终点货位】开始循环查询巷道对应接驳位的状态", "WMS"); foreach (var roadwayVolume in roadwayItemNumList) { int roadway = roadwayVolume.roadway; LogHelper.Info($"【获取入库终点货位】查询巷道内堆垛机的设备状态", "WMS"); List deviceNos = new List() { roadway.ToString()}; LogHelper.Info($"调用WCS的设备状态查询接口,参数:{deviceNos}", "WMS"); var deviceStatuses = WCSDispatch.getDeviceStatus(deviceNos); var agvJbLocList = Settings.getAgvJBLocList( roadway, 1); if (agvJbLocList.Count > 0) { foreach (var agvLocCode in agvJbLocList) { var agvLoc = LocationHelper.GetLoc(agvLocCode); if (agvLoc != null && agvLoc.N_LOCK_STATE == 0 && agvLoc.C_ENABLE == "Y") { LogHelper.Info($"【查询入库终点货位】,接驳位:{agvLoc.S_CODE}状态正常,查询巷道:{roadway}的空货位"); loc = db.Queryable() .Where(a => a.N_CURRENT_NUM == 0 && a.S_AREA_CODE == Settings.storeAreaCode && a.N_LOCK_STATE == 0 && a.C_ENABLE == "Y" && a.N_ROADWAY == roadway && layerList.Contains(a.N_LAYER)) .OrderBy(l => l.N_LAYER) .First(); if (loc != null) { return loc; } else { LogHelper.Info($"【查询入库终点货位】,没有查询巷道:{roadway}的空货位,跳过此巷道"); } } else { LogHelper.Info($"【查询入库终点货位】,接驳位:{agvLoc.S_CODE},暂时不可用,跳过此巷道"); } } } } } else if (inWay == 2) { // 查询空货位 loc = db.Queryable() .Where(a => a.N_CURRENT_NUM == 0 && a.S_AREA_CODE == Settings.storeAreaCode && a.N_LOCK_STATE == 0 && a.C_ENABLE == "Y" && roadwayList.Contains(a.N_ROADWAY) && layerList.Contains(a.N_LAYER)) .OrderBy(l => l.N_LAYER) .First(); if (loc != null) { return loc; } else { LogHelper.Info($"【查询入库终点货位】,巷道:{JsonConvert.SerializeObject(roadwayList)}内没有空货位"); } } } catch (Exception ex) { LogHelper.Error("【查询入库终点货位】内部错误,错误原因:" + ex.Message, ex); } return loc; } /// /// 获取缓存区货位 /// /// public static Location getErrorBufferAreaLoc() { var db = new SqlHelper().GetInstance(); return db.Queryable().Where(a => a.S_AREA_CODE == Settings.errorBufferArea && a.N_CURRENT_NUM == 0 && a.N_LOCK_STATE == 0 && a.C_ENABLE == "Y").First(); } /// /// 获取库区排的货位列表 /// /// /// /// public static List GetLocationList(string area , int row) { List result = new List (); try { var db = new SqlHelper().GetInstance(); result = db.Queryable().Where(a => a.S_AREA_CODE == area && a.N_ROW == row).Includes(a => a.LocCntrRel, a => a.CntrItemRel).ToList(); } catch (Exception ex) { LogHelper.Error("GetLocationList:" + ex.Message, ex); } return result; } public static bool updateShiftOrderDetail(TN_YiKuDetail detail) { bool result = false; var db = new SqlHelper().GetInstance(); LogHelper.Info("移库完成数量变更参数:" + JsonConvert.SerializeObject(detail), "TSSG"); result = db.Updateable() .SetColumns(a => new TN_YiKuDetail() { N_COMPLETE_NUM = a.N_COMPLETE_NUM + 1 }) .Where(a => a.S_NO == detail.S_NO && a.S_START_AREA == detail.S_START_AREA && a.S_START_ROW == detail.S_START_ROW && a.S_END_AREA == detail.S_END_AREA && a.S_END_ROW == detail.S_END_ROW ) .ExecuteCommand() > 0; var completeResult = db.Queryable().Where(a => a.S_NO == detail.S_NO && a.N_QTY > a.N_COMPLETE_NUM).Count() == 0; if(completeResult) { result = db.Updateable().SetColumns(a => new TN_YiKuOrder() { S_B_STATE = "完成" }).Where(a => a.S_NO == detail.S_NO).ExecuteCommand() > 0; } return result; } /// ///获取空托缓存信号列表 /// /// public static List getEmptyTrayBufferList() { var db = new SqlHelper().GetInstance(); return db.Queryable().Where(a => a.IS_CREATED == "N").ToList(); } /// /// 添加空托缓存信号 /// /// /// public static bool addEmptyTrayBuffer(EmptyTrayBuffer emptyTrayBuffer) { bool result = true; var db = new SqlHelper().GetInstance(); result = db.Insertable(emptyTrayBuffer).ExecuteCommand() > 0; return result; } /// /// 更新空托缓存信号 /// /// /// public static bool updateEmptyTrayBuffer(EmptyTrayBuffer emptyTrayBuffer) { bool result = true; var db = new SqlHelper().GetInstance(); result = db.Updateable(emptyTrayBuffer).ExecuteCommand() > 0; return result; } /// /// 批量添加物料条码信息 /// /// public static bool batchAddItemBarcodeInfo(List itemBarcodeInfos) { bool result = true; var db = new SqlHelper().GetInstance(); try { db.BeginTran(); if (itemBarcodeInfos.Count > 0) { itemBarcodeInfos.ForEach(item => { var itemBarcodeInfo = db.Queryable().Where(a => a.S_BC_ENTRIED == item.S_BC_ENTRIED).First(); if (itemBarcodeInfo == null) { var bo = db.Insertable(item).ExecuteCommand() == 0; if (bo) { result = false; LogHelper.Info($"添加物料条码信息失败,物料条码信息:{JsonConvert.SerializeObject(item)}", "GT"); } } }); } db.CommitTran(); } catch (Exception ex) { LogHelper.Info($"添加物料条码信息错误,错误信息:{ex.Message}", "GT"); db.RollbackTran(); } return result; } /// /// 同步条码状态表 /// /// public static bool synBarcodeStatus(List model) { bool result = true; var db = new SqlHelper().GetInstance(); try { db.BeginTran(); if (model.Count > 0) { model.ForEach(update => { db.Insertable(update).ExecuteCommand(); }); } db.CommitTran(); } catch (Exception ex) { LogHelper.Info($"同步条码状态表错误,错误信息:{ex.Message}", "GT"); db.RollbackTran(); result = false; } return result; } /// /// 同步抽检状态表 /// /// public static bool synSamplingStatus(List model) { bool result = true; var db = new SqlHelper().GetInstance(); try { db.BeginTran(); if (model.Count > 0) { model.ForEach(update => { db.Insertable(update).ExecuteCommand(); }); } db.CommitTran(); } catch (Exception ex) { LogHelper.Info($"同步抽检状态表错误,错误信息:{ex.Message}", "GT"); db.RollbackTran(); result = false; } return result; } /// /// 批量更新物料状态 /// /// public static bool batchUpdateItemStatus(List updateMatlStatuses) { bool result = true; var db = new SqlHelper().GetInstance(); try { db.BeginTran(); if (updateMatlStatuses.Count > 0) { updateMatlStatuses.ForEach(update => { var itemBarcodeInfo = db.Queryable().Where(a => a.S_BC_ENTRIED == update.bc_entried).First(); if (itemBarcodeInfo != null) { itemBarcodeInfo.S_JDGE = update.jdge; db.Updateable(itemBarcodeInfo).ExecuteCommand(); var cntrItemRel = db.Queryable().Where(a => a.S_CG_ID == update.bc_entried).First(); if (cntrItemRel != null) { db.Updateable().SetColumns(a => new CntrItemRel() { S_ITEM_STATE = update.jdge }).Where(a => a.S_CG_ID == update.bc_entried).ExecuteCommand(); } } }); } db.CommitTran(); } catch (Exception ex) { LogHelper.Info($"批量更新物料状态错误,错误信息:{ex.Message}", "GT"); db.RollbackTran(); result = false; } return result; } /// /// 添加同步数据时间记录 /// /// /// public static bool addSynDataTimeReord(SynDataTimeRecord record) { bool result = true; var db = new SqlHelper().GetInstance(); try { db.BeginTran(); var synDataTimeRecord = db.Queryable().Where(a => a.S_SYN_TIME == record.S_SYN_TIME && a.RECORD_TABLE == record.RECORD_TABLE).First(); if (synDataTimeRecord == null) { result = db.Insertable(record).ExecuteCommand() > 0; } else { synDataTimeRecord.N_SYN_NUM = record.N_SYN_NUM; synDataTimeRecord.S_SYN_TIME = record.S_SYN_TIME; result = db.Updateable(synDataTimeRecord).ExecuteCommand() > 0; } if (result) { db.CommitTran(); } else { db.RollbackTran(); } } catch (Exception ex) { LogHelper.Info($"添加数据同步时间记录错误,错误信息:{ex.Message}", "GT"); db.RollbackTran(); } return result; } /// /// 查询上一次的同步时间 /// /// /// public static string getDataLastSynTime(int tableType) { var db = new SqlHelper().GetInstance(); string lastTime = null; if (tableType == 1) { lastTime = db.Queryable().OrderByDescending(a => a.LAST_MODIFY_TIME).Select(a => a.LAST_MODIFY_TIME).First(); } else if (tableType == 2) { } else if (tableType == 3) { } return lastTime; } } }