using Newtonsoft.Json; using Rhea.Common; using SqlSugar; using System; using System.Collections.Generic; using System.Drawing.Drawing2D; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using Tiger.Business.SqlSugarHepler; using Tiger.Business.WMS.Sharetronic.Shelf; using Tiger.IBusiness; using Tiger.Model; using Tiger.Model.Entitys.WMS.DTOS; using Tiger.Model.Sharetronic.Shelf; namespace Tiger.Business.WMS.Transaction { public class InFinished : WMSTransactionBase, IInFinished { /// /// T100接口URL /// public string t100Url { get; set; } = @"http://172.18.8.11/wstopprd/ws/r/awsp920"; /// /// 事务初始化函数 /// /// /// /// /// /// public IInFinished Init(string id, string userCode, string apiHost, string orgCode) { TransID = id; UserCode = userCode; ApiHost = apiHost; OrgCode = orgCode; Logger.Console.Info($"Start {this.GetType().Name} Transaction[ID: {TransID}]"); return this; } #region Propertys & Variables public string BillCode { get; set; } public string UserCode { get; set; } public long UserId { get; set; } public string RackCode { get; set; } public string WarehouseCode { get; set; } public string WarehouseName { get; set; } public string OrgCode { get; set; } public WMS_SHELF Shelf { get; set; } public InFinishedPuton FinishedPuton { get; set; } public BIZ_ERP_PROD_IN fin { get; set; } #endregion /// /// 获取完工入库单列表 /// /// /// /// public ApiAction> GetInFinishedHeaders(int pageIndex, int pageSize, string orgcode, string billcode) { var action = new ApiAction>(); var query = Biz.Db.Queryable().Where(x => (x.STATUS == BIZ_ERP_PROD_IN.STATUSs.INIT.GetValue() || x.STATUS == BIZ_ERP_PROD_IN.STATUSs.WORKING.GetValue()) && x.AUTH_ORG == orgcode) .WhereIF(!billcode.IsNullOrEmpty(), x => x.BILLCODE.Contains(billcode)) .OrderByDescending(x => x.UPDATE_TIME.ToString("yyyy-MM-dd")) .OrderBy(x => x.CREATE_TIME) .ToPage(pageIndex, pageSize); action.Data = query; return action; } /// /// 完工入库单选择事件 /// /// /// public async Task> SelectOrder(InFinishedInput input) { var action = new ApiAction(); try { //SelectOrderOption = input.AuthOption; fin = await Biz.Db.Queryable().Where(x => x.BILLCODE == input.FinishedNo).Includes(q => q.DtlsWithGhost, d => d.ItemInfo).IncludesAllFirstLayer().FirstAsync(); //验证明细是否正确 if (!fin.Dtls.Any()) { action.IsSuccessed = false; action.LocaleMsg = new("WMS.ProdMReq.SelectOrder.DtlsException", input.FinishedNo); return action; } BillCode = input.FinishedNo; action.Data = new FinishedInput { IncompleteTips = iWMS.GetBIZ_ERP_PROD_INips(BillCode),//isCompleted ? "数量:0 (0盘)" : }; action.LocaleMsg = Biz.L("选择完工入库单成功"); } catch (Exception ex) { action.CatchExceptionWithLog(ex, $"完工入库单选择异常"); } return action; } /// /// 扫描物料并复核,如果物料已经完成移库则货架上亮灯提醒储位 /// public async Task ScanItem(InFinishedModel input) { var action = new ApiAction(); var multiRet = new Model.Minsun.MultiInvInStorageOutput(); try { if (string.IsNullOrEmpty(input.SN)) { action.IsSuccessed = false; action.LocaleMsg = Biz.L("WMS.CustSupChk.ScanItem.SnEmptyFailure"); // $"条码不能为空!"; return action; } //货架为空则扫描的认为是货架 if (string.IsNullOrEmpty(RackCode)) { //action.IsSuccessed = false; //action.LocaleMsg = Biz.L("WMS.CustSupChk.ScanItem.ShelfEmptyFailure"); var _action = await ScanShelf(input.SN); action.LocaleMsg = _action.LocaleMsg; action.IsSuccessed = _action.IsSuccessed; action.Data = _action.Data; return action; } var nLocation = new WMS_LOCATION(); Result result = WMS_ITEM_Biz.WmsItem.Get(input.SN, input.AuthOption, true); if (!result.IsSuccessed) { action.IsSuccessed = false; action.LocaleMsg = result.LocaleMsg; return action; } var inv = result.Data as Inventory; //验证条码是否正确 if (!inv.isNormalStatus || inv.Status != WMS_ITEM.STATUSs.WaitIn) { action.IsSuccessed = false; action.LocaleMsg = Biz.L("WMS.CustSupChk.ScanItem.StatusException", string.Join(',', inv.StatusList.Select(x => x.GetDesc()))); return action; } // 根据物料Barcode 检索清点扫描表 var barcodeScanned = Biz.Db.Queryable().Where(t => t.SN.ToUpper() == inv.SN.ToUpper()).First(); if (barcodeScanned == null) { action.IsSuccessed = false; action.LocaleMsg = Biz.L("WMS.CustSupChk.ScanItem.NotCounted", inv.SN); // $"此物料条码未做清点,不能入库"; return action; } //物料验证 if (inv.ItemInfo.IsNullOrEmpty() || inv.ItemInfo.IS_ACTIVE == "N") { action.IsSuccessed = false; action.LocaleMsg = Biz.L("WMS.ProdMReq.ScanItem.ItemCodeNotExistsOrNotActive", inv.ItemInfo.ITEM_CODE.IsNullOrEmpty(inv.Barcode.ItemCode)); return action; } else { if (inv.Status != WMS_ITEM.STATUSs.WaitIn || barcodeScanned.BUSINESSCODE.IsNullOrEmpty()) { action.IsSuccessed = false; action.LocaleMsg = Biz.L("WMS.CustSupChk.ScanItem.NotGenerateBill", inv.SN); //$"此物料条码未生成库存单据,不能入库"; return action; } //if (barcodeScanned.WAREHOUSECODE.ToUpper() != WarehouseCode.ToUpper()) //{ // action.IsSuccessed = false; // action.LocaleMsg = Biz.L("此物料条码清点仓库与库位仓库不同,不能入库", inv.SN); //$"此物料条码清点仓库与库位仓库不同,不能入库"; // return action; //} if (barcodeScanned.Qty != inv.Barcode.Qty.ToDecimal()) { action.IsSuccessed = false; action.LocaleMsg = Biz.L("WMS.CustSupChk.ScanItem.DiffQty", inv.SN); //$"此物料条码入库数量与清点数量不同,不能入库"; return action; } } // 判断是否智能货架 if (FinishedPuton.IsSmartRack) { ShelfApiResult shelfApiResult = await Share.Shelf.PutOn(TransID, Shelf, inv.Items[0]); if (!shelfApiResult.IsSuccess) { action.IsSuccessed = false; action.LocaleMsg = Biz.L(shelfApiResult.GetData()); return action; } var reaultShelf = shelfApiResult.GetData(); //Logger.Default.Info($"智能货架返回信息:${JsonConvert.SerializeObject(reaultShelf.)}"); nLocation = reaultShelf.GetLocation(); if (nLocation == null) { action.IsSuccessed = false; action.LocaleMsg = Biz.L($"系统不存在储位,请先维护货架信息"); return action; } var locationData = Biz.Db.Queryable().Where(q => q.LOCATION_ID == nLocation.ID && q.AUTH_ORG == OrgCode).First(); if (!locationData.IsNullOrEmpty()) { action.IsSuccessed = false; action.LocaleMsg = Biz.L($"系统当前库位存在料盘,请检查系统库存信息"); return action; } FinishedPuton.LocationCode = nLocation.LOCATION_CODE; } else { if (FinishedPuton.LocationCode.IsNullOrEmpty() || FinishedPuton.WarehouseCode.IsNullOrEmpty()) { action.IsSuccessed = false; action.LocaleMsg = Biz.L("WMS.CustSupChk.ScanItem.LocationEmptyFailure"); //$"请先扫描库位码"; return action; } //验证库位盘数 和 剩余可放数量 //var nStorageLotInfos = await Biz.Db.Queryable().Where(t => t.LOCATIONCODE == CustomerSupplyPuton.LocationCode.ToUpper()).ToListAsync(); //if (nStorageLotInfos.Count >= CustomerSupplyPuton.LotCount) //{ // action.IsSuccessed = false; // action.Message = $"库位盘数已满,该库位只能存放[{CustomerSupplyPuton.LotCount}]盘"; // return action; //} //var nUsedCapacity = nStorageLotInfos.Any() ? nStorageLotInfos.Sum(x => x.QTY) : 0; //if (CustomerSupplyPuton.MaxSize <= (nUsedCapacity + nDisassembleBarcode.LotQty)) //{ // action.IsSuccessed = false; // action.Message = $"该库位的剩余容量[{Math.Round(CustomerSupplyPuton.MaxSize - nUsedCapacity, 2)}]无法放入当前条码,请确认"; // return action; //} nLocation = await Biz.Db.Queryable().Where(t => t.LOCATION_CODE == FinishedPuton.LocationCode).FirstAsync(); } //判断储位是否单放 if (nLocation.IS_SINGLE == "Y" && inv.Items.Count > 1) { action.IsSuccessed = false; action.LocaleMsg = Biz.L("WMS.CustSupChk.ScanItem.LocationSingleFailure"); //$"储位只能单放一个物料"; return action; } string billCode = barcodeScanned.BUSINESSCODE; string billLine = barcodeScanned.BUSINESSLINE; foreach (var item in inv.Items) { item.TRANS_CODE = nameof(BIZ_ERP_PROD_IN); item.TRANS_NO = billCode; item.TRANS_LINE = billLine.ToString(); } //执行入库 Result onResult = WMS_ITEM_Biz.WmsItem.PutOn(inv, input.AuthOption, nLocation.LOCATION_CODE); if (!onResult.IsSuccessed) { action.IsSuccessed = false; action.LocaleMsg = onResult.LocaleMsg; return action; } PutOnInfo putOnInfo = onResult.Data; #region 更新单据信息 barcodeScanned.STATUS = WMS_ITEM.STATUSs.InStore.GetValue(); //其他出入库单 //新单据行状态 var billDetail = Biz.Db.Queryable().Where(t => t.BILLCODE.ToUpper() == billCode.ToUpper() && t.BILLLINE == billLine).First(); var total = Biz.Db.Queryable().Where(t => t.BUSINESSCODE.ToUpper() == billCode.ToUpper() && t.BUSINESSLINE == billLine) .Where(x => x.STATUS == WMS_ITEM.STATUSs.InStore.GetValue() || x.SN == inv.SN).Sum(x => x.Qty); billDetail.UPDATE_TIME = DateTime.Now.Date; billDetail.INSTOCKQTY = total; //inv.Barcode.Qty.ToDecimal(); billDetail.INVENTORYQTY = total; //inv.Barcode.Qty.ToDecimal(); var isCompleted = false; // 更新单据HEADER状态 var billHeader = Biz.Db.Queryable().Where(t => t.BILLCODE.ToUpper() == billCode).First(); if (billDetail.INSTOCKQTY == billDetail.PRQTY) { billDetail.LINESTATUS = BIZ_ERP_PROD_IN.STATUSs.COMPLETE.GetValue(); if (!Biz.Db.Queryable().Where(t => t.BILLCODE.ToUpper() == billCode.ToUpper() && t.BILLLINE != billLine && t.LINESTATUS != BIZ_ERP_PROD_IN.STATUSs.COMPLETE.GetValue()).Any()) { billHeader.STATUS = BIZ_ERP_PROD_IN.STATUSs.COMPLETE.GetValue(); isCompleted = true; } } else { billDetail.LINESTATUS = BIZ_ERP_PROD_IN.STATUSs.WORKING.GetValue(); } Logger.Default.Info($"更新单据明细信息[BIZ_ERP_OTH_IN_DTL]:单号[{billCode}],项次[{billLine}],数量[{billDetail.INSTOCKQTY}],状态[{billDetail.LINESTATUS}]"); action.LocaleMsg = Biz.L($"更新单据明细信息[BIZ_ERP_OTH_IN_DTL]:单号[{billCode}],项次[{billLine}],数量[{billDetail.INSTOCKQTY}],状态[{billDetail.LINESTATUS}]"); #endregion //保存到数据库 var db = Business.Biz.Db; var dbTran = db.UseTran(() => { //入库 db.Updateable(putOnInfo.Items, UserCode).ExecuteCommand(); var x = db.Storageable(putOnInfo.ItemsExt, UserCode).ToStorage(); x.AsInsertable.ExecuteCommand();//不存在插入 x.AsUpdateable.ExecuteCommand();//存在更新 db.Insertable(putOnInfo.History, UserCode).ExecuteCommand(); db.Updateable(putOnInfo.Packages, UserCode).ExecuteCommand(); db.Updateable(barcodeScanned, UserCode).ExecuteCommand(); db.Updateable(billDetail, UserCode).ExecuteCommand(); db.Updateable(billHeader, UserCode).ExecuteCommand(); }); if (!dbTran.IsSuccess) { Logger.Default.Fatal(dbTran.ErrorException, "Database transaction save exception"); this.Close(!dbTran.IsSuccess); throw dbTran.ErrorException; } //单头完成过账 if(billHeader.STATUS==3) { MaterialToErp(billHeader.BILLCODE); } // 返回其他入库对象 action.Data = new Model.Minsun.OtherInstockBarcodeOutput { Barcode = inv.SN, MaterialCode = inv.ItemInfo.ITEM_CODE, MaterialName = inv.ItemInfo.ITEM_NAME, MaterialStandard = inv.ItemInfo.SPEC, InitialQty = inv.Barcode.Qty ?? 0, CurrentQty = inv.Barcode.Qty ?? 0, Unit = inv.ItemInfo.UNIT, DateCode = inv.Barcode.ProdDate ?? DateTime.MinValue, //Period = inv.PeriodDays.HasValue ? inv.LotDate.AddDays(inv.PeriodDays.Value) : (DateTime?)null, LotNo = inv.SN, //批次号默认为外包装条码 SourceBillCode = billCode, SourceBillLine = Convert.ToInt32(billLine), //StateFlag = inv.StateFlag, LocationCode = nLocation.LOCATION_CODE, ReceiptCode = barcodeScanned?.BUSINESSCODE, IncompleteTips = iWMS.GetFinishedTips(barcodeScanned?.BUSINESSCODE, barcodeScanned?.ITEM_CODE),//isCompleted ? "数量:0 (0盘)" : IsScanShelf = false }; } catch (Exception ex) { //取消当前操作 action.CatchExceptionWithLog(ex, $"扫描物料[{input.SN}]复核异常"); } return action; } /// /// 扫描货架或者储位 /// public async Task> ScanShelf(string Code) { var action = new ApiAction(); try { if (Code.IsNullOrEmpty()) { action.IsSuccessed = false; action.LocaleMsg = Biz.L("WMS.CustSupChk.ScanItem.ShelfCanNotEmpty"); return action; } FinishedPuton = new InFinishedPuton(); // 查询货架信息 var whUnit = await Biz.Db.Queryable().Where(t => t.SHELF_CODE.ToUpper() == Code.ToUpper() && t.AUTH_ORG == OrgCode).IncludesAllFirstLayer().FirstAsync(); // 扫描货架代码,且为智能货架 if (whUnit != null && whUnit.SHELF_TYPE == WMS_SHELF.SHELF_TYPEs.Smart.GetValue()) { FinishedPuton.WarehouseCode = whUnit.WH_CODE; FinishedPuton.RackCode = whUnit.SHELF_CODE; FinishedPuton.ShelfType = whUnit.SHELF_TYPE; FinishedPuton.IsSmartRack = true; Shelf = whUnit.Shelf; } // 扫描库位代码 else { var nLocation = await Biz.Db.Queryable().Where(t => t.LOCATION_CODE.ToUpper() == Code.ToUpper() && t.AUTH_ORG == OrgCode).FirstAsync(); if (nLocation == null) { action.IsSuccessed = false; action.LocaleMsg = Biz.L("WMS.CustSupChk.ScanItem.NotExist", Code); return action; } if (nLocation.IS_ACTIVE == "N") { action.IsSuccessed = false; action.LocaleMsg = Biz.L("WMS.CustSupChk.ScanItem.ShelfOrLocationDisabled"); return action; } if (nLocation.SHELF_TYPE == WMS_SHELF.SHELF_TYPEs.Smart.GetValue() || nLocation.SHELF_TYPE == WMS_SHELF.SHELF_TYPEs.QRCode.GetValue()) { var locationData = Biz.Db.Queryable().Where(q => q.LOCATION_ID == nLocation.LOCATION_ID && q.AUTH_ORG == OrgCode).First(); if (!locationData.IsNullOrEmpty()) { action.IsSuccessed = false; action.LocaleMsg = Biz.L($"系统当前库位存在料盘,请检查系统库存信息"); return action; } } //var nStorageLotInfos = await Biz.Db.Queryable().Where(x => x.LOCATIONCODE.ToUpper() == nLocation.LOCATIONCODE.ToUpper()).ToListAsync(); //if (nStorageLotInfos.Count >= nLocation.LOTCOUNT) //{ // action.IsSuccessed = false; // action.Message = $"库位盘数已满,该库位只能存放[{nLocation.LOTCOUNT}]盘"; // return action; //} // 计算库位剩余容量 //var nUsedCapacity = nStorageLotInfos.Any() ? nStorageLotInfos.Sum(x => x.QTY) : 0; //if (nLocation.MAXSIZE <= nUsedCapacity) //{ // action.IsSuccessed = false; // action.Message = $"该库位已经放满"; // return action; //} FinishedPuton.LocationCode = nLocation.LOCATION_CODE; FinishedPuton.WarehouseCode = nLocation.WH_CODE; //CustomerSupplyPuton.Capacity = nLocation.MAXSIZE - nUsedCapacity; //CustomerSupplyPuton.LotCount = nLocation.LOTCOUNT; //CustomerSupplyPuton.MaxSize = nLocation.MAXSIZE; FinishedPuton.IsSmartRack = false; FinishedPuton.RackCode = nLocation.SHELF_CODE; } WarehouseCode = FinishedPuton.WarehouseCode; RackCode = FinishedPuton.RackCode; FinishedPuton.IsScanShelf = true; action.LocaleMsg = Biz.L("扫描成功"); action.Data = FinishedPuton; } catch (Exception ex) { //取消当前操作 action.CatchExceptionWithLog(ex, $"扫描货架或者储位[{Code}]异常"); } return action; } /// /// 领料单过账到T100 /// /// 单号 /// public ApiAction MaterialToErp(string param) { var action = new ApiAction(); Work.DoAsync(() => { Thread.Sleep(3000); var authOrg = GetAuthOrg(param); #region 创建请求实体 var model = new BodyDTO>>() { host = new HostDTO(), datakey = new DataKey() { EntId = "88", CompanyId = authOrg }, service = new ServiceDTO() { name = "wms_post_asft340" }, payload = new PayLoad>() { std_data = new Std_Data() { parameter = new ParameterPostingDTO() { sfeadocno = param, sfea001 = DateTime.Now.ToString("yyyy-MM-dd") } } } }; #endregion 创建请求实体 #region 发起请求 var result = new T100ActionResult(); try { var requestJson = JsonConvert.SerializeObject(model); var response = HttpHelper.PostAsync(t100Url, requestJson).Result; result = JsonConvert.DeserializeObject>(response.Message); Logger.Scheduler.Info($"成品入库对接T100过账提交Json: {requestJson},返回Json: {response.Message}"); } catch (Exception ex) { Logger.Default.Info($"成品入库对接T100过账失败"); //return "0"; } #endregion 发起请求 var db = Biz.DataSource["WMS57"].Client; var olddata = db.Queryable().Where(i => i.BILLCODE == param).ToList(); var msg = result.payload.std_data?.execution.description.ToString(); if (result.payload.std_data?.execution.code == "S") { //msg = result.payload.std_data?.execution.description.ToString(); foreach (var data in olddata) { data.ERP_BILL_CODE = "T100返回信息已过账"; } } if (msg == "1" && result.payload.std_data?.execution.code == "0") { foreach (var data in olddata) { data.ERP_BILL_CODE = param;// 更新单号 } } BizSqlsugar.UpdateDataTable(olddata, db); }); return action; } /// /// 根据工单号获取据点名称 /// /// /// public string GetAuthOrg(string workOrder) { var authOrg = string.Empty; var org = workOrder.Substring(0, 2); switch (org) { #region 循环取值 case "PH": authOrg = "PHXC"; break; case "YX": authOrg = "YXYY"; break; case "XP": authOrg = "XCXP"; break; case "XN": authOrg = "XCXN"; break; case "TH": authOrg = "STTH"; break; case "XC": authOrg = "XCSJ"; break; case "DG": authOrg = "DGXC"; break; case "HK": authOrg = "HKXC"; break; case "TX": authOrg = "TXXC"; break; case "LR": authOrg = "XCLR"; break; case "OM": authOrg = "OMKJ"; break; case "AH": authOrg = "AHXC"; break; case "YK": authOrg = "XCYK"; break; case "CC": authOrg = "XCCC"; break; case "TC": authOrg = "XCTC"; break; case "TK": authOrg = "STTK"; break; case "MM": authOrg = "STMM"; break; default: throw new Exception($"单号前两位:{org}未能找到对应的据点,请确认!"); #endregion 循环取值 } return authOrg; } public override bool Close(bool needSaveHistoryLog = false) { //保存操作日志 this.IsFinished = true; return IsFinished ? base.Close(needSaveHistoryLog) : IsFinished; } } }