wanshenmean
2026-03-30 85fac67b3bcd53894151a2bce384a945b1b67eb2
Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs
@@ -12,6 +12,7 @@
using WIDESEA_Core.Core;
using WIDESEA_Core.Helper;
using WIDESEA_DTO.GradingMachine;
using WIDESEA_DTO.MES;
using WIDESEA_DTO.Stock;
using WIDESEA_DTO.Task;
using WIDESEA_IBasicService;
@@ -29,6 +30,9 @@
        private readonly HttpClientHelper _httpClientHelper;
        private readonly IConfiguration _configuration;
        private readonly RoundRobinService _roundRobinService;
        private readonly IMesService _mesService;
        private readonly ITask_HtyService _task_HtyService;
        private readonly IStockInfo_HtyService _stockInfo_HtyService;
        public IRepository<Dt_Task> Repository => BaseDal;
@@ -48,7 +52,10 @@
            ILocationInfoService locationInfoService,
            HttpClientHelper httpClientHelper,
            IConfiguration configuration,
            RoundRobinService roundRobinService) : base(BaseDal)
            RoundRobinService roundRobinService,
            IMesService mesService,
            ITask_HtyService task_HtyService,
            IStockInfo_HtyService stockInfo_HtyService) : base(BaseDal)
        {
            _mapper = mapper;
            _stockInfoService = stockInfoService;
@@ -56,6 +63,9 @@
            _httpClientHelper = httpClientHelper;
            _configuration = configuration;
            _roundRobinService = roundRobinService;
            _mesService = mesService;
            _task_HtyService = task_HtyService;
            _stockInfo_HtyService = stockInfo_HtyService;
        }
        #region WCS逻辑处理
