using Rhea.Common; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Tiger.IBusiness; using Tiger.Model; 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(); } } }); if (dbTran.IsSuccess) { //保存成功则清空提交操作列表 DBCommitList.Clear(); } else { //抛出异常 throw dbTran.ErrorException; } } } /// /// 上架 /// /// 要上架的库存对象 /// 授权查询选项 /// 要上架的储位代码 /// 是否移库操作 /// 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.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; } /// /// 下架 /// /// 授权查询选项 /// 下架后状态 /// 是否清理储区货架储位信息 /// 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(); 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; } #endregion Functions public override bool Close(bool needSaveHistoryLog = false) { //needSaveHistoryLog = true; //保存操作日志 this.IsFinished = true; return IsFinished ? base.Close(needSaveHistoryLog) : IsFinished; } } }