using HH.WCS.QingXigongchang.util; using SqlSugar; using System; using System.Collections.Generic; using System.Linq; using System.Security.Cryptography; namespace HH.WCS.QingXigongchang.wms { /// /// 密集型库区 /// internal class IntensiveArea { static IntensiveArea() { //InitRowLockTable(new List { "PGKQ", "PGKTK" }); } /// /// 根据库区和物料获取入库的货位(堆叠先考虑标准的,容量都是一样的,例如均州都是3+3;不考虑峨眉山非标2+2和2+1同时存在) /// /// /// 如果itemCode是空表示空容器 /// 标准搬运数量 /// public static Location GetLocation4In(string area, string itemCode, string itemBatch, int standardCarryQty = 1) { Location result = null; try { //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 查到所有有容器的排 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.Container).OrderByDescending(a => a.N_COL).Take(1).PartitionBy(a => a.N_ROW).ToList(); if (list.Count > 0) { for (int i = list.Count - 1; i >= 0; i--) { //排除已经锁定的货位 和 放满了且是最大列的货位 //其它项目还需要查询排锁 if (list[i].S_LOCK_STATE.Trim() != "无" || (list[i].N_CURRENT_NUM == list[i].N_CAPACITY && listMaxCol.Count(a => a.S_LOC_CODE == list[i].S_LOC_CODE) > 0)) { list.Remove(list[i]); } } if (list.Count > 0) { //1.21 加载货位的容器信息 (mapper之前只能是查询原始数据,如果有其他查询 mapper失效) #region MyRegion /* Console.WriteLine("加载货位的容器信息"); db.ThenMapper(list, loc => { loc.LocCntrRel = db.Queryable().SetContext(x => x.S_LOC_CODE, () => loc.S_LOC_CODE, loc).FirstOrDefault(); }); //1.22 加载容器的物料信息 Console.WriteLine("加载容器的物料信息"); db.ThenMapper(list.Select(loc => loc.LocCntrRel), lcr => { lcr.CntrItemRel = db.Queryable().SetContext(x => x.S_CNTR_CODE, () => lcr.S_CNTR_CODE, lcr).FirstOrDefault(); }); */ #endregion //1.3 遍历判断物料类型是否相同 for (int i = 0; i < list.Count; i++) { //todo 还需要判断锁 #region 空容器或者满容器判断 ,如果是空容器 容器物料信息为空 if (list[i].LocCntrRel != null) { //LogHelper.Info("itemCode=" + itemCode); if ((itemCode != null && list[i].LocCntrRel.CntrItemRel != null && list[i].LocCntrRel.CntrItemRel.S_ITEM_CODE.Trim() == itemCode && list[i].LocCntrRel.CntrItemRel.S_BATCH_NO.Trim() == itemBatch.Trim()) || (itemCode == null && list[i].LocCntrRel.CntrItemRel == null)) { if (list[i].N_CURRENT_NUM < list[i].N_CAPACITY) { //1.31 如果搬运数量=1 //1.32 搬运多个容器,例如3+3模式 ,必须当前数量=0或3;如果是3+3+,必须当前数量=0或3或6 if (list[i].N_CURRENT_NUM % standardCarryQty == 0) { result = list[i]; } else { //1.33 不满足则选择后一列,后一列肯定是空货位 result = db.Queryable().Where(a => a.S_AREA_CODE == area && a.N_ROW == list[i].N_ROW && a.N_COL > list[i].N_COL).OrderBy(a => a.N_COL).First(); } } else { //当前货位满了,比他col大一位的货位,后一列肯定是空货位 result = db.Queryable().Where(a => a.S_AREA_CODE == area && a.N_ROW == list[i].N_ROW && a.N_COL > list[i].N_COL).OrderBy(a => a.N_COL).First(); } if (result != null) { break; } } } else { LogHelper.Info("货位容器物料信息为空"); } #endregion } } } if (result == null) { //todo 还需要判断锁 #region 查找所有数量是空的排 //2.0 简化查询只查每一排第一列 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++) { if (list[i].S_LOCK_STATE.Trim() == "无") { //二次校验当前排所有货位都是空的,防止系统数据错乱 var rowSumInfo = db.Queryable().Where(a => a.S_AREA_CODE == area && a.N_ROW == list[i].N_ROW).Select(a => new { sum = SqlFunc.AggregateSum(a.N_CURRENT_NUM) }).First(); if (rowSumInfo.sum == 0) { result = list[i]; break; } } } #endregion } } catch (Exception ex) { Console.WriteLine("GetLocation4In:" + ex.Message + ex.StackTrace); LogHelper.Error("GetLocation4In:" + ex.Message, ex); } return result; } /// /// 根据库区和物料获取出库的货位(堆叠先考虑标准的,容量都是一样的,例如均州都是3+3;不考虑峨眉山非标2+2和2+1同时存在) /// /// /// 如果itemCode是空表示空容器 /// 标准搬运数量 /// /// public static Location GetLocation4Out(string area, string itemCode, string itemBatch, int standardCarryQty = 1) { //Console.WriteLine($"area={area}"); Location result = null; var db = new SqlHelper().GetInstance(); //1.0 查到所有有容器的排 var list = db.Queryable().Where(a => a.N_CURRENT_NUM>0).Includes(a => a.LocCntrRel, a => a.CntrItemRel).ToList(); 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(); //1.1 判断当前数量是不是满的,如果是满的并且是最大列,需要排除 if (list.Count > 0) { //LogHelper.Info("GetLocation4Out:" + JsonConvert.SerializeObject(list)); #region MyRegion /* //1.21 加载货位的容器信息 db.ThenMapper(list, loc => { loc.LocCntrRel = db.Queryable().SetContext(x => x.S_LOC_CODE, () => loc.S_LOC_CODE, loc).FirstOrDefault(); }); //1.22 加载容器的物料信息 db.ThenMapper(list.Select(loc => loc.LocCntrRel), lcr => { lcr.CntrItemRel = db.Queryable().SetContext(x => x.S_CNTR_CODE, () => lcr.S_CNTR_CODE, lcr).FirstOrDefault(); }); */ #endregion //1.3 遍历判断物料类型是否相同 for (int i = 0; i < list.Count; i++) { //todo 还需要判断锁 #region 空容器或者满容器判断 ,如果是空容器 容器物料信息为空 if (list[i].S_LOCK_STATE.Trim() == "无" && list[i].LocCntrRel != null) { if ((itemCode != null && list[i].LocCntrRel.CntrItemRel != null && list[i].LocCntrRel.CntrItemRel.S_ITEM_CODE.Trim() == itemCode && (itemBatch == null || list[i].LocCntrRel.CntrItemRel.S_BATCH_NO.Trim() == itemBatch.Trim())) || (itemCode == null && list[i].LocCntrRel.CntrItemRel == null)) { //搬运选择货位 //如果当前出库位后面有空位,不能是入库中 var after = new SqlHelper().Get(a => a.S_AREA_CODE == area && a.N_ROW == list[i].N_ROW && a.N_COL == list[i].N_COL + 1); if (after == null || after.S_LOCK_STATE.Trim() == "无") { result = list[i]; } if (result != null) { break; } } } #endregion } } return result; } /// /// 初始化密集排锁表格 /// //private static void InitRowLockTable(List areas) { // var db = new SqlHelper().GetInstance(); // var listRowLocks = db.Queryable().ToList(); // areas.ForEach(a => { // var list = db.Queryable().Where(l => l.S_AREA_CODE == a).Distinct().Select(it => it.N_ROW).ToList(); // list.ForEach(r => { // if (listRowLocks.Count(d => d.S_AREA_CODE.Trim() == a && d.N_ROW == r) == 0) { // var res = db.Insertable(new RowLock { N_ROW = r, S_AREA_CODE = a, S_LOCK_STATE = "无", S_LOCK_SRC = "", S_WORK_MODE = "正常" }).ExecuteCommand(); // } // }); // }); //} private static List GetRowsByArea(string area) { var list = new SqlHelper().GetInstance().Queryable().Where(a => a.S_AREA_CODE == area).Distinct().Select(a => a.N_ROW).ToList(); return list; } internal static void Test() { //UnLockLoc("PGKQ-02-02"); //LockLoc("PGKQ-02-02", "入库锁"); //Binding("PGKQ-02-03", "AAA", "", 3); //UnBinding("PGKQ-02-03", 2); //var full = GetLocation4In("PGKQ", "AAA"); //var empty = GetLocation4In("PGKQ", null); //var fullOut = GetLocation4Out("PGKQ", "AAA"); //var emptyOut = GetLocation4Out("PGKQ", null); //var Locations = new SqlHelper().GetList(); //var LocCntrRels = new SqlHelper().GetList(); //var CntrItemRels = new SqlHelper().GetList(); //var list = new SqlHelper().GetInstance().Queryable().LeftJoin((l, lc) => l.S_LOC_CODE == lc.S_LOC_CODE).ToList(); //var results = context.Client.Queryable().Mapper(t=>t.Person, p=>p.PersonId).ToList(); var db = new SqlHelper().GetInstance(); //var list = db.Queryable().Mapper(l => l.LocCntrRel, lcr => lcr.S_LOC_CODE).Where(a=>a.S_LOC_CODE== "PGKQ-01-01").ToList(); //多级查询会嵌套,需要指定导航属性和主键,循环嵌套查询不建议 //[Navigate(NavigateType.OneToOne, nameof(S_LOC_CODE))]、 [Navigate(NavigateType.OneToOne, nameof(S_CNTR_CODE))]、[SugarColumn(IsPrimaryKey = true)] var list = db.Queryable().Where(a => a.N_CURRENT_NUM > 0).Includes(a => a.LocCntrRel, a => a.CntrItemRel).ToList(); #region MyRegion /* // SetContext不会生成循环操作,高性能 和直接Where性能是不一样的 var list = db.Queryable().Where(a => a.N_CURRENT_NUM > 0).ToList(); //第一层 db.ThenMapper(list, loc => { loc.LocCntrRel = db.Queryable().SetContext(x => x.S_LOC_CODE, () => loc.S_LOC_CODE, loc).FirstOrDefault(); }); //第二层 db.ThenMapper(list.Select(loc => loc.LocCntrRel), lcr => { lcr.CntrItemRel = db.Queryable().SetContext(x => x.S_CNTR_CODE, () => lcr.S_CNTR_CODE, lcr).FirstOrDefault(); }); */ #endregion } } }