#region << 版 本 注 释 >> /*-------------------------------------------------------------------- |* 版权所有 (c) 2026 WenJY 保留所有权利。 |* CLR版本:4.0.30319.42000 |* 机器名称:Mr.Wen's MacBook Pro |* 命名空间:Sln.Wcs.Business |* 唯一标识:7E8A9B2C-3D4F-5E6A-7B8C-9D0E1F2A3B4C |* |* 创建者:WenJY |* 电子邮箱: |* 创建时间:2026-05-15 15:30:00 |* 版本:V1.0.0 |* 描述:通用仓储任务业务处理类,支持入库/出库,包材/成品/托盘分类 |* |*-------------------------------------------------------------------- |* 修改人: |* 时间: |* 修改说明: |* |* 版本:V1.0.0 |*--------------------------------------------------------------------*/ #endregion << 版 本 注 释 >> using System.Linq.Expressions; using Sln.Wcs.Business.Domain.Dto.CreateTask; using Sln.Wcs.Business.Domain.Dto.FilterLocation; using Sln.Wcs.Business.Domain.Dto.SaveTask; using Sln.Wcs.Business.Domain.Dto.ValidateMaterial; using Sln.Wcs.Business.Domain.Enum; using Sln.Wcs.Business.Domain.Model.CreateTask; using Sln.Wcs.Business.Domain.Model.FilterLocation; using Sln.Wcs.Business.Domain.Model.SaveTask; using Sln.Wcs.Business.Util; using Sln.Wcs.Model.Domain; using Sln.Wcs.Repository.service; namespace Sln.Wcs.Business; /// /// 通用仓储任务业务处理类 /// 支持扩展点:子类可重写虚方法实现特定业务逻辑 /// public class StoreTaskBusiness : EntityWrapper { private readonly IBasePathInfoService _basePathInfoService; private readonly ILiveTaskQueueService _liveTaskQueueService; private readonly IBaseStoreInfoService _baseStoreInfoService; /// /// 构造函数 /// /// 路径服务 /// 任务队列服务 /// 仓库服务 public StoreTaskBusiness( IBasePathInfoService basePathInfoService, ILiveTaskQueueService liveTaskQueueService, IBaseStoreInfoService baseStoreInfoService) { _basePathInfoService = basePathInfoService; _liveTaskQueueService = liveTaskQueueService; _baseStoreInfoService = baseStoreInfoService; } #region 虚方法 - 供子类重写的扩展点 /// /// 校验物料(可被子类重写) /// public virtual ValidateMaterialResultDto ValidateMaterial(ValidateMaterialDto validateMaterialDto) { throw new NotImplementedException(); } /// /// 创建任务(可被子类重写) /// /// 创建任务参数(包含taskType和taskCategory) public virtual CreateTaskResultDto CreateTask(CreateTaskDto createTaskDto) { CreateTaskResultDto resultDto = new CreateTaskResultDto(); try { ValidateCreateTaskParams(createTaskDto); BasePathInfo pathInfo = GetPathInfo(createTaskDto); string taskCode = GenerateTaskCode(); List taskDetails = pathInfo.pathDetails .Select(item => LiveTaskDetailWrapper(taskCode, createTaskDto, item)) .ToList(); var taskQueue = LiveTaskQueueWrapper(taskCode, createTaskDto, pathInfo); taskQueue.taskSteps = taskDetails.Count; taskQueue.taskDetails = taskDetails; resultDto.code = Domain.Enum.BusinessStatusEnum.成功; resultDto.msg = $"{GetCategoryName(createTaskDto.taskCategory)}{GetTaskTypeName(createTaskDto.taskType)}任务创建成功:{taskCode};关联路径:{pathInfo.pathName}"; resultDto.data = new CreateTaskResultModel() { taskCode = taskCode, taskQueue = taskQueue, taskDetails = taskDetails, }; } catch (Exception e) { resultDto.code = Domain.Enum.BusinessStatusEnum.方法执行异常; resultDto.msg = e.Message; } return resultDto; } /// /// 筛选库位(可被子类重写) /// /// 筛选库位参数(包含taskType和taskCategory) public virtual FilterLocationResultDto FilterLocation(FilterLocationDto filterLocationDto) { FilterLocationResultDto resultDto = new FilterLocationResultDto(); try { ValidateFilterLocationParams(filterLocationDto); int locationStatus = filterLocationDto.taskType == TaskTypeEnum.InStore ? 0 : 1; Expression> storeWhere = GetStoreWhere(filterLocationDto.taskType, filterLocationDto.taskCategory); Expression> locationWhere = GetLocationWhere(filterLocationDto, locationStatus); List storeInfos = _baseStoreInfoService.GetBasePathInfo(storeWhere, locationWhere); BaseStoreInfo? storeInfo = storeInfos .Where(s => s.locationInfos.Count > 0) .OrderBy(x => x.storeCode) .FirstOrDefault() ?? throw new ArgumentNullException($"未获取到可用仓库"); BaseLocationInfo? locationInfo = storeInfo.locationInfos .OrderBy(x => x.locationRows) .ThenBy(x => x.locationColumns) .ThenBy(x => x.locationLayers) .FirstOrDefault() ?? throw new ArgumentNullException($"目标仓库:{storeInfo.storeName}中未获取到可用库位"); resultDto.code = Domain.Enum.BusinessStatusEnum.成功; resultDto.msg = "执行完成"; resultDto.data = new FilterLocationResultModel() { storeInfo = storeInfo, locationInfos = storeInfo.locationInfos, locationInfo = locationInfo, }; } catch (Exception e) { resultDto.code = Domain.Enum.BusinessStatusEnum.方法执行异常; resultDto.msg = e.Message; } return resultDto; } /// /// 保存任务(可被子类重写) /// /// 保存任务参数 public virtual SaveTaskResultDto SaveTask(SaveTaskDto saveTaskDto) { SaveTaskResultDto resultDto = new SaveTaskResultDto(); try { var inRes = _liveTaskQueueService.InsertTaskQueue(saveTaskDto.taskQueue); resultDto.code = Domain.Enum.BusinessStatusEnum.成功; resultDto.msg = "执行完成"; resultDto.data = new SaveTaskResultModel() { isRes = inRes }; } catch (Exception e) { resultDto.code = Domain.Enum.BusinessStatusEnum.方法执行异常; resultDto.msg = e.Message; } return resultDto; } #endregion #region 受保护虚方法 - 可被子类定制 /// /// 校验创建任务参数(可被子类重写添加额外校验) /// protected virtual void ValidateCreateTaskParams(CreateTaskDto createTaskDto) { if (string.IsNullOrEmpty(createTaskDto.materialCode)) { throw new InvalidOperationException($"物料编号不允许为 NULL"); } if (string.IsNullOrEmpty(createTaskDto.palletBarcode)) { throw new InvalidOperationException($"{GetCategoryName(createTaskDto.taskCategory)}条码不允许为 NULL"); } if (string.IsNullOrEmpty(createTaskDto.startPoint) || string.IsNullOrEmpty(createTaskDto.endPoint)) { throw new InvalidOperationException($"起始位置、终点位置不允许为 NULL"); } } /// /// 校验筛选库位参数(可被子类重写添加额外校验) /// protected virtual void ValidateFilterLocationParams(FilterLocationDto filterLocationDto) { if (string.IsNullOrEmpty(filterLocationDto.materialCode)) { throw new InvalidOperationException($"物料编号不允许为 NULL"); } } /// /// 获取路径信息(可被子类重写定制路径查询逻辑) /// protected virtual BasePathInfo GetPathInfo(CreateTaskDto createTaskDto) { Expression> exp = x => x.startPoint == createTaskDto.startPoint && x.endPoint == createTaskDto.endPoint && x.pathType == (int)createTaskDto.taskType && x.pathCategory == (int)createTaskDto.taskCategory; return _basePathInfoService.GetBasePathInfo(exp) .FirstOrDefault() ?? throw new InvalidOperationException($"{GetCategoryName(createTaskDto.taskCategory)}{GetTaskTypeName(createTaskDto.taskType)}输送路径为 NULL"); } /// /// 生成任务编号(可被子类重写定制生成规则) /// protected virtual string GenerateTaskCode() { return DateTime.Now.ToString("yyyyMMddHHmmss") + new Random().Next(10, 99); } /// /// 获取仓库查询条件(可被子类重写) /// protected virtual Expression> GetStoreWhere(TaskTypeEnum taskType, TaskCategoryEnum taskCategory) { return x => x.storeType == (int)taskCategory && x.isFlag == 1; } /// /// 获取库位查询条件(可被子类重写) /// protected virtual Expression> GetLocationWhere(FilterLocationDto filterLocationDto, int locationStatus) { return x => x.materialCode == filterLocationDto.materialCode && x.locationStatus == locationStatus && x.isFlag == 1; } #endregion /// /// 获取分类名称 /// private string GetCategoryName(TaskCategoryEnum taskCategory) { return taskCategory switch { TaskCategoryEnum.Material => "包材", TaskCategoryEnum.Product => "成品", TaskCategoryEnum.Pallet => "托盘", _ => "未知" }; } /// /// 获取任务类型名称 /// private string GetTaskTypeName(TaskTypeEnum taskType) { return taskType switch { TaskTypeEnum.InStore => "入库", TaskTypeEnum.OutStore => "出库", _ => "未知" }; } }