wanshenmean
2026-03-12 f56441867f2cc77567f97a92348a5d878f0dca05
Code/WMS/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs
@@ -1,4 +1,4 @@
using AutoMapper;
using MapsterMapper;
using Microsoft.Extensions.Configuration;
using SqlSugar;
using System.Text.Json;
@@ -9,6 +9,7 @@
using WIDESEA_Core.BaseRepository;
using WIDESEA_Core.BaseServices;
using WIDESEA_Core.Core;
using WIDESEA_Core.Helper;
using WIDESEA_DTO.GradingMachine;
using WIDESEA_DTO.Task;
using WIDESEA_IBasicService;
@@ -218,14 +219,7 @@
                var updateStockResult = await _stockInfoService.UpdateStockAsync(stockInfo);
                if (!updateLocationResult || !updateStockResult)
                    return WebResponseContent.Instance.Error("任务完成失败");
                var deleteTaskResult = await BaseDal.DeleteDataAsync(task);
                if (!deleteTaskResult) return WebResponseContent.Instance.Error("任务完成失败");
                var historyTask = _mapper.Map<Dt_Task_Hty>(task);
                historyTask.InsertTime = DateTime.Now;
                return WebResponseContent.Instance.OK("任务完成");
                return await CompleteTaskAsync(task);
            }
            catch (Exception ex)
            {
@@ -256,14 +250,50 @@
                var updateStockResult = await _stockInfoService.UpdateStockAsync(stockInfo);
                if (!updateLocationResult || !updateStockResult)
                    return WebResponseContent.Instance.Error("任务完成失败");
                return await CompleteTaskAsync(task);
            }
            catch (Exception ex)
            {
                return WebResponseContent.Instance.Error($"完成任务失败: {ex.Message}");
            }
        }
                var deleteTaskResult = await BaseDal.DeleteDataAsync(task);
                if (!deleteTaskResult) return WebResponseContent.Instance.Error("任务完成失败");
        /// <summary>
        /// 移库任务完成:修改库存位置与状态,修改源/目标货位状态,删除任务数据
        /// </summary>
        public async Task<WebResponseContent> 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 historyTask = _mapper.Map<Dt_Task_Hty>(task);
                historyTask.InsertTime = DateTime.Now;
                var sourceLocation = await _locationInfoService.GetLocationInfo(task.Roadway, task.SourceAddress);
                if (sourceLocation == null) return WebResponseContent.Instance.Error("未找到移库源货位");
                return WebResponseContent.Instance.OK("任务完成");
                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("未找到对应库存信息");
                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)
            {
@@ -385,6 +415,21 @@
        }
        /// <summary>
        /// 完成任务后统一处理(删除任务数据)
        /// </summary>
        private async Task<WebResponseContent> CompleteTaskAsync(Dt_Task task)
        {
            var deleteTaskResult = await BaseDal.DeleteDataAsync(task);
            if (!deleteTaskResult) return WebResponseContent.Instance.Error("任务完成失败");
            // 保留历史对象构建逻辑,后续可接入历史表落库
            var historyTask = _mapper.Map<Dt_Task_Hty>(task);
            historyTask.InsertTime = DateTime.Now;
            return WebResponseContent.Instance.OK("任务完成");
        }
        /// <summary>
        /// 根据巷道确定目标地址(支持多出库口轮询)
        /// </summary>
        private string DetermineTargetAddress(string roadway, Dictionary<string, List<string>> addressMap)
@@ -427,38 +472,12 @@
            {
                // 1. 查询到期库存
                var expiredStocks = await _stockInfoService.Repository
                    .QueryDataAsync(s => s.OutboundDate <= DateTime.Now
                    .QueryDataNavAsync(s => s.OutboundDate <= DateTime.Now
                        && s.StockStatus == StockStatusEmun.入库完成.GetHashCode());
                if (expiredStocks == null || !expiredStocks.Any())
                {
                    return WebResponseContent.Instance.OK("无到期库存需要处理");
                }
                // 批量加载位置详情(优化 N+1 查询问题)
                var locationIds = expiredStocks
                    .Where(s => s.LocationId > 0)
                    .Select(s => s.LocationId)
                    .Distinct()
                    .Cast<object>()
                    .ToList();
                if (locationIds.Any())
                {
                    var locations = await _locationInfoService.Repository
                        .QureyDataByIdsAsync(locationIds);
                    // 创建位置字典以便快速查找
                    var locationDict = locations.ToDictionary(l => l.Id, l => l);
                    // 为每个库存关联位置详情
                    foreach (var stock in expiredStocks)
                    {
                        if (stock.LocationId > 0 && locationDict.ContainsKey(stock.LocationId))
                        {
                            stock.LocationDetails = locationDict[stock.LocationId];
                        }
                    }
                }
                // 过滤有位置且位置有库存的记录
@@ -531,23 +550,55 @@
                    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} 条");
                    }
                }
                // 6. 通知 WCS(异步,不影响主流程)
                _ = Task.Run(() =>
                {
                    foreach (var task in taskList)
                    try
                    {
                        try
                        {
                            var wmstaskDto = _mapper.Map<WMSTaskDTO>(task);
                            _httpClientHelper.Post<WebResponseContent>(
                                "http://localhost:9292/api/Task/ReceiveTask",
                                JsonSerializer.Serialize(wmstaskDto));
                        }
                        catch (Exception ex)
                        {
                            // WCS 通知失败不影响任务创建,记录日志即可
                            Console.WriteLine($"WCS 通知失败,任务编号: {task.TaskNum}, 错误: {ex.Message}");
                        }
                        var wmstaskDtos = _mapper.Map<List<WMSTaskDTO>>(taskList);
                        _httpClientHelper.Post<WebResponseContent>(
                            "http://localhost:9292/api/Task/ReceiveTask",
                            wmstaskDtos.ToJson());
                    }
                    catch (Exception ex)
                    {
                        // WCS 通知失败不影响任务创建,记录日志即可
                        Console.WriteLine($"WCS 批量通知失败,任务数量: {taskList.Count}, 错误: {ex.Message}");
                    }
                });
@@ -744,4 +795,4 @@
        #endregion 分容柜接口
    }
}
}