pan
2025-11-16 cf83e0828b286b61b69a15005e6247d8b03f4cd8
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs
@@ -20,6 +20,7 @@
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Org.BouncyCastle.Asn1.Ocsp;
using Org.BouncyCastle.Asn1.Pkcs;
using SqlSugar;
using System.Reflection;
using System.Reflection.Emit;
@@ -37,6 +38,7 @@
using WIDESEA_Core.Enums;
using WIDESEA_Core.Helper;
using WIDESEA_DTO.Basic;
using WIDESEA_DTO.Inbound;
using WIDESEA_DTO.Task;
using WIDESEA_IBasicService;
using WIDESEA_IInboundService;
@@ -58,10 +60,16 @@
        private readonly ILocationInfoService _locationInfoService;
        private readonly IInboundOrderService _inboundOrderService;
        private readonly IInboundOrderDetailService _inboundOrderDetailService;
        private readonly IOutboundOrderService _outboundOrderService;
        private readonly IOutboundOrderDetailService _outboundOrderDetailService;
        private readonly IOutStockLockInfoService _outStockLockInfoService;
        private readonly ILocationStatusChangeRecordService _locationStatusChangeRecordService;
        private readonly IESSApiService _eSSApiService;
        private readonly IStockService _stockService;
        private readonly IRecordService _recordService;
        private readonly IInvokeMESService _invokeMESService;
        public IRepository<Dt_Task> Repository => BaseDal;
        private Dictionary<string, SqlSugar.OrderByType> _taskOrderBy = new()
@@ -81,7 +89,7 @@
        public List<int> TaskOutboundTypes => typeof(TaskTypeEnum).GetEnumIndexList();
        public TaskService(IRepository<Dt_Task> BaseDal, IMapper mapper, IUnitOfWorkManage unitOfWorkManage, IRepository<Dt_StockInfo> stockRepository, ILocationInfoService locationInfoService, IInboundOrderService inboundOrderService, ILocationStatusChangeRecordService locationStatusChangeRecordService, IESSApiService eSSApiService, ILogger<TaskService> logger, IStockService stockService, IRecordService recordService, IInboundOrderDetailService inboundOrderDetailService) : base(BaseDal)
        public TaskService(IRepository<Dt_Task> BaseDal, IMapper mapper, IUnitOfWorkManage unitOfWorkManage, IRepository<Dt_StockInfo> stockRepository, ILocationInfoService locationInfoService, IInboundOrderService inboundOrderService, ILocationStatusChangeRecordService locationStatusChangeRecordService, IESSApiService eSSApiService, ILogger<TaskService> logger, IStockService stockService, IRecordService recordService, IInboundOrderDetailService inboundOrderDetailService, IOutboundOrderService outboundOrderService, IOutboundOrderDetailService outboundOrderDetailService, IInvokeMESService invokeMESService, IOutStockLockInfoService outStockLockInfoService) : base(BaseDal)
        {
            _mapper = mapper;
            _unitOfWorkManage = unitOfWorkManage;
@@ -94,8 +102,13 @@
            _stockService = stockService;
            _recordService = recordService;
            _inboundOrderDetailService = inboundOrderDetailService;
            _outboundOrderService = outboundOrderService;
            _outboundOrderDetailService = outboundOrderDetailService;
            _invokeMESService = invokeMESService;
            _outStockLockInfoService = outStockLockInfoService;
        }
        /// <summary>
        /// 
        /// </summary>
