using Microsoft.CodeAnalysis; using Rhea.Common; using SqlSugar; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Tiger.IBusiness; using Tiger.Model; namespace Tiger.Business.WMS { public class WMS_ITEM_Biz { private static _Biz_WmsItem _WmsItem = new(); /// /// WMS_ITEM 业务 /// public static _Biz_WmsItem WmsItem => _WmsItem; /// /// WMS_ITEM 业务类 /// public partial class _Biz_WmsItem : IBiz_WmsItem { /// /// 获取条码库存信息,包括仓库,储区,货架,储位,父条码,包装明细等 /// /// 查询的条码 /// 授权查询选项 /// 是否同时执行拆包操作,解除与父条码之间的包装关系 /// public Result Get(string sn, AuthOption option, bool doUnPack) { var result = new Result(Result.Flags.Success); try { var inv = new Inventory(); Barcode barcode = new Barcode(sn); if (sn.IsNullOrEmpty()) { result.Flag = Result.Flags.Failed; result.LocaleMsg = new("WMS.WmsItem.Barcode.EmptyFailure"); } else if (barcode.IsException) { throw barcode.AnalyseException; } //非法条码 else if (!barcode.IsRegular) { result.Flag = Result.Flags.Failed; result.LocaleMsg = new("WMS.WmsItem.Barcode.IllegalFailure"); } //else if (barcode.Qty <= 0) //{ // result.Flag = Result.Flags.Failed; // result.LocaleMsg = new("数量不能小于等于零,请检查二维码!"); //} else { var query = Biz.Db.Queryable().ByAuth(option).Where(q => q.SN == barcode.SN).IncludesAllFirstLayer().First(); //var query = Biz.Db.Queryable().Where(q => q.SN == barcode.SN).IncludesAllFirstLayer().First();//.ByAuth(option) //包装表中找到条码 if (!query.IsNullOrEmpty())// && query.QTY > 0) { inv.SN = barcode.SN; inv.Barcode = barcode; inv.ExtInfo = query.ExtInfo; inv.ItemInfo = query.ItemInfo; inv.Warehouse = query.Warehouse; inv.Region = query.Region; inv.Shelf = query.Shelf; inv.Location = query.Location; inv.Packages = Biz.Db.Ado.UseStoredProcedure().SqlQuery("sp_wms_get_item_pkg", new SugarParameter("root", barcode.SN)); inv.Items = Biz.Db.Ado.UseStoredProcedure().SqlQuery("sp_wms_get_items", new SugarParameter("root", barcode.SN)); inv.ItemsExt = Biz.Db.Queryable().Where(q => inv.Items.Any(s => s.SN == q.SN)).ToList(); //var data = inv.Items.Select(i => i.SN).ToList().Except(inv.ItemsExt.Select(i => i.SN).ToList()); var data = inv.Items.Where(q => !inv.ItemsExt.Any(s => s.SN == q.SN)).ToList(); if (data.Count > 0) { foreach (var item in data) { inv.ItemsExt.Add(new() { SN = item.SN, META_SN = barcode.MetaSn, QR_CODE = barcode.MetaSn }); } } result.LocaleMsg = new($"WMS.WmsItem.Barcode.Get{(doUnPack ? "UnPack" : "")}Success", barcode.SN, query.Parent?.SN); if (!query.Parent.IsNullOrEmpty() && doUnPack && query.Parent.SN != query.SN) { inv.ParentPkg = null; //保存数据到数据库 var db = Biz.Db; var dbTran = db.UseTran(() => { var unPackQty = inv.Items.Sum(q => q.QTY); db.Updateable().SetColumns(q => q.PARENT_SN == null).Where(q => q.ID == query.ID).ExecuteCommand(); db.Updateable().SetColumns(q => q.QTY == q.QTY - unPackQty).Where(q => q.ID == query.Parent.ID).ExecuteCommand(); if (!Biz.Db.Queryable().Any(q => q.PARENT_SN == query.PARENT_SN && q.SN != query.SN)) { db.Deleteable(query.Parent); } }); if (!dbTran.IsSuccess) { throw dbTran.ErrorException; } } else { inv.ParentPkg = query.Parent; } } else { inv.SN = barcode.SN; inv.Barcode = barcode; inv.ItemInfo = Biz.Db.Queryable().Where(q => q.ITEM_CODE == barcode.ItemCode).First(); result.LocaleMsg = new($"WMS.WmsItem.Barcode.NotFound", barcode.SN); } } result.Data = inv; } catch (Exception ex) { result.CatchExceptionWithLog(ex, Biz.L("WMS.WmsItem.Barcode.GetException", sn)); } return result; } /// /// 客供料专用:获取条码库存信息,包括仓库,储区,货架,储位,父条码,包装明细等 /// 注:物料编码自动加K判断和处理 /// /// 查询的条码 /// 授权查询选项 /// 是否同时执行拆包操作,解除与父条码之间的包装关系 /// public Result GetK(string sn, AuthOption option, bool doUnPack) { var result = new Result(Result.Flags.Success, new Inventory()); try { var inv = new Inventory(); Barcode barcode = new Barcode(sn); barcode.ItemCode = (barcode.ItemCode.IsNullOrEmpty("K").StartsWith("K") ? "" : "K") + barcode.ItemCode; if (sn.IsNullOrEmpty()) { result.Flag = Result.Flags.Failed; result.LocaleMsg = new("WMS.WmsItem.Barcode.EmptyFailure"); } else if (barcode.IsException) { throw barcode.AnalyseException; } //非法条码 else if (!barcode.IsRegular) { result.Flag = Result.Flags.Failed; result.LocaleMsg = new("WMS.WmsItem.Barcode.IllegalFailure"); } else if (barcode.Qty <= 0) { result.Flag = Result.Flags.Failed; result.LocaleMsg = new("入库数量不能小于等于零,请检查二维码!"); } else { var query = Biz.Db.Queryable().ByAuth(option).Where(q => q.SN == barcode.SN).IncludesAllFirstLayer().First(); //包装表中找到条码 if (!query.IsNullOrEmpty() && query.QTY > 0) { inv.SN = barcode.SN; inv.Barcode = barcode; inv.ExtInfo = query.ExtInfo; inv.ItemInfo = query.ItemInfo; inv.Warehouse = query.Warehouse; inv.Region = query.Region; inv.Shelf = query.Shelf; inv.Location = query.Location; inv.Packages = Biz.Db.Ado.UseStoredProcedure().SqlQuery("pkg_wms_get_item_pkg", new SugarParameter("root", barcode.SN)); inv.Items = Biz.Db.Ado.UseStoredProcedure().SqlQuery("pkg_wms_get_items", new SugarParameter("root", barcode.SN)); inv.ItemsExt = Biz.Db.Queryable().Where(q => inv.Items.Any(s => s.SN == q.SN)).ToList();//扩展表 //var data = inv.Items.Select(i => i.SN).ToList().Except(inv.ItemsExt.Select(i => i.SN).ToList()); var data = inv.Items.Where(q => !inv.ItemsExt.Any(s => s.SN == q.SN)).ToList(); //扩展表不存在时新建 if (data.Count > 0) { foreach (var item in data) { inv.ItemsExt.Add(new() { SN = item.SN, META_SN = barcode.MetaSn, QR_CODE = barcode.MetaSn }); } } result.LocaleMsg = new($"WMS.WmsItem.Barcode.Get{(doUnPack ? "UnPack" : "")}Success", barcode.SN, query.Parent?.SN); if (!query.Parent.IsNullOrEmpty() && doUnPack && query.Parent.SN != query.SN) { inv.ParentPkg = null; //保存数据到数据库 var db = Biz.Db; var dbTran = db.UseTran(() => { var unPackQty = inv.Items.Sum(q => q.QTY); db.Updateable().SetColumns(q => q.PARENT_SN == null).Where(q => q.ID == query.ID).ExecuteCommand(); db.Updateable().SetColumns(q => q.QTY == q.QTY - unPackQty).Where(q => q.ID == query.Parent.ID).ExecuteCommand(); if (!Biz.Db.Queryable().Any(q => q.PARENT_SN == query.PARENT_SN && q.SN != query.SN)) { db.Deleteable(query.Parent); } }); if (!dbTran.IsSuccess) { throw dbTran.ErrorException; } } else { inv.ParentPkg = query.Parent; } } else { inv.SN = barcode.SN; inv.Barcode = barcode; inv.ItemInfo = Biz.Db.Queryable().Where(q => q.ITEM_CODE == barcode.ItemCode).First(); result.LocaleMsg = new($"WMS.WmsItem.Barcode.NotFound", barcode.SN); } } result.Data = inv; } catch (Exception ex) { result.CatchExceptionWithLog(ex, Biz.L("WMS.WmsItem.Barcode.GetException", sn)); } return result; } /// /// 上架 /// /// 要上架的库存对象 /// 授权查询选项 /// 要上架的储位代码 /// 是否移库操作 /// public Result PutOn(IInventory inventory, AuthOption option, string targetLocation, bool isTransfer = false) { var result = new Result(Result.Flags.Success, new PutOnInfo()); try { var inv = inventory as Inventory; var location = Biz.Db.Queryable().Where(q => q.LOCATION_CODE == targetLocation && q.AUTH_ORG == option.CurOrg).IncludesAllFirstLayer().First(); if (!location.IsNullOrEmpty()) { result.Data.Warehouse = location.Warehouse; result.Data.Region = location.Region; result.Data.Shelf = location.Shelf; result.Data.Location = location.Location; foreach (var item in inventory.Items) { item.STATUS = WMS_ITEM.STATUSs.InStore.GetValue(); item.SUPP_LOTNO = inv.Barcode.LotNo; item.FIRST_IN_DATE = item.FIRST_IN_DATE <= DateTime.MinValue ? DateTime.Now : item.FIRST_IN_DATE; item.PROD_DATE = item.PROD_DATE <= DateTime.MinValue ? item.FIRST_IN_DATE : item.PROD_DATE; item.WH_ID = location.WH_ID; item.REGION_ID = location.REGION_ID; item.SHELF_ID = location.SHELF_ID; item.LOCATION_ID = location.LOCATION_ID; inventory.History.Add(new WMS_ITEM_HIS(item, $"条码[{inventory.SN}]{(isTransfer ? "移库" : "上架")}到储位[{location.LOCATION_CODE}]成功{(isTransfer ? "" : $",操作单据[{item.TRANS_NO}]")}")); } foreach (var item in inventory.Packages) { item.WH_ID = location.WH_ID; item.REGION_ID = location.REGION_ID; item.SHELF_ID = location.SHELF_ID; item.LOCATION_ID = location.LOCATION_ID; } foreach (var item in inventory.ItemsExt) { item.AUTH_ORG = option.OrgCode; item.SN = inv.Barcode.SN; } result.Data.Items = inventory.Items; result.Data.History = inventory.History; result.Data.Packages = inventory.Packages; result.Data.ItemsExt = inventory.ItemsExt; } else { result.Flag = Result.Flags.Failed; result.LocaleMsg = new("WMS.WmsItem.PutOn.LocationNotExists", targetLocation); } } catch (Exception ex) { result.CatchExceptionWithLog(ex, Biz.L("WMS.WmsItem.PutOn.Exception", inventory.SN, targetLocation)); } return result; } /// /// 下架 /// /// 要下架的库存对象 /// 授权查询选项 /// 下架后状态 /// 是否清理储区货架储位信息 /// public Result TakeDown(IInventory inventory, AuthOption option, WMS_ITEM.STATUSs status, bool clearLocation = true) { return TakeDown(inventory, inventory.Items.ToDictionary(k => k.SN, v => v.QTY), option, status, clearLocation); var result = new Result(Result.Flags.Success, new TakeDownInfo()); try { foreach (var item in inventory.Items) { item.STATUS = status.GetValue(); if (clearLocation) { //item.WH_ID = null; item.REGION_ID = null; item.SHELF_ID = null; item.LOCATION_ID = null; } inventory.History.Add(new WMS_ITEM_HIS(item, $"条码[{inventory.SN}]从储位[{inventory?.Location?.LOCATION_CODE}]下架成功,操作单据[{item.TRANS_NO}]")); } foreach (var item in inventory.Packages) { if (clearLocation) { //item.WH_ID = null; item.REGION_ID = null; item.SHELF_ID = null; item.LOCATION_ID = null; } } result.Data.Items = inventory.Items; result.Data.History = inventory.History; result.Data.Packages = inventory.Packages; } catch (Exception ex) { result.CatchExceptionWithLog(ex, Biz.L("WMS.WmsItem.TakeDown.Exception", inventory.SN, inventory?.Location?.LOCATION_CODE)); } return result; } /// /// 下架 /// /// 要下架的库存对象 /// 要下架的最小包装数量字典,key:sn,value:qty /// 授权查询选项 /// 下架后状态 /// 是否清理储区货架储位信息 /// public Result TakeDown(IInventory inventory, Dictionary qtyList, AuthOption option, WMS_ITEM.STATUSs status, bool clearLocation = true) { var result = new Result(Result.Flags.Success, new TakeDownInfo()); try { //如果要下架的数量字典为空则认为是全部下架 qtyList = qtyList.IsNullOrEmpty(inventory.Items.ToDictionary(k => k.SN, v => v.QTY)); foreach (var item in inventory.Items) { if (qtyList.ContainsKey(item.SN) && qtyList[item.SN] > 0) { var downQty = qtyList[item.SN]; if (item.QTY > downQty) { item.QTY -= downQty; var pkg = inventory.Packages.First(q => q.SN == item.SN); pkg.QTY = item.QTY; } else { item.STATUS = status.GetValue(); var pkg = inventory.Packages.First(q => q.SN == item.SN); pkg.PARENT_SN = null; pkg.Parent = null; if (clearLocation) { //item.WH_ID = null; item.REGION_ID = null; item.SHELF_ID = null; item.LOCATION_ID = null; //pkg.WH_ID = null; pkg.REGION_ID = null; pkg.SHELF_ID = null; pkg.LOCATION_ID = null; } } inventory.History.Add(new WMS_ITEM_HIS(item, $"条码[{inventory.SN}]从储位[{inventory?.Location?.LOCATION_CODE}]下架数量[{downQty}]成功,状态[{item.STATUS.GetEnumDesc()}],操作单据[{item.TRANS_NO}]")); } } inventory.Packages = WMS_ITEM_PKG.UpdateQty(inventory.Packages); result.Data.Items = inventory.Items; result.Data.History = inventory.History; result.Data.Packages = inventory.Packages; } catch (Exception ex) { result.CatchExceptionWithLog(ex, Biz.L("WMS.WmsItem.TakeDown.Exception", inventory.SN, inventory?.Location?.LOCATION_CODE)); } return result; } /// /// 下架物料推荐,返回固定个数的最小包装物料库存列表 /// /// 领料单号 /// 物料编码 /// 物料的ERP库位 /// 物料所在的仓库编码 /// 物料所在的储区编码 /// 物料所在的货架编码 /// 授权查询选项 /// 返回的最小包装物料个数,默认返回1个 /// public Result> Suggest(string order, string itemCode, string erpWH, string whID, string regionID, string shelfID, AuthOption option, int returnCount = 1) { var result = new Result>(Result.Flags.Success, new List()) { LocaleMsg = new("WMS.WmsItem.Suggest.Success") }; try { var items = Biz.Db.Queryable((q, p, w, r, s, l) => new JoinQueryInfos( JoinType.Left, q.SN == p.SN, JoinType.Left, q.WH_ID == w.ID, JoinType.Left, q.REGION_ID == r.ID, JoinType.Left, q.SHELF_ID == s.ID, JoinType.Left, q.LOCATION_ID == l.ID)) //检查用户权限 .ByAuth(option) //允许使用已经分配到库存池中的物料 .Where((q, p, w, r, s, l) => SqlFunc.IsNullOrEmpty(p.ID) || (!SqlFunc.IsNullOrEmpty(order) && p.STATUS <= WMS_ITEM_POOL.STATUSs.WaitPick.GetValue() && p.TRANS_NO == order)) //只允许未锁定的 .Where((q, p, w, r, s, l) => q.IS_LOCKED == "N") //只允许物料状态是在库的 .Where((q, p, w, r, s, l) => q.STATUS == WMS_ITEM.STATUSs.InStore.GetValue()) //如果有传入料号,则只允该料号的物料 .WhereIF(!itemCode.IsNullOrEmpty(), (q, p, w, r, s, l) => q.ITEM_CODE == itemCode) //如果有传入库位,则只允该库位中的物料 .WhereIF(!erpWH.IsNullOrEmpty(), (q, p, w, r, s, l) => q.ERP_WH == erpWH && q.AUTH_ORG == option.CurOrg) //如果有传入仓库,则只允该仓库的物料 .WhereIF(!whID.IsNullOrEmpty(), (q, p, w, r, s, l) => q.WH_ID == whID && q.AUTH_ORG == option.CurOrg) //如果有传入储区,则只允该储区的物料 .WhereIF(!regionID.IsNullOrEmpty(), (q, p, w, r, s, l) => q.REGION_ID == regionID && q.AUTH_ORG == option.CurOrg) //如果有传入货架,则只允该货架的物料 .WhereIF(!shelfID.IsNullOrEmpty(), (q, p, w, r, s, l) => q.SHELF_ID == shelfID && q.AUTH_ORG == option.CurOrg) //优先使用库存池中的物料 .OrderBy((q, p, w, r, s, l) => SqlFunc.IsNullOrEmpty(p.ID)) //优先使用尾数物料(截料或者退料之后的物料) .OrderByDescending((q, p, w, r, s, l) => q.SN.Contains("_C") || q.SN.Contains("_T")) //按生产日期先进先出,再按物料数量从小到大,最后按条码排序 .OrderBy((q, p, w, r, s, l) => q.PROD_DATE).OrderBy(q => q.QTY).OrderBy(q => q.SN) .Select((q, p, w, r, s, l) => new SuggestItem { Item = q, poolItem = null, Warehouse = w, Region = r, Shelf = s, Location = l, }) //检查用户权限 .Take(returnCount).ToList(); //foreach (var item in items) //{ // var inv = Get(item.SN, option, false); // if (inv.IsSuccessed) // { // result.Data.Add(inv.Data); // } //} result.Data = items; var totalQty = result.Data.Sum(q => q.Item.QTY); var total = result.Data.Count; if (0 <= total && total < returnCount) { result.Flag = Result.Flags.Warning; result.LocaleMsg = new("WMS.WmsItem.Suggest.Warning", total); } //if (total == 0) //{ // result.Flag = Result.Flags.Failed; // result.LocaleMsg = new("WMS.WmsItem.Suggest.Failed"); //} } catch (Exception ex) { result.CatchExceptionWithLog(ex, Biz.L("WMS.WmsItem.Suggest.Exception")); } return result; } /// /// 下架物料推荐,按需求数量返回满足需求的物料库存列表 /// /// 领料单号 /// 物料编码 /// 物料的ERP库位 /// 物料所在的仓库编码 /// 物料所在的储区编码 /// 物料所在的货架编码 /// 授权查询选项 /// 需求数量,会返回满足需求的物料个数 /// public Result> Suggest(string order, string itemCode, string erpWH, string whID, string regionID, string shelfID, AuthOption option, decimal reqQty) { var result = new Result>(Result.Flags.Success, new List()) { LocaleMsg = new("WMS.WmsItem.Suggest.Success") }; try { var takeCount = 0; var checkSum = (decimal)0; var checkCount = 0; do { takeCount += 50; var check = Biz.Db.Queryable((q, p, w, r, s, l) => new JoinQueryInfos( JoinType.Left, q.SN == p.SN, JoinType.Left, q.WH_ID == w.ID, JoinType.Left, q.REGION_ID == r.ID, JoinType.Left, q.SHELF_ID == s.ID, JoinType.Left, q.LOCATION_ID == l.ID)) //检查用户权限 .ByAuth(option) //允许使用已经分配到库存池中的物料 .Where((q, p, w, r, s, l) => SqlFunc.IsNullOrEmpty(p.ID) || (!SqlFunc.IsNullOrEmpty(order) && p.STATUS <= WMS_ITEM_POOL.STATUSs.WaitPick.GetValue() && p.TRANS_NO == order)) //只允许未锁定的 .Where((q, p, w, r, s, l) => q.IS_LOCKED == "N") //只允许物料状态是在库的 .Where((q, p, w, r, s, l) => q.STATUS == WMS_ITEM.STATUSs.InStore.GetValue()) //如果有传入料号,则只允该料号的物料 .WhereIF(!itemCode.IsNullOrEmpty(), (q, p, w, r, s, l) => q.ITEM_CODE == itemCode) //如果有传入库位,则只允该库位中的物料 .WhereIF(!erpWH.IsNullOrEmpty(), (q, p, w, r, s, l) => q.ERP_WH == erpWH && q.AUTH_ORG == option.CurOrg) //如果有传入仓库,则只允该仓库的物料 .WhereIF(!whID.IsNullOrEmpty(), (q, p, w, r, s, l) => q.WH_ID == whID && q.AUTH_ORG == option.CurOrg) //如果有传入储区,则只允该储区的物料 .WhereIF(!regionID.IsNullOrEmpty(), (q, p, w, r, s, l) => q.REGION_ID == regionID && q.AUTH_ORG == option.CurOrg) //如果有传入货架,则只允该货架的物料 .WhereIF(!shelfID.IsNullOrEmpty(), (q, p, w, r, s, l) => q.SHELF_ID == shelfID && q.AUTH_ORG == option.CurOrg) //优先使用库存池中的物料 .OrderBy((q, p, w, r, s, l) => SqlFunc.IsNullOrEmpty(p.ID)) //优先使用尾数物料(截料或者退料之后的物料) .OrderByDescending((q, p, w, r, s, l) => q.SN.Contains("_C") || q.SN.Contains("_T")) //按生产日期先进先出,再按物料数量从小到大,最后按条码排序 .OrderBy((q, p, w, r, s, l) => q.PROD_DATE).OrderBy(q => q.QTY).OrderBy(q => q.SN) .Select((q, p, w, r, s, l) => new { ItemCode = q.ITEM_CODE, Sn = q.SN, Qty = q.QTY }) .Take(takeCount) .MergeTable() .GroupBy(t => t.ItemCode) .Select(t => new { Count = SqlFunc.AggregateCount(t.Sn), Sum = SqlFunc.AggregateSum(t.Qty), }).First(); if (!check.IsNullOrEmpty()) { checkSum = check.Sum; checkCount = check.Count; } else { checkSum = 0; checkCount = 0; } } while (checkSum < reqQty && checkCount >= takeCount); var items = Biz.Db.Queryable((q, p, w, r, s, l) => new JoinQueryInfos( JoinType.Left, q.SN == p.SN, JoinType.Left, q.WH_ID == w.ID, JoinType.Left, q.REGION_ID == r.ID, JoinType.Left, q.SHELF_ID == s.ID, JoinType.Left, q.LOCATION_ID == l.ID)) //检查用户权限 .ByAuth(option) //允许使用已经分配到库存池中的物料 .Where((q, p, w, r, s, l) => SqlFunc.IsNullOrEmpty(p.ID) || (!SqlFunc.IsNullOrEmpty(order) && p.STATUS <= WMS_ITEM_POOL.STATUSs.WaitPick.GetValue() && p.TRANS_NO == order)) //只允许未锁定的 .Where((q, p, w, r, s, l) => q.IS_LOCKED == "N") //只允许物料状态是在库的 .Where((q, p, w, r, s, l) => q.STATUS == WMS_ITEM.STATUSs.InStore.GetValue()) //如果有传入料号,则只允该料号的物料 .WhereIF(!itemCode.IsNullOrEmpty(), (q, p, w, r, s, l) => q.ITEM_CODE == itemCode) //如果有传入库位,则只允该库位中的物料 .WhereIF(!erpWH.IsNullOrEmpty(), (q, p, w, r, s, l) => q.ERP_WH == erpWH && q.AUTH_ORG == option.CurOrg) //如果有传入仓库,则只允该仓库的物料 .WhereIF(!whID.IsNullOrEmpty(), (q, p, w, r, s, l) => q.WH_ID == whID && q.AUTH_ORG == option.CurOrg) //如果有传入储区,则只允该储区的物料 .WhereIF(!regionID.IsNullOrEmpty(), (q, p, w, r, s, l) => q.REGION_ID == regionID && q.AUTH_ORG == option.CurOrg) //如果有传入货架,则只允该货架的物料 .WhereIF(!shelfID.IsNullOrEmpty(), (q, p, w, r, s, l) => q.SHELF_ID == shelfID && q.AUTH_ORG == option.CurOrg) //优先使用库存池中的物料 .OrderBy((q, p, w, r, s, l) => SqlFunc.IsNullOrEmpty(p.ID)) //优先使用尾数物料(截料或者退料之后的物料) .OrderByDescending((q, p, w, r, s, l) => q.SN.Contains("_C") || q.SN.Contains("_T")) //按生产日期先进先出,再按物料数量从小到大,最后按条码排序 .OrderBy((q, p, w, r, s, l) => q.PROD_DATE).OrderBy(q => q.QTY).OrderBy(q => q.SN) .Select((q, p, w, r, s, l) => new SuggestItem { Item = q, poolItem = null, Warehouse = w, Region = r, Shelf = s, Location = l, }) .Take(takeCount).ToList(); var curQty = (decimal)0; foreach (var item in items) { result.Data.Add(item); curQty += item.Item.QTY; if (curQty >= reqQty) { break; } } var totalQty = result.Data.Sum(q => q.Item.QTY); var total = result.Data.Count; if (0 <= totalQty && totalQty < reqQty) { result.Flag = Result.Flags.Warning; result.LocaleMsg = new("WMS.WmsItem.Suggest.Warning", totalQty); } //if (totalQty == 0) //{ // result.Flag = Result.Flags.Failed; // result.LocaleMsg = new("WMS.WmsItem.Suggest.Failed"); //} } catch (Exception ex) { result.CatchExceptionWithLog(ex, Biz.L("WMS.WmsItem.Suggest.Exception")); } return result; } /// /// 根据SN返回相应的二维码 /// /// /// public string GetQRCode(string sn) { return Biz.Db.Queryable().Where(q => q.SN == sn).First()?.GetQRCode(); } /// /// 储位查询 /// /// /// public ApiAction> QueryLocation(BasePageInput input) { var action = new ApiAction>(); if (input.Code != "") { var query = Biz.Db.Queryable().ByAuth(input.AuthOption).Where(q => q.LOCATION_CODE == input.Code).ToPage(input.pageIndex, input.pageSize); if (query.data.Count > 0) { action.Data = query; } else { action.IsSuccessed = false; action.LocaleMsg = Biz.L("储位未找到有物品"); } } else { action.IsSuccessed = false; } return action; } /// /// 物料汇总查询 /// /// /// public PageAble QueryItemSum(QueryItemInputDtl input) { var ItemCode = Biz.Db.Queryable().ByAuth(input.AuthOption).Where(q => q.SN == input.Code).First()?.ITEM_CODE ?? (input.IsK.IsNullOrEmpty() ? input.Code : (((bool)input.IsK ? "K" : "") + new Barcode(input.Code).ItemCode)); var itemInfo = Biz.Db.Queryable().Where(q => q.ITEM_CODE == ItemCode).First(); if (!itemInfo.IsNullOrEmpty()) { var sumInfo = Biz.Db.Queryable().Where(q => q.ITEM_CODE == ItemCode && q.STATUS == WMS_ITEM.STATUSs.InStore.GetValue()) .ByAuth(input.AuthOption).GroupBy(q => new { q.WH_CODE, q.ITEM_CODE }).Select(q => new { WH_CODE = q.WH_CODE, SumQty = SqlFunc.AggregateSum(q.QTY) }).ToList(); var items = Biz.Db.Queryable().Where(q => q.ITEM_CODE == ItemCode && q.STATUS == WMS_ITEM.STATUSs.InStore.GetValue()) .ByAuth(input.AuthOption).ToPage(input.pageIndex, input.pageSize); items.data2 = new { ItemCode = ItemCode, ItemName = itemInfo.ITEM_NAME, SumInfo = $"{string.Join("\r\n", sumInfo.Select(q => $"{q.WH_CODE}总库存: {(double)q.SumQty}"))}" }; return items; } else { throw new Exception("物料编码不存在"); } } } } /// /// WMS_ITEM扩展方法 /// public static class WMS_ITEMExtension { /// /// 物料添加到物料池 /// /// /// /// /// /// /// /// public static WMS_ITEM_POOL GetPoolItem(this WMS_ITEM item, string orgCode, string transCode, string transNo, string transLine, decimal actQty, bool isFirst) { var poolItem = new WMS_ITEM_POOL() { AUTH_ORG = orgCode, TRANS_CODE = transCode, TRANS_NO = transNo, TRANS_LINE = transLine, ITEM_CODE = item.ITEM_CODE, SN = item.SN, QTY = item.QTY, ALLOC_QTY = actQty >= item.QTY ? item.QTY : actQty, PROD_DATE = item.PROD_DATE, LOCATION_ID = item.LOCATION_ID, IS_FIRST = isFirst ? "Y" : "N", ALLOC_MODE = actQty >= item.QTY ? WMS_ITEM_POOL.ALLOC_MODEs.AllAllocated.GetValue() : WMS_ITEM_POOL.ALLOC_MODEs.PartialAllocate.GetValue(), STATUS = WMS_ITEM_POOL.STATUSs.WaitPick.GetValue(), }; return poolItem; } /// /// 获取相应二维码 /// /// /// public static string GetQRCode(this WMS_ITEM item) { try { //var code = Biz.Db.Queryable().Where(q => q.SN == item.SN).First()?.QR_CODE; var code = ""; if (code.IsNullOrEmpty() && !item.IsNullOrEmpty()) { code += $"V{item.TRANS_NO},"; code += $"P{item.ITEM_CODE},"; code += $"Q{item.QTY},"; code += $"U{item.UNIT},"; code += $"M{item.ITEM_CODE},"; code += $"D{item.PROD_DATE:yyyyMMdd},"; code += $"L{item.SUPP_LOTNO.IsNullOrEmpty(item.PROD_DATE.ToString("yyyyMMdd"))},"; code += $"S{item.SN},"; code = code.IsNullOrEmpty(item?.SN, code.Substring(0, code.Length - 1)); } return code; } catch (System.Exception ex) { return item?.SN; } } /// /// 获取组织编码 /// /// public static List GetOrgList() { var DB = Biz.DataSource["WMS57"].Client; var dataList = Biz.Db.Queryable().Select(i => i.ORG_CODE).Distinct().ToList();// 获取组织编码 return dataList; } } }