using CMS.Plugin.HIAWms.Application.Contracts.Dtos.WmsTask; using CMS.Plugin.HIAWms.Application.Contracts.Services; using CMS.Plugin.HIAWms.Domain.Shared; using CmsQueryExtensions; using CMS.Plugin.HIAWms.Domain.WmsTask; 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.WmsContainers; using CMS.Plugin.HIAWms.Domain.WmsPlaces; using CMS.Plugin.HIAWms.Domain.Shared.Enums; using CMS.Plugin.HIAWms.Domain.WmsMaterialStocks; using CMS.Plugin.HIAWms.Domain.WmsInOutStockOrder; using CMS.Plugin.HIAWms.Domain.WmsInOutStockOrderDetail; using CMS.Plugin.HIAWms.Application.Contracts.Dtos.WmsInOutStockOrderDetail; using CMS.Plugin.HIAWms.Application.Contracts.Dtos.WmsInOutStockRecord; using Volo.Abp.Uow; using Microsoft.Extensions.DependencyInjection; namespace CMS.Plugin.HIAWms.Application.Implements; /// /// Wms任务管理应用服务 /// public class WmsTaskAppService : CMSPluginAppService, IWmsTaskAppService { private readonly IWmsTaskRepository wmsTaskRepository; private readonly IWmsContainerRepository _wmsContainerRepository; private readonly IWmsPlaceRepository _wmsPlaceRepository; private readonly IWmsMaterialStockRepository _wmsMaterialStockRepository; private readonly IWmsInOutStockOrderRepository _wmsInOutStockOrderRepository; private readonly IWmsInOutStockOrderDetailRepository _wmsInOutStockOrderDetailRepository; private readonly IWmsContainerRepository _wmsContainerRepository1; private readonly IWmsInOutStockOrderDetailAppService _wmsInOutStockOrderDetailAppService; private readonly IWmsInOutStockRecordAppService _wmsInOutStockRecordAppService; private readonly IServiceProvider _serviceProvider; /// /// Initializes a new instance of the class. /// /// The task job repository. public WmsTaskAppService(IWmsTaskRepository _WmsTaskRepository, IWmsContainerRepository wmsContainerRepository, IWmsPlaceRepository wmsPlaceRepository, IWmsMaterialStockRepository wmsMaterialStockRepository, IWmsInOutStockOrderRepository wmsInOutStockOrderRepository, IWmsInOutStockOrderDetailRepository wmsInOutStockOrderDetailRepository , IWmsContainerRepository wmsContainerRepository1, IWmsInOutStockOrderDetailAppService wmsInOutStockOrderDetailAppService, IWmsInOutStockRecordAppService wmsInOutStockRecordAppService, IServiceProvider serviceProvider = null) { wmsTaskRepository = _WmsTaskRepository; _wmsContainerRepository = wmsContainerRepository; _wmsPlaceRepository = wmsPlaceRepository; _wmsMaterialStockRepository = wmsMaterialStockRepository; _wmsInOutStockOrderRepository = wmsInOutStockOrderRepository; _wmsInOutStockOrderDetailRepository = wmsInOutStockOrderDetailRepository; _wmsContainerRepository1 = wmsContainerRepository1; _wmsInOutStockOrderDetailAppService = wmsInOutStockOrderDetailAppService; _wmsInOutStockRecordAppService = wmsInOutStockRecordAppService; _serviceProvider = serviceProvider; } /// /// 获取指定Wms任务管理 /// /// /// public virtual async Task GetAsync(Guid id) { return ObjectMapper.Map(await wmsTaskRepository.GetAsync(id)); } /// /// 分页获取Wms任务管理 /// /// /// public virtual async Task> GetListAsync(GetWmsTaskInput input) { Check.NotNull(input, nameof(input)); if (input.Sorting.IsNullOrWhiteSpace()) { input.Sorting = nameof(WmsTask.Sort); } #region 动态构造查询条件 //动态构造查询条件 var whereConditions = DynamicGetQueryParams(input); #endregion var count = await wmsTaskRepository.GetCountAsync(whereConditions); var list = await wmsTaskRepository.GetListAsync(whereConditions, input.Sorting, input.MaxResultCount, input.SkipCount); return new PagedResultDto(count, ObjectMapper.Map, List>(list)); } /// /// 动态构造查询条件 /// /// 输入参数 /// private FunReturnResultModel>> DynamicGetQueryParams(GetWmsTaskInput 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; } /// /// 新建Wms任务管理 /// /// /// /// public virtual async Task CreateAsync(WmsTaskCreateDto input) { await CheckCreateOrUpdateDtoAsync(input); var exist = await wmsTaskRepository.NameExistAsync(input.TaskNo); if (exist) { throw new UserFriendlyException(L[CMSPluginDomainErrorCodes.NameAlreadyExists, input.TaskNo]); } // 校验托盘是否存在 var existContainer = await _wmsContainerRepository.NameExistAsync(input.ContainerNo); if (existContainer) { throw new UserFriendlyException("托盘不存在,请先添加托盘"); } // 校验物料是否存在 var existSourcePlace = await _wmsPlaceRepository.NameExistAsync(input.SourcePlace); if (existSourcePlace) { throw new UserFriendlyException("起始库位不存在,请先添加库位"); } //校验库位是否存在 var existToPlace = await _wmsPlaceRepository.NameExistAsync(input.ToPlace); if (existToPlace) { throw new UserFriendlyException("目标库位不存在,请先添加库位"); } var maxSort = await wmsTaskRepository.GetMaxSortAsync(); var sort = input.Sort ?? maxSort; var insertObj = ObjectMapper.Map(input); insertObj.Sort = sort; input.MapExtraPropertiesTo(insertObj, MappingPropertyDefinitionChecks.None); insertObj.PlcTaskId = new Random(Guid.NewGuid().GetHashCode()).Next(101, 99999); await wmsTaskRepository.InsertAsync(insertObj); if (input.Sort.HasValue && insertObj.Sort != maxSort) { await AdjustSortAsync(insertObj.Id, insertObj.Sort); } return ObjectMapper.Map(insertObj); } /// /// 更新Wms任务管理 /// /// /// /// /// public virtual async Task UpdateAsync(Guid id, WmsTaskUpdateDto input) { await CheckCreateOrUpdateDtoAsync(input); var updateObj = await wmsTaskRepository.GetAsync(id); var exist = await wmsTaskRepository.NameExistAsync(input.TaskNo, updateObj.Id); if (exist) { throw new UserFriendlyException(L[CMSPluginDomainErrorCodes.NameAlreadyExists, input.TaskNo]); } updateObj.SetConcurrencyStampIfNotNull(input.ConcurrencyStamp); if (input.TaskStatus == Domain.Shared.Enums.WmsTaskStatus.WANCHENG || input.TaskStatus == Domain.Shared.Enums.WmsTaskStatus.QUXIAO) { throw new UserFriendlyException("完成或者取消的任务不允许更改"); } input.MapExtraPropertiesTo(updateObj, MappingPropertyDefinitionChecks.None); updateObj.TaskNo = input.TaskNo; updateObj.TaskType = input.TaskType; updateObj.TaskLevel = input.TaskLevel; updateObj.TaskStatus = input.TaskStatus; updateObj.ContainerNo = input.ContainerNo; updateObj.SourcePlace = input.SourcePlace; updateObj.ToPlace = input.ToPlace; updateObj.Aisle = input.Aisle; updateObj.DodeviceId = input.DodeviceId; updateObj.Dodevicetype = input.Dodevicetype; updateObj.TaskDodeviceStatus = input.TaskDodeviceStatus; updateObj.IsRead = input.IsRead; updateObj.SonTaskType = input.SonTaskType; updateObj.SourceOrderNo = input.SourceOrderNo; updateObj.IsNextTask = input.IsNextTask; updateObj.MutableParam1 = input.MutableParam1; updateObj.MutableParam2 = input.MutableParam2; updateObj.MutableParam3 = input.MutableParam3; updateObj.IsDisabled = input.IsDisabled; await wmsTaskRepository.UpdateAsync(updateObj); return ObjectMapper.Map(updateObj); } /// /// 克隆Wms任务管理 /// /// /// public async Task> CloneAsync(IEnumerable ids) { //var wmsTasks = new List(); //if (ids != null) //{ // var sort = await wmsTaskRepository.GetMaxSortAsync(); // foreach (var id in ids) // { // var WmsTask = await wmsTaskRepository.FindAsync(id); // if (WmsTask != null) // { // var name = WmsTask.Name + WmsTaskConsts.CloneTag; // var notExist = false; // while (!notExist) // { // var exist = await wmsTaskRepository.NameExistAsync(name); // if (exist || wmsTasks.Any(x => x.Name == name)) // { // name += WmsTaskConsts.CloneTag; // continue; // } // notExist = true; // } // //WmsTask = await wmsTaskRepository.InsertAsync(WmsTask.Clone(GuidGenerator.Create(), name, sort++)); // wmsTasks.Add(WmsTask); // } // } //} //return ObjectMapper.Map, List>(wmsTasks); return new List(); } /// /// 删除单个Wms任务管理 /// /// /// public virtual Task DeleteAsync(Guid id) { return wmsTaskRepository.DeleteAsync(id); } /// /// 删除多个Wms任务管理 /// /// /// public async Task DeleteManyAsync(IEnumerable ids) { foreach (var id in ids) { await DeleteAsync(id); } } /// /// 调整排序Wms任务管理 /// /// /// /// public virtual async Task AdjustSortAsync(Guid id, int sort) { var list = await wmsTaskRepository.GetListAsync(null, nameof(WmsTask.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 wmsTaskRepository.UpdateManyAsync(list); } /// /// 导入Wms任务管理 /// /// /// /// public async Task ImportAsync(WmsTasksImportModel input) { Check.NotNull(input, nameof(input)); var wmsTaskCreateDtos = new List<(int RowIndex, WmsTaskCreateDto Item)>(); var wmsTaskUpdateDtos = new List<(int RowIndex, Guid Id, WmsTaskUpdateDto Item)>(); var importItems = input.WmsTasks; if (importItems != null && importItems.Any()) { #region 导入校验 // 判断名称是否重复,并输出第几行重复 var duplicateWmsTasks = importItems.GroupBy(x => x.TaskNo).Where(x => x.Count() > 1).ToList(); if (duplicateWmsTasks?.Any() == true) { var duplicateWmsTaskMsgs = duplicateWmsTasks.Select(x => $"第 {string.Join(",", x.Select(x => x.RowIndex))} 行:{x.Key} 名称重复"); var errorMsg = $"导入失败!配置, {string.Join(",", duplicateWmsTaskMsgs)},终止导入"; throw new UserFriendlyException(errorMsg); } #endregion foreach (var impItem in importItems) { if (impItem.TaskNo.IsNullOrWhiteSpace()) { continue; } if (impItem.TaskNo.IsNullOrWhiteSpace()) { var errorMsg = $"导入失败!配置,第{impItem.RowIndex}行:WmsTask名称不能为空"; throw new UserFriendlyException(errorMsg); } var oldWmsTask = await wmsTaskRepository.FindByNameAsync(impItem.TaskNo); if (oldWmsTask != null) { var wmsTaskUpdateDto = new WmsTaskUpdateDto { TaskNo = impItem.TaskNo, TaskType = impItem.TaskType, TaskLevel = impItem.TaskLevel, TaskStatus = impItem.TaskStatus, ContainerNo = impItem.ContainerNo, SourcePlace = impItem.SourcePlace, ToPlace = impItem.ToPlace, Aisle = impItem.Aisle, DodeviceId = impItem.DodeviceId, Dodevicetype = impItem.Dodevicetype, TaskDodeviceStatus = impItem.TaskDodeviceStatus, IsRead = impItem.IsRead, SonTaskType = impItem.SonTaskType, SourceOrderNo = impItem.SourceOrderNo, IsNextTask = impItem.IsNextTask, MutableParam1 = impItem.MutableParam1, MutableParam2 = impItem.MutableParam2, MutableParam3 = impItem.MutableParam3, IsDisabled = impItem.IsDisabled, }; wmsTaskUpdateDtos.Add((impItem.RowIndex, oldWmsTask.Id, wmsTaskUpdateDto)); } else { var wmsTaskCreateDto = new WmsTaskCreateDto { TaskNo = impItem.TaskNo, TaskType = impItem.TaskType, TaskLevel = impItem.TaskLevel, TaskStatus = impItem.TaskStatus, ContainerNo = impItem.ContainerNo, SourcePlace = impItem.SourcePlace, ToPlace = impItem.ToPlace, Aisle = impItem.Aisle, DodeviceId = impItem.DodeviceId, Dodevicetype = impItem.Dodevicetype, TaskDodeviceStatus = impItem.TaskDodeviceStatus, IsRead = impItem.IsRead, SonTaskType = impItem.SonTaskType, SourceOrderNo = impItem.SourceOrderNo, IsNextTask = impItem.IsNextTask, MutableParam1 = impItem.MutableParam1, MutableParam2 = impItem.MutableParam2, MutableParam3 = impItem.MutableParam3, IsDisabled = impItem.IsDisabled, }; wmsTaskCreateDtos.Add((impItem.RowIndex, wmsTaskCreateDto)); } } } // 新增 foreach (var wmsTaskDto in wmsTaskCreateDtos) { try { await CreateAsync(wmsTaskDto.Item); } catch (Exception e) { var errorMsg = $"导入失败!配置,第{wmsTaskDto.RowIndex}行:{e.Message},终止导入"; throw new UserFriendlyException(errorMsg); } } // 更新 foreach (var wmsTaskDto in wmsTaskUpdateDtos) { try { await UpdateAsync(wmsTaskDto.Id, wmsTaskDto.Item); } catch (Exception e) { var errorMsg = $"导入失败!配置,第{wmsTaskDto.RowIndex}行:{e.Message},终止导入"; throw new UserFriendlyException(errorMsg); } } } /// /// 导出Wms任务管理 /// /// /// public async Task<(Dictionary Sheets, string FileName)> ExportAsync(GetWmsTaskInput input) { Check.NotNull(input, nameof(input)); if (input.Sorting.IsNullOrWhiteSpace()) { input.Sorting = nameof(WmsTask.Sort); } #region 动态构造查询条件 //动态构造查询条件 var whereConditions = DynamicGetQueryParams(input); #endregion var list = await wmsTaskRepository.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 ? "Wms任务管理列表" : result.Count == 1 ? result[0]?.TaskNo : "WmsTask模版"; return (sheets, fileName); } /// /// 校验Wms任务管理,当新建或更新时 /// /// /// protected Task CheckCreateOrUpdateDtoAsync(WmsTaskCreateOrUpdateDtoBase input) { Check.NotNull(input, nameof(input)); Check.NotNullOrWhiteSpace(input.TaskNo, "任务号", 50); Check.NotNull(input.TaskType, "任务类型"); Check.NotNull(input.TaskLevel, "任务等级"); Check.NotNull(input.TaskStatus, "任务状态"); Check.NotNull(input.Dodevicetype, "设备类型"); Check.NotNull(input.ContainerNo, "托盘号"); Check.NotNull(input.SourcePlace, "起始位置"); Check.NotNull(input.ToPlace, "目标未知"); Check.NotNull(input.TaskDodeviceStatus, "设备任务状态"); Check.NotNull(input.IsRead, "WCS是否可以读取"); return Task.CompletedTask; } /// /// 任务强制完成 /// /// /// /// public async Task FinishTaskAsync(WmsTaskStatusDto input) { using var scope = _serviceProvider.CreateScope(); var unitOfWorkManager = scope.ServiceProvider.GetRequiredService(); using var uow = unitOfWorkManager.Begin(requiresNew: true); var task = await wmsTaskRepository.FindByNameAsync(input.TaskNo); if (task == null) { throw new UserFriendlyException("任务不存在"); } if (task.TaskStatus == WmsTaskStatus.WANCHENG || task.TaskStatus == WmsTaskStatus.QUXIAO) { throw new UserFriendlyException("取消或者完成的任务不允许操作"); } task.TaskStatus = WmsTaskStatus.WANCHENG; task.TaskDodeviceStatus = TaskDodeviceStatus.SrmFinish; await wmsTaskRepository.UpdateAsync(task); var place = await _wmsPlaceRepository.FindByNameAsync(task.ToPlace); if (place == null) { throw new UserFriendlyException("目标库位不存在"); } // 更新库存 var stockList = await _wmsMaterialStockRepository.GetStockListAsync(new WmsMaterialStock { MaterialModel = task.MutableParam1, PlaceNo = task.SourcePlace }); if (stockList == null || stockList.Count <= 0) { throw new UserFriendlyException("原库位信息不存在"); } var stock = stockList.FirstOrDefault(); stock.PlaceNo = task.ToPlace; stock.StorageTypeNo = place.StorageTypeNo; stock.InStockTime = DateTime.Now; stock.ContainerNo = "TP" + task.ToPlace; await _wmsMaterialStockRepository.UpdateAsync(stock); place.PlaceStatus = PlaceStatusEnum.CUNHUO; await _wmsPlaceRepository.UpdateAsync(place); var container = await _wmsContainerRepository.FindByNameAsync(stock.ContainerNo); if (container == null) { await _wmsContainerRepository.InsertAsync(new WmsContainer { ContainerNo = stock.ContainerNo, ContainerStatus = ContainerStatusEnum.KUWEI, ContainerType = ContainerTypeEnum.XUNI, }); } else { container.ContainerStatus = ContainerStatusEnum.KUWEI; await _wmsContainerRepository.UpdateAsync(container); } var oldContainer = await _wmsContainerRepository.FindByNameAsync(task.ContainerNo); if (oldContainer != null) { await _wmsContainerRepository.DeleteAsync(oldContainer); } if (!string.IsNullOrEmpty(task.SourceOrderNo)) { // 跟新单据完成数量 var orderNo = await _wmsInOutStockOrderRepository.FindByNameAsync(task.SourceOrderNo); if (orderNo != null) { orderNo.CompleteNumber += 1; orderNo.OrderStatus = OrderStatusEnum.Executing; } if (orderNo.MaterialNumber <= orderNo.CompleteNumber) { orderNo.OrderStatus = OrderStatusEnum.Finish; } await _wmsInOutStockOrderRepository.UpdateAsync(orderNo); // 记录一条详情 var detail = new WmsInOutStockOrderDetailCreateDto { OrderNo = orderNo.OrderNo, OrderType = orderNo.OrderType, MaterialId = stock.MaterialId, MaterialBatch = stock.MaterialBatch, MaterialModel = stock.MaterialModel, MaterialName = stock.MaterialName, MaterialNo = stock.MaterialNo, }; await _wmsInOutStockOrderDetailAppService.CreateAsync(detail); } // 出入库记录 var record = new WmsInOutStockRecordCreateDto { TaskNo = task.TaskNo, OrderNo = task.SourceOrderNo, StockType = task.TaskType == TaskTypeEnum.CHUKU ? StockTypeEnum.OutBound : StockTypeEnum.InBound, ContainerNo = task.ContainerNo, MaterialId = stock.MaterialId, MaterialModel = stock.MaterialModel, MaterialName = stock.MaterialName, MaterialNo = stock.MaterialNo, MaterialBatch = stock.MaterialBatch, SourcePlace = task.SourcePlace, ToPlace = task.ToPlace, OperateTime = DateTime.Now, }; await _wmsInOutStockRecordAppService.CreateAsync(record); await uow.SaveChangesAsync(); await uow.CompleteAsync(); } /// /// 取消任务 /// /// /// /// public async Task CancelTaskAysnc(WmsTaskStatusDto input) { using var scope = _serviceProvider.CreateScope(); var unitOfWorkManager = scope.ServiceProvider.GetRequiredService(); using var uow = unitOfWorkManager.Begin(requiresNew: true); var task = await wmsTaskRepository.FindByNameAsync(input.TaskNo); if (task == null) { throw new UserFriendlyException("任务不存在"); } if (task.TaskStatus == WmsTaskStatus.WANCHENG || task.TaskStatus == WmsTaskStatus.QUXIAO) { throw new UserFriendlyException("取消或者完成的任务不允许操作"); } task.TaskStatus = WmsTaskStatus.QUXIAO; // 更新库存 var stockList = await _wmsMaterialStockRepository.GetStockListAsync(new WmsMaterialStock { MaterialModel = task.MutableParam1, PlaceNo = task.SourcePlace }); if (stockList == null || stockList.Count <= 0) { throw new UserFriendlyException("原库位信息不存在"); } var stock = stockList.FirstOrDefault(); await _wmsMaterialStockRepository.DeleteAsync(stock); if (!string.IsNullOrEmpty(task.SourceOrderNo)) { // 跟新单据完成数量 var orderNo = await _wmsInOutStockOrderRepository.FindByNameAsync(task.SourceOrderNo); if (orderNo != null) { orderNo.CompleteNumber -= 1; orderNo.OrderStatus = OrderStatusEnum.NoStart; } if (orderNo.CompleteNumber > 0) { orderNo.OrderStatus = OrderStatusEnum.Executing; } await _wmsInOutStockOrderRepository.UpdateAsync(orderNo); } await uow.SaveChangesAsync(); await uow.CompleteAsync(); } /// /// 修改目标库位 /// /// /// /// public async Task ChangeTaskToPlaceAsync(ChangeTaskToPlaceInput input) { var task = await wmsTaskRepository.FindByNameAsync(input.TaskNo); if (task == null) { throw new UserFriendlyException("任务信息不存在"); } if (task.TaskStatus != WmsTaskStatus.WEIZHIXING) { throw new UserFriendlyException("已开始或者结束的任务不允许修改"); } var toPlaceInfo = await _wmsPlaceRepository.FindByNameAsync(input.ToPlace); if (toPlaceInfo == null) { throw new UserFriendlyException("目标库位信息不存在"); } if(toPlaceInfo.IsDisabled) { throw new UserFriendlyException("目标库位已被禁用"); } var toplaceStock = await _wmsMaterialStockRepository.GetStockListAsync(new WmsMaterialStock { PlaceNo = input.ToPlace }); if (toplaceStock != null && toplaceStock.Count>0) { var model = toplaceStock.FirstOrDefault(); if (model.MaterialModel != input.MutableParam1) { throw new UserFriendlyException("目标库位型号与当前型号不一致不允许修改"); } } task.ToPlace = input.ToPlace; await wmsTaskRepository.UpdateAsync(task); } }