pan
2025-11-15 4476740c214edb7ab667c48fcab00488fbdd9879
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundPickingService.cs
@@ -1,4 +1,6 @@
using System;
using Microsoft.AspNetCore.Http;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -9,6 +11,7 @@
using WIDESEA_Core;
using WIDESEA_Core.BaseRepository;
using WIDESEA_Core.BaseServices;
using WIDESEA_Core.Helper;
using WIDESEA_DTO.Outbound;
using WIDESEA_IBasicService;
using WIDESEA_IOutboundService;
@@ -31,10 +34,11 @@
        private readonly IStockInfoDetailService _stockInfoDetailService;
        private readonly ILocationInfoService _locationInfoService;
        private readonly IOutboundOrderDetailService _outboundOrderDetailService;
        private readonly IOutboundOrderService _outboundOrderService;
        private readonly ISplitPackageService _splitPackageService;
        public OutboundPickingService(IRepository<Dt_PickingRecord> BaseDal, IUnitOfWorkManage unitOfWorkManage, IStockInfoService stockInfoService, IStockService stockService, IOutStockLockInfoService outStockLockInfoService, IStockInfoDetailService stockInfoDetailService, ILocationInfoService locationInfoService, IOutboundOrderDetailService outboundOrderDetailService, ISplitPackageService splitPackageService) : 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) : base(BaseDal)
        {
            _unitOfWorkManage = unitOfWorkManage;
            _stockInfoService = stockInfoService;
@@ -44,9 +48,10 @@
            _locationInfoService = locationInfoService;
            _outboundOrderDetailService = outboundOrderDetailService;
            _splitPackageService = splitPackageService;
            _outboundOrderService = outboundOrderService;
        }
        #region æŸ¥è¯¢å‡ºåº“详情列表
        public async Task<List<OutStockLockListResp>> GetOutStockLockListAsync(string orderNo)
        {
@@ -57,13 +62,13 @@
            return locks.Select(t => new OutStockLockListResp
            {
                Id = t.Id,
               // TaskNum = t.TaskNum,
                // TaskNum = t.TaskNum,
                PalletCode = t.PalletCode,
                CurrentBarcode = t.CurrentBarcode,
                AssignQuantity = t.AssignQuantity,
                PickedQty = t.PickedQty,
                Status = t.Status,
              //  IsSplitted = t.IsSplitted
                //  IsSplitted = t.IsSplitted
            }).ToList();
        }
        #endregion
