using Mapster; using MapsterMapper; using Microsoft.Extensions.Configuration; using SqlSugar; using System.DirectoryServices.Protocols; using System.Text.Json; using WIDESEA_Common.Constants; using WIDESEA_Common.LocationEnum; using WIDESEA_Common.StockEnum; using WIDESEA_Common.TaskEnum; using WIDESEA_Common.WareHouseEnum; using WIDESEA_Core; using WIDESEA_Core.BaseRepository; using WIDESEA_Core.BaseServices; using WIDESEA_Core.Core; using WIDESEA_Core.Enums; using WIDESEA_Core.Helper; using WIDESEA_DTO.GradingMachine; using WIDESEA_DTO.MES; using WIDESEA_DTO.Stock; using WIDESEA_DTO.Task; using WIDESEA_IBasicService; using WIDESEA_IStockService; using WIDESEA_ITaskInfoService; using WIDESEA_Model.Models; namespace WIDESEA_TaskInfoService { public partial class TaskService { #region WCS逻辑处理 /// /// 创建任务(组盘入库任务、空托盘回库任务) /// public async Task CreateTaskInboundAsync(CreateTaskDto taskDto) { try { WebResponseContent content = await GetTaskByPalletCodeAsync(taskDto.PalletCode); if (content.Status) { return content; } if (string.IsNullOrWhiteSpace(taskDto.PalletCode) || string.IsNullOrWhiteSpace(taskDto.Roadway)) { return WebResponseContent.Instance.Error("无效的任务详情"); } if (taskDto.TaskType != TaskTypeEnum.Inbound && taskDto.TaskType != TaskTypeEnum.InEmpty) { return WebResponseContent.Instance.Error("无效的任务详情"); } // 使用 switch 表达式映射任务类型 int taskInboundType = taskDto.TaskType switch { TaskTypeEnum.Inbound => TaskInboundTypeEnum.Inbound.GetHashCode(), TaskTypeEnum.InEmpty => TaskInboundTypeEnum.InEmpty.GetHashCode(), _ => 0 // 理论上不会走到这里,因为已经验证过了 }; var task = new Dt_Task { TaskNum = await BaseDal.GetTaskNo(), PalletCode = taskDto.PalletCode, PalletType = taskDto.PalletType, Roadway = taskDto.Roadway, TaskType = taskInboundType, TaskStatus = TaskInStatusEnum.InNew.GetHashCode(), SourceAddress = taskDto.SourceAddress, TargetAddress = taskDto.TargetAddress, CurrentAddress = taskDto.SourceAddress, NextAddress = taskDto.TargetAddress, WarehouseId = taskDto.WarehouseId, Grade = 1, Creater = "system" }; var result = await Repository.AddDataAsync(task) > 0; if (!result) return WebResponseContent.Instance.Error("任务创建失败"); var wmstaskDto = _mapper.Map(task); return WebResponseContent.Instance.OK("任务创建成功", wmstaskDto); } catch (Exception ex) { return WebResponseContent.Instance.Error($"任务创建失败: {ex.Message}"); } } /// /// 根据指定的任务详情异步创建新的出库任务 /// public async Task CreateTaskOutboundAsync(CreateTaskDto taskDto) { try { var stockResult = await _stockInfoService.GetStockInfoAsync(taskDto.WarehouseId); if (stockResult == null || !stockResult.Any()) return WebResponseContent.Instance.Error("未找到库存信息"); var taskList = stockResult.Select(item => new Dt_Task { WarehouseId = item.WarehouseId, PalletCode = item.PalletCode, PalletType = item.PalletType, SourceAddress = item.LocationCode, TargetAddress = taskDto.TargetAddress, Roadway = item.LocationDetails.RoadwayNo, TaskType = TaskTypeEnum.Outbound.GetHashCode(), TaskStatus = TaskStatusEnum.New.GetHashCode(), Grade = 1, TaskNum = 0, CurrentAddress = item.LocationCode, NextAddress = taskDto.TargetAddress, Creater = "system", }).ToList(); var result = await BaseDal.AddDataAsync(taskList) > 0; var wmstaskDto = result ? _mapper.Map(taskList) : null; return WebResponseContent.Instance.OK(result ? "任务创建成功" : "任务创建失败", wmstaskDto ?? new object()); } catch (Exception ex) { return WebResponseContent.Instance.Error($"任务创建失败: {ex.Message}"); } } /// /// 获取可入库货位 /// public async Task GetTasksLocationAsync(CreateTaskDto taskDto) { try { var task = await BaseDal.QueryFirstAsync(s => s.PalletCode == taskDto.PalletCode); if (task == null) return WebResponseContent.Instance.Error("未找到对应的任务"); var locationInfo = await _locationInfoService.GetLocationInfo(task.Roadway); if (locationInfo == null) return WebResponseContent.Instance.Error("未找到对应的货位"); return await ExecuteWithinTransactionAsync(async () => { locationInfo.LocationStatus = LocationStatusEnum.FreeLock.GetHashCode(); task.CurrentAddress = task.SourceAddress; task.NextAddress = locationInfo.LocationCode; task.TargetAddress = locationInfo.LocationCode; task.TaskStatus = TaskInStatusEnum.Line_InFinish.GetHashCode(); var updateTaskResult = await BaseDal.UpdateDataAsync(task); var updateLocationResult = await _locationInfoService.UpdateLocationInfoAsync(locationInfo); if (!updateTaskResult || !updateLocationResult) { return WebResponseContent.Instance.Error("任务更新失败"); } return WebResponseContent.Instance.OK("任务更新成功", locationInfo.LocationCode); }); } catch (Exception ex) { return WebResponseContent.Instance.Error($"获取任务失败: {ex.Message}"); } } /// /// 入库任务完成:添加库存,修改货位状态,删除任务数据,添加历史任务数据 /// public async Task InboundFinishTaskAsync(CreateTaskDto taskDto) { try { var task = await BaseDal.QueryFirstAsync(s => s.PalletCode == taskDto.PalletCode); if (task == null) return WebResponseContent.Instance.Error("未找到对应的任务"); var location = await _locationInfoService.GetLocationInfo(task.Roadway, task.TargetAddress); if (location == null) return WebResponseContent.Instance.Error("未找到对应的货位"); var stockInfo = await _stockInfoService.GetStockInfoAsync(taskDto.PalletCode); if (stockInfo == null) return WebResponseContent.Instance.Error("未找到对应库存信息"); // 判断是不是极卷库任务 if (taskDto.WarehouseId == (int)WarehouseEnum.FJ1 || taskDto.WarehouseId == (int)WarehouseEnum.ZJ1) { return await CompleteAgvInboundTaskAsync(taskDto); } return await ExecuteWithinTransactionAsync(async () => { WebResponseContent content = new WebResponseContent(); stockInfo.LocationCode = location.LocationCode; stockInfo.LocationId = location.Id; var now = DateTime.Now; if (task.Roadway.Contains("GW")) { if (stockInfo.Remark.IsNullOrEmpty()) { stockInfo.OutboundDate = now.AddHours(OutboundTimeConstants.OUTBOUND_HOURS_GW1_FIRST); stockInfo.Remark = StockRemarkConstants.GW1; } else if (stockInfo.Remark == StockRemarkConstants.GW1) { stockInfo.OutboundDate = now.AddHours(OutboundTimeConstants.OUTBOUND_HOURS_GW1_SECOND); stockInfo.Remark = StockRemarkConstants.GW2; } else { stockInfo.OutboundDate = now.AddHours(OutboundTimeConstants.OUTBOUND_HOURS_GW1_FIRST); } } else if (task.Roadway.Contains("CW")) { if (stockInfo.Remark == StockRemarkConstants.GW2) { stockInfo.OutboundDate = now.AddHours(OutboundTimeConstants.OUTBOUND_HOURS_CW1); stockInfo.Remark = StockRemarkConstants.CW1; } else { stockInfo.OutboundDate = now.AddHours(OutboundTimeConstants.OUTBOUND_HOURS_CW1); } } else { stockInfo.OutboundDate = now; } stockInfo.StockStatus = StockStatusEmun.入库完成.GetHashCode(); location.LocationStatus = LocationStatusEnum.InStock.GetHashCode(); var updateLocationResult = await _locationInfoService.UpdateLocationInfoAsync(location); var updateStockResult = await _stockInfoService.UpdateStockAsync(stockInfo); if (!updateLocationResult || !updateStockResult) return WebResponseContent.Instance.Error("任务完成失败"); // 调用MES托盘进站 //var inboundRequest = new InboundInContainerRequest //{ // EquipmentCode = "STK-GROUP-001", // ResourceCode = "STK-GROUP-001", // LocalTime = DateTime.Now, // ContainerCode = taskDto.PalletCode //}; //var inboundResult = _mesService.InboundInContainer(inboundRequest); //if (inboundResult == null || inboundResult.Data == null || !inboundResult.Data.IsSuccess) //{ // return content.Error($"任务完成失败:MES进站失败: {inboundResult?.Data?.Msg ?? inboundResult?.ErrorMessage ?? "未知错误"}"); //} return await CompleteTaskAsync(task, "入库完成"); }); } catch (Exception ex) { return WebResponseContent.Instance.Error($"完成任务失败: {ex.Message}"); } } /// /// 出库任务完成 :修改库存,修改货位状态,删除任务数据,添加历史任务数据 /// public async Task OutboundFinishTaskAsync(CreateTaskDto taskDto) { try { var task = await BaseDal.QueryFirstAsync(s => s.PalletCode == taskDto.PalletCode); if (task == null) return WebResponseContent.Instance.Error("未找到对应的任务"); var location = await _locationInfoService.GetLocationInfo(task.Roadway, task.SourceAddress); if (location == null) return WebResponseContent.Instance.Error("未找到对应的货位"); var stockInfo = await _stockInfoService.GetStockInfoAsync(taskDto.PalletCode); if (stockInfo == null) return WebResponseContent.Instance.Error("未找到对应库存信息"); // 判断是不是极卷库任务 if (taskDto.WarehouseId == (int)WarehouseEnum.FJ1 || taskDto.WarehouseId == (int)WarehouseEnum.ZJ1) { OutTaskCompleteDto outTaskCompleteDto = new OutTaskCompleteDto() { TaskId = task.OrderNo ?? string.Empty, DevId = task.TargetAddress ?? string.Empty, ReqTime = DateTime.Now.ToString() }; return await OutTaskComplete(outTaskCompleteDto); } WebResponseContent content = new WebResponseContent(); return await ExecuteWithinTransactionAsync(async () => { stockInfo.LocationId = 0; stockInfo.LocationCode = string.Empty; stockInfo.OutboundDate = DateTime.Now; location.LocationStatus = LocationStatusEnum.Free.GetHashCode(); var updateLocationResult = await _locationInfoService.UpdateLocationInfoAsync(location); var updateStockResult = await _stockInfoService.UpdateStockAsync(stockInfo); if (!updateLocationResult || !updateStockResult) return WebResponseContent.Instance.Error("任务完成失败"); // 高温2号出库到CWSC1时,自动创建入库任务到常温1号巷道 WMSTaskDTO? inboundTaskDto = null; if (task.TargetAddress == TaskAddressConstants.GW2_ADDRESS) { var inboundTask = new Dt_Task { TaskNum = await BaseDal.GetTaskNo(), PalletCode = task.PalletCode, PalletType = task.PalletType, Roadway = "CW1", TaskType = TaskInboundTypeEnum.Inbound.GetHashCode(), TaskStatus = TaskInStatusEnum.InNew.GetHashCode(), SourceAddress = task.TargetAddress, TargetAddress = task.TargetAddress, CurrentAddress = task.TargetAddress, NextAddress = task.TargetAddress, WarehouseId = (int)WarehouseEnum.CW1, Grade = 1, Creater = "system_auto" }; await Repository.AddDataAsync(inboundTask); inboundTaskDto = _mapper.Map(inboundTask); } var completeResult = await CompleteTaskAsync(task, "出库完成"); if (!completeResult.Status) return completeResult; // 返回入库任务信息(如果有) if (inboundTaskDto != null) { return content.OK("出库完成,已创建入库任务", inboundTaskDto); } return content.OK("出库完成"); }); } catch (Exception ex) { return WebResponseContent.Instance.Error($"完成任务失败: {ex.Message}"); } } /// /// 移库任务完成:修改库存位置与状态,修改源/目标货位状态,删除任务数据 /// public async Task RelocationFinishTaskAsync(CreateTaskDto taskDto) { try { var task = await BaseDal.QueryFirstAsync(s => s.PalletCode == taskDto.PalletCode && s.TaskType == TaskRelocationTypeEnum.Relocation.GetHashCode()); if (task == null) return WebResponseContent.Instance.Error("未找到对应的移库任务"); var sourceLocation = await _locationInfoService.GetLocationInfo(task.Roadway, task.SourceAddress); if (sourceLocation == null) return WebResponseContent.Instance.Error("未找到移库源货位"); var targetLocation = await _locationInfoService.GetLocationInfo(task.Roadway, task.TargetAddress); if (targetLocation == null) return WebResponseContent.Instance.Error("未找到移库目标货位"); var stockInfo = await _stockInfoService.GetStockInfoAsync(taskDto.PalletCode); if (stockInfo == null) return WebResponseContent.Instance.Error("未找到对应库存信息"); return await ExecuteWithinTransactionAsync(async () => { stockInfo.LocationCode = targetLocation.LocationCode; stockInfo.LocationId = targetLocation.Id; stockInfo.StockStatus = StockStatusEmun.入库完成.GetHashCode(); sourceLocation.LocationStatus = LocationStatusEnum.Free.GetHashCode(); targetLocation.LocationStatus = LocationStatusEnum.InStock.GetHashCode(); var updateSourceResult = await _locationInfoService.UpdateLocationInfoAsync(sourceLocation); var updateTargetResult = await _locationInfoService.UpdateLocationInfoAsync(targetLocation); var updateStockResult = await _stockInfoService.UpdateStockAsync(stockInfo); if (!updateSourceResult || !updateTargetResult || !updateStockResult) return WebResponseContent.Instance.Error("移库任务完成失败"); return await CompleteTaskAsync(task, "移库完成"); }); } catch (Exception ex) { return WebResponseContent.Instance.Error($"完成任务失败: {ex.Message}"); } } /// /// 创建空托盘入库任务 /// /// /// public async Task CreateTaskInboundTrayAsync(CreateTaskDto taskDto) { try { WebResponseContent content = await GetTaskByPalletCodeAsync(taskDto.PalletCode); if (content.Status) { return content; } //var tasks = await BaseDal.QueryAsync(s => s.PalletCode == palletCode); //if (tasks == null || !tasks.Any()) // return WebResponseContent.Instance.Error("未找到对应的任务"); //var taskDtos = _mapper.Map>(tasks); return WebResponseContent.Instance.OK("查询成功"/*, taskDtos*/); } catch (Exception ex) { return WebResponseContent.Instance.Error($"查询任务失败: {ex.Message}"); } } /// /// 空托盘入库完成 /// public async Task InboundFinishTaskTrayAsync(CreateTaskDto taskDto) { try { var task = await BaseDal.QueryFirstAsync(s => s.PalletCode == taskDto.PalletCode); if (task == null) return WebResponseContent.Instance.Error("未找到对应的任务"); var location = await _locationInfoService.GetLocationInfo(task.Roadway, task.TargetAddress); if (location == null) return WebResponseContent.Instance.Error("未找到对应的货位"); var stockInfo = await _stockInfoService.GetStockInfoAsync(taskDto.PalletCode); if (stockInfo == null) return WebResponseContent.Instance.Error("未找到对应库存信息"); return await ExecuteWithinTransactionAsync(async () => { stockInfo.LocationCode = location.LocationCode; stockInfo.LocationId = location.Id; stockInfo.StockStatus = StockStatusEmun.空托盘库存.GetHashCode(); location.LocationStatus = LocationStatusEnum.InStock.GetHashCode(); var updateLocationResult = await _locationInfoService.UpdateLocationInfoAsync(location); var updateStockResult = await _stockInfoService.UpdateStockAsync(stockInfo); if (!updateLocationResult || !updateStockResult) return WebResponseContent.Instance.Error("任务完成失败"); var saveTaskHistoryResult = await SaveTaskHistoryAsync(task, "空托盘入库完成"); if (!saveTaskHistoryResult.Status) return saveTaskHistoryResult; var saveStockHistoryResult = await SaveStockHistoryAsync(stockInfo, "空托盘入库完成"); if (!saveStockHistoryResult.Status) return saveStockHistoryResult; var deleteResult = await BaseDal.DeleteDataAsync(task); if (!deleteResult) return WebResponseContent.Instance.Error("任务完成失败"); return WebResponseContent.Instance.OK("任务完成"); }); } catch (Exception ex) { return WebResponseContent.Instance.Error($"完成任务失败: {ex.Message}"); } } /// /// 创建空托盘出库任务 /// /// /// public async Task GetOutBoundTrayTaskAsync(CreateTaskDto taskDto) { try { var dt_Task = await BaseDal.QueryFirstAsync(x => x.TargetAddress == taskDto.TargetAddress); if (!dt_Task.IsNullOrEmpty()) { var taskDTO = dt_Task.Adapt(); return WebResponseContent.Instance.OK("任务创建成功", taskDTO); } var stockInfo = await _stockInfoService.Repository.QueryDataNavFirstAsync(x => x.LocationDetails.WarehouseId == taskDto.WarehouseId && x.LocationDetails.LocationStatus == LocationStatusEnum.InStock.GetHashCode() && x.StockStatus == StockStatusEmun.空托盘库存.GetHashCode()); if (stockInfo == null) return WebResponseContent.Instance.Error("未找到对应的库存信息"); var task = new Dt_Task() { WarehouseId = stockInfo.LocationDetails.WarehouseId, PalletCode = stockInfo.PalletCode, PalletType = stockInfo.PalletType, SourceAddress = stockInfo.LocationCode, CurrentAddress = stockInfo.LocationCode, NextAddress = taskDto.TargetAddress, TargetAddress = taskDto.TargetAddress, Roadway = stockInfo.LocationDetails.RoadwayNo, TaskType = TaskOutboundTypeEnum.OutEmpty.GetHashCode(), TaskStatus = TaskStatusEnum.New.GetHashCode(), Grade = 1, TaskNum = await BaseDal.GetTaskNo(), Creater = "system", }; return await ExecuteWithinTransactionAsync(async () => { var locationInfo = await _locationInfoService.GetLocationInfoAsync(stockInfo.LocationId); locationInfo.LocationStatus = LocationStatusEnum.InStockLock.GetHashCode(); var updateLocationResult = await _locationInfoService.UpdateLocationInfoAsync(locationInfo); if (!updateLocationResult) return WebResponseContent.Instance.Error("任务创建失败"); var taskDtos = task.Adapt(); var addResult = await BaseDal.AddDataAsync(task) > 0; if (!addResult) return WebResponseContent.Instance.Error("任务创建失败"); return WebResponseContent.Instance.OK("任务创建成功", taskDtos); }); } catch (Exception ex) { return WebResponseContent.Instance.Error($"查询任务失败: {ex.Message}"); } } /// /// 空托盘出库完成 /// public async Task OutboundFinishTaskTrayAsync(CreateTaskDto taskDto) { try { var task = await BaseDal.QueryFirstAsync(s => s.PalletCode == taskDto.PalletCode); if (task == null) return WebResponseContent.Instance.Error("未找到对应的任务"); var location = await _locationInfoService.GetLocationInfo(task.Roadway, task.SourceAddress); if (location == null) return WebResponseContent.Instance.Error("未找到对应的货位"); var stockInfo = await _stockInfoService.GetStockInfoAsync(taskDto.PalletCode); if (stockInfo == null) return WebResponseContent.Instance.Error("未找到对应库存信息"); return await ExecuteWithinTransactionAsync(async () => { stockInfo.LocationId = 0; stockInfo.LocationCode = string.Empty; stockInfo.StockStatus = StockStatusEmun.出库完成.GetHashCode(); location.LocationStatus = LocationStatusEnum.Free.GetHashCode(); var updateLocationResult = await _locationInfoService.UpdateLocationInfoAsync(location); var updateStockResult = await _stockInfoService.UpdateStockAsync(stockInfo); if (!updateLocationResult || !updateStockResult) return WebResponseContent.Instance.Error("任务完成失败"); var saveTaskHistoryResult = await SaveTaskHistoryAsync(task, "空托盘出库完成"); if (!saveTaskHistoryResult.Status) return saveTaskHistoryResult; var saveStockHistoryResult = await SaveStockHistoryAsync(stockInfo, "空托盘出库完成"); if (!saveStockHistoryResult.Status) return saveStockHistoryResult; var deleteResult = await BaseDal.DeleteDataAsync(task); if (!deleteResult) return WebResponseContent.Instance.Error("任务完成失败"); return WebResponseContent.Instance.OK("任务完成"); }); } catch (Exception ex) { return WebResponseContent.Instance.Error($"完成任务失败: {ex.Message}"); } } /// /// 修改任务状态(根据任务ID修改为指定状态) /// /// /// /// public async Task UpdateTaskByStatusAsync(int taskId, int newStatus) { try { var tasks = await BaseDal.QueryFirstAsync(s => s.TaskNum == taskId); if (tasks == null) return WebResponseContent.Instance.Error("未找到对应的任务"); tasks.TaskStatus = newStatus; await BaseDal.UpdateDataAsync(tasks); return WebResponseContent.Instance.OK("修改成功", tasks); } catch (Exception ex) { return WebResponseContent.Instance.Error($"修改失败: {ex.Message}"); } } /// /// 自动创建出库任务 - 查询到期库存并创建任务 /// public async Task CreateAutoOutboundTasksAsync() { try { // 1. 查询到期库存 var expiredStocks = await _stockInfoService.Repository .QueryDataNavAsync(s => s.OutboundDate <= DateTime.Now && s.StockStatus == StockStatusEmun.入库完成.GetHashCode()); if (expiredStocks == null || !expiredStocks.Any()) { return WebResponseContent.Instance.OK("无到期库存需要处理"); } // 过滤有位置且位置有库存的记录 expiredStocks = expiredStocks .Where(s => s.LocationDetails != null && s.LocationDetails.LocationStatus == LocationStatusEnum.InStock.GetHashCode()) .ToList(); if (!expiredStocks.Any()) { return WebResponseContent.Instance.OK("无符合条件的到期库存"); } // 2. 检查已存在的任务 var palletCodes = expiredStocks.Select(s => s.PalletCode).ToList(); var existingTasks = await Repository.QueryDataAsync(t => palletCodes.Contains(t.PalletCode) && (t.TaskStatus == TaskStatusEnum.New.GetHashCode() || t.TaskStatus == TaskStatusEnum.SC_Executing.GetHashCode() || t.TaskStatus == TaskInStatusEnum.InNew.GetHashCode())); var processedPallets = existingTasks.Select(t => t.PalletCode).ToHashSet(); // 3. 筛选需要处理的库存 var stocksToProcess = expiredStocks .Where(s => !processedPallets.Contains(s.PalletCode)) .ToList(); if (!stocksToProcess.Any()) { return WebResponseContent.Instance.OK("所有到期库存已存在任务"); } // 4. 获取配置的目标地址映射 var targetAddressMap = _configuration.GetSection("AutoOutboundTask:TargetAddresses") .Get>>() ?? new Dictionary>(); // 5. 批量创建任务 var taskList = new List(); foreach (var stock in stocksToProcess) { // 根据巷道确定目标地址(优先根据 Remark 确定,Remark 为空则根据巷道配置) var targetAddress = DetermineTargetAddressByRemark( stock.Remark ?? "", stock.LocationDetails?.RoadwayNo ?? "", targetAddressMap); var task = new Dt_Task { WarehouseId = stock.WarehouseId, PalletCode = stock.PalletCode, PalletType = stock.PalletType, SourceAddress = stock.LocationCode, CurrentAddress = stock.LocationCode, NextAddress = targetAddress, TargetAddress = targetAddress, Roadway = stock.LocationDetails?.RoadwayNo ?? "", TaskType = TaskTypeEnum.Outbound.GetHashCode(), TaskStatus = TaskStatusEnum.New.GetHashCode(), Grade = 1, TaskNum = await BaseDal.GetTaskNo(), Creater = "system_auto" }; taskList.Add(task); } var transactionResult = await ExecuteWithinTransactionAsync(async () => { var addResult = await BaseDal.AddDataAsync(taskList) > 0; if (!addResult) { return WebResponseContent.Instance.Error($"批量创建任务失败,共 {taskList.Count} 个任务"); } // 任务创建成功后,同步锁定库存和货位状态,避免重复分配 var stocksToUpdate = stocksToProcess .Select(s => { s.StockStatus = StockStatusEmun.出库锁定.GetHashCode(); return s; }) .ToList(); var updateStockResult = await _stockInfoService.Repository.UpdateDataAsync(stocksToUpdate); if (!updateStockResult) { return WebResponseContent.Instance.Error($"任务创建成功,但库存状态更新失败,共 {stocksToUpdate.Count} 条"); } var locationsToUpdate = stocksToProcess .Where(s => s.LocationDetails != null) .GroupBy(s => s.LocationDetails.Id) .Select(g => { var location = g.First().LocationDetails; location.LocationStatus = LocationStatusEnum.InStockLock.GetHashCode(); return location; }) .ToList(); if (locationsToUpdate.Any()) { var updateLocationResult = await _locationInfoService.Repository.UpdateDataAsync(locationsToUpdate); if (!updateLocationResult) { return WebResponseContent.Instance.Error($"任务创建成功,但货位状态更新失败,共 {locationsToUpdate.Count} 条"); } } return WebResponseContent.Instance.OK(); }); if (!transactionResult.Status) { return transactionResult; } // 6. 通知 WCS(异步,不影响主流程) _ = Task.Run(() => { try { var wmstaskDtos = _mapper.Map>(taskList); _httpClientHelper.Post( "http://localhost:9292/api/Task/ReceiveTask", wmstaskDtos.ToJson()); } catch (Exception ex) { // WCS 通知失败不影响任务创建,记录日志即可 Console.WriteLine($"WCS 批量通知失败,任务数量: {taskList.Count}, 错误: {ex.Message}"); } }); return WebResponseContent.Instance.OK($"成功创建 {taskList.Count} 个出库任务", taskList.Count); } catch (Exception ex) { return WebResponseContent.Instance.Error($"自动创建出库任务失败: {ex.Message}"); } } /// /// 创建机械手组盘任务 /// public async Task CreateRobotGroupPalletTaskAsync(StockDTO stock) { return await CreateRobotPalletTaskAsync( stock, "组盘", RobotTaskTypeEnum.GroupPallet, s => string.IsNullOrWhiteSpace(s.TargetPalletNo) ? s.SourcePalletNo : s.TargetPalletNo, requireStockWithoutLocation: false); } /// /// 创建机械手换盘任务 /// public async Task CreateRobotChangePalletTaskAsync(StockDTO stock) { return await CreateRobotPalletTaskAsync( stock, "换盘", RobotTaskTypeEnum.ChangePallet, s => s.SourcePalletNo, requireStockWithoutLocation: true, stockPalletCodeSelector: s => s.SourcePalletNo); } /// /// 创建机械手拆盘任务 /// public async Task CreateRobotSplitPalletTaskAsync(StockDTO stock) { return await CreateRobotPalletTaskAsync( stock, "拆盘", RobotTaskTypeEnum.SplitPallet, s => s.SourcePalletNo, requireStockWithoutLocation: true, stockPalletCodeSelector: s => s.SourcePalletNo); } private async Task CreateRobotPalletTaskAsync( StockDTO stock, string taskName, RobotTaskTypeEnum taskType, Func palletCodeSelector, bool requireStockWithoutLocation, Func? stockPalletCodeSelector = null) { try { if (stock == null) return WebResponseContent.Instance.Error("任务参数不能为空"); var palletCode = palletCodeSelector(stock)?.Trim(); if (string.IsNullOrWhiteSpace(palletCode)) return WebResponseContent.Instance.Error("托盘号不能为空"); var sourceLineNo = stock.SourceLineNo?.Trim(); var targetLineNo = stock.TargetLineNo?.Trim(); if (string.IsNullOrWhiteSpace(sourceLineNo) || string.IsNullOrWhiteSpace(targetLineNo)) return WebResponseContent.Instance.Error("来源线体编号和目标线体编号不能为空"); var existingTask = await BaseDal.QueryFirstAsync(t => t.PalletCode == palletCode && (t.TaskStatus == TaskRobotStatusEnum.RobotNew.GetHashCode() || t.TaskStatus == TaskRobotStatusEnum.RobotExecuting.GetHashCode() || t.TaskStatus == TaskRobotStatusEnum.RobotPickFinish.GetHashCode() || t.TaskStatus == TaskRobotStatusEnum.RobotPutFinish.GetHashCode() || t.TaskStatus == TaskRobotStatusEnum.RobotPending.GetHashCode())); if (existingTask != null) return WebResponseContent.Instance.Error($"托盘[{palletCode}]已存在未完成任务"); Dt_StockInfo? stockInfo = null; if (requireStockWithoutLocation) { var stockPalletCode = (stockPalletCodeSelector ?? palletCodeSelector).Invoke(stock)?.Trim(); if (string.IsNullOrWhiteSpace(stockPalletCode)) return WebResponseContent.Instance.Error("源托盘号不能为空"); stockInfo = await _stockInfoService.GetStockInfoAsync(stockPalletCode); if (stockInfo == null) return WebResponseContent.Instance.Error($"托盘[{stockPalletCode}]库存不存在"); if (stockInfo.LocationId > 0 || !string.IsNullOrWhiteSpace(stockInfo.LocationCode)) return WebResponseContent.Instance.Error($"托盘[{stockPalletCode}]库存已绑定货位,不能创建机械手{taskName}任务"); } var section = App.Configuration.GetSection("RobotTaskAddressRules").GetSection(targetLineNo).GetChildren().Select(c => c.Value).ToArray(); var task = new Dt_Task { TaskNum = await BaseDal.GetTaskNo(), PalletCode = palletCode, PalletType = stockInfo?.PalletType ?? 0, Roadway = stock.Roadway ?? string.Empty, TaskType = taskType.GetHashCode(), TaskStatus = TaskRobotStatusEnum.RobotNew.GetHashCode(), SourceAddress = section[0], TargetAddress = section[1], CurrentAddress = targetLineNo, NextAddress = targetLineNo, WarehouseId = stockInfo?.WarehouseId ?? 1, Grade = 1, Remark = $"机械手{taskName}", Creater = "system" }; var result = await Repository.AddDataAsync(task) > 0; if (!result) return WebResponseContent.Instance.Error($"机械手{taskName}任务创建失败"); var wmstaskDto = _mapper.Map(task) ?? new WMSTaskDTO(); return WebResponseContent.Instance.OK($"机械手{taskName}任务创建成功", wmstaskDto); } catch (Exception ex) { return WebResponseContent.Instance.Error($"机械手{taskName}任务创建失败: {ex.Message}"); } } /// /// 手动创建任务 /// /// 手动创建任务参数 /// public async Task CreateManualTaskAsync(CreateManualTaskDto dto) { try { // 1. 根据任务类型字符串确定 TaskType 和 TaskStatus int taskType; int taskStatus; switch (dto.TaskType) { case "入库": taskType = TaskTypeEnum.Inbound.GetHashCode(); taskStatus = TaskInStatusEnum.InNew.GetHashCode(); break; case "出库": taskType = TaskTypeEnum.Outbound.GetHashCode(); taskStatus = TaskOutStatusEnum.OutNew.GetHashCode(); break; case "移库": taskType = TaskTypeEnum.Relocation.GetHashCode(); taskStatus = TaskRelocationStatusEnum.RelocationNew.GetHashCode(); break; default: return WebResponseContent.Instance.Error($"不支持的任务类型: {dto.TaskType}"); } // 2. 生成任务号 int taskNum = await BaseDal.GetTaskNo(); // 3. 构建任务实体 var task = new Dt_Task { TaskNum = taskNum, PalletCode = dto.Barcode, SourceAddress = dto.SourceAddress, TargetAddress = dto.TargetAddress, TaskType = taskType, TaskStatus = taskStatus, Grade = dto.Grade, WarehouseId = dto.WarehouseId, CurrentAddress = dto.SourceAddress, NextAddress = dto.TargetAddress, Creater = "manual", CreateDate = DateTime.Now, ModifyDate = DateTime.Now }; // 4. 保存到数据库 var result = await BaseDal.AddDataAsync(task) > 0; if (!result) return WebResponseContent.Instance.Error("创建任务失败"); // 5. 发送到 WCS var wmsTaskDto = new WMSTaskDTO { TaskNum = task.TaskNum, PalletCode = task.PalletCode, SourceAddress = task.SourceAddress, TargetAddress = task.TargetAddress, TaskType = task.TaskType, TaskStatus = task.TaskStatus, WarehouseId = task.WarehouseId }; var wcsResult = _httpClientHelper.Post( "http://localhost:9292/api/Task/ReceiveManualTask", wmsTaskDto.ToJson()); if (!wcsResult.IsSuccess || !wcsResult.Data.Status) return WebResponseContent.Instance.Error($"任务已创建但发送给WCS失败: {wcsResult.Data?.Message}"); return WebResponseContent.Instance.OK($"手动创建任务成功,任务号: {taskNum}"); } catch (Exception ex) { return WebResponseContent.Instance.Error($"手动创建任务异常: {ex.Message}"); } } #endregion WCS逻辑处理 } }