using System;
|
using System.Collections.Generic;
|
using System.Linq;
|
using System.Text;
|
using Model.ModelDto.DataDto;
|
using SqlSugar;
|
using WMS.Entity.Context;
|
using WMS.Entity.DataEntity;
|
using WMS.Entity.SysEntity;
|
|
namespace WMS.BLL.Logic
|
{
|
public class AllotSku
|
{
|
/// <summary>
|
/// 分配货物
|
/// </summary>
|
/// <param name="palletList">库存明细集合</param>
|
/// <param name="needQty">需要分配的数量</param>
|
/// <param name="fullPalletQty">满托数量</param>
|
/// <param name="fullBoxQty">满箱数量</param>
|
/// <param name="stockQtyDic">托出库物品数 key:库存托盘表的ID、val:托盘上的数量</param>
|
/// <returns></returns>
|
public decimal AllotPallets(List<DataStockDetail> palletList, decimal needQty, int fullPalletQty, int fullBoxQty, Dictionary<int, decimal> stockQtyDic)
|
{
|
//优先先进先出(快过期的先出)
|
//优先零箱、零托(出完零箱出整箱)
|
//优先匹配数、(分配合适的数量)
|
|
try
|
{
|
var contextDb = DataContext.Db;
|
|
#region 分配规则
|
|
var funSet = contextDb.Queryable<SysFunSetting>().Where(m => m.IsDel == "0" && m.FunSetName == "分配规则" && m.IsEnable == "NO").ToList().FirstOrDefault();
|
|
var allotSet = 1;//分配规则设定
|
|
if (funSet != null)
|
{
|
switch (funSet.FunSetNo)
|
{
|
case "Fun001":
|
allotSet = 0;//优先零托(出完零托出整托)
|
break;
|
case "Fun002":
|
allotSet = 1;//优先整托(分配合适的整托数量)
|
break;
|
default:
|
allotSet = 1;// 默认:优先整托、
|
break;
|
}
|
}
|
#endregion
|
decimal qty = 0; //分配的总数量
|
var ztNum = needQty / fullPalletQty;//需要整托数
|
|
var list = GetDataListOrderByDept(palletList);
|
|
var zps = list.Where(s => s.Qty >= fullPalletQty).ToList();//整托
|
var sps = list.Where(s => s.Qty < fullPalletQty).ToList();//散托(有可能是被锁定了数量的)
|
|
if (allotSet == 0)//优先零箱(出完零箱出整箱)
|
{
|
//已分配的托盘 key:库存明细ID,value:分配的数量
|
var st = sps.OrderBy(s => s.ExpirationTime).ThenBy(s => s.Qty - s.LockQty - s.FrozenQty).ToList();//所有未使用的托盘(未被分配的)
|
//散托
|
foreach (var s in st)
|
{
|
var detailQty = decimal.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 = zps.OrderBy(s => s.ExpirationTime).ToList();//所有未使用的托盘(未被分配的)
|
foreach (var ss in zt)
|
{
|
var detailQty = decimal.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 = zps.OrderBy(s => s.ExpirationTime).ToList();//所有未使用的托盘(未被分配的)
|
foreach (var ss in zt)
|
{
|
var detailQty = decimal.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 = sps.Where(s => !sIds.Contains(s.Id)).OrderBy(s => s.ExpirationTime).ThenBy(m => m.Qty - m.LockQty - m.FrozenQty).ToList();//所有未使用(未被分配的)
|
|
foreach (var ss in zt)
|
{
|
var detailQty = decimal.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 sIds = stockQtyDic.Select(s => s.Key).ToList();
|
var zt = zps.Where(s => !sIds.Contains(s.Id)).OrderBy(s => s.ExpirationTime).ThenBy(m => m.Qty - m.LockQty - m.FrozenQty).ToList();//所有未使用(未被分配的)
|
foreach (var ss in zt)
|
{
|
var detailQty = decimal.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)
|
{
|
throw new Exception("库存数量不足");
|
}
|
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, decimal> dic, int key, decimal v)
|
{
|
if (dic.ContainsKey(key))
|
{
|
dic[key] += v;
|
}
|
else
|
{
|
dic.Add(key, v);
|
}
|
}
|
|
//--------------------------------------------------------------------------------------------------------------
|
|
#region MyRegion
|
|
///// <summary>
|
///// 获得背包承重w,装货物o,从第k件向后考虑,得到的最大价值
|
///// </summary>
|
///// <param name="w">背包承重</param>
|
///// <param name="o">货物o</param>
|
///// <param name="k">第几件开始默认索引0</param>
|
///// <returns></returns>
|
//public static int GetMaxValue(int w, int[,] o, int k)
|
//{
|
// int v, t1, t2;
|
// //如果是最后一件货物
|
// if (k == o.GetLength(1) - 1)
|
// {
|
// if (w >= o[0, k])
|
// {
|
// v = o[1, k];
|
// }
|
// else
|
// {
|
// v = 0;
|
// }
|
// }
|
// //如果装得下当前货物
|
// else if (w >= o[0, k])
|
// {
|
// t1 = GetMaxValue(w - o[0, k], o, k + 1) + o[1, k];
|
// t2 = GetMaxValue(w, o, k + 1);
|
// v = GetMax(t1, t2);
|
// }
|
// //装不下当前货物的情况
|
// else
|
// {
|
// v = GetMaxValue(w, o, k + 1);
|
// }
|
// return v;
|
//}
|
//public static int GetMax(int a, int b)
|
//{
|
// return a > b ? a : b;
|
//}
|
|
#endregion
|
|
|
private List<StockDetailDto> GetDataListOrderByDept(List<DataStockDetail> palletList)
|
{
|
try
|
{
|
var Db = DataContext.Db;
|
var data = new List<StockDetailDto>();
|
|
var list = palletList.Select(m => new StockDetailDto()
|
{
|
Id = m.Id,
|
LotNo = m.LotNo,
|
LotText = m.LotText,
|
SupplierLot = m.SupplierLot,
|
OwnerNo = m.OwnerNo,
|
OwnerName = m.OwnerName,
|
SupplierNo = m.SupplierNo,
|
SupplierName = m.SupplierName,
|
SkuNo = m.SkuNo,
|
SkuName = m.SkuName,
|
Standard = m.Standard,
|
Qty = m.Qty,
|
LockQty = m.LockQty,
|
FrozenQty = m.FrozenQty,
|
InspectQty = m.InspectQty,
|
ASNNo = m.ASNNo,
|
ASNDetailNo = m.ASNDetailNo,
|
WareHouseNo = m.WareHouseNo,
|
RoadwayNo = m.RoadwayNo,
|
AreaNo = m.AreaNo,
|
LocatNo = m.LocatNo,
|
PalletNo = m.PalletNo,
|
PalletNo2 = m.PalletNo2,
|
PalletNo3 = m.PalletNo3,
|
CompleteTime = m.CompleteTime,
|
ProductionTime = m.ProductionTime,
|
ExpirationTime = m.ExpirationTime,
|
Status = m.Status,
|
InspectMark = m.InspectMark,
|
BitPalletMark = m.BitPalletMark,
|
InspectStatus = m.InspectStatus,
|
InspectTime = m.InspectTime,
|
PackagNo = m.PackagNo,
|
IsBale = m.IsBale,
|
IsBelt = m.IsBelt,
|
Demo = m.Demo,
|
|
}).ToList();
|
//库外托盘
|
var detail1 = list.Where(m => string.IsNullOrWhiteSpace(m.LocatNo)).ToList();
|
//平库内托盘
|
var detail2 = list.Where(m => m.WareHouseNo == "W02").ToList();
|
//立库内托盘
|
var detail3 = list.Where(m => m.WareHouseNo == "W01").ToList();
|
|
foreach (var item in detail2)
|
{
|
var dept = item.LocatNo.Substring(5,2);
|
|
item.Dept = int.Parse(dept);
|
}
|
foreach (var item in detail3)
|
{
|
var dept = item.LocatNo.Substring(6, 2);
|
|
item.Dept = int.Parse(dept);
|
}
|
data.AddRange(detail1);
|
data.AddRange(detail2.OrderBy(m => m.Dept).ToList());
|
data.AddRange(detail3.OrderBy(m => m.Dept).ToList());
|
|
return data;
|
}
|
catch (Exception e)
|
{
|
throw new Exception(e.Message);
|
}
|
}
|
|
|
}
|
}
|