@@ -145,7 +158,7 @@
            decimal beforeQuantity = 0;
            //查库存
            Dt_StockInfo stockInfo = _stockRepository.Db.Queryable<Dt_StockInfo>().Where(x => x.PalletCode == task.PalletCode && x.WarehouseId == task.WarehouseId).First();
            Dt_StockInfo stockInfo = _stockRepository.Db.Queryable<Dt_StockInfo>().Includes(x => x.Details).Where(x => x.PalletCode == task.PalletCode && x.WarehouseId == task.WarehouseId).First();
            if (stockInfo == null)
            {
                return WebResponseContent.Instance.Error($"未找到托盘对应的组盘信息");
@@ -227,7 +240,52 @@
            _locationStatusChangeRecordService.AddLocationStatusChangeRecord(locationInfo, beforeStatus, StockChangeType.Inbound.ObjToInt(), "", task.TaskNum);
            _recordService.StockQuantityChangeRecordService.AddStockChangeRecord(stockInfo, stockInfo.Details, beforeQuantity, stockInfo.Details.Sum(x => x.StockQuantity) + beforeQuantity, WIDESEA_Common.StockEnum.StockChangeType.MaterielGroup);
            try
            {
                foreach (var inboundOrder in inboundOrders)
                {
                    if (inboundOrder != null && inboundOrder.OrderStatus == InOrderStatusEnum.入库完成.ObjToInt())
                    {
                        var feedmodel = new FeedbackInboundRequestModel
                        {
                            reqCode = Guid.NewGuid().ToString(),
                            reqTime = DateTime.Now.ToString(),
                            business_type = inboundOrder.BusinessType,
                            factoryArea = inboundOrder.FactoryArea,
                            operationType = 1,
                            Operator = inboundOrder.Operator,
                            orderNo = inboundOrder.UpperOrderNo,
                            status = inboundOrder.OrderStatus,
                            details = new List<FeedbackInboundDetailsModel>()
                        };
                        var groupedData = inboundOrder.Details.GroupBy(item => new { item.MaterielCode, item.SupplyCode, item.BatchNo, item.lineNo, item.BarcodeUnit, item.WarehouseCode})
                           .Select(group => new FeedbackInboundDetailsModel
                           {
                               materialCode = group.Key.MaterielCode,
                               supplyCode = group.Key.SupplyCode,
                               batchNo = group.Key.BatchNo,
                               lineNo = group.Key.lineNo,
                               warehouseCode = group.Key.WarehouseCode ,
                              // warehouseCode= "1072",
                               unit = group.Key.BarcodeUnit,
                               barcodes = group.Select(row => new FeedbackBarcodesModel
                               {
                                   barcode = row.Barcode,
                                   qty = row.BarcodeQty
                               }).ToList()
                           }).ToList();
                        feedmodel.details = groupedData;
                        _invokeMESService.FeedbackInbound(feedmodel);
                    }
                }
            }
            catch (Exception ex) {
                _logger.LogInformation("InboundTaskCompleted å›žå†™MES失败:  " + ex.Message);
            }
            return WebResponseContent.Instance.OK();
        }
