pan
2025-11-19 c84db706e8c8d82a96bb4b4c18c243a42b2976c1
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundPickingService.cs
@@ -17,6 +17,7 @@
using WIDESEA_Core.BaseServices;
using WIDESEA_Core.Helper;
using WIDESEA_DTO.Basic;
using WIDESEA_DTO.Inbound;
using WIDESEA_DTO.Outbound;
using WIDESEA_IBasicService;
using WIDESEA_IOutboundService;
@@ -43,7 +44,7 @@
        private readonly ISplitPackageService _splitPackageService;
        private readonly IRepository<Dt_Task> _taskRepository;
        private readonly IESSApiService _eSSApiService;
        private readonly IInvokeMESService _invokeMESService;
        private readonly ILogger<OutboundPickingService> _logger;
@@ -61,7 +62,7 @@
        };
        public OutboundPickingService(IRepository<Dt_PickingRecord> BaseDal, IUnitOfWorkManage unitOfWorkManage, IStockInfoService stockInfoService, IStockService stockService, IOutStockLockInfoService outStockLockInfoService, IStockInfoDetailService stockInfoDetailService, ILocationInfoService locationInfoService, IOutboundOrderDetailService outboundOrderDetailService, ISplitPackageService splitPackageService, IOutboundOrderService outboundOrderService, IRepository<Dt_Task> taskRepository, IESSApiService eSSApiService, ILogger<OutboundPickingService> logger) : base(BaseDal)
        public OutboundPickingService(IRepository<Dt_PickingRecord> BaseDal, IUnitOfWorkManage unitOfWorkManage, IStockInfoService stockInfoService, IStockService stockService, IOutStockLockInfoService outStockLockInfoService, IStockInfoDetailService stockInfoDetailService, ILocationInfoService locationInfoService, IOutboundOrderDetailService outboundOrderDetailService, ISplitPackageService splitPackageService, IOutboundOrderService outboundOrderService, IRepository<Dt_Task> taskRepository, IESSApiService eSSApiService, ILogger<OutboundPickingService> logger, IInvokeMESService invokeMESService) : base(BaseDal)
        {
            _unitOfWorkManage = unitOfWorkManage;
            _stockInfoService = stockInfoService;
@@ -75,6 +76,7 @@
            _taskRepository = taskRepository;
            _eSSApiService = eSSApiService;
            _logger = logger;
            _invokeMESService = invokeMESService;
        }
@@ -177,6 +179,12 @@
                if (lockInfo.PalletCode != palletCode)
                    throw new Exception($"条码{barcode}不属于托盘{palletCode}");
                var outorderdetail = _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>().First(x => x.Id == lockInfo.OrderDetailId);
                if (outorderdetail != null && lockInfo.AssignQuantity > outorderdetail.OrderQuantity)
                {
                    throw new Exception($"条码{barcode}的出库数量大于订单的数量");
                }
                var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
                        .Where(x => x.Barcode == barcode && x.StockId == lockInfo.StockId)
                        .FirstAsync();
