using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using Volo.Abp.Application.Services; using Volo.Abp.BackgroundJobs; using Volo.Abp.Domain.Repositories; using Volo.Abp.Uow; using WmsWebApi.BackgroundJob; using WmsWebApi.Domain; using WmsWebApi.EntityFrameworkCore; using WmsWebApi.Purchase; using WmsWebApi.Wms; namespace WmsWebApi.PPlan; /// /// 采购 /// [Route("/api/Purchase")] public class PurchaseService : ApplicationService, IPurchaseService { private readonly ITsStockDetailRepository _tsStockDetailRepository; private readonly ITbProductReceiveRepository _tbProductReceiveRepository; private readonly ITbBillRepository _tbBillRepository; private readonly ITaPartRepository _taPartRepository; private readonly ITaStoreLocationRepository _taStoreLocationRepository; private readonly IPurchaseManager _purchaseManager; private readonly ITLTransactionRepository _tlTransactionRepository; private readonly TmPgWmsUpdate _tmPgWmsUpdate; private readonly Volo.Abp.Uow.IUnitOfWorkManager _unitOfWorkManager; private readonly IBackgroundJobManager _backgroundJobManager; /// /// 是否是请求重试 /// public bool IsRequestRetry { get; set; } = false; public PurchaseService(ITsStockDetailRepository tsStockDetailRepository, ITbProductReceiveRepository tbProductReceiveRepository, ITbBillRepository tbBillRepository, ITaPartRepository taPartRepository, ITaStoreLocationRepository taStoreLocationRepository, IPurchaseManager purchaseManager, ITLTransactionRepository tlTransactionRepository, TmPgWmsUpdate tmPgWmsUpdate, IUnitOfWorkManager unitOfWorkManager, IBackgroundJobManager backgroundJobManager) { _tsStockDetailRepository = tsStockDetailRepository; _tbProductReceiveRepository = tbProductReceiveRepository; _tbBillRepository = tbBillRepository; _taPartRepository = taPartRepository; _taStoreLocationRepository = taStoreLocationRepository; _purchaseManager = purchaseManager; _tlTransactionRepository = tlTransactionRepository; _tmPgWmsUpdate = tmPgWmsUpdate; _unitOfWorkManager = unitOfWorkManager; _backgroundJobManager = backgroundJobManager; } [HttpPost("add")] //[UnitOfWork(false)] public async Task AddAsync([FromBody] object content) { var result = new ReturnResult(); PurchaseDto _purchaseDto; bool bUpdate = false,bOtherWork = false,bErr = false; bool bTypeErr = false; try { _purchaseDto = JsonConvert.DeserializeObject(content.ToString()); } catch (Exception ex) { result.TYPE = 'E'; result.MESSAGE = "Json格式不正确,详细信息:" + ex.Message; return result; } WmsWebApiPURCHASEDTO dto = new WmsWebApiPURCHASEDTO() { MBLNR = _purchaseDto.MBLNR, MJAHR = _purchaseDto.MJAHR, BUDAT = _purchaseDto.BUDAT, JSON = content.ToString() }; dto.SetId(GuidGenerator); try { var _dtoDetails = _purchaseDto.zzmseg.Where(p => p.WERKS == "1000"); if(_dtoDetails == null || _dtoDetails.Count() == 0) { bOtherWork = true; result.MESSAGE = "err:没有1000工厂数据!"; } else { // 查找是否有该计划 var bill = await _tbBillRepository.FirstOrDefaultAsync(p => p.SourceBillNum2 == _purchaseDto.MBLNR); if (bill == null) { List _billList = new List(); List _recieveList = new List(); List _stockList = new List(); List _stockUpdateList = new List(); List _stockDelList = new List(); List _transList = new List(); var _poList = _dtoDetails.Select(p => p.EBELN).Distinct().ToList(); foreach (var po in _poList) { var tbBill = new TB_BILL { BillNum = _purchaseDto.MBLNR+"."+po, SourceBillNum2 = _purchaseDto.MBLNR, BillTime = DateTime.Now, StartTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), FinishTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), OperName = "SAP", DetailQty = _dtoDetails.Count(), BillType = 201, SubBillType = 10100, State = 2, Remark = "zll", AccountDate = DateTime.ParseExact(_purchaseDto.BUDAT, "yyyyMMdd", System.Globalization.CultureInfo.CurrentCulture) }; //_billList.Add(tbBill); bool bHaveDetails = false; var newDtoList = _dtoDetails.Where(p=>p.EBELN == po).GroupBy(x => new { x.MATNR, x.CHARG }). Select(group => new { MATNR = group.Key.MATNR, CHARG = group.Key.CHARG, ERFMG = group.Sum(t => t.ERFMG), LGORT = group.Max(t => t.LGORT) }); foreach (var item in newDtoList) { //判断物料信息 var part = await _taPartRepository.FirstOrDefaultAsync(p => p.PartCode == item.MATNR); if (part == null) { //result.TYPE = 'E'; bTypeErr = true; result.MESSAGE += $"err:物料 {item.MATNR} 不在WinWMS管理!"; continue; } if(!part.IsAskMerge) { //result.TYPE = 'E'; bTypeErr = true; result.MESSAGE += $"err:物料 {item.MATNR} 不属于买入卖出件!"; continue; } if (string.IsNullOrEmpty(part.DefaultReceiveLocCode.Trim())) { //result.TYPE = 'E'; bTypeErr = true; result.MESSAGE += $"err:物料 {item.MATNR} 未设置收货库位!"; continue; //part.DefaultReceiveLocCode = item.LGORT; } var partLoc = await _taStoreLocationRepository.FirstOrDefaultAsync(p => p.LocCode == part.DefaultReceiveLocCode); if (partLoc == null || partLoc.ErpLocCode != item.LGORT) { bTypeErr = true; result.MESSAGE += $"err:物料 {item.MATNR} 的默认收货库位与单据中的{item.LGORT}不匹配!"; continue; } var _barcode = $"{item.MATNR}_{item.CHARG}"; var tmp = _dtoDetails.FirstOrDefault(p => p.EBELN == po && p.MATNR == item.MATNR && p.CHARG == item.CHARG); //插入productrecieve var tbRecieve = new TB_PRODUCT_RECEIVE { BillNum = tbBill.BillNum, BarCode = _barcode, PartCode = item.MATNR, Batch = item.CHARG, FromLocCode = "", ToLocCode = part.DefaultReceiveLocCode, Remark = part.QLevel, Qty = item.ERFMG, GoodQty = item.ERFMG, State = 2, ReceiveDate = DateTime.Now, ProduceDate = DateTime.Now, LineId = tmp.BWART, //移动类型 ShiftName = tmp.ERFME, //录入项单位(条目单位) TeamName = tmp.ZEILE, //物料凭证中的项目 Unit = tmp.EBELN, //采购订单编号 TraceBackCode = tmp.SHKZG, //借贷标识 CellCode = tmp.EBELP, //采购凭证的项目编号 }; if (tbRecieve.LineId == "161") { tbRecieve.Qty = 0 - tbRecieve.Qty; _recieveList.Add(tbRecieve); //插入ts_stock_detail var tsStock = new TS_STOCK_DETAIL { BarCode = _barcode, PartCode = item.MATNR, Batch = item.CHARG, EqptCode = "", LocCode = part.DefaultReceiveLocCode, AreaCode = "FG", Qty = item.ERFMG, UpdateQty = item.ERFMG, VendId = "", ProduceDate = DateTime.Now, OverdueDate = (DateTime.Now).AddDays(part.ValidityDays), ReceiveDate = DateTime.Now, VendBatch = item.CHARG, Remark = "", State = EnumStockState.合格, Amount = 0, VinState = 0, }; var stock = await _tsStockDetailRepository.FirstOrDefaultAsync(p => p.BarCode == _barcode && p.LocCode == part.DefaultReceiveLocCode && p.State == EnumStockState.合格); if (stock == null || stock.Qty - item.ERFMG < 0) { result.TYPE = 'E'; bErr = true; result.MESSAGE = $"err:物料 {item.MATNR} 批次 {item.CHARG} 的库存不足!"; break; } else if (stock.Qty - item.ERFMG == 0) { _stockDelList.Add(tsStock); } else { tsStock.Qty = 0 - tsStock.Qty; tsStock.UpdateQty = tsStock.Qty; _stockUpdateList.Add(tsStock); } //插入tl_transaction var tlTrans = new TL_TRANSACTION { OperName = "SAP", LogTime = tbBill.AccountDate ?? DateTime.Now, BillNum = tbBill.BillNum, BillType = tbBill.BillType, SubBillType = tbBill.SubBillType, PartCode = item.MATNR, Batch = item.CHARG, Qty = 0 - item.ERFMG, BarCode = _barcode, LocCode = part.DefaultReceiveLocCode, EqptCode = item.LGORT, Remark = "Out", State = 2, TransType = 0 }; _transList.Add(tlTrans); } else { _recieveList.Add(tbRecieve); //插入ts_stock_detail var tsStock = new TS_STOCK_DETAIL { BarCode = _barcode, PartCode = item.MATNR, Batch = item.CHARG, EqptCode = "", LocCode = part.DefaultReceiveLocCode, AreaCode = "FG", Qty = item.ERFMG, UpdateQty = item.ERFMG, VendId = "", ProduceDate = DateTime.Now, OverdueDate = (DateTime.Now).AddDays(part.ValidityDays), ReceiveDate = DateTime.Now, VendBatch = item.CHARG, Remark = "", State = EnumStockState.合格, Amount = 0, VinState = 0, }; var stock = await _tsStockDetailRepository.FirstOrDefaultAsync(p => p.BarCode == _barcode && p.LocCode == part.DefaultReceiveLocCode && p.State == EnumStockState.合格); if (stock == null) { _stockList.Add(tsStock); } else { _stockUpdateList.Add(tsStock); } //插入tl_transaction var tlTrans = new TL_TRANSACTION { OperName = "SAP", LogTime = tbBill.AccountDate ?? DateTime.Now, BillNum = tbBill.BillNum, BillType = tbBill.BillType, SubBillType = tbBill.SubBillType, PartCode = item.MATNR, Batch = item.CHARG, Qty = item.ERFMG, BarCode = _barcode, LocCode = part.DefaultReceiveLocCode, EqptCode = item.LGORT, Remark = "In", State = 2, TransType = 1 }; _transList.Add(tlTrans); } bHaveDetails = true; } if(bHaveDetails) _billList.Add(tbBill); } if (!bErr) { await _tbBillRepository.AddManyAsync(_billList); await _tbProductReceiveRepository.AddAsync(_recieveList); if (_stockList != null && _stockList.Count() > 0) await _tsStockDetailRepository.AddAsync(_stockList); if(_stockUpdateList != null && _stockUpdateList.Count() > 0) await _tmPgWmsUpdate.UpdateTsStock(_stockUpdateList); if(_stockDelList != null && _stockDelList.Count() > 0) await _tmPgWmsUpdate.DeleteTsStock(_stockDelList); await _tlTransactionRepository.AddAsync(_transList); } } else { result.TYPE = 'E'; bUpdate = true; result.MESSAGE = $"err:单据 {_purchaseDto.MBLNR} 已存在"; } } } catch(Exception ex) { bErr = true; dto.EnumRetryStatus = Enums.EnumRetryStatus.WaitRetry; result.TYPE = 'E'; result.MESSAGE = ex.GetBaseException().Message; if (IsRequestRetry == false) { await AddBackgroundJobAsync(content.ToString()); } throw new Exception($"接口异常,请稍后重试:{ex.GetBaseException().Message}", ex); } finally { if (IsRequestRetry == false) { if (bUpdate) { dto.ITYPE = $"err:单据 {_purchaseDto.MBLNR} 已存在!"; } if (bOtherWork) { dto.ITYPE = "非长春工厂数据!"; } if (bErr || bTypeErr) { dto.ITYPE = result.MESSAGE; } await AddWmsWebApiPURCHASEDTONowUnitOfWorkAsync(dto); } } return result; } private async Task AddWmsWebApiPURCHASEDTONowUnitOfWorkAsync(WmsWebApiPURCHASEDTO wmsWebApiPURCHASEDTO) { if (wmsWebApiPURCHASEDTO == null) { return; } using (var uow = _unitOfWorkManager.Begin(requiresNew: true, isTransactional: false)) { await _purchaseManager.AddAsync(wmsWebApiPURCHASEDTO); await uow.SaveChangesAsync(); } } /// /// 添加后台工作者 /// /// Json参数 /// private async Task AddBackgroundJobAsync(string strJson) { if (strJson == null || strJson == "") { return; } using (var uow = _unitOfWorkManager.Begin(requiresNew: true, isTransactional: false)) { var requestRetryArgs = new RequestRetryArgs() { ActionName = Enums.EnumActionName.PurchaseAdd, StrJson = strJson }; await _backgroundJobManager.EnqueueAsync(requestRetryArgs, priority: BackgroundJobPriority.Normal, delay: TimeSpan.FromSeconds(60)); await uow.SaveChangesAsync(); } } }