using System; using System.Collections.Generic; using System.Linq; using System.Text; using SqlSugar; using WMS.Entity.Context; using WMS.Entity.DataEntity; using WMS.Entity.SysEntity; namespace WMS.BLL.Logic { public class AllotSku { private static readonly SqlSugarScope Db = DataContext.Db; /// /// 分配货物 /// /// 库存明细集合 /// 物料编码 /// 批次 /// 需要分配的数量 /// 满托数量 /// 满箱数量 /// 托出库物品数 key:库存托盘表的ID、val:托盘上的数量 /// public int AllotPallets(List palletList, int needQty, int fullPalletQty, int fullBoxQty, Dictionary stockQtyDic) { //优先先进先出(快过期的先出) //优先零箱、零托(出完零箱出整箱) //优先匹配数、(分配合适的数量) try { var contextDb = DataContext.Db; #region 分配规则 var funSet = contextDb.Queryable().First(m => m.IsDel == "0" && m.FunSetName == "分配规则" && m.IsEnable == "NO"); var allotSet = 1;//分配规则设定 if (funSet != null) { switch (funSet.FunSetNo) { case "Fun001": allotSet = 0;//优先零箱(出完零箱出整箱) break; case "Fun002": allotSet = 1;//优先匹配数、(分配合适的数量) break; case "Fun017": allotSet = 3;//优先零箱(若分配数量是整托数量的倍数 那么整箱优先) break; default: allotSet = 1;// 默认:优先匹配数、 break; } } #endregion var roadway = Db.Queryable().Where(a => a.IsDel == "0" && a.WareHouseNo == "W03" && a.Status == "0").Select(a => a.RoadwayNo).ToList(); var qty = 0; //分配的总数量 var ztNum = needQty / fullPalletQty;//需要整托数 if (allotSet == 3) { decimal num = 0; decimal numBer = needQty%fullPalletQty; //var a = decimal.TryParse(numBer, out num); //判断是否为整数 if (numBer == 0) { allotSet = 1; } else { allotSet = 0; } } var zps = palletList.Where(s => s.Qty >= fullPalletQty).ToList();//整托 var sps = palletList.Where(s => s.Qty < fullPalletQty).ToList();//散托(有可能是被锁定了数量的) //整托 var list = zps.Select(m => m.Id).ToList(); var ceShi = Db.Queryable().Where(m => m.IsDel == "0" && list.Contains(m.Id)); if (roadway.Count == 0) { ceShi = ceShi.Where(a => string.IsNullOrWhiteSpace(a.RoadwayNo)); } else if (roadway.Count > 0) { ceShi = ceShi.Where(a => roadway.Contains(a.RoadwayNo)); } var ceShi2 = ceShi.LeftJoin((a, b) => a.LocatNo == b.LocatNo) .Select((a, b) => new { Id = a.Id, Qty = a.Qty, LockQty = a.LockQty, FrozenQty = a.FrozenQty, Depth = b.Depth, ExpirationTime = a.ExpirationTime }).ToList(); //if (roadway.Count == 0) //{ // throw new Exception("当前巷道已被全部禁用,禁止分配!"); //} //散托 var list2 = sps.Select(m => m.Id).ToList(); var ceShi3 = Db.Queryable().Where(m => m.IsDel == "0" && list2.Contains(m.Id)); if (roadway.Count == 0) { ceShi3 = ceShi3.Where(a => string.IsNullOrWhiteSpace(a.RoadwayNo)); } else if (roadway.Count > 0) { ceShi3 = ceShi3.Where(a => roadway.Contains(a.RoadwayNo)); } if (palletList.Count == 0) { throw new Exception("当前未禁用巷道无可分配货物,禁止分配!"); } var ceShi4 = ceShi3.LeftJoin((a, b) => a.LocatNo == b.LocatNo) .Select((a, b) => new { Id = a.Id, Qty = a.Qty, LockQty = a.LockQty, FrozenQty = a.FrozenQty, Depth = b.Depth, ExpirationTime = a.ExpirationTime }).ToList(); int? dataStockQtyCount = 0; foreach (var item in palletList) { dataStockQtyCount += item.Qty; if (dataStockQtyCount >= needQty) { break; } } if (dataStockQtyCount < needQty) { throw new Exception("当前未禁用巷道可分配货物不足,禁止分配!"); } if (allotSet == 0)//优先零箱(出完零箱出整箱) { //已分配的托盘 key:库存明细ID,value:分配的数量 var st = ceShi4.OrderBy(s => s.ExpirationTime).ThenBy(m => m.Depth).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 = ceShi2.OrderBy(m=>m.ExpirationTime).ThenBy(m => m.Depth).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 = ceShi2.OrderBy(s => s.ExpirationTime).ThenBy(m=>m.Depth).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 = ceShi4.Where(s => !sIds.Contains(s.Id)).OrderBy(s => s.ExpirationTime).ThenBy(m=>m.Depth).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 zt = ceShi2.OrderBy(s => s.ExpirationTime).ThenBy(m=>m.Depth).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; } } } } return qty; } catch (Exception e) { throw new Exception("分配出库物料失败:" + e.Message); } } /// /// 保存字典 /// /// /// /// private void SaveDic(Dictionary dic, int key, int v) { if (dic.ContainsKey(key)) { dic[key] += v; } else { dic.Add(key, v); } } } }