using System;
|
using System.Collections.Generic;
|
using System.Linq;
|
using System.Text;
|
using SqlSugar;
|
using WMS.Entity.Context;
|
using WMS.Entity.DataEntity;
|
using WMS.Entity.SysEntity;
|
|
namespace WMS.BLL.Logic
|
{
|
public class AllotSku
|
{
|
private static readonly SqlSugarScope Db = DataContext.Db;
|
/// <summary>
|
/// 分配货物
|
/// </summary>
|
/// <param name="palletList">库存明细集合</param>
|
/// <param name="goodCode">物料编码</param>
|
/// <param name="lotNo">批次</param>
|
/// <param name="needQty">需要分配的数量</param>
|
/// <param name="fullPalletQty">满托数量</param>
|
/// <param name="fullBoxQty">满箱数量</param>
|
/// <param name="stockQtyDic">托出库物品数 key:库存托盘表的ID、val:托盘上的数量</param>
|
/// <returns></returns>
|
public int AllotPallets(List<DataStockDetail> palletList, int needQty, int fullPalletQty, int fullBoxQty, Dictionary<int, int> stockQtyDic)
|
{
|
//优先先进先出(快过期的先出)
|
//优先零箱、零托(出完零箱出整箱)
|
//优先匹配数、(分配合适的数量)
|
|
try
|
{
|
var contextDb = DataContext.Db;
|
|
#region 分配规则
|
|
var funSet = contextDb.Queryable<SysFunSetting>().First(m => m.IsDel == "0" && m.FunSetName == "分配规则" && m.IsEnable == "NO");
|
|
var allotSet = 1;//分配规则设定
|
|
if (funSet != null)
|
{
|
switch (funSet.FunSetNo)
|
{
|
case "Fun001":
|
allotSet = 0;//优先零箱(出完零箱出整箱)
|
break;
|
case "Fun002":
|
allotSet = 1;//优先匹配数、(分配合适的数量)
|
break;
|
case "Fun017":
|
allotSet = 3;//优先零箱(若分配数量是整托数量的倍数 那么整箱优先)
|
break;
|
default:
|
allotSet = 1;// 默认:优先匹配数、
|
break;
|
}
|
}
|
#endregion
|
var roadway = Db.Queryable<SysStorageRoadway>().Where(a => a.IsDel == "0" && a.WareHouseNo == "W03" && a.Status == "0").Select(a => a.RoadwayNo).ToList();
|
|
var qty = 0; //分配的总数量
|
var ztNum = needQty / fullPalletQty;//需要整托数
|
|
if (allotSet == 3)
|
{
|
decimal num = 0;
|
decimal numBer = needQty%fullPalletQty;
|
//var a = decimal.TryParse(numBer, out num);
|
//判断是否为整数
|
if (numBer == 0)
|
{
|
allotSet = 1;
|
}
|
else
|
{
|
allotSet = 0;
|
}
|
}
|
|
var zps = palletList.Where(s => s.Qty >= fullPalletQty).ToList();//整托
|
var sps = palletList.Where(s => s.Qty < fullPalletQty).ToList();//散托(有可能是被锁定了数量的)
|
//整托
|
var list = zps.Select(m => m.Id).ToList();
|
var ceShi = Db.Queryable<DataStockDetail>().Where(m => m.IsDel == "0" && list.Contains(m.Id));
|
if (roadway.Count == 0)
|
{
|
ceShi = ceShi.Where(a => string.IsNullOrWhiteSpace(a.RoadwayNo));
|
}
|
else if (roadway.Count > 0)
|
{
|
ceShi = ceShi.Where(a => roadway.Contains(a.RoadwayNo));
|
}
|
var ceShi2 = ceShi.LeftJoin<SysStorageLocat>((a, b) => a.LocatNo == b.LocatNo)
|
.Select((a, b) => new
|
{
|
Id = a.Id,
|
Qty = a.Qty,
|
LockQty = a.LockQty,
|
FrozenQty = a.FrozenQty,
|
Depth = b.Depth,
|
ExpirationTime = a.ExpirationTime
|
}).ToList();
|
|
//if (roadway.Count == 0)
|
//{
|
// throw new Exception("当前巷道已被全部禁用,禁止分配!");
|
//}
|
//散托
|
var list2 = sps.Select(m => m.Id).ToList();
|
var ceShi3 = Db.Queryable<DataStockDetail>().Where(m => m.IsDel == "0" && list2.Contains(m.Id));
|
if (roadway.Count == 0)
|
{
|
ceShi3 = ceShi3.Where(a => string.IsNullOrWhiteSpace(a.RoadwayNo));
|
}
|
else if (roadway.Count > 0)
|
{
|
ceShi3 = ceShi3.Where(a => roadway.Contains(a.RoadwayNo));
|
}
|
if (palletList.Count == 0)
|
{
|
throw new Exception("当前未禁用巷道无可分配货物,禁止分配!");
|
}
|
var ceShi4 = ceShi3.LeftJoin<SysStorageLocat>((a, b) => a.LocatNo == b.LocatNo)
|
.Select((a, b) => new
|
{
|
Id = a.Id,
|
Qty = a.Qty,
|
LockQty = a.LockQty,
|
FrozenQty = a.FrozenQty,
|
Depth = b.Depth,
|
ExpirationTime = a.ExpirationTime
|
}).ToList();
|
|
int? dataStockQtyCount = 0;
|
foreach (var item in palletList)
|
{
|
dataStockQtyCount += item.Qty;
|
if (dataStockQtyCount >= needQty)
|
{
|
break;
|
}
|
}
|
if (dataStockQtyCount < needQty)
|
{
|
throw new Exception("当前未禁用巷道可分配货物不足,禁止分配!");
|
}
|
|
if (allotSet == 0)//优先零箱(出完零箱出整箱)
|
{
|
//已分配的托盘 key:库存明细ID,value:分配的数量
|
var st = ceShi4.OrderBy(s => s.ExpirationTime).ThenBy(m => m.Depth).ThenBy(s => s.Qty - s.LockQty - s.FrozenQty).ToList();//所有未使用的托盘(未被分配的)
|
//散托
|
foreach (var s in st)
|
{
|
var detailQty = int.Parse((s.Qty - s.LockQty - s.FrozenQty).ToString());
|
if (needQty - qty < detailQty)
|
{
|
var num = needQty - qty;
|
qty += num;
|
SaveDic(stockQtyDic, s.Id, num);
|
break;
|
}
|
|
qty += detailQty;
|
SaveDic(stockQtyDic, s.Id, detailQty);
|
if (qty >= needQty)
|
{
|
break;
|
}
|
}
|
|
//不够//取整托
|
if (qty < needQty)
|
{
|
|
var zt = ceShi2.OrderBy(m=>m.ExpirationTime).ThenBy(m => m.Depth).ToList();//所有未使用的托盘(未被分配的)
|
foreach (var ss in zt)
|
{
|
var detailQty = int.Parse((ss.Qty - ss.LockQty - ss.FrozenQty).ToString());
|
if (needQty - qty < detailQty)
|
{
|
var num = needQty - qty;
|
qty += num;
|
SaveDic(stockQtyDic, ss.Id, num);
|
break;
|
}
|
qty += detailQty;
|
SaveDic(stockQtyDic, ss.Id, detailQty);
|
|
if (qty >= needQty)
|
{
|
break;
|
}
|
}
|
|
|
}
|
|
}
|
else if (allotSet == 1)//优先匹配数、(分配合适的数量)
|
{
|
//先判断需要的数量
|
//判断需要整托的数量是否大于0
|
//是:先出整托,剩余的数量从托盘上数量最少的出、(如果找合适的数量、可能小数量很小概率会被分配到、有先进先出日期卡着)
|
//否:数量从托盘上数量最少的出、(如果找合适的数量、可能小数量很小概率会被分配到、有先进先出日期卡着)
|
//
|
//取整托
|
if (ztNum > 0)
|
{
|
var zt = ceShi2.OrderBy(s => s.ExpirationTime).ThenBy(m=>m.Depth).ToList();//所有未使用的托盘(未被分配的)
|
foreach (var ss in zt)
|
{
|
var detailQty = int.Parse((ss.Qty - ss.LockQty - ss.FrozenQty).ToString());
|
if (needQty - qty < detailQty)
|
{
|
break;
|
}
|
qty += detailQty;
|
SaveDic(stockQtyDic, ss.Id, detailQty);
|
if (qty >= needQty)
|
{
|
break;
|
}
|
}
|
}
|
//从整托和和散托中查找合适的(从数量少的先出往)
|
if (qty < needQty)
|
{
|
var sIds = stockQtyDic.Select(s => s.Key).ToList();
|
var zt = ceShi4.Where(s => !sIds.Contains(s.Id)).OrderBy(s => s.ExpirationTime).ThenBy(m=>m.Depth).ThenBy(m => m.Qty - m.LockQty - m.FrozenQty).ToList();//所有未使用(未被分配的)
|
|
foreach (var ss in zt)
|
{
|
var detailQty = int.Parse((ss.Qty - ss.LockQty - ss.FrozenQty).ToString());
|
if (needQty - qty < detailQty)
|
{
|
var num = needQty - qty;
|
qty += num;
|
SaveDic(stockQtyDic, ss.Id, num);
|
break;
|
}
|
qty += detailQty;
|
SaveDic(stockQtyDic, ss.Id, detailQty);
|
if (qty >= needQty)
|
{
|
break;
|
}
|
}
|
}
|
|
if (qty < needQty)
|
{
|
var zt = ceShi2.OrderBy(s => s.ExpirationTime).ThenBy(m=>m.Depth).ToList();//所有未使用的托盘(未被分配的)
|
foreach (var ss in zt)
|
{
|
var detailQty = int.Parse((ss.Qty - ss.LockQty - ss.FrozenQty).ToString());
|
if (needQty - qty < detailQty)
|
{
|
var num = needQty - qty;
|
qty += num;
|
SaveDic(stockQtyDic, ss.Id, num);
|
break;
|
}
|
qty += detailQty;
|
SaveDic(stockQtyDic, ss.Id, detailQty);
|
if (qty >= needQty)
|
{
|
break;
|
}
|
}
|
}
|
|
}
|
return qty;
|
|
}
|
catch (Exception e)
|
{
|
throw new Exception("分配出库物料失败:" + e.Message);
|
}
|
|
}
|
|
|
/// <summary>
|
/// 保存字典
|
/// </summary>
|
/// <param name="dic"></param>
|
/// <param name="key"></param>
|
/// <param name="v"></param>
|
private void SaveDic(Dictionary<int, int> dic, int key, int v)
|
{
|
if (dic.ContainsKey(key))
|
{
|
dic[key] += v;
|
}
|
else
|
{
|
dic.Add(key, v);
|
}
|
}
|
|
|
}
|
}
|