using System; using System.Collections.Generic; using System.IO; using System.Linq; using Model.ModelDto.SysDto; using SqlSugar; using WMS.DAL; using WMS.Entity.BllAsnEntity; using WMS.Entity.Context; using WMS.Entity.DataEntity; using WMS.Entity.LogEntity; using WMS.Entity.SysEntity; namespace WMS.BLL.Logic { /// /// 分配库位 /// public class AllotLocation { /// /// 获取密集库合适的巷道(适用项目:JC34) /// /// 巷道集合 /// 区域集合 /// 批次号 /// public string GetMiJiSuiTableRoad(string house, List roadways, List areaList, string sku, string lotNo = "") { var db = DataContext.Db; var dataStock = db.Queryable().Where(m => m.IsDel == "0" && m.WareHouseNo == house && m.SkuNo == sku); if (!string.IsNullOrWhiteSpace(lotNo)) { dataStock = dataStock.Where(m => m.LotNo == lotNo); } //库存查找相同物料/批次的巷道 var yiYouRoad = dataStock.GroupBy(m => m.RoadwayNo).Select(m => m.RoadwayNo).OrderBy(m => m).ToList(); foreach (var l in yiYouRoad) { // 判断当前巷道(组)是否有空余储位 var locateCount = db.Queryable().Count(m => m.Status == "0" && m.Flag == "0" && areaList.Contains(m.AreaNo) && m.RoadwayNo == l); var bindNum = db.Queryable().Where(m => m.IsDel == "0" && (m.Status == "0" || m.Status == "1") && m.EndRoadway == l) .GroupBy(m => m.PalletNo).Select(m => m.PalletNo).Count(); if (locateCount - bindNum > 0) { return l; } } //获取库存内已有物料的巷道 var dataStockRoad = db.Queryable().Where(m => m.IsDel == "0" && m.WareHouseNo == house).GroupBy(m => m.RoadwayNo).OrderBy(m => m.RoadwayNo).Select(m => m.RoadwayNo).ToList(); //排除掉已有物料的巷道 roadways = roadways.Where(m => !dataStockRoad.Contains(m)).ToList(); foreach (var l in roadways) { var bl = true; //判断当前巷道(组)是否有任务 var taskList = db.Queryable().Where(m => m.IsDel == "0" && m.EndRoadway == l && (m.Status == "0" || m.Status == "1")).ToList(); if (taskList.Count > 0) { //判断物料批次是否和当前一致 foreach (var item in taskList) { var palletBind = db.Queryable().First(m => m.IsDel == "0" && m.TaskNo == item.TaskNo); if (palletBind != null) { if (palletBind.SkuNo !=sku || palletBind.LotNo != lotNo) { bl = false; continue; } } } if (bl) { // 判断当前巷道(组)是否有空余储位 var locateCount = db.Queryable().Count(m => m.Status == "0" && m.Flag == "0" && areaList.Contains(m.AreaNo) && m.RoadwayNo == l); var bindNum = db.Queryable().Where(m => m.IsDel == "0" && (m.Status == "0" || m.Status == "1") && m.EndRoadway == l) .GroupBy(m => m.PalletNo).Select(m => m.PalletNo).Count(); if (locateCount - bindNum > 0) { return l; } } } } return ""; } /// /// 获取密集库合适的储位(适用项目:JC34) /// /// 巷道集合 /// 区域集合 /// 批次号 /// public SysStorageLocat GetMiJiSuiTableLocate(string roadwayNo, List areaList) { var db = DataContext.Db; // 判断当前巷道(组)是否有空余储位 var locateList = db.Queryable().Where(m => m.IsDel == "0" && m.RoadwayNo == roadwayNo && areaList.Contains(m.AreaNo)).ToList(); if (locateList.Count(m => m.Status == "0") > 0) { var bl = GetLocateASCOrDesc(roadwayNo); var locate = locateList.OrderBy(m => m.LocatNo).First(); if (bl) { locate = locateList.OrderByDescending(m => m.LocatNo).First(); } var bl2 = MiJiLocateIsOk(locate, bl); //验证储位是否可入库方法 if (bl2) { return locate; } } return null; } /// /// 获取储位的排列顺序 /// /// /// true:desc倒序 false:asc正序 public bool GetLocateASCOrDesc(string roadStr) { var db = DataContext.Db; var locate = db.Queryable().First(m => m.IsDel == "0" && m.RoadwayNo == roadStr); var a = locate.LocatNo.Substring(2,2);//储位列 var b = locate.AisleOne.Substring(2, 2);//通道口列 return int.Parse(a) < int.Parse(b); } /// /// 验证储位是否可入库 /// /// /// private bool MiJiLocateIsOk(SysStorageLocat locate,bool bl) { var db = DataContext.Db; var a = int.Parse(locate.LocatNo.Substring(2, 2));//储位列 var b = int.Parse(locate.AisleOne.Substring(2, 2));//通道口列 var str1 = new List() { "0", "3", "5" }; var str2 = new List() { "1", "2", "4" }; var locatList1 = db.Queryable().Where(m => m.IsDel == "0" && m.RoadwayNo == locate.RoadwayNo && m.Column < a).ToList(); var locatList2 = db.Queryable().Where(m => m.IsDel == "0" && m.RoadwayNo == locate.RoadwayNo && m.Column > a).ToList(); if (bl) { if (locatList1.Count(m => str1.Contains(m.Status)) > 0) { return false; } if (locatList2.Count(m => str2.Contains(m.Status)) > 0) { return false; } } else { if (locatList1.Count(m => str2.Contains(m.Status)) > 0) { return false; } if (locatList2.Count(m => str1.Contains(m.Status)) > 0) { return false; } } return true; } /// /// 根据起始组获取位置最优的四项车取货工位 /// /// 起始组 /// 出库口工位 9、 17、 18 /// public string RoadwayToStationNum(string straRoadway, string outModel) { var db = DataContext.Db; string stationNum = ""; string[] lists = straRoadway.Split("MR"); var model = db.Queryable().First(m => m.RoadwayNo == straRoadway && m.IsDel == "0"); string stat = model.AisleOne; if (model.Layer == 1) { // 一层 switch (outModel) // 申请的入库口 { case "9": var path13 = Math.Abs(19 - int.Parse(stat.Substring(0, 2))) + Math.Abs(6 - int.Parse(stat.Substring(2, 2))); var path14 = Math.Abs(19 - int.Parse(stat.Substring(0, 2))) + Math.Abs(12 - int.Parse(stat.Substring(2, 2))); if (path13 <= path14) { stationNum = "190601"; } else { stationNum = "191201"; } break; case "17": stationNum = "030401"; break; case "18": var path03 = Math.Abs(03 - int.Parse(stat.Substring(0, 2))) + Math.Abs(06 - int.Parse(stat.Substring(2, 2))); var path05 = Math.Abs(03 - int.Parse(stat.Substring(0, 2))) + Math.Abs(12 - int.Parse(stat.Substring(2, 2))); if (path03 <= path05) { stationNum = "030601"; } else { stationNum = "031201"; } break; default: break; } } else { // 二层 switch (outModel) // 申请的入库口 { case "9": var path15 = Math.Abs(19 - int.Parse(stat.Substring(0, 2))) + Math.Abs(6 - int.Parse(stat.Substring(2, 2))); var path16 = Math.Abs(19 - int.Parse(stat.Substring(0, 2))) + Math.Abs(12 - int.Parse(stat.Substring(2, 2))); if (path15 <= path16) { stationNum = "190602"; } else { stationNum = "191202"; } break; case "17": stationNum = "030402"; break; case "18": var path03 = Math.Abs(03 - int.Parse(stat.Substring(0, 2))) + Math.Abs(06 - int.Parse(stat.Substring(2, 2))); var path05 = Math.Abs(03 - int.Parse(stat.Substring(0, 2))) + Math.Abs(12 - int.Parse(stat.Substring(2, 2))); if (path03 <= path05) { stationNum = "030602"; } else { stationNum = "031202"; } break; default: break; } } return stationNum; } /// /// 获取合适的库位 /// /// 仓库号 /// 区域集合 /// 巷道号(可空) /// public SysStorageLocat GetSuiTableLocate(string houseNo, List areaList,string roadwayNo = "") { try { var db = DataContext.Db; /* 1.先判断仓库(立库或者平库) * 2.如果是立库 再判断是否指定巷道号 */ var house = db.Queryable().First(m => m.WareHouseNo == houseNo); if (house == null) { throw new Exception($"未查询到{houseNo}仓库信息"); } var roadList = db.Queryable().Where(m => m.WareHouseNo == houseNo && areaList.Contains(m.AreaNo) ) .GroupBy(m=>m.RoadwayNo).Select(m=>m.RoadwayNo).ToList(); //数据字典(获取字典中仓库类型) var dic = db.Queryable().First(m => m.Id.ToString() == house.Type); switch (dic.DictName) { //指定巷道 case "立体库" when !string.IsNullOrWhiteSpace(roadwayNo): { var roadwayList = new List(); var roadway = db.Queryable().First(m => m.RoadwayNo == roadwayNo); if (roadway == null) { throw new Exception($"未查询到{roadwayNo}巷道信息"); } if (!roadList.Contains(roadwayNo)) { throw new Exception("当前物料存放区域未在指定巷道中"); } if (roadway.Status == "1") { throw new Exception($"{roadwayNo}巷道已停用"); } //查询该巷道并且标志为正常的的储位 roadwayList.Add(roadway); var locate = GetLocateByRoadways(roadwayList,areaList,true,houseNo); if (locate == null) { throw new Exception($"{roadwayNo}巷道没有合适的空储位"); } return locate; } //立体库没有指定巷道(循环巷道根据优先级分配) case "立体库" when string.IsNullOrWhiteSpace(roadwayNo): { var roadwayList = db.Queryable().Where(m => m.WareHouseNo == houseNo && m.Status == "0" && roadList.Contains(m.RoadwayNo)).OrderBy(m => new { m.Priority, m.RoadwayNo }).ToList(); var locate = GetLocateByRoadways(roadwayList,areaList,false, houseNo); if (locate == null) { throw new Exception($"{houseNo}仓库已启用的巷道中没有合适的空储位"); } return locate; } //平库 该代码块目前是错误的逻辑、后期有库位信息了改 case "平库": { //查询该巷道并且标志为正常的的储位 var locates = db.Queryable() .Where(m => m.WareHouseNo == houseNo && m.Flag == "0" && m.Status == "0") .OrderBy(m => new { m.Layer, m.Column, m.Row }).ToList(); return locates.First(); } //没有仓库类型 default: throw new Exception($"未查询到{houseNo}仓库类型信息,无法为其分配储位"); } } catch (Exception e) { throw new Exception(e.Message); } } /// /// 获取合适空储位信息(根据巷道集合判断) /// /// 巷道集合 /// 区域集合 /// 是否指定巷道 /// private SysStorageLocat GetLocateByRoadways(List roadways,List areaList,bool isRoadway = false ,string houseNo = "W01") { try { var db = DataContext.Db; #region 入库分配规则 var funSet = db.Queryable().First(m => m.IsDel == "0" && m.FunSetName == "储位分配上下" && m.IsEnable == "NO"); var funSet2 = db.Queryable().First(m => m.IsDel == "0" && m.FunSetName == "储位分配左右" && m.IsEnable == "NO"); var funSet3 = db.Queryable().First(m => m.IsDel == "0" && m.FunSetName == "储位跳巷分配" && m.IsEnable == "NO"); var topOrBom = 1; // 储位分配上下 0 上 1 下 var leftOrRight = 0; // 储位分配上下 0 左 1 右 var laneAllot = 0; //储位跳巷分配 0:跳着分配(一个一个分配)1:巷道按照优先级分配,同优先级顺序分配(一个巷道满了再分配下一个的巷道储位) if (funSet != null) { switch (funSet.SetValue) { case "Top": topOrBom = 0;//立库储位分配由上往下分配 break; case "Bottom": topOrBom = 1;//立库储位分配由下往上分配 break; default: topOrBom = 1;// 默认:由下往上 break; } } if (funSet2 != null) { switch (funSet2.SetValue) { case "Left": leftOrRight = 0;//立库储位分配由上往下分配 break; case "Right": leftOrRight = 1;//立库储位分配由下往上分配 break; default: leftOrRight = 1;// 默认:由下往上 break; } } if (funSet3 != null) { switch (funSet3.SetValue) { case "JumpLaneAllot": laneAllot = 0;//立库储位分配 巷道同优先级巷道跳着分配(一个一个分配) break; case "RankLaneAllot": laneAllot = 1;//立库储位分配 巷道按照优先级分配,同优先级顺序分配(一个巷道满了再分配下一个的巷道储位) break; default: laneAllot = 1;// 默认 跳着分配 break; } } #endregion #region MyRegion SysStorageLocat locate = null; // 储位信息 //SysStorageLocat log = db.Ado.SqlQuerySingle("select * from SysStorageLocat where LocatNo = (select Top(1) LocatNo from BllPalletBind order by CreateTime desc)"); //巷道最后一次使用记录 SysRoadwayUseLog log= db.Ado.SqlQuerySingle($"select Top(1) * from SysRoadwayUseLog where IsDel=0 and WareHouseNo ='{houseNo}' order by CreateTime desc"); //巷道最后一次使用记录 if (laneAllot == 0)//跳巷道平均分配 { //如果同级巷道有多条则查上次位置日志 if (roadways.Count > 1) { log = db.Queryable().Where(m=>m.WareHouseNo == houseNo).OrderByDescending(l => l.Id).First(); } //取各巷道所有排第一个合适位 foreach (var l in roadways) { if (!isRoadway) { //如果上次是当前巷道则跳出 if (log != null && l.RoadwayNo == log.RoadwayNo) { continue; } } var list = new List(); var count = 0; do { locate = GetLocateByRoadway(l.RoadwayNo, topOrBom, leftOrRight, areaList, list, ref count); if (locate != null) { break; //list.Add(locate.LocatNo); //var isOk = LocateIsOk(locate); //if (!isOk) //{ // locate = null; //} //if (isOk) //{ // break; //} } } while (count != 0 && locate == null);//当查询储位数量不等0 并且储位为空时,再次循环巷道、区域查找储位 if (locate!=null) { break; } } //如果跳巷道并且未找到合适空储位,则跳到最后一次使用的巷道查询 if (!isRoadway) { if (locate == null) { if (log != null) { var list = new List(); var count = 0; do { locate = GetLocateByRoadway(log.RoadwayNo, topOrBom, leftOrRight, areaList, list, ref count); if (locate != null) { break; //list.Add(locate.LocatNo); //var isOk = LocateIsOk(locate); //if (!isOk) //{ // locate = null; //} } } while (count != 0 && locate == null);//当查询储位数量不等0 并且储位为空时,再次循环巷道、区域查找储位 } } } } else//按照巷道优先级分配 { foreach (var item in roadways) { var list = new List(); var count = 0; do { locate = GetLocateByRoadway(item.RoadwayNo, topOrBom, leftOrRight, areaList, list, ref count); if (locate != null) { break; //list.Add(locate.LocatNo); //var isOk = LocateIsOk(locate); //if (!isOk) //{ // locate = null; //} //if (isOk) //{ // break; //} } } while (count != 0 && locate == null);//当查询储位数量不等0 并且储位为空时,再次循环巷道、区域查找储位 if (locate != null) { break; } } } #endregion return locate; } catch (Exception e) { throw new Exception(e.Message); } } /// /// 取当前巷最优位置 /// /// 巷道号 /// 储位分配上下 0 上 1 下 /// 储位分配上下 0 左 1 右 /// 区域集合 /// 排除的储位集合 /// private SysStorageLocat GetLocateByRoadway(string roadwayNo, int topOrBom, int leftOrRight,List areaList,List locateNoStr,ref int count) { var db = DataContext.Db; var str = ""; foreach (var item in locateNoStr) { if (str == "") { str += item; } str += "," + item; } if (str == "") { str = "''"; } //查询该巷道并且标志为正常的的储位 SysStorageLocat data; foreach (var area in areaList) { var sql = $@"select * from SysStorageLocat where IsDel = 0 and Flag = 0 and [Status] = 0 and RoadwayNo = '{roadwayNo}' and AreaNo = '{area}' and LocatNo not in({str}) "; sql += "order by "; sql += topOrBom == 0 ? "Layer desc, " : "Layer, "; sql += leftOrRight == 0 ? "[Column], " : "[Column] desc, "; sql += " Row desc, Depth desc; "; var locateList = db.Ado.SqlQuery(sql); data = locateList.FirstOrDefault(); count = locateList.Count; if (data != null) { return data; } } return null; } /// /// 验证储位是否可入库 双深位验证 /// /// /// private bool LocateIsOk(SysStorageLocat locate) { try { Common common = new Common(); if (locate.Depth == "01") { var locate2 = common.GetLocateNoDepth2("W01", locate.LocatNo); var str = new List() { "0", "3", "5" }; if (str.Contains(locate2.Status)) { return false; } return true; } else { var locate2 = common.GetLocateNoDepth1("W01", locate.LocatNo); var str = new List() { "1", "2", "4" }; if (str.Contains(locate2.Status)) { return false; } return true; } } catch { return false; } } /// /// 获取平库储位 JC23四楼专用 /// /// 区域 /// 出库单据号 /// 物料 /// public SysStorageLocat GetPingLocate(string soNo,string sku) { try { var db = DataContext.Db; var house = "W02"; var area = new List() { "B01","B02" }; //四楼所有储位集合 var locateList = db.Queryable().Where(m=>m.IsDel == "0" && m.WareHouseNo == house && area.Contains(m.AreaNo)).ToList(); //储位Str集合 var locateStr = locateList.Select(m => m.LocatNo).ToList(); //库存在四楼平库的托盘 var stockDetail = db.Queryable().Where(m => m.IsDel == "0" && locateStr.Contains(m.LocatNo)).ToList(); var detailLocate = stockDetail.Where(m=>m.SONo == soNo && m.SkuNo == sku).Select(m=>m.AreaNo).Distinct().ToList(); if (detailLocate.Count != 0) { //判断是否有合适的巷道储位 foreach (var item in detailLocate) { var locateList2 = locateList.Where(m => m.AreaNo == item).ToList(); if (locateList2.Count(m=>m.Status == "0" && m.Flag == "0") == 0) { continue; } var locate = locateList2.Where(m => m.Flag == "0" && m.Status == "0").OrderBy(m => new { m.Layer, m.Column, m.Row }).First(); return locate; } } //查找新的巷道出库 foreach (var item2 in area) { var locateList2 = locateList.Where(m => m.AreaNo == item2).ToList(); if (locateList2.Count(m => m.Status != "0" && m.Flag == "0") > 0) { continue; } var locate = locateList2.Where(m => m.Flag == "0" && m.Status == "0").OrderBy(m => new { m.Layer, m.Column, m.Row }).First(); return locate; } return null; } catch (Exception e) { throw new Exception(e.Message); } } } }