@@ -67,7 +77,7 @@
        {
            try
            {
                WebResponseContent content = await GetTasksByPalletCodeAsync(taskDto.PalletCode);
                WebResponseContent content = await GetTaskByPalletCodeAsync(taskDto.PalletCode);
                if (content.Status)
                {
                    return content;
@@ -172,18 +182,23 @@
                var locationInfo = await _locationInfoService.GetLocationInfo(task.Roadway);
                if (locationInfo == null) return WebResponseContent.Instance.Error("未找到对应的货位");
                locationInfo.LocationStatus = LocationStatusEnum.FreeLock.GetHashCode();
                task.CurrentAddress = task.SourceAddress;
                task.NextAddress = locationInfo.LocationCode;
                task.TargetAddress = locationInfo.LocationCode;
                task.TaskStatus = TaskInStatusEnum.Line_InFinish.GetHashCode();
                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 updateResult = await BaseDal.UpdateDataAsync(task);
                var locationResult = await _locationInfoService.UpdateLocationInfoAsync(locationInfo);
                    var updateTaskResult = await BaseDal.UpdateDataAsync(task);
                    var updateLocationResult = await _locationInfoService.UpdateLocationInfoAsync(locationInfo);
                    if (!updateTaskResult || !updateLocationResult)
                    {
                        return WebResponseContent.Instance.Error("任务更新失败");
                    }
                return WebResponseContent.Instance.OK(
                    updateResult && locationResult ? "任务更新成功" : "任务更新失败",
                    locationInfo.LocationCode);
                    return WebResponseContent.Instance.OK("任务更新成功", locationInfo.LocationCode);
                });
            }
            catch (Exception ex)
            {
@@ -205,23 +220,42 @@
                if (location == null) return WebResponseContent.Instance.Error("未找到对应的货位");
                var stockInfo = await _stockInfoService.GetStockInfoAsync(taskDto.PalletCode);
                stockInfo.LocationCode = location.LocationCode;
                stockInfo.LocationId = location.Id;
                stockInfo.OutboundDate = task.Roadway switch
                if (stockInfo == null) return WebResponseContent.Instance.Error("未找到对应库存信息");
                return await ExecuteWithinTransactionAsync(async () =>
                {
                    var r when r.Contains("GW") => DateTime.Now.AddHours(2),
                    var r when r.Contains("CW") => DateTime.Now.AddHours(1),
                    _ => DateTime.Now
                };
                stockInfo.StockStatus = StockStatusEmun.入库完成.GetHashCode();
                    WebResponseContent content = new WebResponseContent();
                    stockInfo.LocationCode = location.LocationCode;
                    stockInfo.LocationId = location.Id;
                    stockInfo.OutboundDate = task.Roadway switch
                    {
                        var r when r.Contains("GW") => DateTime.Now.AddHours(2),
                        var r when r.Contains("CW") => DateTime.Now.AddHours(1),
                        _ => DateTime.Now
                    };
                    stockInfo.StockStatus = StockStatusEmun.入库完成.GetHashCode();
                location.LocationStatus = LocationStatusEnum.InStock.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("任务完成失败");
                return await CompleteTaskAsync(task);
                    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)
            {
@@ -242,18 +276,40 @@
                var location = await _locationInfoService.GetLocationInfo(task.Roadway, task.SourceAddress);
                if (location == null) return WebResponseContent.Instance.Error("未找到对应的货位");
                var stockInfo = await _stockInfoService.GetStockInfoAsync(taskDto.PalletCode);
                stockInfo.LocationId = 0;
                stockInfo.LocationCode = null;
                stockInfo.OutboundDate = DateTime.Now;
                var stockInfo = await _stockInfoService.GetStockInfoAsync(taskDto.PalletCode);
                if (stockInfo == null) return WebResponseContent.Instance.Error("未找到对应库存信息");
                location.LocationStatus = LocationStatusEnum.Free.GetHashCode();
                WebResponseContent content = new WebResponseContent();
                return await ExecuteWithinTransactionAsync(async () =>
                {
                    stockInfo.LocationId = 0;
                    stockInfo.LocationCode = null;
                    stockInfo.OutboundDate = DateTime.Now;
                var updateLocationResult = await _locationInfoService.UpdateLocationInfoAsync(location);
                var updateStockResult = await _stockInfoService.UpdateStockAsync(stockInfo);
                if (!updateLocationResult || !updateStockResult)
                    return WebResponseContent.Instance.Error("任务完成失败");
                return await CompleteTaskAsync(task);
                    location.LocationStatus = LocationStatusEnum.Free.GetHashCode();
                    var updateLocationResult = await _locationInfoService.UpdateLocationInfoAsync(location);
                    var updateStockResult = await _stockInfoService.UpdateStockAsync(stockInfo);
                    if (!updateLocationResult || !updateStockResult)
                        return WebResponseContent.Instance.Error("任务完成失败");
                    // 调用MES托盘出站
                    var outboundRequest = new OutboundInContainerRequest
                    {
                        EquipmentCode = "STK-GROUP-001",
                        ResourceCode = "STK-GROUP-001",
                        LocalTime = DateTime.Now,
                        ContainerCode = taskDto.PalletCode,
                        ParamList = new List<ParamItem>()
                    };
                    var outboundResult = _mesService.OutboundInContainer(outboundRequest);
                    if (outboundResult == null || outboundResult.Data == null || !outboundResult.Data.IsSuccess)
                    {
                        return content.Error($"任务完成失败:MES出站失败: {outboundResult?.Data?.Msg ?? outboundResult?.ErrorMessage ?? "未知错误"}");
                    }
                    return await CompleteTaskAsync(task, "出库完成");
                });
            }
            catch (Exception ex)
            {
@@ -282,21 +338,24 @@
                var stockInfo = await _stockInfoService.GetStockInfoAsync(taskDto.PalletCode);
                if (stockInfo == null) return WebResponseContent.Instance.Error("未找到对应库存信息");
                stockInfo.LocationCode = targetLocation.LocationCode;
                stockInfo.LocationId = targetLocation.Id;
                stockInfo.StockStatus = StockStatusEmun.入库完成.GetHashCode();
                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();
                    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);
                    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("移库任务完成失败");
                    if (!updateSourceResult || !updateTargetResult || !updateStockResult)
                        return WebResponseContent.Instance.Error("移库任务完成失败");
                return await CompleteTaskAsync(task);
                    return await CompleteTaskAsync(task, "移库完成");
                });
            }
            catch (Exception ex)
            {
@@ -313,7 +372,7 @@
        {
            try
            {
                WebResponseContent content = await GetTasksByPalletCodeAsync(taskDto.PalletCode);
                WebResponseContent content = await GetTaskByPalletCodeAsync(taskDto.PalletCode);
                if (content.Status)
                {
                    return content;
@@ -328,6 +387,61 @@
            catch (Exception ex)
            {
                return WebResponseContent.Instance.Error($"查询任务失败: {ex.Message}");
            }
        }
        /// <summary>
        /// 空托盘入库完成
        /// </summary>
        public async Task<WebResponseContent> 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 historyTask = _mapper.Map<Dt_Task_Hty>(task);
                    historyTask.InsertTime = DateTime.Now;
                    historyTask.OperateType = "空托盘入库完成";
                    if (await _task_HtyService.Repository.AddDataAsync(historyTask) <= 0)
                        return WebResponseContent.Instance.Error("任务历史保存失败");
                    // 保存库存历史
                    var historyStock = _mapper.Map<Dt_StockInfo_Hty>(stockInfo);
                    historyStock.InsertTime = DateTime.Now;
                    historyStock.OperateType = "空托盘入库完成";
                    if (await _stockInfo_HtyService.Repository.AddDataAsync(historyStock) <= 0)
                        return WebResponseContent.Instance.Error("库存历史保存失败");
                    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}");
            }
        }
