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.ChangeBoxRecord; using WMS.Web.Core.Dto.Inventory; using WMS.Web.Core.Dto.Login; using WMS.Web.Core.Dto.MoveBoxRecord; using WMS.Web.Core.Help; 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; namespace WMS.Web.Domain.Services { ///改箱 移箱服务 public class ChangeMoveBoxService : IChangeMoveBoxService { private readonly IMapper _mapper; private readonly ILoginService _loginService; private readonly IChangeBoxRecordRepositories _changeBoxRecordRepositories; public readonly IBasicsRepositories _basbicsRepositories; private readonly IMoveBoxRecordRepositories _moveBoxRecordRepositories; private readonly IBoxRepositories _boxRepositories; private readonly ISerialNumberService _serialNumberService; private readonly IBoxInventoryService _boxInventoryService; private readonly IBoxInventoryRepositories _boxInventoryRepositories; private readonly ILogger _logger; private readonly ISerialNumbersRepositories _serialNumbersRepositories; private readonly IBoxService _boxService; public ChangeMoveBoxService(IMapper mapper, ILoginService loginService, IChangeBoxRecordRepositories changeBoxRecordRepositories, IBasicsRepositories basbicsRepositories, IMoveBoxRecordRepositories moveBoxRecordRepositories, IBoxRepositories boxRepositories, ISerialNumberService serialNumberService, IBoxInventoryService boxInventoryService, IBoxInventoryRepositories boxInventoryRepositories, ILogger logger, ISerialNumbersRepositories serialNumbersRepositories, IBoxService boxService) { _mapper = mapper; _loginService = loginService; _changeBoxRecordRepositories = changeBoxRecordRepositories; _basbicsRepositories = basbicsRepositories; _moveBoxRecordRepositories = moveBoxRecordRepositories; _boxRepositories = boxRepositories; _serialNumberService = serialNumberService; _boxInventoryService = boxInventoryService; _boxInventoryRepositories = boxInventoryRepositories; _logger = logger; _serialNumbersRepositories = serialNumbersRepositories; _boxService = boxService; } /// /// 改箱保存 /// /// /// /// public async Task ChangeBoxSave(List dto, LoginInDto loginInfo, bool isTransaction = false, bool IsInventory = true, bool IsPDA = false) { _logger.LogInformation($"改箱:{JsonConvert.SerializeObject(dto)} 操作人:{loginInfo.UserInfo.StaffId}"); bool isAddBox = false; if (IsPDA) { //处理目标箱不在系统的情况,需要先增加箱信息 var d = dto.First(); if (d.DestBoxId == 0) { var dBox = await _boxRepositories.GetByNo(d.DestBoxBillNo); if (dBox == null) { var res = await CreateBox(d); if (!res.IsSuccess) return res; dBox = await _boxRepositories.GetByNo(d.DestBoxBillNo); dto.First().DestBoxId = dBox.Id; isAddBox = true; } } } //1.有原箱时 需要判断 物料对应的序列号是否存在 var srcIds = dto.Select(s => s.SrcBoxId).Distinct().ToList(); var destIds = dto.Select(s => s.DestBoxId).Distinct().ToList(); var boxs = await _boxInventoryRepositories.GetList(srcIds); var serialNumbers = dto.SelectMany(s => s.Details).SelectMany(s => s.SerialNumbers).ToList(); var serialNumberList = await _serialNumbersRepositories.GetEntityList(serialNumbers); foreach (var d in dto) { if (d.SrcBoxId == 0) { //没有原箱的情况下需要验证序列号是否有箱子绑定 var s = d.Details.SelectMany(s => s.SerialNumbers).ToList(); var sCount = serialNumberList.Where(w => s.Contains(w.SerialNumber) && w.BoxId != 0).Count(); if (sCount > 0) return Result.ReFailure(ResultCodes.SerialNumbersBoxError); } else { //有原箱的情况下验证序列号和原箱是否一致 var s = d.Details.SelectMany(s => s.SerialNumbers).ToList(); var boxCount = serialNumberList.Where(w => s.Contains(w.SerialNumber)).GroupBy(s => s.BoxId).Select(s => s.Key).ToList(); if (boxCount.Count() > 1 || (boxCount.Count() == 1 && boxCount[0] != d.SrcBoxId)) return Result.ReFailure(ResultCodes.SerialNumbersSrcBoxError); } var box = boxs.FirstOrDefault(f => f.BoxId == d.SrcBoxId); //原箱在库存中的话 进行验证 if (box != null) { foreach (var bd in box.Details) { var bDe = box.Details.FirstOrDefault(f => f.MaterialId == bd.MaterialId); if (bDe == null) return Result.ReFailure(ResultCodes.BoxMateriaNoData); var ex = bd.SerialNumbers.Except(bDe.SerialNumbers).ToList(); if (ex.Count() > 0) return Result.ReFailure(ResultCodes.BoxInventorySerialNumbersNoData); } } } List boxList = new List(); //原箱有可能没有 var srcBoxs = await _boxRepositories.GetEntityList(srcIds); var destBoxs = await _boxRepositories.GetEntityList(destIds); //if (srcBox == null) return Result.ReFailure(ResultCodes.BoxNoData); if (destBoxs.Count() != destIds.Count()) return Result.ReFailure(ResultCodes.BoxNoData); foreach (var d in dto) { var l = d.Details.Select(s => (s.MaterialId, s.Qty, s.SerialNumbers)).ToList(); var srcBox = srcBoxs.FirstOrDefault(f => f.Id == d.SrcBoxId); var destBox = destBoxs.FirstOrDefault(f => f.Id == d.DestBoxId); //原箱移出 Result res; if (srcBox != null) { res = srcBox.Out(l); if (!res.IsSuccess) return res; } if (srcBox != null) boxList.Add(srcBox); //目标箱移入 if (!isAddBox) { res = destBox.In(l); if (!res.IsSuccess) return res; if (destBox != null) boxList.Add(destBox); } } List list = new List(); var subIds = dto.Select(s => s.SubStockId).ToList(); var subStocks = await _basbicsRepositories.GetSubUcStockAsync(subIds, loginInfo.UserInfo.CompanyId); foreach (var dt in dto) { var subStock = subStocks.FirstOrDefault(f => f.Id == dt.SubStockId); var boxi = boxs.FirstOrDefault(f => f.BoxId == dt.SrcBoxId); foreach (var d in dt.Details) { ChangeBoxRecord entity = new ChangeBoxRecord(); entity.Create(loginInfo.UserInfo.StaffId, d.Qty, d.MaterialId, d.SerialNumbers, dt.SrcBoxId, dt.DestBoxId); entity.SrcSubStockId = boxi?.SubStockId ?? 0;//原乡仓位需要去拉一下库存获取 if (subStock != null) { entity.DestSubStockId = dt.SubStockId; entity.DestBoxOrgCode = subStock.ErpOrgCode; entity.DestStockCode = subStock.StockCode; } list.Add(entity); } } IDbContextTransaction _transaction = null; if (isTransaction) _transaction = _basbicsRepositories.GetTransaction(); Result res_Rollback = Result.ReSuccess(); bool isSuccess = true; if (res_Rollback.IsSuccess) { isSuccess = await _changeBoxRecordRepositories.AddRange(list, false); if (!isSuccess) res_Rollback = Result.ReFailure(ResultCodes.DateWriteError); } if (res_Rollback.IsSuccess) { var res_change = await _serialNumberService.ChangeBox(list, loginInfo, false); if (!res_change.IsSuccess) res_Rollback = res_change; } if (res_Rollback.IsSuccess) { isSuccess = await _boxRepositories.EditEntityList(boxList, false); if (!isSuccess) res_Rollback = Result.ReFailure(ResultCodes.DateWriteError); } if (res_Rollback.IsSuccess && IsInventory) { var res_Inventory = await _boxInventoryService.GenerateChangeBox(list, false); if (!res_Inventory.IsSuccess) res_Rollback = res_Inventory; } //提交事务 if (isTransaction) { isSuccess = _basbicsRepositories.CommitTransaction(res_Rollback.IsSuccess ? false : true, _transaction); if (!res_Rollback.IsSuccess) return res_Rollback; if (!isSuccess) return Result.ReFailure(ResultCodes.DateWriteError); } return Result.ReSuccess(); } /// /// 自动生成箱信息 /// /// /// private async Task CreateBox(SaveChangeBoxRecordRequest dto) { //增加一个空箱子 List list = new List(); OpsBoxResponse response = new OpsBoxResponse() { BoxBillNo = dto.DestBoxBillNo }; foreach (var d in dto.Details) { List s = new List(); foreach (var sd in d.SerialNumbers) { s.Add(new OpsSerialNumbersResponse() { SerialNumber = sd }); } OpsBoxDetailsResponse dr = new OpsBoxDetailsResponse() { MaterialId = d.MaterialId, Qty = d.Qty, SerialNumbers = s }; response.Details.Add(dr); } list.Add(response); return await _boxService.Sync(list); } /// /// 移箱保存 /// /// /// /// public async Task MoveBoxSave(List dto, bool IsUp, LoginInDto loginInfo) { _logger.LogInformation($"移箱:{JsonConvert.SerializeObject(dto)} 是否上架:{IsUp} 操作人:{loginInfo.UserInfo.StaffId}"); //1.下架时 需要验证箱是否在库存里 var boxIds = dto.Select(s => s.BoxId).ToList(); var boxList = await _boxInventoryRepositories.GetList(boxIds); if (!IsUp) { if (boxIds.Count() != boxList.Count()) return Result.ReFailure(ResultCodes.BoxInventoryNoDataError); } else { //上架时 箱子不能在库存里 if (boxList.Count() > 0) { var boxs = await _boxRepositories.GetEntityList(boxList.Select(s => s.BoxId).ToList()); return Result.ReFailure($"箱号{ string.Join(",", boxs.Select(s => s.BoxBillNo))} 已上架", 343433); } } List entityList = new List(); foreach (var d in dto) { var subStock = await _basbicsRepositories.GetSubUcStockAsync(d.SubStockId, loginInfo.UserInfo.CompanyId); var entity = new MoveBoxRecord(); entity.Create(IsUp == true ? MoveBoxType.Up : MoveBoxType.Down, d.BoxId, d.Qty, subStock?.ErpOrgCode, subStock?.StockCode, d.SubStockId, loginInfo.UserInfo.StaffId); entity.Details = d.Details.Select(s => new MoveBoxRecordDetails() { MaterialId = s.MaterialId, Qty = s.Qty, SerialNumbers = s.SerialNumbers }).ToList(); entityList.Add(entity); } IDbContextTransaction _transaction = _basbicsRepositories.GetTransaction(); bool isSuccess = true; Result res_Rollback = Result.ReSuccess(); if (res_Rollback.IsSuccess) { isSuccess = await _moveBoxRecordRepositories.AddRange(entityList, false); if (!isSuccess) res_Rollback = Result.ReFailure(ResultCodes.DateWriteError); } if (res_Rollback.IsSuccess) { var res_change = await _serialNumberService.MoveBox(entityList, loginInfo, false); if (!res_change.IsSuccess) res_Rollback = res_change; } if (res_Rollback.IsSuccess) { var res_Inventory = await _boxInventoryService.GenerateMoveBox(entityList, false); if (!res_Inventory.IsSuccess) res_Rollback = res_Inventory; } //提交事务 isSuccess = _basbicsRepositories.CommitTransaction(res_Rollback.IsSuccess ? false : true, _transaction); if (!res_Rollback.IsSuccess) return res_Rollback; if (!isSuccess) return Result.ReFailure(ResultCodes.DateWriteError); return Result.ReSuccess(); } /// /// 出入库回退改箱 /// /// /// /// /// public async Task ChangeBox_BackRecord(BackRecord backRecord, LoginInDto loginInfo, bool isTransaction = true) { if (backRecord.Method == InventoryInOutMethod.Box) return Result.ReSuccess(); List dtoList = new List(); var boxIds = backRecord.Details.Select(s => s.BoxId).Distinct().ToList(); var boxs = await _boxRepositories.GetEntityList(boxIds); foreach (var d in backRecord.Details) { var box = boxs.FirstOrDefault(f => f.Id == d.BoxId); if (box == null) continue; if (backRecord.Type == BackRecordType.InstockOff) box.BackRecordDown(d.MaterialId, d.Qty); else box.BackRecordUp(d.MaterialId, d.Qty); } IDbContextTransaction _transaction = null; if (isTransaction) _transaction = _basbicsRepositories.GetTransaction(); Result res_Rollback = Result.ReSuccess(); bool isSuccess = true; if (res_Rollback.IsSuccess) { isSuccess = await _boxRepositories.EditEntityList(boxs, false); if (!isSuccess) res_Rollback = Result.ReFailure(ResultCodes.DateWriteError); } //提交事务 if (isTransaction) { isSuccess = _basbicsRepositories.CommitTransaction(res_Rollback.IsSuccess ? false : true, _transaction); if (!res_Rollback.IsSuccess) return res_Rollback; if (!isSuccess) return Result.ReFailure(ResultCodes.DateWriteError); } return Result.ReSuccess(); } /// /// 非采购入库 /// /// /// /// /// public async Task ChangeBox_InStock(InStock inStock, LoginInDto loginInfo, bool isTransaction = true) { List dtoList = new List(); //目标箱 var destIds = inStock.Details.GroupBy(g => g.BoxId); var serialNumbers = inStock.Details.SelectMany(s => s.SerialNumbers).ToList(); var serialNumberList = await _serialNumbersRepositories.GetEntityList(serialNumbers); foreach (var detail in inStock.Details) { if (detail.Qty == 0) continue; var detailClone = detail.Clone(); //处理序列号 var sList = serialNumberList.Where(w => detailClone.SerialNumbers.Contains(w.SerialNumber)).ToList(); foreach (var s in sList) { //原箱和目标箱一样不处理 if (s.BoxId == detailClone.BoxId) { detailClone.Qty = detailClone.Qty - 1; detailClone.SerialNumbers.Remove(s.SerialNumber); continue; } var d = dtoList.FirstOrDefault(f => f.DestBoxId == detailClone.BoxId && f.SrcBoxId == s.BoxId); if (d == null) { d = new SaveChangeBoxRecordRequest(s.BoxId, detailClone.BoxId); d.Details.Add(new SaveChangeBoxRecordDetailsRequest(detailClone.MaterialId, 1, s.SerialNumber)); } else { var dtoDetail = d.Details.FirstOrDefault(f => f.MaterialId == detailClone.MaterialId); if (dtoDetail == null) d.Details.Add(new SaveChangeBoxRecordDetailsRequest(detailClone.MaterialId, 1, s.SerialNumber)); else { dtoDetail.Qty += 1; dtoDetail.SerialNumbers.Add(s.SerialNumber); } } detailClone.Qty = detailClone.Qty - 1; detailClone.SerialNumbers.Remove(s.SerialNumber); } //处理非序列号的数据 if (detailClone.Qty <= 0) continue; var dto = dtoList.FirstOrDefault(f => f.DestBoxId == detailClone.BoxId && f.SrcBoxId == 0); if (dto == null) { dto = new SaveChangeBoxRecordRequest(0, detailClone.BoxId); dto.Details.Add(new SaveChangeBoxRecordDetailsRequest(detailClone.MaterialId, detailClone.Qty, detailClone.SerialNumbers)); } else { var dtoDetail = dto.Details.FirstOrDefault(f => f.MaterialId == detailClone.MaterialId); if (dtoDetail == null) dto.Details.Add(new SaveChangeBoxRecordDetailsRequest(detailClone.MaterialId, detailClone.Qty, detailClone.SerialNumbers)); else { dtoDetail.Qty += detailClone.Qty; dtoDetail.SerialNumbers.AddRange(detailClone.SerialNumbers); } } } return await ChangeBoxSave(dtoList, loginInfo, isTransaction, false); } } }