@@ -293,7 +351,7 @@
            WebResponseContent content = new WebResponseContent();
            try
            {
                Dt_StockInfo stockInfo = _stockRepository.Db.Queryable<Dt_StockInfo>().Where(x => x.PalletCode == task.PalletCode && x.WarehouseId == task.WarehouseId).First();
                Dt_StockInfo stockInfo = _stockRepository.Db.Queryable<Dt_StockInfo>().Where(x => x.PalletCode == task.PalletCode  ).First();
                if (stockInfo == null)
                {
                    return WebResponseContent.Instance.Error($"未找到托盘对应的库存信息");
@@ -305,8 +363,7 @@
                    return content.Error($"未找到对应的终点货位信息");
                }
                _stockRepository.Db.Deleteable(stockInfo);
                int beforeStatus = locationInfo.LocationStatus;
                locationInfo.LocationStatus = LocationStatusEnum.Free.ObjToInt();
@@ -317,6 +374,7 @@
                task.TaskStatus = TaskStatusEnum.Finish.ObjToInt();
                BaseDal.DeleteAndMoveIntoHty(task, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
                _stockService.StockInfoService.Repository.DeleteAndMoveIntoHty(stockInfo, App.User.UserId == 0 ? OperateTypeEnum.自动完成 : OperateTypeEnum.人工完成);
                _stockRepository.Db.Deleteable(stockInfo).ExecuteCommand();
                _locationStatusChangeRecordService.AddLocationStatusChangeRecord(locationInfo, beforeStatus, StockChangeType.Outbound.ObjToInt(), stockInfo.Details.FirstOrDefault()?.OrderNo ?? "", task.TaskNum);
@@ -329,5 +387,149 @@
            }
        }
        /// <summary>
        /// å›žåº“完成回调
        public async Task<WebResponseContent> BackToStockComplete(Dt_Task task)
        {
            try
            {
                _unitOfWorkManage.BeginTran();
                // èŽ·å–ç›¸å…³çš„å‡ºåº“é”å®šä¿¡æ¯
                var lockInfos = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
                    .Where(x => x.TaskNum == task.TaskNum &&
                               x.Status == (int)OutLockStockStatusEnum.回库中)
                    .ToListAsync();
                if (!lockInfos.Any())
                    return WebResponseContent.Instance.Error("未找到回库中的锁定信息");
                //  æ¢å¤åº“存出库数量(回库的部分)
                await RestoreStockOutboundQuantity(lockInfos);
                //  æ›´æ–°å‡ºåº“单明细的锁定数量
                var orderDetailGroups = lockInfos.GroupBy(x => x.OrderDetailId);
                foreach (var group in orderDetailGroups)
                {
                    var orderDetailId = group.Key;
                    var totalUnpicked = group.Sum(x => x.AssignQuantity - x.PickedQty);
                    if (totalUnpicked > 0)
                    {
                        var orderDetail = await _outboundOrderService.Db.Queryable<Dt_OutboundOrderDetail>()
                            .Where(x => x.Id == orderDetailId)
                            .FirstAsync();
                        orderDetail.LockQuantity -= totalUnpicked;
                        // æ¢å¤çŠ¶æ€
                        if (orderDetail.LockQuantity <= 0 && orderDetail.OverOutQuantity <= 0)
                        {
                            orderDetail.OrderDetailStatus = (int)OrderDetailStatusEnum.New;
                        }
                        else if (orderDetail.OverOutQuantity > 0)
                        {
                            orderDetail.OrderDetailStatus = (int)OrderDetailStatusEnum.AssignOverPartial;
                        }
                        await _outboundOrderService.Db.Updateable(orderDetail).ExecuteCommandAsync();
                    }
                }
                //  æ›´æ–°é”å®šä¿¡æ¯çŠ¶æ€ä¸ºå·²å›žåº“
                foreach (var lockInfo in lockInfos)
                {
                    lockInfo.Status = (int)OutLockStockStatusEnum.已回库;
                }
                await _outStockLockInfoService.Db.Updateable(lockInfos).ExecuteCommandAsync();
                // 6. æ›´æ–°åº“存状态
                var stockIds = lockInfos.Select(x => x.StockId).Distinct().ToList();
                var stocks = await _stockService.StockInfoService.Db.Queryable<Dt_StockInfo>()
                    .Where(x => stockIds.Contains(x.Id))
                    .ToListAsync();
                foreach (var stock in stocks)
                {
                    stock.StockStatus = (int)StockStatusEmun.入库完成;
                    stock.LocationCode = task.TargetAddress; // æ›´æ–°è´§ä½
                }
                await _stockService.StockInfoService.Db.Updateable(stocks).ExecuteCommandAsync();
                // 7. æ›´æ–°è´§ä½çŠ¶æ€
                var location = await _locationInfoService.Db.Queryable<Dt_LocationInfo>()
                    .Where(x => x.LocationCode == task.TargetAddress)
                    .FirstAsync();
                if (location != null)
                {
                    location.LocationStatus = (int)LocationStatusEnum.InStock;
                    await _locationInfoService.Db.Updateable(location).ExecuteCommandAsync();
                }
                //  æ›´æ–°ä»»åŠ¡çŠ¶æ€ä¸ºå·²å®Œæˆ
                task.TaskStatus = (int)TaskStatusEnum.Finish;
                await Db.Updateable(task).ExecuteCommandAsync();
                _unitOfWorkManage.CommitTran();
                return WebResponseContent.Instance.OK("回库完成", new
                {
                    TaskNum = task.TaskNum,
                    PalletCode = task.PalletCode,
                    RestoredQuantity = lockInfos.Sum(x => x.AssignQuantity - x.PickedQty)
                });
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return WebResponseContent.Instance.Error($"回库完成处理失败: {ex.Message}");
            }
        }
        /// <summary>
        /// æ¢å¤åº“存出库数量(回库的部分)
        /// </summary>
        private async Task RestoreStockOutboundQuantity(List<Dt_OutStockLockInfo> lockInfos)
        {
            // æŒ‰åº“å­˜ID和物料分组
            var stockGroups = lockInfos.GroupBy(x => new { x.StockId, x.MaterielCode });
            foreach (var group in stockGroups)
            {
                var stockId = group.Key.StockId;
                var materielCode = group.Key.MaterielCode;
                var totalUnpicked = group.Sum(x => x.AssignQuantity - x.PickedQty);
                if (totalUnpicked <= 0) continue;
                // èŽ·å–è¯¥ç‰©æ–™åœ¨åº“å­˜ä¸­çš„æ‰€æœ‰æ¡ç 
                var stockDetails = await _stockService.StockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
                    .Where(x => x.StockId == stockId && x.MaterielCode == materielCode)
                    .ToListAsync();
                if (!stockDetails.Any()) continue;
                // æŒ‰å‡ºåº“数量的比例分配恢复数量
                var totalOutbound = stockDetails.Sum(x => x.OutboundQuantity);
                if (totalOutbound <= 0) continue;
                foreach (var detail in stockDetails)
                {
                    if (detail.OutboundQuantity <= 0) continue;
                    decimal ratio = detail.OutboundQuantity / totalOutbound;
                    decimal restoreAmount = Math.Min(detail.OutboundQuantity, totalUnpicked * ratio);
                    detail.OutboundQuantity -= restoreAmount;
                    await _stockService.StockInfoDetailService.Db.Updateable(detail).ExecuteCommandAsync();
                }
            }
        }
    }
}