@@ -248,10 +256,15 @@
        private async Task CheckAndUpdateOrderStatus(string orderNo)
        {
            var orderDetails = _stockInfoDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
                      .LeftJoin<Dt_OutboundOrder>((o, item) => o.OrderId == item.Id) // å…³è”条件:父表 Id = å­è¡¨ OrderId
                      .Where((o, item) => item.OrderNo == orderNo) // è¿‡æ»¤çˆ¶è¡¨ OrderNo
                      .Select((o, item) => o) // åªè¿”回子表数据
                      .ToList();
            var orderDetails = await _stockInfoDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
                .Where(x => x.OrderId == orderNo.ObjToInt())
                .ToListAsync();
            //var orderDetails = await _stockInfoDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
            //    .Where(x => x.OrderId == orderNo.ObjToInt())
            //    .ToListAsync();
            bool allCompleted = true;
            foreach (var detail in orderDetails)
@@ -265,10 +278,72 @@
            if (allCompleted)
            {
                await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>()
                    .SetColumns(x => x.OrderStatus == 2) // å·²å®Œæˆ
                    .Where(x => x.OrderNo == orderNo)
                    .ExecuteCommandAsync();
                try
                {
                    await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>()
                        .SetColumns(x => x.OrderStatus == 2) // å·²å®Œæˆ
                        .Where(x => x.OrderNo == orderNo)
                        .ExecuteCommandAsync();
                    var outboundOrder = _stockInfoService.Db.Queryable<Dt_OutboundOrder>().First(x => x.OrderNo == orderNo);
                    if (outboundOrder != null && outboundOrder.OrderStatus == OutOrderStatusEnum.出库完成.ObjToInt())
                    {
                        if (outboundOrder.OrderType == OutOrderTypeEnum.Allocate.ObjToInt().ObjToInt())//调拨出库
                        {
                        }
                        else if (outboundOrder.OrderType == OutOrderTypeEnum.ReCheck.ObjToInt()) //重检出库
                        {
                        }
                        else
                        {
                            var feedmodel = new FeedbackOutboundRequestModel
                            {
                                reqCode = Guid.NewGuid().ToString(),
                                reqTime = DateTime.Now.ToString(),
                                business_type = outboundOrder.BusinessType,
                                factoryArea = outboundOrder.FactoryArea,
                                operationType = 1,
                                Operator = outboundOrder.Operator,
                                orderNo = outboundOrder.UpperOrderNo,
                                status = outboundOrder.OrderStatus,
                                details = new List<FeedbackOutboundDetailsModel>()
                            };
                            var lists = _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>().Where(x => x.OrderNo == orderNo).ToList();
                            var groupedData = lists.GroupBy(item => new { item.MaterielCode, item.lineNo, item.Unit, item.WarehouseCode })
                               .Select(group => new FeedbackOutboundDetailsModel
                               {
                                   materialCode = group.Key.MaterielCode,
                                   lineNo = group.Key.lineNo,
                                   warehouseCode = group.Key.WarehouseCode,
                                   currentDeliveryQty = group.Sum(x => x.OrderQuantity),
                                   // warehouseCode= "1072",
                                   unit = group.Key.Unit,
                                   barcodes = group.Select(row => new WIDESEA_DTO.Outbound.BarcodesModel
                                   {
                                       barcode = row.CurrentBarcode,
                                       supplyCode = row.SupplyCode,
                                       batchNo = row.BatchNo,
                                       unit = row.Unit,
                                       qty = row.AssignQuantity
                                   }).ToList()
                               }).ToList();
                            feedmodel.details = groupedData;
                            _invokeMESService.FeedbackOutbound(feedmodel);
                        }
                    }
                }
                catch (Exception ex) {
                    _logger.LogError(" OutboundPickingService  FeedbackOutbound : " + ex.Message);
                }
            }
        }
