pan
2025-11-17 5fc251a847ccc0540da8b112ed2bddba846455d8
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundPickingService.cs
@@ -139,99 +139,6 @@
            }
        }
        /// <summary>
        /// æ‰«ç æ‹£é€‰ç¡®è®¤
        /// </summary>
        public async Task<WebResponseContent> ConfirmPicking(PickingConfirmRequest request)
        {
            try
            {
                _unitOfWorkManage.BeginTran();
                // 1. éªŒè¯æ¡ç æœ‰æ•ˆæ€§
                var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
                    .Where(x => x.Barcode == request.Barcode && x.MaterielCode == request.MaterielCode)
                    .FirstAsync();
                if (stockDetail == null)
                    return WebResponseContent.Instance.Error("无效的条码或物料编码");
                // 2. æ£€æŸ¥åº“存可用数量
                decimal availableQuantity = stockDetail.StockQuantity - stockDetail.OutboundQuantity;
                if (request.PickQuantity > availableQuantity)
                    return WebResponseContent.Instance.Error($"拣选数量超过可用库存,可用数量:{availableQuantity}");
                // 3. æŸ¥æ‰¾ç›¸å…³çš„出库锁定信息(支持拆包后的新条码)
                var lockInfo = await FindLockInfoByBarcode(request.OrderDetailId, request.Barcode, request.MaterielCode);
                if (lockInfo == null)
                    return WebResponseContent.Instance.Error("未找到相关的出库锁定信息");
                // 4. æ£€æŸ¥é”å®šæ•°é‡
                decimal remainingLockQuantity = lockInfo.AssignQuantity - lockInfo.PickedQty;
                if (request.PickQuantity > remainingLockQuantity)
                    return WebResponseContent.Instance.Error($"拣选数量超过锁定数量,剩余可拣选:{remainingLockQuantity}");
                // 5. æ›´æ–°é”å®šä¿¡æ¯çš„已拣选数量
                lockInfo.PickedQty += request.PickQuantity;
                await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
                // 6. æ›´æ–°åº“存出库数量 - å®žé™…减少库存
                stockDetail.OutboundQuantity += request.PickQuantity;
                await _stockInfoService.Db.Updateable(stockDetail).ExecuteCommandAsync();
                // 7. æ›´æ–°å‡ºåº“单明细
                var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
                    .Where(x => x.Id == request.OrderDetailId)
                    .FirstAsync();
                orderDetail.OverOutQuantity += request.PickQuantity;
                orderDetail.LockQuantity -= request.PickQuantity;
                // æ£€æŸ¥æ˜¯å¦å®Œæˆå‡ºåº“
                if (Math.Abs(orderDetail.OverOutQuantity - orderDetail.OrderQuantity) < 0.001m)
                {
                    orderDetail.OrderDetailStatus = (int)OrderDetailStatusEnum.Over;
                    orderDetail.LockQuantity = 0;
                    // æ›´æ–°ç›¸å…³çš„锁定信息状态为已出库
                    var relatedLockInfos = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
                        .Where(x => x.OrderDetailId == request.OrderDetailId &&
                                   x.Status == (int)OutLockStockStatusEnum.出库中)
                        .ToListAsync();
                    foreach (var relatedLock in relatedLockInfos)
                    {
                        relatedLock.Status = (int)OutLockStockStatusEnum.已出库;
                    }
                    await _outStockLockInfoService.Db.Updateable(relatedLockInfos).ExecuteCommandAsync();
                }
                await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync();
                // 8. è®°å½•拣选历史
                var pickHistory = new Dt_PickingRecord
                {
                    OrderDetailId = request.OrderDetailId,
                    Barcode = request.Barcode,
                    PickQuantity = request.PickQuantity,
                    PickTime = DateTime.Now,
                    LocationCode = request.LocationCode,
                    StockId = stockDetail.StockId
                };
                await Db.Insertable(pickHistory).ExecuteCommandAsync();
                _unitOfWorkManage.CommitTran();
                return WebResponseContent.Instance.OK("拣选确认成功");
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return WebResponseContent.Instance.Error($"拣选确认失败: {ex.Message}");
            }
        }
        public async Task<WebResponseContent> ConfirmPicking(string orderNo, string palletCode, string barcode)
        {
@@ -637,13 +544,14 @@
                    try
                    {
                        await _taskRepository.Db.Insertable(tasks).ExecuteCommandAsync();
                        var targetAddress = task.TargetAddress;
                        _taskRepository.DeleteData(task);
                        // ç»™ ESS æµåŠ¨ä¿¡å·å’Œåˆ›å»ºä»»åŠ¡
                        try
                        {
                            var result = await _eSSApiService.MoveContainerAsync(new WIDESEA_DTO.Basic.MoveContainerRequest
                            {
                                slotCode = movestations[task.TargetAddress],
                                slotCode = movestations[targetAddress],
                                containerCode = palletCode
                            });
                            if (result)
@@ -662,7 +570,7 @@
                                            taskDescribe = new TaskDescribeType {
                                                containerCode = palletCode,
                                                containerType = "CT_KUBOT_STANDARD",
                                                fromLocationCode = stations.GetValueOrDefault(task.TargetAddress) ?? "",
                                                fromLocationCode = stations.GetValueOrDefault(targetAddress) ?? "",
                                                toStationCode = "",
                                                toLocationCode = tasks.First().TargetAddress,
                                                deadline = 0, storageTag = ""
@@ -670,7 +578,7 @@
                                        }
                                    }
                                };
                                var resulttask = await _eSSApiService.CreateTaskAsync(esstask);
@@ -682,7 +590,7 @@
                            _logger.LogInformation("ReturnRemaining åˆ›å»ºä»»åŠ¡è¿”å›ž catch err:  " + ex.Message);
                        }
                        return WebResponseContent.Instance.OK($"回库操作成功,共回库数量:{totalReturnQty}");
                    }
