using System;
using System.Collections.Generic;
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.SysEntity;
namespace WMS.BLL.Logic
{
///
/// 分配库位
///
public class AllotLocation
{
///
/// 获取合适的库位
///
/// 仓库号
/// 区域集合
/// 巷道号(可空)
///
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);
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);
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)
{
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 order by CreateTime desc"); //巷道最后一次使用记录
if (laneAllot == 0)//跳巷道平均分配
{
//如果同级巷道有多条则查上次位置日志
if (roadways.Count > 1)
{
log = db.Queryable().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)
{
list.Add(locate.LocatNo);
var isOk = LocateIsOk(locate);
if (!isOk)
{
locate = null;
}
if (isOk)
{
break;
}
}
} while (count != 0 && locate == null);//当查询储位数量不等0 并且储位为空时,再次循环巷道、区域查找储位
}
//如果跳巷道并且未找到合适空储位,则跳到最后一次使用的巷道查询
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)
{
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)
{
list.Add(locate.LocatNo);
var isOk = LocateIsOk(locate);
if (!isOk)
{
locate = null;
}
if (isOk)
{
break;
}
}
} while (count != 0 && locate == null);//当查询储位数量不等0 并且储位为空时,再次循环巷道、区域查找储位
}
}
#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);
}
}
}
}