using Rhea.Common; using Tiger.Model.Minsun; 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 Newtonsoft.Json; namespace Tiger.Business.WMS.Transaction { /// /// 客供料入库清点事务 /// public class CustomerSupplyIn : WMSTransactionBase, ICustomerSupplyIn { public ICustomerSupplyIn Init(string id, string userCode, string apiHost) { TransID = id; UserCode = userCode; ApiHost = apiHost; 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 RackCode { get; set; } public string WarehouseCode { get; set; } public string WarehouseName { get; set; } public CustomerSupplyPuton CustomerSupplyPuton { get; set; } #endregion #region Functions /// /// 扫描物料并复核,如果物料已经完成移库则货架上亮灯提醒储位 /// public async Task ScanItem(string sn) { var action = new ApiAction(); var multiRet = new MultiInvInStorageOutput(); try { if (string.IsNullOrEmpty(RackCode)) { action.IsSuccessed = false; action.Message = $"货架不能为空!"; return action; } if (string.IsNullOrEmpty(sn)) { action.IsSuccessed = false; action.Message = $"条码不能为空!"; return action; } var nLocation = new Model.Minsun.WMS_LOCATION(); var nDisassembleBarcode = iWMS.SplitFullBarcode(sn).Data; //验证条码是否已经存在 var nBarcode = Biz.Db.Queryable().Where(t => t.BARCODE.ToUpper() == nDisassembleBarcode.Barcode.ToUpper()).First(); if (nBarcode != null) { action.IsSuccessed = false; action.Message = $"扫描的条码已经入过库,无法重复扫描!"; return action; } // 根据物料Barcode 检索清点扫描表 var barcodeScanned = Biz.Db.Queryable().Where(t => t.BARCODE.ToUpper() == nDisassembleBarcode.Barcode.ToUpper()).First(); if (barcodeScanned == null) { action.IsSuccessed = false; action.Message = $"此物料条码未做清点,不能入库"; return action; } else { if (barcodeScanned.STATUS != ScannedBarcodeStatus.Billed.ToString() || barcodeScanned.BUSINESSCODE.IsNullOrEmpty()) { action.IsSuccessed = false; action.Message = $"此物料条码未生成库存单据,不能入库"; return action; } if (barcodeScanned.WAREHOUSECODE.ToUpper() != WarehouseCode.ToUpper()) { action.IsSuccessed = false; action.Message = $"此物料条码清点仓库与库位仓库不同,不能入库"; return action; } if (barcodeScanned.QTY != nDisassembleBarcode.LotQty) { action.IsSuccessed = false; action.Message = $"此物料条码入库数量与清点数量不同,不能入库"; return action; } } // 判断是否智能货架 if (CustomerSupplyPuton.IsSmartRack) { Result result = await Shelf.UpShelf(new ShelfOperateInput { ShelfNo = CustomerSupplyPuton.RackCode, OperateType = "1" }); if (result.Flag != Result.Flags.Success) { action.IsSuccessed = false; action.Message = result.Message; return action; } var reaultShelf = result.Data; Logger.Default.Info($"智能货架返回信息:${JsonConvert.SerializeObject(reaultShelf)}"); if (reaultShelf.IsSuccess?.ToUpper() == "TRUE") { var rackCode = reaultShelf.ShelfNo; var locationCode = reaultShelf.LocationCode; //增加判断系统当前库位是否存在料盘 2022/07/30 Ben Lin var storageBarcode = await Biz.Db.Queryable().Where(t => t.LOCATIONCODE == locationCode).FirstAsync(); if (storageBarcode != null) { action.IsSuccessed = false; action.Message = $"系统当前库位存在料盘,请检查系统库存信息"; return action; } CustomerSupplyPuton.LocationCode = locationCode; action.Message += $", 储位[{CustomerSupplyPuton.LocationCode}]"; nLocation = await Biz.Db.Queryable().Where(t => t.LOCATIONCODE == locationCode && t.RACKCODE == rackCode).FirstAsync(); } else { action.IsSuccessed = false; action.Message = $"发起上架失败,货架服务器异常"; return action; } } else { if (CustomerSupplyPuton.LocationCode.IsNullOrEmpty() || CustomerSupplyPuton.WarehouseCode.IsNullOrEmpty()) { action.IsSuccessed = false; action.Message = $"请先扫描库位码"; 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.LOCATIONCODE == CustomerSupplyPuton.LocationCode).FirstAsync(); } string billCode = barcodeScanned.BUSINESSCODE; int? billLine = barcodeScanned.BUSINESSLINE; int nScanStatus = (int)InvStorageInfoSides.ScanStatus.WORKING; int? nSourceBillType = (int)InventoryTransferSides.BillType.ProductInstock; int? nTargetBillType = null; var nScanMain = await Biz.Db.Queryable().Where(t => t.SOURCEBILLTYPE == nSourceBillType && t.TARGETBILLTYPE == nTargetBillType && t.SOURCEBILLCODE.ToUpper() == billCode.ToUpper() && t.BILLSTATUS == nScanStatus).FirstAsync(); if (nScanMain == null) { nScanMain = new WMS_SCAN_H { Id = Guid.NewGuid().ToString(), SOURCEBILLTYPE = nSourceBillType, TARGETBILLTYPE = null, BILLSTATUS = nScanStatus, BILLCODE = DateTime.Now.ToString("yyyyMMddHHmmss"), SOURCEBILLCODE = nDisassembleBarcode.OrderNo, WAREHOUSECODE = CustomerSupplyPuton.WarehouseCode, SUBMITTIME = DateTime.Now, LastModificationTime = DateTime.Now, CreationTime = DateTime.Now, CreatorUserId = UserId, SUBMITSTATUS = (int)InvStorageInfoSides.ScanSubmitStatus.INIT }; } //插入条码表 nBarcode = new WMS_BARCODE { Id = Guid.NewGuid().ToString(), BARCODE = nDisassembleBarcode.Barcode, //接口直接将拆分好的Barcode传入 BARCODESTATUS = (int)InvStorageInfoSides.BarcodeStatus.Instock, BARCODETYPE = (int)InvStorageInfoSides.BarcodeType.SN, LOTNO = nDisassembleBarcode.Barcode, //批次代码采用外包装条码 DATECODE = nDisassembleBarcode.LotDate, PERIOD = (nDisassembleBarcode.PeriodDays??0) >0 ? nDisassembleBarcode.LotDate.AddDays(nDisassembleBarcode.PeriodDays.Value) : (DateTime?)null, MATERIALCODE = nDisassembleBarcode.MaterialCode, SOURCETYPE = (int)InventoryTransferSides.BillType.OtherInStock, SOURCECODE = billCode, SOURCEDETAILLINE = billLine, PACKQTY = nDisassembleBarcode.LotQty, CURRENTQTY = nDisassembleBarcode.LotQty, INITIALQTY = nDisassembleBarcode.LotQty, QCSTATUS = (int)InvStorageInfoSides.QCStatus.GOOD, SOURCEORDER = nDisassembleBarcode.OrderNo, CreationTime = DateTime.Now, CreatorUserId = UserId, STATEFLAG = nDisassembleBarcode.StateFlag }; var nScanDetail = Biz.Db.Queryable().Where(t => t.SCANMAINID == nScanMain.Id && t.SOURCEDETAILLINE == billLine && t.WAREHOUSECODE.ToUpper() == CustomerSupplyPuton.WarehouseCode.ToUpper() && t.MATERIALCODE.ToUpper() == nBarcode.MATERIALCODE.ToUpper()).ToList().FirstOrDefault(); if (nScanDetail != null) { nScanDetail.SCANQTY = (nScanDetail.SCANQTY ?? 0) + nDisassembleBarcode.LotQty < 0 ? 0 : (nScanDetail.SCANQTY ?? 0) + nDisassembleBarcode.LotQty; } else { nScanDetail = new WMS_SCAN_D { Id = Guid.NewGuid().ToString(), SCANMAINID = nScanMain.Id, BILLCODE = nScanMain.BILLCODE, SOURCEDETAILLINE = billLine, WAREHOUSECODE = CustomerSupplyPuton.WarehouseCode, MATERIALCODE = nBarcode.MATERIALCODE, SCANQTY = nDisassembleBarcode.LotQty, LastModificationTime = DateTime.Now, CreationTime = DateTime.Now, CreatorUserId = UserId }; } //执行入库 action = iWMS.MultiInStorageAsync(new MultiInvInStorageInput { InvBarcodes = new List() { nBarcode }, InvBarcodeLogs = new List { new WMS_BARCODE_LOG { Id = Guid.NewGuid().ToString(), INOUTTYPE = (int)InvStorageInfoSides.InOutType.InStock, SOURCEBILLTYPE = (int)InventoryTransferSides.BillType.ProductInstock, TARGETBILLTYPE = null, BILLCODE = billCode, BARCODE = nBarcode.BARCODE, BARCODEREMARK = null, BARCODETYPE = nBarcode.BARCODETYPE, BOXTYPE = nBarcode.BOXTYPE, PARENTBOXBARCODE = nBarcode.PARENTBOXBARCODE, SOURCEBARCODE = nBarcode.SOURCEBARCODE, LOTNO = nBarcode.LOTNO, DATECODE = nBarcode.DATECODE, MATERIALCODE = nBarcode.MATERIALCODE, WAREHOUSECODE = WarehouseCode, LOCATIONCODE = CustomerSupplyPuton.LocationCode, SOURCETYPE = nBarcode.SOURCETYPE, SOURCECODE = nBarcode.SOURCECODE, SOURCEDETAILLINE = billLine, INITIALQTY = 0, QTY = nDisassembleBarcode.LotQty, LASTQTY = nBarcode.CURRENTQTY ?? 0, SCANMAINID = nScanMain.Id, LastModificationTime = DateTime.Now, CreationTime = DateTime.Now, CreatorUserId = UserId, SCANDETAILID = nScanDetail.Id } }, InvStorageLotInfos = new List{ new WMS_STORAGELOTINFO { Id = Guid.NewGuid().ToString(), BARCODE = nBarcode.BARCODE, BARCODESTATUS = (int)InvStorageInfoSides.BarcodeStatus.Instock, MATERIALCODE = nBarcode.MATERIALCODE, QTY = nBarcode.CURRENTQTY ?? 0, WAREHOUSECODE = WarehouseCode, LOCATIONCODE = CustomerSupplyPuton.LocationCode, INSTOCKTYPE = (int)InventoryTransferSides.BillType.ProductInstock, INSTOCKCODE = billCode, INSTOCKDETAILLINE = billLine, CreationTime = DateTime.Now, CreatorUserId = UserId } }, InvStorageInfos = new List{ new WMS_STORAGEINFO { Id = Guid.NewGuid().ToString(), WAREHOUSECODE = WarehouseCode, MATERIALCODE = nBarcode.MATERIALCODE, QTY = nBarcode.CURRENTQTY ?? 0, LOCKQTY = 0, CreationTime = DateTime.Now, LastModificationTime = DateTime.Now, CreatorUserId = UserId } }, InvScanDetails = new List{ nScanDetail }, InvScanMains = new List { nScanMain }, WarehousCode = CustomerSupplyPuton.WarehouseCode, LocationCode = CustomerSupplyPuton.LocationCode, BusinessCode = billCode, BusinessType = (int)InventoryTransferSides.BillType.ProductInstock, }); if (!action.IsSuccessed) { return action; } action.Message += $"{action.Message.IsNullOrEmpty("", ";")}执行入库成功"; #region 更新单据信息 //其他出入库单 //新单据行状态 var billDetail = Biz.Db.Queryable().Where(t => t.BILLCODE.ToUpper() == billCode.ToUpper() && t.BILLLINE == billLine).First(); billDetail.DELIVERYDATE = DateTime.Now.Date; billDetail.QTY += nDisassembleBarcode.LotQty; var isCompleted = false; // 更新单据HEADER状态 var billHeader = Biz.Db.Queryable().Where(t => t.BILLCODE.ToUpper() == billCode).First(); if (billDetail.QTY == billDetail.PRQTY) { billDetail.LINESTATUS = OtherInstockSides.Status.COMPLETE.ToString(); if (!Biz.Db.Queryable().Where(t => t.BILLCODE.ToUpper() == billCode.ToUpper() && t.BILLLINE != billLine && t.LINESTATUS != OtherInstockSides.Status.COMPLETE.ToString()).Any()) { billHeader.STATUS = OtherInstockSides.Status.COMPLETE.ToString(); isCompleted = true; } } else { billDetail.LINESTATUS = OtherInstockSides.Status.WORKING.ToString(); } Logger.Default.Info($"更新单据明细信息[WMS_OTHERINSTOCK_D]:单号[{billCode}],项次[{billLine}],数量[{billDetail.QTY}],状态[{billDetail.LINESTATUS}]"); #endregion //保存到数据库 var db = Business.Biz.Db; var dbTran = db.UseTran(() => { // 删除清点扫描条码记录 db.Deleteable(barcodeScanned).ExecuteCommand(); db.Updateable(billDetail).ExecuteCommand(); db.Updateable(billHeader).ExecuteCommand(); }); if (!dbTran.IsSuccess) { throw dbTran.ErrorException; } //生成其他入库单 if (isCompleted) { List detail2s = new List(); var Details = await Biz.Db.Queryable().Where(t => t.BILLCODE.ToUpper() == billCode.ToUpper()).ToListAsync(); foreach (var item in Details) { detail2s.Add(new Detail4 { pmdtseq = "1", pmdt027 = billHeader.ERP_BILL_CODE, pmdt028 = item.BILLLINE.ToString(), pmdt006 = item.MATERIALCODE, pmdt020 = item.QTY.ToString(), pmdtud011 = "0", pmdt016 = item.WAREHOUSECODE, pmdt017 = "", pmdt018 = billHeader.REMARK }); } var ret = ErpT100.GenerateOtherIn(new OtherInputParameter { parameter = new InParameter { pmdstype = "6", pmdsdocno = "3538", //--单别 pmdsdocdt = DateTime.Now.ToString("yyyy-MM-dd"), //"2022/3/24", pmds002 = UserCode == "admin" ? "00000" : UserCode, //"00000", pmds003 = "", pmds006 = billHeader.ERP_BILL_CODE, pmds007 = "C0006", detail = detail2s }, datakey = new Datakey { EntId = "88", CompanyId = "DGXC" } }); if (ret.payload.std_data.execution.code != "0") { action.IsSuccessed = false; action.Message = $"其他入库单[{billCode}],收货单[{billHeader.ERP_BILL_CODE}],错误信息:[{ret.payload.std_data.execution.description}]"; return action; } else { action.Message += $"其他入库单[{billCode}],收货单[{billHeader.ERP_BILL_CODE}]入库完成,扣账成功返回T100入库单据[{ret.payload.std_data.parameter.docno}]"; } } // 返回其他入库对象 action.Data = new OtherInstockBarcodeOutput { Barcode = nDisassembleBarcode.Barcode, MaterialCode = nDisassembleBarcode.MaterialCode, MaterialName = nDisassembleBarcode?.MaterialName, MaterialStandard = nDisassembleBarcode?.MaterialStandard, InitialQty = nDisassembleBarcode.LotQty, CurrentQty = nDisassembleBarcode.LotQty, Unit = nDisassembleBarcode.Unit, DateCode = nDisassembleBarcode.LotDate, Period = nDisassembleBarcode.PeriodDays.HasValue ? nDisassembleBarcode.LotDate.AddDays(nDisassembleBarcode.PeriodDays.Value) : (DateTime?)null, LotNo = nDisassembleBarcode.Barcode, //批次号默认为外包装条码 SourceBillCode = billCode, SourceBillLine = billLine, StateFlag = nDisassembleBarcode.StateFlag, LocationCode = nLocation.LOCATIONCODE, ReceiptCode = barcodeScanned?.BUSINESSCODE, IncompleteTips = isCompleted? "数量:0 (0盘)" : iWMS.GetIncompleteTips(barcodeScanned?.BUSINESSCODE, barcodeScanned?.MATERIALCODE), }; } catch (Exception ex) { //取消当前操作 action.CatchExceptionWithLog(ex, $"扫描物料[{sn}]复核异常"); } return action; } /// /// 扫描货架或者储位 /// public async Task> ScanShelf(string Code) { var action = new ApiAction(); try { if (Code.IsNullOrEmpty()) { action.IsSuccessed = false; action.Message = $"请输入或扫描有效的货架/储位码"; return action; } CustomerSupplyPuton = new CustomerSupplyPuton(); // 查询货架信息 var nRack = await Biz.Db.Queryable().Where(t => t.RACKCODE.ToUpper() == Code.ToUpper()).FirstAsync(); // 扫描货架代码,且为智能货架 if (nRack != null && nRack.RACKTYPE.ToUpper() == "SMARTRACK") { CustomerSupplyPuton.WarehouseCode = nRack.WHCODE; CustomerSupplyPuton.RackCode = nRack.RACKCODE; CustomerSupplyPuton.RackType = nRack.RACKTYPE; CustomerSupplyPuton.IsSmartRack = true; } // 扫描库位代码 else { var nLocation = await Biz.Db.Queryable().Where(t => t.LOCATIONCODE.ToUpper() == Code.ToUpper()).FirstAsync(); if (nLocation == null) { action.IsSuccessed = false; action.Message = $"扫描的库位不存在"; return action; } if (!nLocation.ISUSE) { action.IsSuccessed = false; action.Message = $"扫描的库位未启用"; 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; } CustomerSupplyPuton.LocationCode = nLocation.LOCATIONCODE; CustomerSupplyPuton.WarehouseCode = nLocation.WHCODE; CustomerSupplyPuton.Capacity = nLocation.MAXSIZE - nUsedCapacity; CustomerSupplyPuton.LotCount = nLocation.LOTCOUNT; CustomerSupplyPuton.MaxSize = nLocation.MAXSIZE; CustomerSupplyPuton.IsSmartRack = false; CustomerSupplyPuton.RackCode = nLocation.RACKCODE; } WarehouseCode = CustomerSupplyPuton.WarehouseCode; RackCode = CustomerSupplyPuton.RackCode; action.Data = CustomerSupplyPuton; } catch (Exception ex) { //取消当前操作 action.CatchExceptionWithLog(ex, $"扫描货架或者储位[{Code}]异常"); } return action; } /// /// 测试用 /// /// /// public async Task Test(string Code) { var action = new ApiAction(); try { List detail2s = new List(); var Details = await Biz.Db.Queryable().Where(t => t.BILLCODE.ToUpper() == Code).ToListAsync(); foreach (var item in Details) { detail2s.Add(new Detail4 { pmdtseq = "1", pmdt027 = "DG3453-230500213", pmdt028 = item.BILLLINE.ToString(), pmdt006 = item.MATERIALCODE, pmdt020 = item.QTY.ToString(), pmdtud011 = "0", pmdt016 = item.WAREHOUSECODE, pmdt017 = "", pmdt018 ="创米科技" }); } var ret = ErpT100.GenerateOtherIn(new OtherInputParameter { parameter = new InParameter { pmdstype = "6", pmdsdocno = "3538", //--单别 pmdsdocdt = DateTime.Now.ToString("yyyy-MM-dd"), //"2022/3/24", pmds002 = UserCode == "admin" ? "00000" : UserCode, //"00000", pmds003 = "", pmds006 = "DG3453-230500213", pmds007 = "C0006", detail = detail2s // }, datakey = new Datakey { EntId = "88", CompanyId = "DGXC" } }); if (ret.payload.std_data.execution.code != "0") { action.IsSuccessed = false; action.Message = $"错误信息:[{ret.payload.std_data.execution.description}]"; return action; } else { action.Message = $"入库完成,扣账成功返回T100入库单据[{ret.payload.std_data.parameter.docno}]"; } } catch (Exception ex) { //取消当前操作 action.CatchExceptionWithLog(ex, $"扫描货架或者储位[{Code}]异常"); } return action; } #endregion public override bool Close(bool needSaveHistoryLog = false) { //如果CurItem不为空则清空,且判断是否亮灯储位,如果是则灭灯 //if (CurItem != null) //{ // try // { // LocationLightOff(CurItem).Wait(); // } // catch (System.Exception ex) // { // Logger.Console.Fatal(ex, "一般移库事务Close关灯异常"); // } // CurItem = null; //} //保存操作日志 this.IsFinished = true; return IsFinished ? base.Close(needSaveHistoryLog) : IsFinished; } }//endClass }