using Rhea.Common; using Microsoft.AspNetCore.Http; using SqlSugar; using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Text; using System.Threading; using System.Threading.Tasks; using Tiger.IBusiness; using Tiger.Model; using Tiger.Model.Sharetronic.Shelf; using Tiger.Business.WMS.Sharetronic.Shelf; namespace Tiger.Business.WMS.Transaction { /// /// 客供料入库清点事务 /// public class InProductionReturn : WMSTransactionBase, IInProductionReturn { public IInProductionReturn 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 UserCode { get; set; } public long UserId { get; set; } public string CurrentShlefCode { get; set; } public string WarehouseCode { get; set; } public string WarehouseName { get; set; } public string OrgCode { get; set; } public WMS_SHELF Shelf { get; set; } public IncomingMatStorage IncomingMatStorage { get; set; } #endregion #region Functions /// /// 获取生产领料单明细 /// /// /// public async Task>> GetProdMaterialReqDetails() { var action = new ApiAction>(); action.Data = await Biz.Db.Queryable() .Where(t => t.ITEM_CODE.ToUpper() == IncomingMatStorage.itemCode.ToUpper() && t.STATUS > 0).ToListAsync(); return action; } /// /// 扫描物料并复核,如果物料已经完成移库则货架上亮灯提醒储位 /// public async Task ScanItem(CustSupplyCheckingInput 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.InProductionReturn.ScanItem.SnEmptyFailure"); // $"条码不能为空!"; return action; } //货架为空则扫描的认为是货架 if (string.IsNullOrEmpty(CurrentShlefCode)) { //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 = new(); if (WarehouseName.Contains("客供")) { result = WMS_ITEM_Biz.WmsItem.GetK(input.SN, input.AuthOption, true); } else { 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.IsQRCode) { action.IsSuccessed = false; action.LocaleMsg = Biz.L("WMS.CustSupChk.ScanItem.NotQrCode", inv.Barcode.MetaSn); return action; } //验证条码是否正确 if (inv.Status.GetValue() != WMS_ITEM.STATUSs.NotExists.GetValue() && inv.Status.GetValue() <= WMS_ITEM.STATUSs.InStore.GetValue()) { action.IsSuccessed = false; action.LocaleMsg = Biz.L("状态异常{0}", string.Join(',', inv.StatusList.Select(x => x.GetDesc()))); //Biz.L("WMS.CustSupChk.ScanItem.StatusException", string.Join(',', res.Data.StatusList.Select(x => x.GetDesc()))); 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; } var barcodeScanneds = Biz.Db.Queryable().Where(t =>inv.Items.Select(q=>q.SN).Contains(t.SN) && t.STATUS==WMS_ITEM.STATUSs.WaitIn.GetValue()).First(); var barcodeScannedsT = Biz.Db.Queryable().Where(t =>inv.Items.Select(q=>q.SN).Contains(t.SN) && t.STATUS == WMS_ITEM.STATUSs.WaitIn.GetValue()).First(); //if (barcodeScanneds.Count != inv.Items.Count || barcodeScannedsT.Count !=inv.Items.Count) //{ // action.IsSuccessed = false; // action.LocaleMsg = Biz.L("WMS.InProductionReturn.ScanItem.NotCounted", inv.SN); // $"此物料条码未做清点,不能入库"; // return action; //} //if (inv.Items.Any(t => t.STATUS != WMS_ITEM.STATUSs.Sended.GetValue() /*|| barcodeScanneds.Any(q => q.SN == t.SN && !q.BUSINESSCODE.StartsWith("TU"))*/)) //{ // action.IsSuccessed = false; // action.LocaleMsg = Biz.L("WMS.InProductionReturn.ScanItem.NotGenerateBill", inv.SN); //$"此物料条码未生成库存单据,不能入库"; // return action; //} //if (inv.Items.Any(t => barcodeScanneds.Any(q => q.SN == t.SN && q.QTY != t.QTY))) //{ // action.IsSuccessed = false; // action.LocaleMsg = Biz.L("WMS.CustSupChk.ScanItem.DiffQty", inv.SN); //$"此物料条码入库数量与清点数量不同,不能入库"; // return action; //} //foreach (var item in inv.Items) //{ // var barcodeScanned = Biz.Db.Queryable().Where(t => t.SN.ToUpper() == item.SN.ToUpper()).First(); // if (barcodeScanned == null) // { // action.IsSuccessed = false; // action.LocaleMsg = Biz.L("WMS.CustSupChk.ScanItem.NotCounted", inv.SN); // $"此物料条码未做清点,不能入库"; // return action; // } // else // { // barcodeScanneds.Add(barcodeScanned); // if (inv.Status != WMS_ITEM.STATUSs.WaitIn || barcodeScanned.BILLCODE.IsNullOrEmpty()) // { // action.IsSuccessed = false; // action.LocaleMsg = Biz.L("WMS.CustSupChk.ScanItem.NotGenerateBill", inv.SN); //$"此物料条码未生成库存单据,不能入库"; // return action; // } // if (barcodeScanned.SCANQTY != inv.Barcode.Qty.ToDecimal()) // { // action.IsSuccessed = false; // action.LocaleMsg = Biz.L("WMS.CustSupChk.ScanItem.DiffQty", inv.SN); //$"此物料条码入库数量与清点数量不同,不能入库"; // return action; // } // } //} //List ItemHistorys = new List(); //WMS_ITEM Item; //WMS_ITEM_PKG ItemPkgs; //var IsNull = false; if (!inv.IsNullOrEmpty()) { if (inv.Items.Count == 0) { action.IsSuccessed = false; action.LocaleMsg = Biz.L("WMS.InProductionReturn.ScanItem.NotExist", inv.Barcode); return action; } else { foreach (var item in inv.Items) { item.QTY = inv.Barcode.Qty.ToDecimal(); } foreach (var item in inv.Packages) { item.QTY = inv.Barcode.Qty.ToDecimal(); } } //CustomerSupplyPuton.LocationCode = nLocation.LOCATION_CODE; } // 判断是否智能货架 if (IncomingMatStorage.IsSmartRack) { IncomingMatStorage.location = new(); 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(); 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; } IncomingMatStorage.location.LOCATION_CODE = nLocation.LOCATION_CODE; } else { if (IncomingMatStorage.location.LOCATION_CODE.IsNullOrEmpty()) { action.IsSuccessed = false; action.LocaleMsg = Biz.L("WMS.InProductionReturn.ScanItem.LocationEmptyFailure"); //$"请先扫描库位码"; return action; } nLocation = await Biz.Db.Queryable().Where(t => t.LOCATION_CODE == IncomingMatStorage.location.LOCATION_CODE).FirstAsync(); } //判断储位是否单放 if (nLocation.IS_SINGLE == "Y" && inv.Items.Count > 1) { action.IsSuccessed = false; action.LocaleMsg = Biz.L("WMS.InProductionReturn.ScanItem.LocationSingleFailure"); //$"储位只能单放一个物料"; return action; } string billCode = barcodeScanneds?.BUSINESSCODE; string billCodeT = barcodeScannedsT?.BILLCODE; //string billLine = barcodeScanneds[0].BILLLINE; foreach (var item in inv.Items) { item.TRANS_CODE = nameof(BIZ_ERP_PROD_RETURN); item.TRANS_NO = billCode; item.ERP_WH = WarehouseCode; //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 更新单据信息 //foreach (var barcodeScanned in barcodeScanneds) { barcodeScanneds.STATUS = WMS_ITEM.STATUSs.InStore.GetValue(); } //foreach (var barcodeScanned in barcodeScannedsT) { barcodeScanneds.STATUS = WMS_ITEM.STATUSs.InStore.GetValue(); } //其他出入库单 //新单据行状态 //生成退料单据 var lotNo=Biz.Db.Queryable().Where(q=>q.SN==input.SN).First(); var billDetail = Biz.Db.Queryable().Where(t => t.BILLCODE.ToUpper() == billCode.ToUpper() && t.ITEM_CODE == inv.ItemInfo.ITEM_CODE).ToList(); foreach (var dtl in billDetail) { dtl.WAREHOUSECODE = putOnInfo.Warehouse.WH_CODE; } var total = Biz.Db.Queryable() .Where(t => t.BUSINESSCODE.ToUpper() == billCode.ToUpper() && t.ITEM_CODE == inv.ItemInfo.ITEM_CODE) .Where(t=> t.STATUS == WMS_ITEM.STATUSs.InStore.GetValue() || inv.Items.Select(q=>q.SN).Contains(t.SN)) .Sum(x => x.QTY); foreach (var dtl in billDetail) { dtl.WAREHOUSECODE = WarehouseCode; dtl.INVENTORYQTY = total; } //billDetail.DELIVERYDATE = DateTime.Now.Date; //billDetail.QTY = total; //inv.Barcode.Qty.ToDecimal(); var isCompleted = false; // 更新单据HEADER状态 var billHeader = Biz.Db.Queryable().Where(t => t.BILLCODE.ToUpper() == billCode).First(); if (billDetail.Sum(t=>t.PRQTY) == total) { foreach (var dtl in billDetail) { dtl.LINESTATUS = BIZ_ERP_PROD_RETURN.STATUSs.COMPLETE.GetValue(); } if (!Biz.Db.Queryable().Where(t => t.BILLCODE.ToUpper() == billCode.ToUpper() && t.ITEM_CODE != inv.ItemInfo.ITEM_CODE && t.LINESTATUS != BIZ_ERP_PROD_RETURN.STATUSs.COMPLETE.GetValue()).Any()) { billHeader.STATUS = BIZ_ERP_PROD_RETURN.STATUSs.COMPLETE.GetValue(); isCompleted = true; } } else { foreach (var dtl in billDetail) { dtl.LINESTATUS = BIZ_ERP_PROD_RETURN.STATUSs.WORKING.GetValue(); } } Logger.Default.Info($"更新单据明细信息:单号[{billCode}],项次[{string.Join(",", billDetail.Select(q=>q.BILLLINE))}],数量[{string.Join(",", billDetail.Select(q => q.INVENTORYQTY))}],状态[{string.Join(",", billDetail.Select(q => q.LINESTATUS))}]"); //调拨单 var billDetailT = Biz.Db.Queryable().Where(t => t.BILLCODE.ToUpper() == billCodeT.ToUpper() && t.ITEM_CODE == inv.ItemInfo.ITEM_CODE).ToList(); foreach (var dtl in billDetailT) { dtl.INWAREHOUSECODE = putOnInfo.Warehouse.WH_CODE; } var totalT = Biz.Db.Queryable() .Where(t => t.BILLCODE.ToUpper() == billCodeT.ToUpper() && t.ITEM_CODE == inv.ItemInfo.ITEM_CODE) .Where(t => t.STATUS == WMS_ITEM.STATUSs.InStore.GetValue() || inv.Items.Select(q => q.SN).Contains(t.SN)) .Sum(x => x.QTY); foreach (var dtl in billDetailT) { dtl.INQTY = total; dtl.INVENTORYQTY = total; if (dtl.ITEM_CODE == lotNo?.ITEM_CODE) { dtl.BATCH_NO_IN = WarehouseName.Contains("客供") ? lotNo.LOTNO : ""; dtl.BATCH_NO_OUT = WarehouseName.Contains("客供") ? lotNo.LOTNO : ""; } } //billDetail.DELIVERYDATE = DateTime.Now.Date; //billDetail.QTY = total; //inv.Barcode.Qty.ToDecimal(); var isCompletedT = false; // 更新单据HEADER状态 var billHeaderT = Biz.Db.Queryable().Where(t => t.BILLCODE.ToUpper() == billCodeT).First(); if (billDetailT.Sum(t => t.PRQTY) == totalT) { foreach (var dtl in billDetailT) { dtl.LINESTATUS = BIZ_WMS_TRANSFER.STATUSs.FINISHED.GetValue(); } //barcodeScanned.STATUS = WMS_ITEM.STATUSs.InStore.GetValue(); if (!Biz.Db.Queryable().Where(t => t.BILLCODE.ToUpper() == billCodeT.ToUpper() && t.ITEM_CODE != inv.ItemInfo.ITEM_CODE && t.LINESTATUS != BIZ_WMS_TRANSFER.STATUSs.FINISHED.GetValue()).Any()) { billHeaderT.STATUS = BIZ_WMS_TRANSFER.STATUSs.FINISHED.GetValue(); isCompletedT = true; } } else { foreach (var dtl in billDetailT) { dtl.LINESTATUS = BIZ_WMS_TRANSFER.STATUSs.WORKING.GetValue(); } } Logger.Default.Info($"更新单据明细信息:单号[{billCodeT}],项次[{string.Join(",", billDetailT.Select(q => q.BILLLINE))}],数量[{string.Join(",", billDetailT.Select(q => q.INVENTORYQTY))}],状态[{string.Join(",", billDetail.Select(q => q.LINESTATUS))}]"); #endregion if (putOnInfo.Items[0].QTY == 0) { action.IsSuccessed = false; action.LocaleMsg = Biz.L($"扫描的数量为0,不能入库"); return action; } //保存到数据库 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(barcodeScanneds, UserCode).ExecuteCommand(); db.Updateable(billDetail, UserCode).ExecuteCommand(); db.Updateable(billHeader, UserCode).ExecuteCommand(); //更新挑拨单状态 db.Updateable(barcodeScannedsT, UserCode).ExecuteCommand(); db.Updateable(billDetailT, UserCode).ExecuteCommand(); db.Updateable(billHeaderT, UserCode).ExecuteCommand(); }); if (!dbTran.IsSuccess) { Logger.Default.Fatal(dbTran.ErrorException, "Database transaction save exception"); this.Close(!dbTran.IsSuccess); throw dbTran.ErrorException; } action.LocaleMsg = Biz.L($"退料入库成功,入库单{billCode}"); //$"入库成功"; // 返回其他入库对象 action.Data = new IncomingMatStorage { sn = "退料单号:"+billCode+"调拨单号:"+ billCodeT, itemCode = inv.ItemInfo.ITEM_CODE, itemName = inv.ItemInfo.ITEM_NAME, itemDesc = inv.ItemInfo.SPEC, qty = inv.CurPkg.QTY, dateCode = inv.Barcode.ProdDate.ToString()??DateTime.MinValue.ToString(), Tips = iWMS.GetERP_ReturnTips(barcodeScanneds?.BUSINESSCODE, barcodeScanneds?.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.InProductionReturn.ScanItem.ShelfCanNotEmpty"); return action; } IncomingMatStorage = new IncomingMatStorage(); // 查询货架信息 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()) { if (whUnit.IS_ACTIVE == "N") { action.IsSuccessed = false; action.LocaleMsg = Biz.L("WMS.InProductionReturn.ScanItem.ShelfOrLocationDisabled"); return action; } WarehouseName = whUnit.WH_NAME; WarehouseCode = whUnit.WH_CODE; IncomingMatStorage.IsSmartRack = true; IncomingMatStorage.shelf = whUnit.Shelf; Shelf = whUnit.Shelf; } // 扫描库位代码 else { var nLocation = await Biz.Db.Queryable().Where(t => t.LOCATION_CODE.ToUpper() == Code.ToUpper() && t.AUTH_ORG == OrgCode).IncludesAllFirstLayer().FirstAsync(); if (nLocation == null) { action.IsSuccessed = false; action.LocaleMsg = Biz.L("WMS.InProductionReturn.ScanItem.NotExist", Code); return action; } if (nLocation.IS_ACTIVE == "N") { action.IsSuccessed = false; action.LocaleMsg = Biz.L("WMS.InProductionReturn.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; //} WarehouseName = nLocation.WH_NAME; WarehouseCode = nLocation.WH_CODE; IncomingMatStorage.location = nLocation.Location; IncomingMatStorage.IsSmartRack = false; IncomingMatStorage.shelf = nLocation.Shelf; } CurrentShlefCode = IncomingMatStorage.shelf.SHELF_CODE; IncomingMatStorage.IsScanShelf = true; action.Data = IncomingMatStorage; action.LocaleMsg = Biz.L("扫描货架或储位成功"); //action.LocaleMsg = Biz.L($"扫描成功"); } catch (Exception ex) { //取消当前操作 action.CatchExceptionWithLog(ex, $"扫描货架或者储位[{Code}]异常"); } return action; } #endregion public override bool Close(bool needSaveHistoryLog = false) { this.IsFinished = true; return IsFinished ? base.Close(needSaveHistoryLog) : IsFinished; } }//endClass }