using Microsoft.AspNetCore.Http.HttpResults; using Newtonsoft.Json; using System.Diagnostics; 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.Helper; using WIDESEA_DTO.MES; using WIDESEA_DTO.Task; using WIDESEA_IBasicService; using WIDESEA_Model.Models; namespace WIDESEA_TaskInfoService { public partial class TaskService { #region 入库任务 /// /// 创建任务(组盘入库任务、空托盘回库任务) /// 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 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 _unitOfWorkManage.BeginTranAsync(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) { var stopwatch = Stopwatch.StartNew(); 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 await _unitOfWorkManage.BeginTranAsync(async () => { stockInfo = new Dt_StockInfo { PalletCode = taskDto.PalletCode, WarehouseId = task.WarehouseId, StockStatus = StockStatusEmun.空托盘库存.GetHashCode(), Creater = StockConstants.SYSTEM_USER, Details = null, LocationCode = location.LocationCode, LocationId = location.Id }; var updateLocationResult = await _locationInfoService.UpdateLocationInfoAsync(location); var updateStockResult = await _stockInfoService.Repository.AddDataAsync(stockInfo); return await CompleteTaskAsync(task, "入库完成"); }); } else { // 判断是不是极卷库任务 if (taskDto.WarehouseId == (int)WarehouseEnum.FJ1 || taskDto.WarehouseId == (int)WarehouseEnum.ZJ1) { return await CompleteAgvInboundTaskAsync(taskDto); } return await _unitOfWorkManage.BeginTranAsync(async () => { WebResponseContent content = new WebResponseContent(); stockInfo.LocationCode = location.LocationCode; stockInfo.LocationId = location.Id; SetOutboundDateByRoadway(task, stockInfo); 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("任务完成失败"); // 根据库存Remark选择静置设备,查MES动态凭证 string deviceName = stockInfo.Remark == "GW_1" ? "高温静置1" : stockInfo.Remark == "GW_2" ? "高温静置2" : "常温静置1"; var mesConfig = _mesDeviceConfigService.GetByDeviceName(deviceName); string equipmentCode = mesConfig?.EquipmentCode ?? StockConstants.MES_EQUIPMENT_CODE; string resourceCode = mesConfig?.ResourceCode ?? StockConstants.MES_RESOURCE_CODE; string token = mesConfig?.Token; // 异步调用MES托盘进站,不阻塞主逻辑 var palletCode = taskDto.PalletCode; var localEquipmentCode = equipmentCode; var localResourceCode = resourceCode; var localToken = token; _ = Task.Run(async () => { var localStopwatch = Stopwatch.StartNew(); try { var inboundRequest = new InboundInContainerRequest { EquipmentCode = localEquipmentCode, ResourceCode = localResourceCode, LocalTime = DateTime.Now, ContainerCode = palletCode }; string localRequestJson = inboundRequest.ToJson(); var inboundResult = string.IsNullOrWhiteSpace(localToken) ? _mesService.InboundInContainer(inboundRequest) : _mesService.InboundInContainer(inboundRequest, localToken); localStopwatch.Stop(); bool isSuccess = inboundResult?.Data?.IsSuccess ?? false; int status = isSuccess ? (int)MesUploadStatusEnum.进站上传成功 : (int)MesUploadStatusEnum.进站上传失败; await _stockInfoService.UpdateMesUploadStatusAsync(palletCode, status); await _mesLogService.LogAsync(new MesApiLogDto { PalletCode = palletCode, ApiType = "InboundInContainer", RequestJson = localRequestJson, ResponseJson = JsonConvert.SerializeObject(inboundResult), IsSuccess = isSuccess, ErrorMessage = inboundResult?.Data?.Msg ?? inboundResult?.ErrorMessage ?? "未知错误", ElapsedMs = (int)localStopwatch.ElapsedMilliseconds, Creator = "systeam" }); } catch (Exception ex) { localStopwatch.Stop(); await _stockInfoService.UpdateMesUploadStatusAsync(palletCode, (int)MesUploadStatusEnum.进站上传失败); await _mesLogService.LogAsync(new MesApiLogDto { PalletCode = palletCode, ApiType = "InboundInContainer", IsSuccess = false, ErrorMessage = ex.Message, ElapsedMs = (int)localStopwatch.ElapsedMilliseconds, Creator = "systeam" }); } }); return await CompleteTaskAsync(task, "入库完成"); }); } } catch (Exception ex) { return WebResponseContent.Instance.Error($"完成任务失败: {ex.Message}"); } } /// /// 根据巷道类型设置库存的出库时间和备注 /// /// 任务信息 /// 库存信息 private void SetOutboundDateByRoadway(Dt_Task task, Dt_StockInfo stockInfo) { var now = DateTime.Now; if (task.Roadway.Contains("GW")) { stockInfo.OutboundDate = string.IsNullOrEmpty(stockInfo.Remark) ? now.AddHours(OutboundTimeConstants.OUTBOUND_HOURS_GW1_FIRST) : stockInfo.Remark == StockRemarkConstants.GW1 ? now.AddHours(OutboundTimeConstants.OUTBOUND_HOURS_GW1_SECOND) : now.AddHours(OutboundTimeConstants.OUTBOUND_HOURS_GW1_FIRST); stockInfo.Remark = string.IsNullOrEmpty(stockInfo.Remark) ? StockRemarkConstants.GW1 : stockInfo.Remark == StockRemarkConstants.GW1 ? StockRemarkConstants.GW2 : stockInfo.Remark; } else if (task.Roadway.Contains("CW")) { stockInfo.OutboundDate = now.AddHours(OutboundTimeConstants.OUTBOUND_HOURS_CW1); if (stockInfo.Remark == StockRemarkConstants.GW2) stockInfo.Remark = StockRemarkConstants.CW1; } else { stockInfo.OutboundDate = now; } } #endregion 入库任务 } }