@@ -764,7 +672,7 @@
                        .Where(x => x.OrderNo == orderNo &&
                                   x.PalletCode == palletCode &&
                                   x.CurrentBarcode == barcode &&
                                   x.Status == 2)
                                   x.Status == 6)
                        .FirstAsync();
                if (outStockInfo == null)
@@ -775,11 +683,15 @@
                outStockInfo.Status = 1;
                await _outStockLockInfoService.Db.Updateable(outStockInfo).ExecuteCommandAsync();
                //// è¿˜åŽŸåº“å­˜å‡ºåº“æ•°é‡
                //await _stockInfoDetailService.Db.Updateable<Dt_StockInfoDetail>()
                //        .SetColumns(x => x.OutboundQuantity == x.OutboundQuantity - outStockInfo.AssignQuantity)
                //        .Where(x => x.Barcode == barcode)
                //        .ExecuteCommandAsync();
                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>()
@@ -802,19 +714,6 @@
            {
                return WebResponseContent.Instance.Error($"取消拣选失败:{ex.Message}");
            }
        }
        /// <summary>
        /// æ ¹æ®æ¡ç æŸ¥æ‰¾é”å®šä¿¡æ¯
        /// </summary>
        private async Task<Dt_OutStockLockInfo> FindLockInfoByBarcode(int orderDetailId, string barcode, string materielCode)
        {
            return await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
                .Where(x => x.OrderDetailId == orderDetailId &&
                           x.MaterielCode == materielCode &&
                           x.CurrentBarcode == barcode &&
                           x.Status == (int)OutLockStockStatusEnum.出库中 &&
                           x.AssignQuantity > x.PickedQty)
                .FirstAsync();
        }
        // èŽ·å–æœªæ‹£é€‰åˆ—è¡¨
@@ -896,88 +795,6 @@
                .ToListAsync();
        }
        public async Task GetPalletPickingSummary(string orderNo, string palletCode)
        {
            var summary = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
                .Where(x => x.OrderNo == orderNo && x.PalletCode == palletCode)
                .GroupBy(x => new { x.PalletCode, x.Status })
                .Select(x => new
                {
                    PalletCode = x.PalletCode,
                    Status = x.Status,
                    TotalAssignQty = SqlFunc.AggregateSum(x.AssignQuantity),
                    TotalPickedQty = SqlFunc.AggregateSum(x.PickedQty)
                })
                .ToListAsync();
            //   return summary;
        }
        /// <summary>
        /// æ’¤é”€æ‹£é€‰
        /// </summary>
        public async Task<WebResponseContent> CancelPicking(CancelPickingRequest request)
        {
            // å®žçŽ°æ’¤é”€æ‹£é€‰çš„é€»è¾‘ï¼Œéœ€è¦ï¼š
            // 1. æ¢å¤åº“存出库数量
            // 2. æ¢å¤é”å®šä¿¡æ¯çš„已拣选数量
            // 3. æ¢å¤å‡ºåº“单明细的已出数量和锁定数量
            // 4. åˆ é™¤æˆ–标记拣选历史记录
            // æ³¨æ„ï¼šè¿™é‡Œéœ€è¦äº‹åŠ¡å¤„ç†
            try
            {
                _unitOfWorkManage.BeginTran();
                var pickHistory = await Db.Queryable<Dt_PickingRecord>()
                    .Where(x => x.Id == request.PickingHistoryId)
                    .FirstAsync();
                if (pickHistory == null)
                    return WebResponseContent.Instance.Error("未找到拣选记录");
                // æ¢å¤åº“å­˜
                var stockDetail = await _stockInfoService.Db.Queryable<Dt_StockInfoDetail>()
                    .Where(x => x.Barcode == pickHistory.Barcode && x.StockId == pickHistory.StockId)
                    .FirstAsync();
                if (stockDetail != null)
                {
                    stockDetail.OutboundQuantity -= pickHistory.PickQuantity;
                    await _stockInfoService.Db.Updateable(stockDetail).ExecuteCommandAsync();
                }
                // æ¢å¤é”å®šä¿¡æ¯
                var lockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
                    .Where(x => x.OrderDetailId == pickHistory.OrderDetailId && x.StockId == pickHistory.StockId)
                    .FirstAsync();
                lockInfo.PickedQty -= pickHistory.PickQuantity;
                await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
                // æ¢å¤å‡ºåº“单明细
                var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
                    .Where(x => x.Id == pickHistory.OrderDetailId)
                    .FirstAsync();
                orderDetail.OverOutQuantity -= pickHistory.PickQuantity;
                orderDetail.LockQuantity += pickHistory.PickQuantity;
                if (orderDetail.OverOutQuantity < orderDetail.OrderQuantity)
                {
                    orderDetail.OrderDetailStatus = orderDetail.LockQuantity > 0 ?
                        (int)OrderDetailStatusEnum.Outbound : (int)OrderDetailStatusEnum.AssignOverPartial;
                }
                await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync();
                // åˆ é™¤æ‹£é€‰åŽ†å²è®°å½•
                await Db.Deleteable<Dt_PickingRecord>().Where(x => x.Id == request.PickingHistoryId).ExecuteCommandAsync();
                _unitOfWorkManage.CommitTran();
                return WebResponseContent.Instance.OK("撤销成功");
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return WebResponseContent.Instance.Error($"撤销失败: {ex.Message}");
            }
        }
        /// <summary>
        /// èŽ·å–æ‰˜ç›˜çš„å‡ºåº“çŠ¶æ€ä¿¡æ¯