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); } } } }