using Microsoft.Extensions.Options; using Rhea.Common; using SqlSugar; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Tiger.IBusiness; using Tiger.Model; using Tiger.Model.Entitys.MES.Position; using Tiger.Model.Entitys.MES.U9C; using static IronPython.Modules._ast; namespace Tiger.Business.WMS.Transaction { /// /// 仓库作业任务,包括清点、上架、下架、移库、盘点等 /// public class WmsTask : WMSTransactionBase, IWmsTask { #region Propertys & Variables public string UserCode { get; set; } public string OrgCode { get; set; } private DbClient _MainDB; public DbClient MainDB => _MainDB; private DbClient CommitDB; public Inventory CurInvItem { get; set; } public ScanShelfInfo CurScanShelf { get; set; } /// /// 跟客户端通讯时的指令,有具体功能定义,默认为Normal /// public string Command { get; set; } = "Normal"; /// /// 是否需要临时存储数据库提交操作,待需要的时候再提交 /// public bool NeedTemporaryStoreDBCommitAction { get; set; } = false; protected Dictionary> DBCommitList { get; set; } = new(); #endregion Propertys & Variables #region Functions public IWmsTask Init(string id, string userCode, string apiHost, string orgCode) { TransID = id; UserCode = userCode; ApiHost = apiHost; OrgCode = orgCode; _MainDB = Biz.Db; return this; } /// /// 获取提交数据的DbClient对象 /// /// public DbClient GetCommitDB() { return CommitDB ??= Biz.Db; } /// /// 增加暂存的数据库操作 /// /// 暂存的分组 /// 暂存的数据库操作 public void AddCommitAction(string group, Action action) { //增加附加的保存内容 if (!action.IsNullOrEmpty()) { if (!DBCommitList.ContainsKey(group)) { DBCommitList.Add(group, new List()); } var commitList = DBCommitList[group]; commitList.Add(action); } } /// /// 暂存的数据库操作提交到数据库 /// /// 附加的保存内容 public void SaveCommitListToDB(Action appendToSave = null) { //增加附加的保存内容 if (!appendToSave.IsNullOrEmpty()) { if (!DBCommitList.ContainsKey("AppendSaveAction")) { DBCommitList.Add("AppendSaveAction", new List()); } var appendList = DBCommitList["AppendSaveAction"]; appendList.Add(appendToSave); } //如果不需要临时存储数据库提交操作,则把提交操作列表提交到数据库 if (!NeedTemporaryStoreDBCommitAction) { //恢复临时存储标记为false NeedTemporaryStoreDBCommitAction = false; var dbTran = GetCommitDB().UseTran(() => { //在同一个事务中保存所有工步的数据 foreach (var wipSn in DBCommitList.Keys.Where(q => q != "AppendSaveAction")) { foreach (var action in DBCommitList[wipSn]) { action.Invoke(); } } //附加的保存内容 if (DBCommitList.ContainsKey("AppendSaveAction")) { foreach (var action in DBCommitList["AppendSaveAction"]) { action.Invoke(); } } }); //保存成功则清空提交操作列表 DBCommitList.Clear(); if (!dbTran.IsSuccess) { //抛出异常 throw dbTran.ErrorException; } } } /// /// 获取条码库存信息,包括仓库,储区,货架,储位,父条码,包装明细等 /// /// 查询的条码 /// 授权查询选项 /// 是否同时执行拆包操作,解除与父条码之间的包装关系 /// public Result GetInventory(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; } /// /// 上架 /// /// 要上架的库存对象 /// 授权查询选项 /// 要上架的储位代码 /// 是否移库操作 /// public Result PutOn(AuthOption option, string targetLocation) { var result = new Result(Result.Flags.Success); try { var location = Biz.Db.Queryable().Where(q => q.LOCATION_CODE == targetLocation && q.AUTH_ORG == option.CurOrg).IncludesAllFirstLayer().First(); if (!location.IsNullOrEmpty()) { var isTransfer = CurInvItem?.Location?.LOCATION_CODE != location.LOCATION_CODE; foreach (var item in CurInvItem.Items) { item.STATUS = WMS_ITEM.STATUSs.InStore.GetValue(); item.LOTNO = item.LOTNO.IsNullOrEmpty(new Barcode(item.SN).LotNo); item.SUPP_LOTNO = CurInvItem.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; CurInvItem.History.Add(new WMS_ITEM_HIS(item, $"条码[{CurInvItem.SN}]{(isTransfer ? $"从储位[{CurInvItem?.Location?.LOCATION_CODE}]移库" : "上架")}到储位[{location.LOCATION_CODE}]成功{(isTransfer ? "" : $",操作单据[{item.TRANS_NO}]")}")); } foreach (var item in CurInvItem.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 CurInvItem.ItemsExt) { item.AUTH_ORG = option.OrgCode; item.SN = CurInvItem.Barcode.SN; } //更新储存信息 CurInvItem.Warehouse = location.Warehouse; CurInvItem.Region = location.Region; CurInvItem.Shelf = location.Shelf; CurInvItem.Location = location.Location; //创建变量克隆对象用于传入DBSubmitAction中保存当前需要暂存的数据值 var _Items = CurInvItem.Items.Clone(); var _Packages = CurInvItem.Packages.Clone(); var _History = CurInvItem.History.Clone(); var _ItemsExt = CurInvItem.ItemsExt.Clone(); AddCommitAction("PutOn", () => { //使用统一的事务DB对象 var db = GetCommitDB(); //数据保存逻辑 db.Storageable(_Items, UserCode).ExecuteCommand(); db.Storageable(_Packages, UserCode).ExecuteCommand(); db.Insertable(_History, UserCode).ExecuteCommand(); var x = db.Storageable(_ItemsExt, UserCode).ToStorage(); x.AsInsertable.ExecuteCommand();//不存在插入 x.AsUpdateable.ExecuteCommand();//存在更新 }); } 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", CurInvItem.SN, targetLocation)); } return result; } /// /// 下架物料推荐,返回固定个数的最小包装物料库存列表 /// /// 领料单号 /// 物料编码 /// 备料物料推荐选项 /// 授权查询选项 /// 返回的最小包装物料个数,默认返回1个 /// public Result> Suggest(string order, string itemCode, SuggestOption option, AuthOption auth, int returnCount = 1) { var result = new Result>(Result.Flags.Success, new List()) { LocaleMsg = new("WMS.WmsItem.Suggest.Success") }; try { var query = 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(auth) //允许使用已经分配到库存池中同一个单据的物料 .Where((q, p, w, r, s, l) => SqlFunc.IsNullOrEmpty(p.ID) || (!SqlFunc.IsNullOrEmpty(order) && p.TRANS_NO == order) || p.IS_LOCKED == "N") //只允许未锁定的 .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(!option.ErpWH.IsNullOrEmpty(), (q, p, w, r, s, l) => q.ERP_WH == option.ErpWH && q.AUTH_ORG == auth.CurOrg) //如果有传入仓库,则只允该仓库的物料 .WhereIF(!option.WHID.IsNullOrEmpty(), (q, p, w, r, s, l) => q.WH_ID == option.WHID && q.AUTH_ORG == auth.CurOrg) //如果有传入储区,则只允该储区的物料 .WhereIF(!option.RegionID.IsNullOrEmpty(), (q, p, w, r, s, l) => q.REGION_ID == option.RegionID && q.AUTH_ORG == auth.CurOrg) //如果有传入货架,则只允该货架的物料 .WhereIF(!option.ShelfID.IsNullOrEmpty(), (q, p, w, r, s, l) => q.SHELF_ID == option.ShelfID && q.AUTH_ORG == auth.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")) //备料策略:按生产日期先进先出 .OrderByIF(option.Strategy.HasFlag(WMS_ITEM_POOL.STRATEGYs.FIFO), (q, p, w, r, s, l) => q.PROD_DATE) //按生产日期先进先出,再按物料数量从小到大, .OrderByIF(option.Strategy.HasFlag(WMS_ITEM_POOL.STRATEGYs.FSFO), q => q.QTY) //最后按条码排序 .OrderBy(q => q.SN); var items = query.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; } /// /// 下架物料推荐,按需求数量返回满足需求的物料库存列表 /// /// 领料单号 /// 物料编码 /// 备料物料推荐选项 /// 授权查询选项 /// 需求数量,会返回满足需求的物料个数 /// public Result> Suggest(string order, string itemCode, SuggestOption option, AuthOption auth, double reqQty) { var result = new Result>(Result.Flags.Success, new List()) { LocaleMsg = new("WMS.WmsItem.Suggest.Success") }; try { var query = 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(auth) //允许使用已经分配到库存池中的物料 .Where((q, p, w, r, s, l) => SqlFunc.IsNullOrEmpty(p.ID) || (!SqlFunc.IsNullOrEmpty(order) && p.TRANS_NO == order) || p.IS_LOCKED == "N") //只允许未锁定的 .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(!option.ErpWH.IsNullOrEmpty(), (q, p, w, r, s, l) => q.ERP_WH == option.ErpWH && q.AUTH_ORG == auth.CurOrg) //如果有传入仓库,则只允该仓库的物料 .WhereIF(!option.WHID.IsNullOrEmpty(), (q, p, w, r, s, l) => q.WH_ID == option.WHID && q.AUTH_ORG == auth.CurOrg) //如果有传入储区,则只允该储区的物料 .WhereIF(!option.RegionID.IsNullOrEmpty(), (q, p, w, r, s, l) => q.REGION_ID == option.RegionID && q.AUTH_ORG == auth.CurOrg) //如果有传入货架,则只允该货架的物料 .WhereIF(!option.ShelfID.IsNullOrEmpty(), (q, p, w, r, s, l) => q.SHELF_ID == option.ShelfID && q.AUTH_ORG == auth.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")) //备料策略:按生产日期先进先出 .OrderByIF(option.Strategy.HasFlag(WMS_ITEM_POOL.STRATEGYs.FIFO), (q, p, w, r, s, l) => q.PROD_DATE) //按生产日期先进先出,再按物料数量从小到大, .OrderByIF(option.Strategy.HasFlag(WMS_ITEM_POOL.STRATEGYs.FSFO), q => q.QTY) //最后按条码排序 .OrderBy(q => q.SN); var takeCount = 0; var checkSum = 0.0; var checkCount = 0; do { takeCount += 50; var check = query.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 = query.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 = 0.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; } /// /// 下架 /// /// 授权查询选项 /// 下架后状态 /// 是否清理储区货架储位信息 /// public Result TakeDown(AuthOption option, WMS_ITEM.STATUSs status) { return TakeDown(CurInvItem.Items.ToDictionary(k => k.SN, v => v.QTY), option, status); } /// /// 下架 /// /// 要下架的最小包装数量字典,key:sn,value:qty /// 授权查询选项 /// 下架后状态 /// public Result TakeDown(Dictionary qtyList, AuthOption option, WMS_ITEM.STATUSs status) { var result = new Result(Result.Flags.Success); try { //如果要下架的数量字典为空则认为是全部下架 qtyList = qtyList.IsNullOrEmpty(CurInvItem.Items.ToDictionary(k => k.SN, v => v.QTY)); foreach (var item in CurInvItem.Items) { if (qtyList.ContainsKey(item.SN) && qtyList[item.SN] > 0) { var downQty = qtyList[item.SN]; if (item.QTY > downQty) { item.QTY -= downQty; var pkg = CurInvItem.Packages.First(q => q.SN == item.SN); pkg.QTY = item.QTY; } else { item.STATUS = status.GetValue(); item.CARTON_NO = null; item.PALLET_NO = null; var pkg = CurInvItem.Packages.First(q => q.SN == item.SN); pkg.PARENT_SN = null; pkg.Parent = null; //如果下架数量等于库存数量则清理储区货架储位信息,否则保留仓库信息 //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; } CurInvItem.History.Add(new WMS_ITEM_HIS(item, $"条码[{CurInvItem.SN}]从储位[{CurInvItem?.Location?.LOCATION_CODE}]下架数量[{downQty}]成功,状态[{item.STATUS.GetEnumDesc()}],操作单据[{item.TRANS_NO}]")); } } CurInvItem.Packages = WMS_ITEM_PKG.UpdateQty(CurInvItem.Packages); //创建变量克隆对象用于传入DBSubmitAction中保存当前需要暂存的数据值 var _Items = CurInvItem.Items.Clone(); var _Packages = CurInvItem.Packages.Clone(); var _History = CurInvItem.History.Clone(); AddCommitAction("TakeDown", () => { //使用统一的事务DB对象 var db = GetCommitDB(); //数据保存逻辑 db.Updateable(_Items, UserCode).ExecuteCommand(); db.Insertable(_History, UserCode).ExecuteCommand(); db.Updateable(_Packages, UserCode).ExecuteCommand(); }); } catch (Exception ex) { result.CatchExceptionWithLog(ex, Biz.L("WMS.WmsItem.TakeDown.Exception", CurInvItem.SN, CurInvItem?.Location?.LOCATION_CODE)); } return result; } /// /// 备料下架 /// /// 要下架的最小包装数量字典,key:sn,value:qty /// 授权查询选项 /// 下架后状态 /// public Result TakeDown(List snList, AuthOption option, WMS_ITEM.STATUSs status) { var result = new Result(Result.Flags.Success); try { foreach (var item in CurInvItem.Items) { var sn = snList.First(q => q.SN == item.SN); var pkg = CurInvItem.Packages.First(q => q.SN == item.SN); //前端返回Y认为是截料发料,N认为是整盘发料 if (sn.QTY > sn.QTY_DLVY && sn.NEED_CUTTING == "Y") { CurInvItem.History.Add(new WMS_ITEM_HIS(item, $"条码[{item.SN}]截料发料,截料发出条码[{sn.DeliverySN}]数量[{sn.QTY_DLVY}],保留在库条码[{sn.ReserveSN}]数量[{sn.QTY - sn.QTY_DLVY}],操作单据[{item.TRANS_NO}]")); item.SN = sn.ReserveSN; item.QTY = sn.QTY - sn.QTY_DLVY; pkg.SN = sn.ReserveSN; pkg.QTY = sn.QTY - sn.QTY_DLVY; CurInvItem.History.Add(new WMS_ITEM_HIS(item, $"条码[{item.SN}]截料发料后保留在库,原条码[{sn.SN}]数量[{sn.QTY}],操作单据[{item.TRANS_NO}]")); //创建截料发出的物料信息 var newItem = item.Clone(); newItem.ID = Guid.NewGuid().ToString(); newItem.SN = sn.DeliverySN; newItem.STATUS = status.GetValue(); newItem.QTY = sn.QTY_DLVY; newItem.CARTON_NO = null; newItem.PALLET_NO = null; newItem.REGION_ID = null; newItem.SHELF_ID = null; newItem.LOCATION_ID = null; WMS_ITEM_HIS his = new(newItem, $"条码[{newItem.SN}]从储位[{CurInvItem?.Location?.LOCATION_CODE}]截料发料成功,发出数量[{newItem.QTY}],状态[{newItem.STATUS.GetEnumDesc()}],原条码[{sn.SN}]数量[{sn.QTY}],操作单据[{item.TRANS_NO}]"); var newPkg = pkg.Clone(); newPkg.ID = Guid.NewGuid().ToString(); newPkg.PARENT_SN = null; newPkg.Parent = null; newPkg.REGION_ID = null; newPkg.SHELF_ID = null; newPkg.LOCATION_ID = null; CurInvItem.ItemsExt.Add(new() { SN = newItem.SN, META_SN = newItem.SN, }); CurInvItem.Items.Add(newItem); CurInvItem.History.Add(his); CurInvItem.Packages.Add(newPkg); } else { item.STATUS = status.GetValue(); item.CARTON_NO = null; item.PALLET_NO = null; pkg.PARENT_SN = null; pkg.Parent = null; //如果下架数量等于库存数量则清理储区货架储位信息,否则保留仓库信息 //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; CurInvItem.History.Add(new WMS_ITEM_HIS(item, $"条码[{CurInvItem.SN}]从储位[{CurInvItem?.Location?.LOCATION_CODE}]发料下架成功,状态[{item.STATUS.GetEnumDesc()}],操作单据[{item.TRANS_NO}]")); } } CurInvItem.Packages = WMS_ITEM_PKG.UpdateQty(CurInvItem.Packages); //创建变量克隆对象用于传入DBSubmitAction中保存当前需要暂存的数据值 var _Items = CurInvItem.Items.Clone(); var _Packages = CurInvItem.Packages.Clone(); var _History = CurInvItem.History.Clone(); var _ItemsExt = CurInvItem.ItemsExt.Clone(); AddCommitAction("TakeDown", () => { //使用统一的事务DB对象 var db = GetCommitDB(); //数据保存逻辑 db.Storageable(_Items, UserCode).ExecuteCommand(); db.Insertable(_History, UserCode).ExecuteCommand(); db.Storageable(_Packages, UserCode).ExecuteCommand(); db.Storageable(_ItemsExt, UserCode).ToStorage().AsInsertable.ExecuteCommand(); }); } catch (Exception ex) { result.CatchExceptionWithLog(ex, Biz.L("WMS.WmsItem.TakeDown.Exception", CurInvItem.SN, CurInvItem?.Location?.LOCATION_CODE)); } return result; } /// /// 设置当前条码的工序信息 /// public ApiAction SetOutPutMqttMsg(ApiAction action, string locale = null) { MQTT.Message msg = new() { IsSuccessed = action.IsSuccessed, Content = Biz.T(action.LocaleMsg, locale), }; switch (action.Status) { case ApiAction.StatusCodes.Success: msg.Voice = MQTT.Voice.Success; msg.Color = "#FF1E90FF"; break; case ApiAction.StatusCodes.Warning: msg.Voice = MQTT.Voice.Warning; msg.Color = "#FFB8860B"; break; case ApiAction.StatusCodes.Error: case ApiAction.StatusCodes.Failed: msg.Voice = MQTT.Voice.Fail; msg.Color = "#FFFF0000"; break; case ApiAction.StatusCodes.Exception: msg.Voice = MQTT.Voice.Fail; msg.Color = "#FF8B0000"; break; case ApiAction.StatusCodes.Normal: case ApiAction.StatusCodes.NeedConfrim: case ApiAction.StatusCodes.Confrimed: default: msg.Voice = MQTT.Voice.Silent; msg.Color = "#FF000000"; break; } if (action.IsSuccessed) { msg.Voice = MQTT.Voice.Pass; msg.Color = "#FF228B22"; } else if (!action.IsSuccessed) { msg.Voice = MQTT.Voice.Fail; msg.Color = "#FFFF0000"; } else { msg.Voice = MQTT.Voice.Silent; msg.Color = "#FF000000"; } action.Data.MqttMsg = msg; return action; } /// /// 设置当前物料的默认储位 /// public ApiAction SetDefaultLocation(DbClient db, BAS_ITEM Item, WMS_LOCATION location, long RcvLineId) { var action = new ApiAction(new ScanOutput()); //调用设置默认储位接口 var iInput = new CreateRcvLineLocationInput { IsLogin = true, RcvLineLocationParam = new() { RcvLineId = RcvLineId, BinCode = location.LOCATION_CODE, } }; var result = DI.Resolve().CreateRcvLineLocation(iInput).Result; if (!result.IsSuccessed) { action.IsSuccessed = false; action.LocaleMsg = result.LocaleMsg; } else { Item.DEFAULT_LOCATION = location.LOCATION_CODE; db.Updateable(Item, UserCode).UpdateColumns(q => new { q.DEFAULT_LOCATION, q.UPDATE_TIME, q.UPDATE_USER }).ExecuteCommand(); } return action; } #endregion Functions /// /// 重置本次扫码信息 /// public virtual void ResetScan() { //清理暂存数据提交操作 DBCommitList.Clear(); } public override bool Close(bool needSaveHistoryLog = false) { //needSaveHistoryLog = true; //保存操作日志 this.IsFinished = true; return IsFinished ? base.Close(needSaveHistoryLog) : IsFinished; } } }