@@ -363,12 +477,69 @@
                };
                var taskDtos = task.Adapt<WMSTaskDTO>();
                BaseDal.AddData(task);
                return WebResponseContent.Instance.OK("查询成功", taskDtos);
                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}");
            }
        }
        /// <summary>
        /// 空托盘出库完成
        /// </summary>
        public async Task<WebResponseContent> 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 = null;
                    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 historyTask = _mapper.Map<Dt_Task_Hty>(task);
                    historyTask.InsertTime = DateTime.Now;
                    historyTask.OperateType = "空托盘出库完成";
                    if (await _task_HtyService.Repository.AddDataAsync(historyTask) <= 0)
                        return WebResponseContent.Instance.Error("任务历史保存失败");
                    // 保存库存历史
                    var historyStock = _mapper.Map<Dt_StockInfo_Hty>(stockInfo);
                    historyStock.InsertTime = DateTime.Now;
                    historyStock.OperateType = "空托盘出库完成";
                    if (await _stockInfo_HtyService.Repository.AddDataAsync(historyStock) <= 0)
                        return WebResponseContent.Instance.Error("库存历史保存失败");
                    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}");
            }
        }
@@ -403,15 +574,15 @@
        /// </summary>
        /// <param name="palletCode"></param>
        /// <returns></returns>
        private async Task<WebResponseContent> GetTasksByPalletCodeAsync(string palletCode)
        private async Task<WebResponseContent> GetTaskByPalletCodeAsync(string palletCode)
        {
            try
            {
                var tasks = await BaseDal.QueryFirstAsync(s => s.PalletCode == palletCode);
                if (tasks == null)
                var task = await BaseDal.QueryFirstAsync(s => s.PalletCode == palletCode);
                if (task == null)
                    return WebResponseContent.Instance.Error("未找到对应的任务");
                var taskDtos = _mapper.Map<List<WMSTaskDTO>>(tasks);
                return WebResponseContent.Instance.OK("查询成功", taskDtos);
                var taskDto = _mapper.Map<WMSTaskDTO>(task);
                return WebResponseContent.Instance.OK("查询成功", taskDto);
            }
            catch (Exception ex)
            {
@@ -422,14 +593,16 @@
        /// <summary>
        /// 完成任务后统一处理(删除任务数据)
        /// </summary>
        private async Task<WebResponseContent> CompleteTaskAsync(Dt_Task task)
        private async Task<WebResponseContent> CompleteTaskAsync(Dt_Task task, string operateType = "")
        {
            var deleteTaskResult = await BaseDal.DeleteDataAsync(task);
            if (!deleteTaskResult) return WebResponseContent.Instance.Error("任务完成失败");
            // 保留历史对象构建逻辑,后续可接入历史表落库
            var historyTask = _mapper.Map<Dt_Task_Hty>(task);
            historyTask.InsertTime = DateTime.Now;
            historyTask.OperateType = operateType;
            var saveResult = await _task_HtyService.Repository.AddDataAsync(historyTask) > 0;
            if (!saveResult) return WebResponseContent.Instance.Error("任务历史保存失败");
            return WebResponseContent.Instance.OK("任务完成");
        }
@@ -549,45 +722,54 @@
                    taskList.Add(task);
                }
                var addResult = await BaseDal.AddDataAsync(taskList) > 0;
                if (!addResult)
                var transactionResult = await ExecuteWithinTransactionAsync(async () =>
                {
                    return WebResponseContent.Instance.Error($"批量创建任务失败,共 {taskList.Count} 个任务");
                }
                // 任务创建成功后,同步锁定库存和货位状态,避免重复分配
                var stocksToUpdate = stocksToProcess
                    .Select(s =>
                    var addResult = await BaseDal.AddDataAsync(taskList) > 0;
                    if (!addResult)
                    {
                        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.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(异步,不影响主流程)
@@ -752,30 +934,26 @@
            try
            {
                var stockInfo = await _stockInfoService.GetStockInfoAsync(input.PalletCode, input.LocationCode);
                int locationStatus;
                if (stockInfo == null)
                {
                    var location = await _locationInfoService.GetLocationInfoAsync(input.LocationCode);
                    OutputDto outPutDto = new OutputDto()
                    {
                        LocationCode = input.LocationCode,
                        PalletCode = input.PalletCode,
                        IsNormalProcedure = 1,
                        LocationStatus = location.LocationStatus
                    };
                    content.OK(data: outPutDto);
                    locationStatus = location?.LocationStatus ?? 0;
                }
                else
                {
                    OutputDto outPutDto = new OutputDto()
                    {
                        LocationCode = input.LocationCode,
                        PalletCode = input.PalletCode,
                        IsNormalProcedure = 1,
                        LocationStatus = stockInfo.LocationDetails.LocationStatus
                    };
                    content.OK(data: outPutDto);
                    locationStatus = stockInfo.LocationDetails?.LocationStatus ?? 0;
                }
                OutputDto outPutDto = new OutputDto()
                {
                    LocationCode = input.LocationCode,
                    PalletCode = input.PalletCode,
                    IsNormalProcedure = 1,
                    LocationStatus = locationStatus
                };
                return content.OK(data: outPutDto);
            }
            catch (Exception ex)
            {