@@ -87,13 +92,13 @@
                    return WebResponseContent.Instance.Error("条码不存在");
                }
                var result = new
                {
                    Barcode = barcode,
                    MaterielCode = stockDetail.MaterielCode,
                    BatchNo = stockDetail.BatchNo,
                    AvailableQuantity = stockDetail.StockQuantity - stockDetail.OutboundQuantity,
                    LocationCode = stockDetail.StockInfo?.LocationCode,
@@ -203,6 +208,162 @@
            }
        }
        public async Task<WebResponseContent> ConfirmPicking(string orderNo, string palletCode, string barcode)
        {
            try
            {
                _unitOfWorkManage.BeginTran();
                // 1. éªŒè¯æ¡ç æœ‰æ•ˆæ€§
                var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
                        .Where(x => x.Barcode == barcode)
                        .FirstAsync();
                if (stockDetail == null)
                    return WebResponseContent.Instance.Error("无效的条码或物料编码");
                // 2. æ£€æŸ¥åº“存可用数量
                var availableQty = stockDetail.StockQuantity - stockDetail.OutboundQuantity;
                if (availableQty <= 0)
                    return WebResponseContent.Instance.Error("库存数量不足");
                // 3. æŸ¥æ‰¾ç›¸å…³çš„出库详情信息
                var outStockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
                    .Where(x => x.OrderNo == orderNo &&
                               x.PalletCode == palletCode &&
                               x.CurrentBarcode == barcode &&
                               x.Status == 0 &&
                               x.RemainQuantity > 0)
                    .FirstAsync();
                if (outStockInfo == null)
                    return WebResponseContent.Instance.Error("未找到对应的拣选信息或已拣选完成");
                // 4. æ£€æŸ¥å‡ºåº“详情锁定数量
                if (outStockInfo.RemainQuantity <= 0)
                    return WebResponseContent.Instance.Error("该条码已无剩余可拣选数量");
                // 5. æ›´æ–°å‡ºåº“详情的已拣选数量
                outStockInfo.PickedQty = outStockInfo.AssignQuantity;
                outStockInfo.Status = 1;
                await _outStockLockInfoService.Db.Updateable(outStockInfo).ExecuteCommandAsync();
                // 6. æ›´æ–°åº“存出库数量
                await _stockInfoDetailService.Db.Updateable<Dt_StockInfoDetail>()
                    .SetColumns(x => x.OutboundQuantity == x.OutboundQuantity + outStockInfo.AssignQuantity)
                    .Where(x => x.Id == stockDetail.Id)
                    .ExecuteCommandAsync();
                // 7. æ›´æ–°å‡ºåº“单明细
                var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
                    .Where(x => x.Id == outStockInfo.OrderDetailId)
                    .FirstAsync();
                orderDetail.OverOutQuantity += outStockInfo.AssignQuantity;
                await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync();
                // 8. æ£€æŸ¥æ˜¯å¦å®Œæˆå‡ºåº“
                await CheckAndUpdateOrderStatus(orderNo);
                // 9. è®°å½•拣选历史
                var pickingHistory = new Dt_PickingRecord
                {
                    OrderNo = orderNo,
                    PalletCode = palletCode,
                    Barcode = barcode,
                    MaterielCode = outStockInfo.MaterielCode,
                    PickQuantity = outStockInfo.AssignQuantity,
                    PickTime = DateTime.Now,
                    OutStockLockId = outStockInfo.Id
                };
                await Db.Insertable(pickingHistory).ExecuteCommandAsync();
                _unitOfWorkManage.CommitTran();
                return WebResponseContent.Instance.OK("拣选确认成功");
            }
            catch (Exception ex)
            {
                return WebResponseContent.Instance.Error($"拣选确认失败:{ex.Message}");
            }
        }
        // æ£€æŸ¥å¹¶æ›´æ–°è®¢å•状态
        private async Task CheckAndUpdateOrderStatus(string orderNo)
        {
            var orderDetails = await _stockInfoDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
                .Where(x => x.OrderId == orderNo.ObjToInt())
                .ToListAsync();
            bool allCompleted = true;
            foreach (var detail in orderDetails)
            {
                if (detail.OverOutQuantity < detail.NeedOutQuantity)
                {
                    allCompleted = false;
                    break;
                }
            }
            if (allCompleted)
            {
                await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>()
                    .SetColumns(x => x.OrderStatus == 2) // å·²å®Œæˆ
                    .Where(x => x.OrderNo == orderNo)
                    .ExecuteCommandAsync();
            }
        }
        // å–消拣选功能
        public async Task<WebResponseContent> CancelPicking(string orderNo, string palletCode, string barcode)
        {
            try
            {
                _unitOfWorkManage.BeginTran();
                // æŸ¥æ‰¾æ‹£é€‰è®°å½•
                var outStockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
                        .Where(x => x.OrderNo == orderNo &&
                                   x.PalletCode == palletCode &&
                                   x.CurrentBarcode == barcode &&
                                   x.Status == 1)
                        .FirstAsync();
                if (outStockInfo == null)
                    return WebResponseContent.Instance.Error("未找到已拣选记录");
                // è¿˜åŽŸå‡ºåº“è¯¦æƒ…çŠ¶æ€
                outStockInfo.PickedQty = 0;
                outStockInfo.Status = 0;
                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 orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
                    .Where(x => x.Id == outStockInfo.OrderDetailId)
                    .FirstAsync();
                orderDetail.OverOutQuantity -= outStockInfo.AssignQuantity;
                await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync();
                // åˆ é™¤æ‹£é€‰åŽ†å²
                await Db.Deleteable<Dt_PickingRecord>()
                    .Where(x => x.OutStockLockId == outStockInfo.Id)
                    .ExecuteCommandAsync();
                _unitOfWorkManage.CommitTran();
                return WebResponseContent.Instance.OK("取消拣选成功");
            }
            catch (Exception ex)
            {
                return WebResponseContent.Instance.Error($"取消拣选失败:{ex.Message}");
            }
        }
        /// <summary>
        /// æ ¹æ®æ¡ç æŸ¥æ‰¾é”å®šä¿¡æ¯
        /// </summary>
@@ -217,6 +378,45 @@
                .FirstAsync();
        }
        // èŽ·å–æœªæ‹£é€‰åˆ—è¡¨
        public async Task<List<Dt_OutStockLockInfo>> GetUnpickedList(string orderNo, string palletCode)
        {
            var list = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
                .Where(x => x.OrderNo == orderNo &&
                           x.PalletCode == palletCode &&
                           x.Status == 0 &&
                       x.RemainQuantity > 0)
                .ToListAsync();
            return list;
        }
        // èŽ·å–å·²æ‹£é€‰åˆ—è¡¨
        public async Task<List<Dt_OutStockLockInfo>> GetPickedList(string orderNo, string palletCode)
        {
            var list = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
                .Where(x => x.OrderNo == orderNo &&
                           x.PalletCode == palletCode &&
                           x.Status == 1)
                .ToListAsync();
            return list;
        }
        // èŽ·å–æ‹£é€‰æ±‡æ€»
        public async Task<object> GetPickingSummary(string orderNo)
        {
            var summary = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
                .Where(x => x.OrderNo == orderNo && x.Status == 0)
                .GroupBy(x => new { x.PalletCode, x.MaterielCode })
                .Select(x => new
                {
                    PalletCode = x.PalletCode,
                    MaterielCode = x.MaterielCode,
                    UnpickedCount = SqlFunc.AggregateCount(x.Id),
                    UnpickedQuantity = SqlFunc.AggregateSum(x.RemainQuantity)
                })
                .ToListAsync();
            return  summary;
        }
        /// <summary>
        /// èŽ·å–æ‹£é€‰åŽ†å²
        /// </summary>
@@ -235,6 +435,25 @@
                .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>