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
{
///
/// 分配货物
///
/// 库存明细集合
/// 需要分配的数量
/// 满托数量
/// 满箱数量
/// 托出库物品数 key:库存托盘表的ID、val:托盘上的数量
///
public decimal AllotPallets(List palletList, decimal needQty, int fullPalletQty, int fullBoxQty, Dictionary stockQtyDic)
{
//优先先进先出(快过期的先出)
//优先零箱、零托(出完零箱出整箱)
//优先匹配数、(分配合适的数量)
try
{
var contextDb = DataContext.Db;
#region 分配规则
var funSet = contextDb.Queryable().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);
}
}
///
/// 保存字典
///
///
///
///
private void SaveDic(Dictionary dic, int key, decimal v)
{
if (dic.ContainsKey(key))
{
dic[key] += v;
}
else
{
dic.Add(key, v);
}
}
//--------------------------------------------------------------------------------------------------------------
#region MyRegion
/////
///// 获得背包承重w,装货物o,从第k件向后考虑,得到的最大价值
/////
///// 背包承重
///// 货物o
///// 第几件开始默认索引0
/////
//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 GetDataListOrderByDept(List palletList)
{
try
{
var Db = DataContext.Db;
var data = new List();
//库外托盘
var detail1 = palletList.Where(m => string.IsNullOrWhiteSpace(m.LocatNo)).ToList();
//平库内托盘
var detail2 = palletList.Where(m => m.WareHouseNo == "W02").ToList();
//立库内托盘
var detail3 = palletList.Where(m => m.WareHouseNo == "W01").ToList();
var data1 = detail1.Select(m => new StockDetailDto()).ToList();
var data2 = detail2.Select(m => new StockDetailDto()).ToList();
var data3 = detail3.Select(m => new StockDetailDto()).ToList();
foreach (var item in data2)
{
var dept = item.LocatNo.Substring(5,2);
item.Dept = int.Parse(dept);
}
foreach (var item in data3)
{
var dept = item.LocatNo.Substring(6, 2);
item.Dept = int.Parse(dept);
}
data.AddRange(data1);
data.AddRange(data2.OrderBy(m => m.Dept).ToList());
data.AddRange(data3.OrderBy(m => m.Dept).ToList());
return data;
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
}
}