@@ -276,165 +351,18 @@
        /// <summary>
        /// å›žåº“操作  
        /// </summary>
        //public async Task<WebResponseContent> ReturnRemaining(string orderNo, string palletCode, string reason)
        //{
        //    try
        //    {
        //        // 1. èŽ·å–æ‰€æœ‰æœªåˆ†æ‹£çš„å‡ºåº“é”å®šè®°å½•ï¼ŒåŒ…æ‹¬æ‹†åŒ…äº§ç”Ÿçš„è®°å½•
        //        var remainingLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
        //            .Where(it => it.OrderNo == orderNo && it.Status == 1)
        //            .ToListAsync();
        //        if (!remainingLocks.Any())
        //        {
        //            return WebResponseContent.Instance.Error("没有需要回库的剩余货物");
        //        }
        //        var tasks = new List<Dt_Task>();
        //        // æŒ‰æ‰˜ç›˜åˆ†ç»„
        //        var palletGroups = remainingLocks.GroupBy(x => x.PalletCode);
        //        //查询任务表
        //        var task = _taskRepository.QueryData(x => x.TaskNum == remainingLocks.First().TaskNum).FirstOrDefault();
        //        foreach (var group in palletGroups)
        //        {
        //            if (group.Key == palletCode)
        //            {
        //                var totalReturnQty = group.Sum(x => x.AssignQuantity - x.PickedQty);
        //                if (totalReturnQty <= 0) continue;
        //                // åˆ†é…æ–°è´§ä½
        //                var newLocation = _locationInfoService.AssignLocation();
        //                // æ›´æ–°å‡ºåº“锁定记录状态
        //                var lockIds = group.Where(x => x.PalletCode == palletCode).Select(x => x.Id).ToList();
        //                await _outStockLockInfoService.Db.Updateable<Dt_OutStockLockInfo>()
        //                    .SetColumns(it => new Dt_OutStockLockInfo { Status = OutLockStockStatusEnum.回库中.ObjToInt() })
        //                    .Where(it => lockIds.Contains(it.Id))
        //                    .ExecuteCommandAsync();
        //                // æ›´æ–°æ‹†åŒ…条码记录状态
        //                var splitBarcodes = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>()
        //                    .Where(it => lockIds.Contains(it.OutStockLockInfoId))
        //                    .ToListAsync();
        //                foreach (var splitBarcode in splitBarcodes)
        //                {
        //                    splitBarcode.Status = 3;
        //                    await _splitPackageService.Db.Updateable(splitBarcode).ExecuteCommandAsync();
        //                }
        //                foreach (var lockInfo in group)
        //                {
        //                    if (lockInfo.PalletCode == palletCode)
        //                    {
        //                        decimal returnQty = lockInfo.AssignQuantity - lockInfo.PickedQty;
        //                        // æ£€æŸ¥åº“存记录是否存在
        //                        var existingStock = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
        //                            .Where(it => it.Barcode == lockInfo.CurrentBarcode && it.StockId == lockInfo.StockId)
        //                            .FirstAsync();
        //                        if (existingStock != null)
        //                        {
        //                            // åº“存记录存在,恢复锁定数量
        //                            await _stockInfoDetailService.Db.Updateable<Dt_StockInfoDetail>()
        //                                .SetColumns(it => new Dt_StockInfoDetail
        //                                {
        //                                    OutboundQuantity = it.OutboundQuantity - returnQty
        //                                })
        //                                .Where(it => it.Barcode == lockInfo.CurrentBarcode && it.StockId == lockInfo.StockId)
        //                                .ExecuteCommandAsync();
        //                        }
        //                        else
        //                        {
        //                            // åº“存记录不存在(可能是拆包产生的新条码),创建新的库存记录
        //                            var newStockDetail = new Dt_StockInfoDetail
        //                            {
        //                                StockId = lockInfo.StockId,
        //                                MaterielCode = lockInfo.MaterielCode,
        //                                OrderNo = lockInfo.OrderNo,
        //                                BatchNo = lockInfo.BatchNo,
        //                                StockQuantity = returnQty, // å®žé™…库存数量
        //                                OutboundQuantity = 0, // å›žåº“后不再锁定
        //                                Barcode = lockInfo.CurrentBarcode,
        //                                InboundOrderRowNo = "0",
        //                                Status = StockStatusEmun.入库确认.ObjToInt(),
        //                            };
        //                            await _stockInfoDetailService.Db.Insertable(newStockDetail).ExecuteCommandAsync();
        //                        }
        //                    }
        //                }
        //                Dt_Task newtask = new()
        //                {
        //                    CurrentAddress = stations[task.TargetAddress],
        //                    Grade = 0,
        //                    PalletCode = palletCode,
        //                    NextAddress = "",
        //                    OrderNo= task.OrderNo,
        //                    Roadway = newLocation.RoadwayNo,
        //                    SourceAddress = stations[task.TargetAddress],
        //                    TargetAddress = newLocation.LocationCode,
        //                    TaskStatus = TaskStatusEnum.New.ObjToInt(),
        //                    TaskType = TaskTypeEnum.InPick.ObjToInt(),
        //                    // TaskNum = BaseDal.GetTaskNum(nameof(SequenceEnum.SeqTaskNum)),
        //                    PalletType = task.PalletType,
        //                    WarehouseId = task.WarehouseId,
        //                };
        //                tasks.Add(newtask);
        //            }
        //        }
        //        try
        //        {
        //            await _taskRepository.Db.Insertable(tasks).ExecuteCommandAsync();
        //            //删除 å‡ºåº“çš„  task
        //            //给 ess  æµåŠ¨ä¿¡å·  å’Œåˆ›å»ºä»»åŠ¡
        //        }
        //        catch (Exception ex)
        //        {
        //        }
        //        return WebResponseContent.Instance.OK();
        //    }
        //    catch (Exception ex)
        //    {
        //        return WebResponseContent.Instance.Error($"回库操作失败: {ex.Message}");
        //    }
        //}
        public async Task<WebResponseContent> ReturnRemaining(string orderNo, string palletCode, string reason)
        {
            try
            {
                // 1. èŽ·å–æ‰€æœ‰æœªåˆ†æ‹£çš„å‡ºåº“é”å®šè®°å½•ï¼ŒåŒ…æ‹¬æ‹†åŒ…äº§ç”Ÿçš„è®°å½•
                //  èŽ·å–æ‰€æœ‰æœªåˆ†æ‹£çš„å‡ºåº“é”å®šè®°å½•ï¼ŒåŒ…æ‹¬æ‹†åŒ…äº§ç”Ÿçš„è®°å½•
                var remainingLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
                    .Where(it => it.OrderNo == orderNo && it.Status == 1)
                    .ToListAsync();
                var stockinfo = _stockInfoService.Db.Queryable<Dt_StockInfo>().First(x => x.PalletCode == palletCode);
                // 2. æ£€æŸ¥æ‰˜ç›˜ä¸Šæ˜¯å¦æœ‰å…¶ä»–非出库货物(库存货物)
                var palletStockGoods = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
                    .Where(it => it.StockId == stockinfo.Id && it.Status == StockStatusEmun.入库确认.ObjToInt())
                    .Where(it => it.OutboundQuantity == 0 || it.OutboundQuantity < it.StockQuantity) // æœªå®Œå…¨å‡ºåº“çš„
                    .ToListAsync();
                // 3. å¦‚果没有需要回库的货物(既无未分拣出库货物,也无其他库存货物)
                if (!remainingLocks.Any() && !palletStockGoods.Any())
                {
                    return WebResponseContent.Instance.Error("没有需要回库的剩余货物");
                }
                var tasks = new List<Dt_Task>();
@@ -447,6 +375,21 @@
                {
                    return WebResponseContent.Instance.Error("未找到对应的任务信息");
                }
                //  æ£€æŸ¥æ‰˜ç›˜ä¸Šæ˜¯å¦æœ‰å…¶ä»–非出库货物(库存货物)
                var palletStockGoods = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
                    .Where(it => it.StockId == stockinfo.Id && (it.Status == StockStatusEmun.入库确认.ObjToInt() || it.Status == StockStatusEmun.入库完成.ObjToInt() || it.Status == StockStatusEmun.出库锁定.ObjToInt()))
                    .Where(it => it.OutboundQuantity == 0 || it.OutboundQuantity < it.StockQuantity) // æœªå®Œå…¨å‡ºåº“çš„
                    .ToListAsync();
                //  å¦‚果没有需要回库的货物(既无未分拣出库货物,也无其他库存货物)
                if (!remainingLocks.Any() && !palletStockGoods.Any())
                {
                    //是否自动回库,把之前出库的任务删除,然后组个空盘入库。
                    return WebResponseContent.Instance.Error("没有需要回库的剩余货物");
                }
                var firstlocation = _locationInfoService.Db.Queryable<Dt_LocationInfo>().First(x => x.LocationCode == task.SourceAddress);
                decimal totalReturnQty = 0;
                var hasRemainingLocks = remainingLocks.Any(x => x.PalletCode == palletCode);
@@ -538,7 +481,7 @@
                    totalReturnQty = palletStockGoods.Sum(x => x.StockQuantity - x.OutboundQuantity);
                }
                // ä¿å­˜ä»»åŠ¡
                // ä¿å­˜ä»»åŠ¡ ç»™ESS下发任务
                if (tasks.Any())
                {
                    try
@@ -687,11 +630,11 @@
                var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
                       .Where(x => x.Barcode == barcode && x.StockId == outStockInfo.StockId)
                       .FirstAsync();
                stockDetail.StockQuantity += outStockInfo.AssignQuantity;
                stockDetail.OutboundQuantity += outStockInfo.AssignQuantity;
                await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync();
                // è¿˜åŽŸå‡ºåº“å•æ˜Žç»†
                var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
@@ -699,6 +642,7 @@
                    .FirstAsync();
                orderDetail.OverOutQuantity -= outStockInfo.AssignQuantity;
                orderDetail.PickedQty = 0;
                await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync();
                // åˆ é™¤æ‹£é€‰åŽ†å²