using CMS.Plugin.HIAWms.Application.Contracts.Dtos.WmsMaterialStocks; using CMS.Plugin.HIAWms.Application.Contracts.Services; using CMS.Plugin.HIAWms.Domain.Shared.WmsMaterialStocks; using CMS.Plugin.HIAWms.Domain.WmsAreas; using CMS.Plugin.HIAWms.Domain.WmsContainers; using CMS.Plugin.HIAWms.Domain.WmsMaterials; using CMS.Plugin.HIAWms.Domain.WmsMaterialStocks; using CMS.Plugin.HIAWms.Domain.WmsPlaces; using CmsQueryExtensions; using Microsoft.Extensions.DependencyInjection; using System.Text.Json; using Volo.Abp; using Volo.Abp.Application.Dtos; using Volo.Abp.Data; using Volo.Abp.ObjectExtending; using Volo.Abp.Uow; namespace CMS.Plugin.HIAWms.Application.Implements; /// public class WmsMaterialStockAppService : CMSPluginAppService, IWmsMaterialStockAppService { private readonly IWmsMaterialStockRepository _wmsmaterialstockRepository; private readonly IWmsMaterialRepository _wmsMaterialRepository; private readonly IWmsContainerRepository _wmscontainerRepository; private readonly IWmsPlaceRepository _wmsplaceRepository; private readonly IWmsAreaRepository _wmsareaRepository; private readonly IServiceProvider _serviceProvider; /// /// Initializes a new instance of the class. /// /// The task job repository. public WmsMaterialStockAppService(IWmsMaterialStockRepository wmsmaterialstockRepository, IWmsMaterialRepository wmsMaterialRepository, IWmsContainerRepository wmscontainerRepository, IWmsPlaceRepository wmsplaceRepository, IWmsAreaRepository wmsareaRepository , IServiceProvider serviceProvider) { _wmsmaterialstockRepository = wmsmaterialstockRepository; _wmsMaterialRepository = wmsMaterialRepository; _wmscontainerRepository = wmscontainerRepository; _wmsplaceRepository = wmsplaceRepository; _wmsareaRepository = wmsareaRepository; _serviceProvider = serviceProvider; } /// public virtual async Task GetAsync(Guid id) { return ObjectMapper.Map(await _wmsmaterialstockRepository.GetAsync(id)); } /// public virtual async Task> GetListAsync(GetWmsMaterialStocksInput input) { Check.NotNull(input, nameof(input)); if (input.Sorting.IsNullOrWhiteSpace()) { input.Sorting = nameof(WmsMaterialStock.Sort); } var specification = new WmsMaterialStockSpecification(input.Name); var stock = ObjectMapper.Map(input); var count = await _wmsmaterialstockRepository.GetCountAsync(stock, input.StartTime, input.EndTime, input.Filter, specification); var list = await _wmsmaterialstockRepository.GetListAsync(stock, input.StartTime, input.EndTime, input.Sorting, input.MaxResultCount, input.SkipCount, input.Filter, specification); return new PagedResultDto(count, ObjectMapper.Map, List>(list)); } /// public virtual async Task CreateAsync(WmsMaterialStockCreateDto input) { using var scope = _serviceProvider.CreateScope(); var unitOfWorkManager = scope.ServiceProvider.GetRequiredService(); using var uow = unitOfWorkManager.Begin(requiresNew: true); await CheckCreateOrUpdateDtoAsync(input); //var exist = await _wmsmaterialstockRepository.NameExistAsync(input.MaterialNo); //if (exist) //{ // throw new UserFriendlyException(L[CMSPluginDomainErrorCodes.NameAlreadyExists, input.MaterialNo]); //} var material = await _wmsMaterialRepository.FindByNameAsync(input.MaterialNo); if (material == null) { throw new UserFriendlyException("物料信息不存在"); } var container = await _wmscontainerRepository.FindByNameAsync(input.ContainerNo); if (container == null) { throw new UserFriendlyException("托盘信息不存在"); } var wmsmaterialstock = ObjectMapper.Map(input); input.MapExtraPropertiesTo(wmsmaterialstock, MappingPropertyDefinitionChecks.None); wmsmaterialstock.MaterialId = Guid.NewGuid().ToString("N"); wmsmaterialstock.MaterialName = material.MaterialName; wmsmaterialstock.ContainerStatus = Domain.Shared.Enums.ContainerStatusEnum.KUWEI; wmsmaterialstock.ContainerType = container.ContainerType; wmsmaterialstock.StorageTypeNo = Domain.Shared.Enums.PlaceTypeEnum.XUNIKUWEI; wmsmaterialstock.PlaceStatus = Domain.Shared.Enums.PlaceStatusEnum.DAIRU; if (!string.IsNullOrEmpty(input.PlaceNo)) { var place = await _wmsplaceRepository.FindByNameAsync(input.PlaceNo); if (place == null) { throw new UserFriendlyException("库位信息不存在"); } var area = await _wmsareaRepository.FindByNameAsync(place.AreaCode); if (area == null) { throw new UserFriendlyException("库位库区信息不存在"); } wmsmaterialstock.PlaceStatus = Domain.Shared.Enums.PlaceStatusEnum.CUNHUO; wmsmaterialstock.StorageTypeNo = place.StorageTypeNo; wmsmaterialstock.AreaCode = place.AreaCode; wmsmaterialstock.AreaName = area.AreaName; place.PlaceStatus = Domain.Shared.Enums.PlaceStatusEnum.CUNHUO; place.Islock = input.IsLock; await _wmsplaceRepository.UpdateAsync(place); } var wmsmaterialstockList = await _wmsmaterialstockRepository.GetStockListAsync(new WmsMaterialStock { PlaceNo = input.PlaceNo }); if (wmsmaterialstockList.Count > 0) { if (wmsmaterialstockList[0].MaterialNo != input.MaterialNo) { throw new UserFriendlyException("当前库位已存放别的物料"); } } var maxSort = await _wmsmaterialstockRepository.GetMaxSortAsync(); var sort = input.Sort ?? maxSort; wmsmaterialstock.MaterialModel = material.MaterialModel; wmsmaterialstock.MaterialBatch = input.MaterialBatch; wmsmaterialstock.Sort = sort; wmsmaterialstock.InStockTime = DateTime.Now; var stockList = new List(); for (int i = 0; i < input.StockNumber; i++) { var stock = new WmsMaterialStock(); var json = JsonSerializer.Serialize(wmsmaterialstock); stock = JsonSerializer.Deserialize(json); stock.MaterialId = Guid.NewGuid().ToString("N"); stock.StockNumber = 1; stockList.Add(stock); } await _wmsmaterialstockRepository.InsertManyAsync(stockList); container.ContainerStatus = Domain.Shared.Enums.ContainerStatusEnum.KUWEI; await _wmscontainerRepository.UpdateAsync(container); //if (input.Sort.HasValue && wmsmaterialstock.Sort != maxSort) //{ // await AdjustSortAsync(wmsmaterialstock.Id, wmsmaterialstock.Sort); //} await uow.SaveChangesAsync(); await uow.CompleteAsync(); return ObjectMapper.Map(wmsmaterialstock); } /// public virtual async Task UpdateAsync(Guid id, WmsMaterialStockUpdateDto input) { using var scope = _serviceProvider.CreateScope(); var unitOfWorkManager = scope.ServiceProvider.GetRequiredService(); using var uow = unitOfWorkManager.Begin(requiresNew: true); await CheckCreateOrUpdateDtoAsync(input); var wmsmaterialstockList = await _wmsmaterialstockRepository.GetStockListAsync(new WmsMaterialStock { MaterialNo = input.MaterialNo }); //var exist = await _wmsmaterialstockRepository.NameExistAsync(input.MaterialNo, wmsmaterialstock.Id); //if (exist) //{ // throw new UserFriendlyException(L[CMSPluginDomainErrorCodes.NameAlreadyExists, input.MaterialNo]); //} var material = await _wmsMaterialRepository.FindByNameAsync(input.MaterialNo); if (material == null) { throw new UserFriendlyException("物料信息不存在"); } var container = await _wmscontainerRepository.FindByNameAsync(input.ContainerNo); if (container == null) { throw new UserFriendlyException("托盘信息不存在"); } var place = await _wmsplaceRepository.FindByNameAsync(input.PlaceNo); if (place == null) { throw new UserFriendlyException("库位信息不存在"); } var area = await _wmsareaRepository.FindByNameAsync(place.AreaCode); if (area == null) { throw new UserFriendlyException("库位库区信息不存在"); } foreach (var wmsmaterialstock in wmsmaterialstockList) { if (input.StockNumber < wmsmaterialstockList.Count) { wmsmaterialstock.IsDeleted = true; input.StockNumber += 1; } wmsmaterialstock.SetConcurrencyStampIfNotNull(input.ConcurrencyStamp); input.MapExtraPropertiesTo(wmsmaterialstock, MappingPropertyDefinitionChecks.None); wmsmaterialstock.MaterialNo = input.MaterialNo; wmsmaterialstock.ContainerNo = input.ContainerNo; //wmsmaterialstock.StockNumber = input.StockNumber; wmsmaterialstock.PlaceNo = input.PlaceNo; wmsmaterialstock.IsLock = input.IsLock; wmsmaterialstock.EmptyContainer = input.EmptyContainer; //wmsmaterialstock.InStockTime = input.InStockTime; wmsmaterialstock.Remark = input.Remark; wmsmaterialstock.MaterialName = material.MaterialName; wmsmaterialstock.ContainerStatus = Domain.Shared.Enums.ContainerStatusEnum.KUWEI; wmsmaterialstock.ContainerType = container.ContainerType; wmsmaterialstock.PlaceStatus = Domain.Shared.Enums.PlaceStatusEnum.CUNHUO; wmsmaterialstock.StorageTypeNo = place.StorageTypeNo; wmsmaterialstock.AreaCode = place.AreaCode; wmsmaterialstock.AreaName = area.AreaName; wmsmaterialstock.MaterialModel = material.MaterialModel; wmsmaterialstock.MaterialBatch = input.MaterialBatch; } if (input.StockNumber > wmsmaterialstockList.Count) { var stockList = new List(); for (int i = 0; i < input.StockNumber - wmsmaterialstockList.Count; i++) { var stock = new WmsMaterialStock(); var json = JsonSerializer.Serialize(wmsmaterialstockList[0]); stock = JsonSerializer.Deserialize(json); stock.MaterialId = Guid.NewGuid().ToString("N"); stock.StockNumber = 1; stockList.Add(stock); } await _wmsmaterialstockRepository.InsertManyAsync(stockList); } await _wmsmaterialstockRepository.UpdateManyAsync(wmsmaterialstockList); container.ContainerStatus = Domain.Shared.Enums.ContainerStatusEnum.KUWEI; place.PlaceStatus = Domain.Shared.Enums.PlaceStatusEnum.CUNHUO; place.Islock = input.IsLock; await _wmscontainerRepository.UpdateAsync(container); await _wmsplaceRepository.UpdateAsync(place); await uow.SaveChangesAsync(); await uow.CompleteAsync(); var result = wmsmaterialstockList.GroupBy(x => new { x.MaterialNo, x.PlaceNo, x.ContainerNo }) .Select(g => new WmsMaterialStock { MaterialNo = g.Key.MaterialNo, MaterialName = g.First().MaterialName, PlaceNo = g.Key.PlaceNo, ContainerNo = g.Key.ContainerNo, ContainerStatus = g.First().ContainerStatus, PlaceStatus = g.First().PlaceStatus, StorageTypeNo = g.First().StorageTypeNo, MaterialBatch = g.First().MaterialBatch, MaterialModel = g.First().MaterialModel, AreaCode = g.First().AreaCode, AreaName = g.First().AreaName, CheckStatus = g.First().CheckStatus, IsLock = g.First().IsLock, EmptyContainer = g.First().EmptyContainer, InStockTime = g.First().InStockTime, StockNumber = g.Sum(x => x.StockNumber) }) .FirstOrDefault(); return ObjectMapper.Map(result); } /// public async Task> CloneAsync(IEnumerable ids) { var wmsmaterialstocks = new List(); if (ids != null) { var sort = await _wmsmaterialstockRepository.GetMaxSortAsync(); foreach (var id in ids) { var wmsmaterialstock = await _wmsmaterialstockRepository.FindAsync(id); if (wmsmaterialstock != null) { var name = wmsmaterialstock.MaterialNo + WmsMaterialStockConsts.CloneTag; var notExist = false; while (!notExist) { var exist = await _wmsmaterialstockRepository.NameExistAsync(name); if (exist || wmsmaterialstocks.Any(x => x.MaterialNo == name)) { name += WmsMaterialStockConsts.CloneTag; continue; } notExist = true; } //wmsmaterialstock = await _wmsmaterialstockRepository.InsertAsync(wmsmaterialstock.Clone(GuidGenerator.Create(), name, sort++)); wmsmaterialstocks.Add(wmsmaterialstock); } } } return ObjectMapper.Map, List>(wmsmaterialstocks); } /// public virtual Task DeleteAsync(Guid id) { return _wmsmaterialstockRepository.DeleteAsync(id); } /// public async Task DeleteManyAsync(IEnumerable ids) { foreach (var id in ids) { await DeleteAsync(id); } } /// /// 删除库存 /// /// /// public async Task DeleteByMaterialAsync(string materialNo) { var wmsmaterialstockList = await _wmsmaterialstockRepository.GetStockListAsync(new WmsMaterialStock { MaterialNo = materialNo }); var ids = wmsmaterialstockList.Select(x => x.Id); await DeleteManyAsync(ids); } /// public virtual async Task AdjustSortAsync(Guid id, int sort) { var list = await _wmsmaterialstockRepository.GetListAsync(null, null, null, nameof(WmsMaterialStock.Sort)); if (list != null && list.Any()) { var initSort = 1; list.ForEach(x => x.AdjustSort(initSort++)); var entity = list.FirstOrDefault(x => x.Id == id); if (entity != null) { if (sort == 1) { list.Where(x => x.Id != id).ToList()?.ForEach(x => x.AdjustSort(x.Sort + 1)); } else if (entity.Sort > sort) { list.Where(x => x.Id != id && x.Sort >= sort).ToList()?.ForEach(x => x.AdjustSort(x.Sort + 1)); list.Where(x => x.Id != id && x.Sort < sort).ToList()?.ForEach(x => x.AdjustSort(x.Sort - 1)); } else if (entity.Sort < sort) { list.Where(x => x.Id != id && x.Sort > sort).ToList()?.ForEach(x => x.AdjustSort(x.Sort + 1)); list.Where(x => x.Id != id && x.Sort <= sort).ToList()?.ForEach(x => x.AdjustSort(x.Sort - 1)); } entity.AdjustSort(sort); } } await _wmsmaterialstockRepository.UpdateManyAsync(list); } /// public async Task ImportAsync(WmsMaterialStocksImportModel input) { Check.NotNull(input, nameof(input)); var wmsmaterialstockCreateDtos = new List<(int RowIndex, WmsMaterialStockCreateDto Item)>(); var wmsmaterialstockUpdateDtos = new List<(int RowIndex, Guid Id, WmsMaterialStockUpdateDto Item)>(); var wmsmaterialstocks = input.WmsMaterialStocks; if (wmsmaterialstocks != null && wmsmaterialstocks.Any()) { #region 导入校验 // 判断名称是否重复,并输出第几行重复 var duplicateWmsMaterialStocks = wmsmaterialstocks.GroupBy(x => x.MaterialNo).Where(x => x.Count() > 1).ToList(); if (duplicateWmsMaterialStocks?.Any() == true) { var duplicateWmsMaterialStockMsgs = duplicateWmsMaterialStocks.Select(x => $"第 {string.Join(",", x.Select(x => x.RowIndex))} 行:{x.Key} 名称重复"); var errorMsg = $"导入失败!配置, {string.Join(",", duplicateWmsMaterialStockMsgs)},终止导入"; throw new UserFriendlyException(errorMsg); } #endregion foreach (var wmsmaterialstock in wmsmaterialstocks) { if (wmsmaterialstock.MaterialNo.IsNullOrWhiteSpace() && wmsmaterialstock.MaterialNo.IsNullOrWhiteSpace()) { continue; } if (wmsmaterialstock.MaterialNo.IsNullOrWhiteSpace()) { var errorMsg = $"导入失败!配置,第{wmsmaterialstock.RowIndex}行:WmsMaterialStock名称不能为空"; throw new UserFriendlyException(errorMsg); } var oldWmsMaterialStock = await _wmsmaterialstockRepository.FindByNameAsync(wmsmaterialstock.MaterialNo); if (oldWmsMaterialStock != null) { var wmsMaterialStockUpdateDto = new WmsMaterialStockUpdateDto { // 基础信息 MaterialNo = wmsmaterialstock.MaterialNo, MaterialName = wmsmaterialstock.MaterialName, Remark = wmsmaterialstock.Remark, // 容器信息 ContainerNo = wmsmaterialstock.ContainerNo, ContainerStatus = wmsmaterialstock.ContainerStatus, ContainerType = wmsmaterialstock.ContainerType, // 库存信息 StockNumber = wmsmaterialstock.StockNumber, MaterialBatch = wmsmaterialstock.MaterialBatch, // 供应商信息 SupplierCode = wmsmaterialstock.SupplierCode, MaterialModel = wmsmaterialstock.MaterialModel, // 库位信息 PlaceNo = wmsmaterialstock.PlaceNo, PlaceStatus = wmsmaterialstock.PlaceStatus, StorageTypeNo = wmsmaterialstock.StorageTypeNo, // 库区信息 AreaCode = wmsmaterialstock.AreaCode, AreaName = wmsmaterialstock.AreaName, // 状态信息 IsLock = wmsmaterialstock.IsLock, InStockTime = wmsmaterialstock.InStockTime, // 并发控制 ConcurrencyStamp = oldWmsMaterialStock.ConcurrencyStamp }; wmsmaterialstockUpdateDtos.Add((wmsmaterialstock.RowIndex, oldWmsMaterialStock.Id, wmsMaterialStockUpdateDto)); } else { var wmsmaterialstockCreateDto = new WmsMaterialStockCreateDto { // 基础信息 MaterialNo = wmsmaterialstock.MaterialNo, MaterialName = wmsmaterialstock.MaterialName, Remark = wmsmaterialstock.Remark, // 容器信息 ContainerNo = wmsmaterialstock.ContainerNo, ContainerStatus = wmsmaterialstock.ContainerStatus, ContainerType = wmsmaterialstock.ContainerType, // 库存信息 StockNumber = wmsmaterialstock.StockNumber, MaterialBatch = wmsmaterialstock.MaterialBatch, // 供应商信息 SupplierCode = wmsmaterialstock.SupplierCode, MaterialModel = wmsmaterialstock.MaterialModel, // 库位信息 PlaceNo = wmsmaterialstock.PlaceNo, PlaceStatus = wmsmaterialstock.PlaceStatus, StorageTypeNo = wmsmaterialstock.StorageTypeNo, // 库区信息 AreaCode = wmsmaterialstock.AreaCode, AreaName = wmsmaterialstock.AreaName, // 状态信息 IsLock = wmsmaterialstock.IsLock, InStockTime = wmsmaterialstock.InStockTime, }; wmsmaterialstockCreateDtos.Add((wmsmaterialstock.RowIndex, wmsmaterialstockCreateDto)); } } } // 新增 foreach (var wmsmaterialstockDto in wmsmaterialstockCreateDtos) { try { await CreateAsync(wmsmaterialstockDto.Item); } catch (Exception e) { var errorMsg = $"导入失败!配置,第{wmsmaterialstockDto.RowIndex}行:{e.Message},终止导入"; throw new UserFriendlyException(errorMsg); } } // 更新 foreach (var wmsmaterialstockDto in wmsmaterialstockUpdateDtos) { try { await UpdateAsync(wmsmaterialstockDto.Id, wmsmaterialstockDto.Item); } catch (Exception e) { var errorMsg = $"导入失败!配置,第{wmsmaterialstockDto.RowIndex}行:{e.Message},终止导入"; throw new UserFriendlyException(errorMsg); } } } /// public async Task<(Dictionary Sheets, string FileName)> ExportAsync(GetWmsMaterialStocksInput input) { Check.NotNull(input, nameof(input)); if (input.Sorting.IsNullOrWhiteSpace()) { input.Sorting = nameof(WmsMaterialStock.Sort); } var specification = new WmsMaterialStockSpecification(input.Name); var stock = ObjectMapper.Map(input); var list = await _wmsmaterialstockRepository.GetListAsync(stock, input.StartTime, input.EndTime, input.Sorting, input.MaxResultCount, input.SkipCount, input.Filter, specification, includeDetails: true); var result = ObjectMapper.Map, List>(list); var sheets = new Dictionary { ["配置"] = ExportHelper.ConvertListToExportData(result), }; var fileName = result.Count > 1 ? "WmsMaterialStock列表" : result.Count == 1 ? result.First()?.MaterialNo : "WmsMaterialStock模版"; return (sheets, fileName); } /// /// Checks the create or update dto asynchronous. /// /// The input. protected Task CheckCreateOrUpdateDtoAsync(WmsMaterialStockCreateOrUpdateDtoBase input) { Check.NotNull(input, nameof(input)); Check.NotNullOrWhiteSpace(input.MaterialNo, "编号", WmsMaterialStockConsts.MaxCodeLength); Check.NotNullOrWhiteSpace(input.MaterialName, "名称", WmsMaterialStockConsts.MaxNameLength); Check.Length(input.Remark, "备注", WmsMaterialStockConsts.MaxRemarkLength); return Task.CompletedTask; } }