using System;
|
using System.Collections.Generic;
|
using System.Linq;
|
using System.Text;
|
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="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>().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
|
var qty = 0; //分配的总数量
|
var ztNum = needQty / fullPalletQty;//需要整托数
|
|
var zps = palletList.Where(s => s.Qty >= fullPalletQty).ToList();//整托
|
var sps = palletList.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 = 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 = zps.OrderBy(s => s.ExpirationTime).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 = zps.OrderBy(s => s.ExpirationTime).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 = 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 = 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 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 = 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)
|
{
|
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, int> dic, int key, int v)
|
{
|
if (dic.ContainsKey(key))
|
{
|
dic[key] += v;
|
}
|
else
|
{
|
dic.Add(key, v);
|
}
|
}
|
|
//--------------------------------------------------------------------------------------------------------------
|
|
|
///// <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;
|
//}
|
|
}
|
}
|