using AutoMapper; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using WMS.Web.Core.Dto; using WMS.Web.Core.Dto.Erp; using WMS.Web.Core.Dto.Erp.TakeStock; using WMS.Web.Core.Dto.Inventory; using WMS.Web.Core.Dto.Login; using WMS.Web.Core.Dto.TakeStock; using WMS.Web.Core.Internal.Results; using WMS.Web.Domain.Entitys; using WMS.Web.Domain.Infrastructure; using WMS.Web.Domain.IService; using WMS.Web.Domain.IService.Public; using WMS.Web.Domain.Values; using WMS.Web.Domain.Values.Erp; using WMS.Web.Domain.Values.Single; namespace WMS.Web.Domain.Services { /// /// 盘点单服务 /// public class TakeStockService : ITakeStockService { private readonly IMapper _mapper; private readonly ILoginService _loginService; public readonly IBasicsRepositories _transactionRepositories; private readonly ITakeStockRepositories _takeStockRepositories; private readonly ILoginRepositories _loginRepositories; private readonly ISingleDataService _singleDataService; private readonly IErpService _erpService; private readonly ILogger _logger; private readonly IBoxInventoryService _boxInventoryService; private readonly IErpBasicDataExtendService _erpBasicDataExtendService; private readonly ISerialNumberService _serialNumberService; public TakeStockService(IMapper mapper, ILoginService loginService, IBasicsRepositories transactionRepositories, ITakeStockRepositories takeStockRepositories, ILoginRepositories loginRepositories, ISingleDataService singleDataService, IErpService erpService, ILogger logger, IBoxInventoryService boxInventoryService, IErpBasicDataExtendService erpBasicDataExtendService, ISerialNumberService serialNumberService) { _mapper = mapper; _loginService = loginService; _transactionRepositories = transactionRepositories; _takeStockRepositories = takeStockRepositories; _loginRepositories = loginRepositories; _singleDataService = singleDataService; _erpService = erpService; _logger = logger; _boxInventoryService = boxInventoryService; _erpBasicDataExtendService = erpBasicDataExtendService; _serialNumberService = serialNumberService; } /// /// 保存 /// /// /// /// public async Task Save(List dto, LoginInDto loginInfo) { _logger.LogInformation($"盘点保存:{JsonConvert.SerializeObject(dto)} 盘点人:{loginInfo.UserInfo.StaffId}"); if(dto.GroupBy(g=>g.BoxId).Count()>1) return Result.ReFailure(ResultCodes.TakeStockBoxError); List list = new List(); var profitList = dto.Where(w => w.AfterQty >= w.BeforeQty).ToList();//盘盈 var lossList = dto.Where(w => w.AfterQty < w.BeforeQty).ToList();//盘亏 if (profitList.Count() > 0) { TakeStock takeStock = new TakeStock(); takeStock.Create(loginInfo.UserInfo.StaffId, TakeStockType.Profit); takeStock.Details = _mapper.Map>(dto); foreach (var d in takeStock.Details) { var subStock = await _transactionRepositories.GetSubUcStockAsync(d.SubStockId, loginInfo.UserInfo.CompanyId); d.OrgCode = subStock?.ErpOrgCode; d.StockCode = subStock?.StockCode; } if (takeStock.Details.GroupBy(g => g.StockCode).Count() > 1) return Result.ReFailure(ResultCodes.TakeStockStockError); list.Add(takeStock); } if (lossList.Count() > 0) { TakeStock takeStock = new TakeStock(); takeStock.Create(loginInfo.UserInfo.StaffId, TakeStockType.Loss); takeStock.Details = _mapper.Map>(dto); foreach (var d in takeStock.Details) { var subStock = await _transactionRepositories.GetSubUcStockAsync(d.SubStockId, loginInfo.UserInfo.CompanyId); d.OrgCode = subStock?.ErpOrgCode; d.StockCode = subStock?.StockCode; } if (takeStock.Details.GroupBy(g => g.StockCode).Count() > 1) return Result.ReFailure(ResultCodes.TakeStockStockError); list.Add(takeStock); } IDbContextTransaction _transaction = _transactionRepositories.GetTransaction(); Result res_Rollback = Result.ReSuccess(); bool isSuccess = true; if (res_Rollback.IsSuccess) { isSuccess = await _takeStockRepositories.AddRange(list, false); if (!isSuccess) res_Rollback = Result.ReFailure(ResultCodes.DateWriteError); } if (res_Rollback.IsSuccess) { var res_change = await _serialNumberService.TakeStock(list, loginInfo, false); if (!res_change.IsSuccess) res_Rollback = res_change; } if (res_Rollback.IsSuccess) { var res_Inventory = await _boxInventoryService.GenerateTakeBox(list, false); if (!res_Inventory.IsSuccess) res_Rollback = res_Inventory; } //提交事务 isSuccess = _transactionRepositories.CommitTransaction(res_Rollback.IsSuccess ? false : true, _transaction); if (!res_Rollback.IsSuccess) return res_Rollback; if (!isSuccess) return Result.ReFailure(ResultCodes.DateWriteError); //同步金蝶 foreach (var entity in list) await Loss_Profit(entity); return Result.ReSuccess(); } /// /// 同步金蝶 /// /// /// public async Task Sync(OperateRequest dto) { var list = await _takeStockRepositories.GetEntityList(dto.Ids); list = list.Where(w => w.SuccessSync == SyncStatus.Fail).ToList(); foreach (var entity in list) await Loss_Profit(entity); return Result.ReSuccess(); } /// /// 盘盈盘亏同步金蝶 /// /// /// public async Task Loss_Profit(TakeStock entity) { //获取金蝶仓库仓位编码 //var stockCode = _singleDataService.GetSingleDataCode(SingleAction.Stocks, _loginRepositories.CompanyId, entity.StockId); //var subStockCode = _singleDataService.GetSingleDataCode(SingleAction.Stocks, _loginRepositories.CompanyId, entity.SubStockId); try { var materials_result = await _erpService.BillQueryForMaterial(); if (!materials_result.IsSuccess) return Result.ReFailure(ResultCodes.ErpMaterialError); var materials = materials_result.Data.ToList(); var res = await _erpService.BillQueryForStock(); if (!res.IsSuccess) return Result.ReFailure(ResultCodes.ErpStockError); var resSub = await _erpService.BillQueryForSubStock(); if (!resSub.IsSuccess) return Result.ReFailure(ResultCodes.ErpStockError); var stock = res.Data.FirstOrDefault(f => f.Code == entity.Details[0].StockCode);//需要根据单点code搜索 if (stock == null) return Result.ReFailure(ResultCodes.ErpStockNoData); //组装dto #region 组装dto //子仓库 ORICO_JD:1000008 GD:1000005 HD:1000007 AD:1000004 List detils = new List(); foreach (var d in entity.Details) { var subStockCode = _singleDataService.GetSingleDataCode(SingleAction.Stocks, _loginRepositories.CompanyId, d.SubStockId); //var subStock = resSub.Data.FirstOrDefault(f => f.Code == subStockCode);//需要根据单点code搜索 var unitNumber = _erpBasicDataExtendService.GetMaterialUnitNumber(materials, d.MaterialId); detils.Add(new ErpTakeStockDetailsSaveDto() { FOwnerid = new ErpNumberDto(stock.OrgCode.ToString()), FKeeperId = new ErpNumberDto(stock.OrgCode.ToString()), MaterialId = new ErpNumberDto(_erpBasicDataExtendService.GetMaterialNumber(materials, d.MaterialId)), UnitId = new ErpNumberDto(unitNumber), //物料带出来 StockId = new ErpNumberDto(stock.Code), SubStockId = new ErpSubStockDto(stock.Code, resSub.Data.FirstOrDefault(f => f.Id == d.Erp_SubStockId)?.Code), BeforeQty = d.BeforeQty, AfterQty = d.AfterQty, FinalQty = entity.ResultType == TakeStockType.Profit ? d.FinalQty : 0, LossQty = entity.ResultType == TakeStockType.Loss ? d.FinalQty : 0, Fnote = d.Remark }); } ErpTakeStockSaveDto dto = new ErpTakeStockSaveDto() { BillNo = entity.BillNo, StockOrgId = new ErpNumberDto(stock.OrgCode), Type = new ErpNumberDto(entity.ResultType == TakeStockType.Loss ? "PK01_SYS" : "PY01_SYS"), Date = entity.Date, Details = detils }; #endregion //判断盘盈盘亏 FormIdParam type = entity.ResultType == TakeStockType.Loss ? FormIdParam.STK_StockCountLoss : FormIdParam.STK_StockCountGain; //操作金蝶 var resSync = await ErpOperate(dto, type); entity.Sync(resSync.result.IsSuccess, resSync.result.Message, resSync.syncStatus, resSync.erpBillNo); await _takeStockRepositories.Edit(entity, true); return res; } catch (Exception ex) { _logger.LogError($"盘点同步金蝶: {ex.ToString()}"); return Result.ReFailure(ResultCodes.NoDateError); } } /// /// 同步金蝶操作 /// /// /// /// private async Task<(Result result, SyncStatus syncStatus, string erpBillNo)> ErpOperate(ErpTakeStockSaveDto dto, FormIdParam type) { string formId = type.ToString(); _logger.LogInformation($"盘点单->开始同步金蝶 单号:{dto.BillNo} 数据: {JsonConvert.SerializeObject(dto)}"); var res_s = await _erpService.Save(dto, formId); if (!res_s.IsSuccess) { _logger.LogInformation($"盘点单->保存失败 单号:{dto.BillNo} 错误:{res_s.Message}"); return (Result.ReFailure(res_s.Message, res_s.Status), SyncStatus.Fail, ""); } //提交 _logger.LogInformation($"盘点单->保存成功 开始提交 单号:{dto.BillNo}"); ErpOperateDto o_dto = new ErpOperateDto(formId, res_s.Data);//res_s.Data var res = await _erpService.Submit(o_dto, formId); if (!res.IsSuccess) { //如果提交失败 //1.则调删单接口 //var del_res = await _erpService.Delete(o_dto, formId); //if (!del_res.IsSuccess) // _logger.LogError($"盘盈盘亏同步金蝶 单号:{dto.BillNo} 提交失败原因: {res.Message} 删单失败原因:{del_res.Message}"); _logger.LogInformation($"盘点单->提交失败 单号:{dto.BillNo} 错误:{res.Message}"); return (res, SyncStatus.SubmitFail, o_dto.Numbers.First()); } //审核 _logger.LogInformation($"盘点单->提交成功 开始审核 单号:{dto.BillNo}"); res = await _erpService.Audit(o_dto, formId); if (!res.IsSuccess) { //如果审核失败 //1.调反审核接口 //2.调删除接口 //var noAudit_res = await _erpService.NoAudit(o_dto, formId); //if (!noAudit_res.IsSuccess) //{ // _logger.LogError($"盘盈盘亏同步金蝶 单号:{dto.BillNo} 审核失败原因: {res.Message} 反审核失败原因:{noAudit_res.Message}"); // return res; //} //var del_res = await _erpService.Delete(o_dto, formId); //if (!del_res.IsSuccess) // _logger.LogError($"盘盈盘亏同步金蝶 单号:{dto.BillNo} 审核失败原因: {res.Message} 删单失败原因:{del_res.Message}"); _logger.LogInformation($"盘点单->审核失败 单号:{dto.BillNo} 错误:{res.Message}"); return (res, SyncStatus.CheckFail, o_dto.Numbers.First()); } _logger.LogInformation($"同步金蝶成功"); return (Result.ReSuccess(), SyncStatus.Success, o_dto.Numbers.First()); } } }