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>
|
/// <param name="lotNo">批次</param>
|
/// <param name="isMixBox">是否接受拼箱 0:否 1:是</param>
|
/// <returns></returns>
|
public decimal AllotPallets(List<DataStockDetail> palletList, decimal needQty, int fullPalletQty, int fullBoxQty, Dictionary<int, decimal> stockQtyDic,string house)
|
{
|
//优先先进先出(快过期的先出)
|
//优先零箱、零托(出完零箱出整箱)
|
//优先匹配数、(分配合适的数量)
|
|
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 list = palletList;
|
decimal qty = 0; //分配的总数量
|
|
if (house == "W01") //仓库是密集库先进行排序
|
{
|
list = GetDataListOrder(palletList);
|
}
|
|
if (fullPalletQty == 0)//无包装物料分配
|
{
|
//已分配的托盘 key:库存明细ID,value:分配的数量
|
var st = list.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;
|
}
|
}
|
}
|
else
|
{
|
var ztNum = needQty / fullPalletQty;//需要整托数
|
|
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="palletList"></param>
|
/// <returns></returns>
|
public List<DataStockDetail> GetDataListOrder(List<DataStockDetail> palletList)
|
{
|
try
|
{
|
var Db = DataContext.Db;
|
var data = new List<DataStockDetail>();
|
var locateList = Db.Queryable<SysStorageLocat>().Where(m => m.IsDel == "0" && m.WareHouseNo == "W01").ToList();
|
var list = palletList;
|
//库外托盘
|
var detail1 = list.Where(m => string.IsNullOrWhiteSpace(m.LocatNo)).OrderByDescending(a => a.PalletTags).ToList();
|
// 库外
|
data.AddRange(detail1);
|
//密集库内托盘
|
var detail2 = list.Where(m => m.WareHouseNo == "W01").ToList();
|
|
var detail3 = detail2.GroupBy(m=>m.RoadwayNo).OrderBy(m=>m.Key).ToList();
|
|
foreach (var item in detail3)
|
{
|
var locates = locateList.Where(m => m.RoadwayNo == item.Key).FirstOrDefault();
|
if (locates == null)
|
{
|
throw new Exception("未查询到巷道内的储位信息");
|
}
|
//如果结果为0,则说明两个字符串相等; ABC BCE
|
//如果结果小于0,则说明第一个字符串小于第二个字符串;
|
//如果结果大于0,则说明第一个字符串大于第二个字符串。
|
var bol = String.CompareOrdinal(locates.LocatNo, locates.AisleOne);
|
|
//储位小于通道口 倒序
|
//储位大于通道口 正序
|
if (bol < 0)
|
{
|
//var s = item.OrderByDescending(m => m.LocatNo).ToList();
|
data.AddRange(item.OrderByDescending(m => m.LocatNo));
|
}
|
if (bol > 0)
|
{
|
data.AddRange(item.OrderBy(m => m.LocatNo));
|
}
|
|
}
|
|
return data;
|
}
|
catch (Exception e)
|
{
|
throw new Exception(e.Message);
|
}
|
}
|
|
/// <summary>
|
/// 查找出混箱中其他批次总数量
|
/// </summary>
|
/// <param name="stockDetailId"></param>
|
/// <param name="lotNo"></param>
|
/// <returns></returns>
|
private decimal GetMixBoxQty(int stockDetailId,string lotNo)
|
{
|
var contextDb = DataContext.Db;
|
//查找出混箱集合
|
List<string> mixBoxList = contextDb.Queryable<DataBoxInfo>()
|
.Where(w => w.IsDel == "0" && w.StockDetailId == stockDetailId)
|
.GroupBy(g => g.LotNo)
|
.Having(h => SqlFunc.AggregateCount(h.LotNo) > 1)
|
.Select(s => s.BoxNo).ToList();
|
|
decimal otherLotQty = contextDb.Queryable<DataBoxInfo>()
|
.Where(w => w.IsDel == "0" && w.StockDetailId == stockDetailId && mixBoxList.Contains(w.BoxNo) && w.LotNo != lotNo)
|
.Sum(s => s.Qty);
|
|
return otherLotQty;
|
}
|
|
/// <summary>
|
/// JC23领料出库分配货物(分配托盘上全部物料,防止四楼不同投料口分配同一托盘物料冲突)
|
/// </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 LingLiaoAllotPallets(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
|
|
//分配:优先库外(正常情况下不存在库外托盘)、平库、立库 2:数量少的先出(零托优先)
|
decimal qty = 0; //分配的总数量
|
var list = GetDataListOrderByDept(palletList);
|
|
if (fullPalletQty == 0)//无包装物料分配
|
{
|
//已分配的托盘 key:库存明细ID,value:分配的数量
|
var st = list.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());
|
|
qty += detailQty;
|
SaveDic(stockQtyDic, s.Id, detailQty);
|
if (qty >= needQty)
|
{
|
break;
|
}
|
}
|
}
|
else
|
{
|
var ztNum = needQty / fullPalletQty;//需要整托数
|
|
|
|
var zps = list.Where(s => s.Qty >= fullPalletQty).ToList();//整托
|
var sps = list.Where(s => s.Qty < fullPalletQty).ToList();//散托(有可能是被锁定了数量的)
|
|
|
//已分配的托盘 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());
|
|
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());
|
|
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="palletList">托盘明细</param>
|
/// <param name="boxInfoList">箱码明细</param>
|
/// <param name="needQty">需求数</param>
|
/// <param name="stockQtyDic">托出库物品数</param>
|
/// <param name="useBoxQtyDic">托出库物品数</param>
|
/// <param name="type">取样类型1:规则取样 2:随机取样</param>
|
/// <param name="boxNum">需分配的箱数量 随机取样用</param>
|
/// <param name="pickNum"></param>
|
/// <returns></returns>
|
public decimal AllotPalletsQuYang(List<DataStockDetail> palletList, List<DataBoxInfo> boxInfoList, decimal needQty, Dictionary<int, decimal> stockQtyDic, Dictionary<int, decimal> useBoxQtyDic, string type, int boxNum, decimal pickNum)
|
{
|
try
|
{
|
decimal? qty = 0;
|
var listOrder = boxInfoList.Where(m => m.IsDel == "0").OrderBy(m => m.BoxNo).ThenBy(m => m.Qty).ToList();//根据箱码、数量排序 整箱的
|
var boxList = listOrder.GroupBy(m => m.BoxNo).Select(m => m.Key).ToList();//分组后的箱码集合
|
var boxCount = boxList.Count();//箱数量
|
#region 旧分配原则
|
|
//var outInfoCount = 0;
|
//var boxStrList = new List<string>();//随机使用箱
|
//Dictionary<string, decimal> useInfoQtyDic = new Dictionary<string, decimal>();//使用箱
|
|
//if (type == "1")//规则取样(N<3;3<N<300;300<N)
|
//{
|
// if (boxCount<=3)//箱子小于3
|
// {
|
// foreach (var item in boxList)//循环箱子
|
// {
|
// boxStrList.Add(item);
|
// }
|
// }
|
// else if (boxCount > 3)//箱子小于3
|
// {
|
// var a = Math.Sqrt(boxCount)+1;//开平方 //规则 箱数 √N+1
|
// if (boxCount > 300)
|
// {
|
// a = Math.Sqrt(boxCount) / 2 + 1;//规则 箱数 √N/2+1
|
// }
|
// var b = Math.Floor(a); //取样的箱数
|
|
// var lit = new List<int>();
|
// do
|
// {
|
// byte[] buffer = Guid.NewGuid().ToByteArray();
|
// int iSeed = BitConverter.ToInt32(buffer, 0);
|
// Random random = new Random(iSeed);
|
// var j = random.Next(0, boxCount);
|
// if (lit.Contains(j))
|
// {
|
// continue;
|
// }
|
|
// var boxCode = boxList[j];//箱码
|
// boxStrList.Add(boxCode);
|
// lit.Add(j);
|
|
// } while (lit.Count < b);
|
|
// }
|
//}
|
//else if(type == "2") //随机取样(一批次出一箱)
|
//{
|
// if (boxCount < boxNum)
|
// {
|
// throw new Exception("当前库存整箱数少于输入的取样数");
|
// }
|
// var lit = new List<int>();
|
// do
|
// {
|
// byte[] buffer = Guid.NewGuid().ToByteArray();
|
// int iSeed = BitConverter.ToInt32(buffer, 0);
|
// Random random = new Random(iSeed);
|
// var j = random.Next(0, boxCount);
|
// if (lit.Contains(j))
|
// {
|
// continue;
|
// }
|
|
// var boxCode = boxList[j];//箱码
|
// boxStrList.Add(boxCode);
|
// lit.Add(j);
|
|
// } while (lit.Count < boxNum);
|
//}
|
//else
|
//{
|
// throw new Exception("请选择取样规则");
|
//}
|
//foreach (var item in boxStrList)//循环箱子
|
//{
|
// var box = listOrder.Where(m => m.BoxCode == item).ToList();
|
// var infoCount = box.Count;//箱内支数量
|
// if (infoCount <= 3) //支数量<=3
|
// {
|
// outInfoCount += infoCount;
|
// SaveDic(useInfoQtyDic, item, infoCount);
|
// }
|
// else if (infoCount > 3)//箱内数量 > 3 且 <=300
|
// {
|
// //规则 取样支数 √N+1
|
// var c = Math.Sqrt(infoCount) + 1;//开平方
|
|
// if (infoCount > 300) //箱内数量 > 300
|
// {
|
// //规则 箱数 √N/2+1
|
// c = Math.Sqrt(infoCount) / 2 + 1;
|
// }
|
// var d = Math.Floor(c); //取样的支数量
|
|
// outInfoCount += (int)d;
|
// SaveDic(useInfoQtyDic, item, (decimal)d);
|
// }
|
//}
|
|
//var pingJunNum = needQty / outInfoCount;//平均每支取的数量
|
//foreach (var item in useInfoQtyDic)
|
//{
|
// var box = listOrder.Where(m => m.BoxCode == item.Key).ToList();
|
// var infoCount = box.Count;//箱内支数量
|
// if (infoCount <= 3) //支数量<=3
|
// {
|
// foreach (var item2 in box)
|
// {
|
// if (pingJunNum >= item2.Qty)
|
// {
|
// throw new Exception("平均需取样数量大于等于箱支内数量");
|
// }
|
// qty += pingJunNum;
|
// var tray = palletList.First(m => m.Id == item2.TrayId);
|
|
// SaveDic(stockQtyDic, tray.Id, pingJunNum);
|
|
// SaveDic(useBoxQtyDic, item2.Id, pingJunNum);
|
// }
|
// }
|
// else if (infoCount > 3)//箱内数量 > 3 且 <=300
|
// {
|
// var e = item.Value; //取样的支数量
|
|
// var lit2 = new List<int>();
|
|
// do
|
// {
|
// byte[] buffer = Guid.NewGuid().ToByteArray();
|
// int iSeed = BitConverter.ToInt32(buffer, 0);
|
// Random random = new Random(iSeed);
|
// var j = random.Next(0, infoCount);//随机箱内支码
|
|
// if (lit2.Contains(j))
|
// {
|
// continue;
|
// }
|
|
// var info = box[j];
|
// if (pingJunNum >= info.Qty)
|
// {
|
// throw new Exception("平均需取样数量大于等于箱支内数量");
|
// }
|
|
// qty += pingJunNum;
|
// var tray = palletList.First(m => m.Id == info.TrayId);
|
|
// SaveDic(stockQtyDic, tray.Id, pingJunNum);
|
// SaveDic(useBoxQtyDic, info.Id, pingJunNum);
|
// lit2.Add(j);
|
|
|
// } while (lit2.Count < e);
|
// }
|
//}
|
|
#endregion
|
|
var outInfoCount = 0;
|
var boxStrList = new List<string>();//随机使用箱
|
Dictionary<string, int> useInfoQtyDic = new Dictionary<string, int>();//使用箱 及每箱出多少支
|
|
|
if (type == "1")//规则取样(N<3;3<N<300;300<N)
|
{
|
if (boxCount <= 3)//箱子小于3
|
{
|
foreach (var item in boxList)//循环箱子
|
{
|
boxStrList.Add(item);
|
}
|
}
|
else if (boxCount > 3)//箱子小于3
|
{
|
var a = Math.Sqrt(boxCount) + 1;//开平方 //规则 箱数 √N+1
|
if (boxCount > 300)
|
{
|
a = Math.Sqrt(boxCount) / 2 + 1;//规则 箱数 √N/2+1
|
}
|
var b = Math.Floor(a); //取样的箱数
|
|
var lit = new List<int>();
|
do
|
{
|
byte[] buffer = Guid.NewGuid().ToByteArray();
|
int iSeed = BitConverter.ToInt32(buffer, 0);
|
Random random = new Random(iSeed);
|
var j = random.Next(0, boxCount);
|
if (lit.Contains(j))
|
{
|
continue;
|
}
|
|
var boxCode = boxList[j];//箱码
|
boxStrList.Add(boxCode);
|
lit.Add(j);
|
|
} while (lit.Count < b);
|
|
}
|
var zhi = listOrder.Count();
|
if (zhi <= 3) //支数量<=3
|
{
|
outInfoCount += zhi;
|
}
|
else if (zhi > 3)//箱内数量 > 3 且 <=300
|
{
|
//规则 取样支数 √N+1
|
var c = Math.Sqrt(zhi) + 1;//开平方
|
|
if (zhi > 300) //箱内数量 > 300
|
{
|
//规则 箱数 √N/2+1
|
c = Math.Sqrt(zhi) / 2 + 1;
|
}
|
var d = Math.Floor(c); //取样的支数量
|
|
outInfoCount += (int)d;
|
}
|
}
|
else if (type == "2") //随机取样(一批次出一箱)
|
{
|
if (boxCount < boxNum)
|
{
|
throw new Exception("当前库存整箱数少于输入的取样数");
|
}
|
var lit = new List<int>();
|
do
|
{
|
byte[] buffer = Guid.NewGuid().ToByteArray();
|
int iSeed = BitConverter.ToInt32(buffer, 0);
|
Random random = new Random(iSeed);
|
var j = random.Next(0, boxCount);
|
if (lit.Contains(j))
|
{
|
continue;
|
}
|
|
var boxCode = boxList[j];//箱码
|
boxStrList.Add(boxCode);
|
lit.Add(j);
|
|
} while (lit.Count < boxNum);
|
|
var zhi = listOrder.Count(m => boxStrList.Contains(m.BoxNo));
|
if (zhi <= 3) //支数量<=3
|
{
|
outInfoCount += zhi;
|
}
|
else if (zhi > 3)//箱内数量 > 3 且 <=300
|
{
|
//规则 取样支数 √N+1
|
var c = Math.Sqrt(zhi) + 1;//开平方
|
|
if (zhi > 300) //箱内数量 > 300
|
{
|
//规则 箱数 √N/2+1
|
c = Math.Sqrt(zhi) / 2 + 1;
|
}
|
var d = Math.Floor(c); //取样的支数量
|
|
outInfoCount += (int)d;
|
}
|
}
|
else
|
{
|
throw new Exception("请选择取样规则");
|
}
|
|
var zhiCount = outInfoCount;
|
var xiangCount = boxStrList.Count; //随机出的箱数量
|
for (int i = 1; i <= boxStrList.Count; i++)
|
{
|
decimal t = zhiCount / xiangCount;
|
var t2 = zhiCount % xiangCount;
|
var t3 = 5 / 2;
|
var t4 = 5 % 2;
|
if (t2 > 0)
|
{
|
t += 1;
|
}
|
var q = (int)t;//箱内出多少支
|
var infoCount = listOrder.Count(m => m.BoxNo == boxStrList[i - 1]);
|
if (q > infoCount)
|
{
|
throw new Exception("箱内支数小于要分配的支数");
|
}
|
zhiCount -= q;
|
xiangCount -= 1;
|
SaveDic2(useInfoQtyDic, boxStrList[i - 1], q);
|
}
|
|
|
var pingJunNum = needQty / outInfoCount;// / pickNum;平均每支取的数量
|
|
foreach (var item in useInfoQtyDic)
|
{
|
var box = listOrder.Where(m => m.BoxNo == item.Key).ToList();
|
var infoCount = box.Count;//箱内支数量
|
if (infoCount == item.Value) //支数量<=3
|
{
|
foreach (var item2 in box)
|
{
|
if (pingJunNum > item2.Qty)
|
{
|
throw new Exception("平均需取样数量大于等于箱支内数量");
|
}
|
qty += pingJunNum;
|
var tray = palletList.First(m => m.Id == item2.Id);
|
|
SaveDic(stockQtyDic, tray.Id, pingJunNum);
|
|
SaveDic(useBoxQtyDic, item2.Id, pingJunNum);
|
}
|
}
|
else
|
{
|
var e = item.Value; //取样的支数量
|
|
var lit2 = new List<int>();
|
|
do
|
{
|
byte[] buffer = Guid.NewGuid().ToByteArray();
|
int iSeed = BitConverter.ToInt32(buffer, 0);
|
Random random = new Random(iSeed);
|
var j = random.Next(0, infoCount);//随机箱内支码
|
|
if (lit2.Contains(j))
|
{
|
continue;
|
}
|
|
var info = box[j];
|
if (pingJunNum > info.Qty)
|
{
|
throw new Exception("平均需取样数量大于等于箱支内数量");
|
}
|
|
qty += pingJunNum;
|
var tray = palletList.First(m => m.Id == info.Id);
|
|
SaveDic(stockQtyDic, tray.Id, pingJunNum);
|
SaveDic(useBoxQtyDic, info.Id, pingJunNum);
|
lit2.Add(j);
|
|
|
} while (lit2.Count < e);
|
}
|
}
|
|
|
return (decimal)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);
|
}
|
}
|
|
private void SaveDic2(Dictionary<string, int> dic, string key, int 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
|
|
/// <summary>
|
/// 根据储位深度获取分配的优先级别信息
|
/// </summary>
|
/// <param name="palletList"></param>
|
/// <returns></returns>
|
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,
|
PalletTags = m.PalletTags
|
|
}).ToList();
|
//库外托盘
|
var detail1 = list.Where(m => string.IsNullOrWhiteSpace(m.LocatNo)).OrderByDescending(a => a.PalletTags).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);
|
}
|
//平库
|
//var locate1 = Db.Queryable<SysStorageLocat>().Where(m => m.IsDel == "0" && m.WareHouseNo == "W02");
|
//var data2 = new List<StockDetailDto>();
|
//foreach (var pingku in detail2.OrderByDescending(a => a.PalletTags).ThenBy(m => m.Dept).ToList())
|
//{
|
// if (data2.Contains(pingku))
|
// {
|
// continue;
|
// }
|
|
// var currentLocate = locate1.First(m => m.LocatNo == pingku.LocatNo);
|
// var locateAfter = locate1.Where(m => m.AreaNo == currentLocate.AreaNo && m.Layer == currentLocate.Layer && m.Row == currentLocate.Row && int.Parse(m.Depth) < int.Parse(currentLocate.Depth)).OrderBy(m => m.Depth).ToList();
|
// foreach (var locat in locateAfter)
|
// {
|
// if (detail2.Any(m => m.LocatNo == locat.LocatNo) && !data2.Contains(detail2.First(m => m.LocatNo == locat.LocatNo)))
|
// {
|
// data2.Add(detail2.First(m => m.LocatNo == locat.LocatNo));
|
// }
|
|
// }
|
// data2.Add(pingku);
|
//}
|
|
//立库
|
var locate2 = Db.Queryable<SysStorageLocat>().Where(m => m.IsDel == "0" && m.WareHouseNo == "W01").ToList();
|
var data3 = new List<StockDetailDto>();
|
foreach (var liku in detail3.OrderByDescending(a => a.PalletTags).ThenBy(m => m.Dept).ToList())
|
{
|
if (data3.Contains(liku))
|
{
|
continue;
|
}
|
|
var currentLocate = locate2.First(m => m.LocatNo == liku.LocatNo);
|
var locateAfter = locate2.Where(m => m.Column == currentLocate.Column && m.Layer == currentLocate.Layer && m.Row == currentLocate.Row && int.Parse(m.Depth) < int.Parse(currentLocate.Depth)).OrderBy(m => m.Depth).ToList();
|
foreach (var locat in locateAfter)
|
{
|
if (detail3.Any(m=>m.LocatNo == locat.LocatNo) && !data3.Contains(detail3.First(m => m.LocatNo == locat.LocatNo)))
|
{
|
data3.Add(detail3.First(m=>m.LocatNo == locat.LocatNo));
|
}
|
|
}
|
data3.Add(liku);
|
}
|
|
|
data.AddRange(detail1); // 库外
|
data.AddRange(detail2); // 平库
|
data.AddRange(data3); // 立库
|
|
return data;
|
}
|
catch (Exception e)
|
{
|
throw new Exception(e.Message);
|
}
|
}
|
|
|
}
|
}
|