using CMS.Plugin.HIAWms.Application.Contracts.Dtos.WmsInOutStockOrder; using CMS.Plugin.HIAWms.Application.Contracts.Services; using CMS.Plugin.HIAWms.Domain.Shared; using CmsQueryExtensions; using CMS.Plugin.HIAWms.Domain.WmsInOutStockOrder; using CmsQueryExtensions.Extension; using System.Linq.Expressions; using Volo.Abp; using Volo.Abp.Application.Dtos; using Volo.Abp.Data; using Volo.Abp.ObjectExtending; using Volo.Abp.ObjectMapping; using CMS.Plugin.HIAWms.Domain.WmsMaterials; namespace CMS.Plugin.HIAWms.Application.Implements; /// /// 出入库单据应用服务 /// public class WmsInOutStockOrderAppService : CMSPluginAppService, IWmsInOutStockOrderAppService { private readonly IWmsInOutStockOrderRepository wmsInOutStockOrderRepository; private readonly IWmsMaterialRepository _wmsMaterialRepository; /// /// Initializes a new instance of the class. /// /// The task job repository. public WmsInOutStockOrderAppService(IWmsInOutStockOrderRepository _WmsInOutStockOrderRepository, IWmsMaterialRepository wmsMaterialRepository) { wmsInOutStockOrderRepository = _WmsInOutStockOrderRepository; _wmsMaterialRepository = wmsMaterialRepository; } /// /// 获取指定出入库单据 /// /// /// public virtual async Task GetAsync(Guid id) { return ObjectMapper.Map(await wmsInOutStockOrderRepository.GetAsync(id)); } /// /// 分页获取出入库单据 /// /// /// public virtual async Task> GetListAsync(GetWmsInOutStockOrderInput input) { Check.NotNull(input, nameof(input)); if (input.Sorting.IsNullOrWhiteSpace()) { input.Sorting = nameof(WmsInOutStockOrder.Sort); } #region 动态构造查询条件 //动态构造查询条件 var whereConditions = DynamicGetQueryParams(input); #endregion var count = await wmsInOutStockOrderRepository.GetCountAsync(whereConditions); var list = await wmsInOutStockOrderRepository.GetListAsync(whereConditions, input.Sorting, input.MaxResultCount, input.SkipCount); return new PagedResultDto(count, ObjectMapper.Map, List>(list)); } /// /// 动态构造查询条件 /// /// 输入参数 /// private FunReturnResultModel>> DynamicGetQueryParams(GetWmsInOutStockOrderInput input) { //动态构造查询条件 var whereConditions = WhereConditionsExtensions.GetWhereConditions(input); if (!whereConditions.IsSuccess) { throw new Exception("动态构造查询条件失败:" + whereConditions.ErrMsg); } //也可再次自定义构建查询条件 Expression> extendExpression = a => a.IsDeleted == false; // 使用 System.Linq.PredicateBuilder 的 And var pres = (System.Linq.Expressions.Expression>)(whereConditions.data); whereConditions.data = System.Linq.PredicateBuilder.And(pres, extendExpression); return whereConditions; } /// /// 新建出入库单据 /// /// /// /// public virtual async Task CreateAsync(WmsInOutStockOrderCreateDto input) { await CheckCreateOrUpdateDtoAsync(input); var material = await _wmsMaterialRepository.FindByNameAsync(input.MaterialNo); if (material == null) { throw new UserFriendlyException("物料信息不存在"); } var exist = await wmsInOutStockOrderRepository.NameExistAsync(input.OrderNo); if (exist) { throw new UserFriendlyException(L[CMSPluginDomainErrorCodes.NameAlreadyExists, input.OrderNo]); } var maxSort = await wmsInOutStockOrderRepository.GetMaxSortAsync(); var sort = input.Sort ?? maxSort; var maxPriority = await wmsInOutStockOrderRepository.GetMaxPriorityAsync(); var priority = input.Priority > 0 ? input.Priority : maxPriority; var insertObj = ObjectMapper.Map(input); insertObj.MaterialName = material.MaterialName; insertObj.MaterialModel = material.MaterialModel; insertObj.OrderStatus = Domain.Shared.Enums.OrderStatusEnum.NoStart; var type = "RK-"; insertObj.StockType = Domain.Shared.Enums.StockTypeEnum.InBound; if (input.OrderType == Domain.Shared.Enums.OrderTypeEnum.PRODUCTCALL || input.OrderType == Domain.Shared.Enums.OrderTypeEnum.PERSONOT) { type = "CK-"; insertObj.StockType = Domain.Shared.Enums.StockTypeEnum.OutBound; } insertObj.OrderNo = type + DateTime.Now.ToString("yyyyMMddHHmmssfff"); insertObj.Sort = sort; insertObj.Priority = priority; input.MapExtraPropertiesTo(insertObj, MappingPropertyDefinitionChecks.None); await wmsInOutStockOrderRepository.InsertAsync(insertObj); //if (input.Sort.HasValue && insertObj.Sort != maxSort) //{ // await AdjustSortAsync(insertObj.Id, insertObj.Sort); //} return ObjectMapper.Map(insertObj); } /// /// 更新出入库单据 /// /// /// /// /// public virtual async Task UpdateAsync(Guid id, WmsInOutStockOrderUpdateDto input) { await CheckCreateOrUpdateDtoAsync(input); var updateObj = await wmsInOutStockOrderRepository.GetAsync(id); var exist = await wmsInOutStockOrderRepository.NameExistAsync(input.OrderNo, updateObj.Id); if (exist) { throw new UserFriendlyException(L[CMSPluginDomainErrorCodes.NameAlreadyExists, input.OrderNo]); } updateObj.SetConcurrencyStampIfNotNull(input.ConcurrencyStamp); input.MapExtraPropertiesTo(updateObj, MappingPropertyDefinitionChecks.None); updateObj.OrderNo = input.OrderNo; updateObj.OrderStatus = input.OrderStatus; updateObj.MaterialName = input.MaterialName; updateObj.MaterialNo = input.MaterialNo; updateObj.MaterialModel = input.MaterialModel; updateObj.MaterialBatch = input.MaterialBatch; updateObj.OrderType = input.OrderType; updateObj.StockType = input.StockType; updateObj.MaterialNumber = input.MaterialNumber; updateObj.DistributeNumber = input.DistributeNumber; updateObj.CompleteNumber = input.CompleteNumber; updateObj.Priority = input.Priority; updateObj.PlanNo = input.PlanNo; updateObj.OperateTime = input.OperateTime; updateObj.Remark = input.Remark; updateObj.IsDisabled = input.IsDisabled; await wmsInOutStockOrderRepository.UpdateAsync(updateObj); return ObjectMapper.Map(updateObj); } /// /// 克隆出入库单据 /// /// /// public async Task> CloneAsync(IEnumerable ids) { //var wmsInOutStockOrders = new List(); //if (ids != null) //{ // var sort = await wmsInOutStockOrderRepository.GetMaxSortAsync(); // foreach (var id in ids) // { // var WmsInOutStockOrder = await wmsInOutStockOrderRepository.FindAsync(id); // if (WmsInOutStockOrder != null) // { // var name = WmsInOutStockOrder.Name + WmsInOutStockOrderConsts.CloneTag; // var notExist = false; // while (!notExist) // { // var exist = await wmsInOutStockOrderRepository.NameExistAsync(name); // if (exist || wmsInOutStockOrders.Any(x => x.Name == name)) // { // name += WmsInOutStockOrderConsts.CloneTag; // continue; // } // notExist = true; // } // //WmsInOutStockOrder = await wmsInOutStockOrderRepository.InsertAsync(WmsInOutStockOrder.Clone(GuidGenerator.Create(), name, sort++)); // wmsInOutStockOrders.Add(WmsInOutStockOrder); // } // } //} //return ObjectMapper.Map, List>(wmsInOutStockOrders); return new List(); } /// /// 删除单个出入库单据 /// /// /// public virtual async Task DeleteAsync(Guid id) { var order = await wmsInOutStockOrderRepository.GetAsync(id); if(order != null && order.OrderStatus != Domain.Shared.Enums.OrderStatusEnum.NoStart) { throw new UserFriendlyException("只能删除未开始的单据"); } await wmsInOutStockOrderRepository.DeleteAsync(id); } /// /// 删除多个出入库单据 /// /// /// public async Task DeleteManyAsync(IEnumerable ids) { foreach (var id in ids) { await DeleteAsync(id); } } /// /// 调整排序出入库单据 /// /// /// /// public virtual async Task AdjustSortAsync(Guid id, int sort) { var list = await wmsInOutStockOrderRepository.GetListAsync(null, nameof(WmsInOutStockOrder.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 wmsInOutStockOrderRepository.UpdateManyAsync(list); } /// /// 导入出入库单据 /// /// /// /// public async Task ImportAsync(WmsInOutStockOrdersImportModel input) { Check.NotNull(input, nameof(input)); var wmsInOutStockOrderCreateDtos = new List<(int RowIndex, WmsInOutStockOrderCreateDto Item)>(); var wmsInOutStockOrderUpdateDtos = new List<(int RowIndex, Guid Id, WmsInOutStockOrderUpdateDto Item)>(); var importItems = input.WmsInOutStockOrders; if (importItems != null && importItems.Any()) { #region 导入校验 // 判断名称是否重复,并输出第几行重复 var duplicateWmsInOutStockOrders = importItems.GroupBy(x => x.OrderNo).Where(x => x.Count() > 1).ToList(); if (duplicateWmsInOutStockOrders?.Any() == true) { var duplicateWmsInOutStockOrderMsgs = duplicateWmsInOutStockOrders.Select(x => $"第 {string.Join(",", x.Select(x => x.RowIndex))} 行:{x.Key} 名称重复"); var errorMsg = $"导入失败!配置, {string.Join(",", duplicateWmsInOutStockOrderMsgs)},终止导入"; throw new UserFriendlyException(errorMsg); } #endregion foreach (var impItem in importItems) { if (impItem.OrderNo.IsNullOrWhiteSpace()) { continue; } if (impItem.OrderNo.IsNullOrWhiteSpace()) { var errorMsg = $"导入失败!配置,第{impItem.RowIndex}行:WmsInOutStockOrder名称不能为空"; throw new UserFriendlyException(errorMsg); } var oldWmsInOutStockOrder = await wmsInOutStockOrderRepository.FindByNameAsync(impItem.OrderNo); if (oldWmsInOutStockOrder != null) { var wmsInOutStockOrderUpdateDto = new WmsInOutStockOrderUpdateDto { OrderNo = impItem.OrderNo, OrderStatus = impItem.OrderStatus, MaterialName = impItem.MaterialName, MaterialNo = impItem.MaterialNo, MaterialModel = impItem.MaterialModel, MaterialBatch = impItem.MaterialBatch, OrderType = impItem.OrderType, StockType = impItem.StockType, MaterialNumber = impItem.MaterialNumber, DistributeNumber = impItem.DistributeNumber, CompleteNumber = impItem.CompleteNumber, Priority = impItem.Priority, PlanNo = impItem.PlanNo, OperateTime = impItem.OperateTime, Remark = impItem.Remark, IsDisabled = impItem.IsDisabled, }; wmsInOutStockOrderUpdateDtos.Add((impItem.RowIndex, oldWmsInOutStockOrder.Id, wmsInOutStockOrderUpdateDto)); } else { var wmsInOutStockOrderCreateDto = new WmsInOutStockOrderCreateDto { OrderNo = impItem.OrderNo, OrderStatus = impItem.OrderStatus, MaterialName = impItem.MaterialName, MaterialNo = impItem.MaterialNo, MaterialModel = impItem.MaterialModel, MaterialBatch = impItem.MaterialBatch, OrderType = impItem.OrderType, StockType = impItem.StockType, MaterialNumber = impItem.MaterialNumber, DistributeNumber = impItem.DistributeNumber, CompleteNumber = impItem.CompleteNumber, Priority = impItem.Priority, PlanNo = impItem.PlanNo, OperateTime = impItem.OperateTime, Remark = impItem.Remark, IsDisabled = impItem.IsDisabled, }; wmsInOutStockOrderCreateDtos.Add((impItem.RowIndex, wmsInOutStockOrderCreateDto)); } } } // 新增 foreach (var wmsInOutStockOrderDto in wmsInOutStockOrderCreateDtos) { try { await CreateAsync(wmsInOutStockOrderDto.Item); } catch (Exception e) { var errorMsg = $"导入失败!配置,第{wmsInOutStockOrderDto.RowIndex}行:{e.Message},终止导入"; throw new UserFriendlyException(errorMsg); } } // 更新 foreach (var wmsInOutStockOrderDto in wmsInOutStockOrderUpdateDtos) { try { await UpdateAsync(wmsInOutStockOrderDto.Id, wmsInOutStockOrderDto.Item); } catch (Exception e) { var errorMsg = $"导入失败!配置,第{wmsInOutStockOrderDto.RowIndex}行:{e.Message},终止导入"; throw new UserFriendlyException(errorMsg); } } } /// /// 导出出入库单据 /// /// /// public async Task<(Dictionary Sheets, string FileName)> ExportAsync(GetWmsInOutStockOrderInput input) { Check.NotNull(input, nameof(input)); if (input.Sorting.IsNullOrWhiteSpace()) { input.Sorting = nameof(WmsInOutStockOrder.Sort); } #region 动态构造查询条件 //动态构造查询条件 var whereConditions = DynamicGetQueryParams(input); #endregion var list = await wmsInOutStockOrderRepository.GetListAsync(whereConditions, input.Sorting, input.MaxResultCount, input.SkipCount, includeDetails: true); var result = ObjectMapper.Map, List>(list); var sheets = new Dictionary { ["配置"] = ExportHelper.ConvertListToExportData(result), }; var fileName = result.Count > 1 ? "出入库单据列表" : result.Count == 1 ? result[0]?.OrderNo : "WmsInOutStockOrder模版"; return (sheets, fileName); } /// /// 校验出入库单据,当新建或更新时 /// /// /// protected Task CheckCreateOrUpdateDtoAsync(WmsInOutStockOrderCreateOrUpdateDtoBase input) { Check.NotNull(input, nameof(input)); Check.NotNullOrWhiteSpace(input.MaterialNo, "物料编号", 50); Check.NotNullOrWhiteSpace(input.MaterialBatch, "批次号", 50); Check.NotNull(input.OrderType, "单据类型"); Check.NotNull(input.StockType, "操作类型"); Check.NotNull(input.MaterialNumber, "单据数量"); return Task.CompletedTask; } }