pan
2025-11-16 e31ca4e3e1774b7ddb832e8ec498b5ada24b2608
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundPickingService.cs
@@ -1,4 +1,6 @@
using Microsoft.AspNetCore.Http;
using Dm.filter;
using MailKit.Search;
using Microsoft.AspNetCore.Http;
using SqlSugar;
using System;
using System.Collections.Generic;
@@ -36,9 +38,10 @@
        private readonly IOutboundOrderDetailService _outboundOrderDetailService;
        private readonly IOutboundOrderService _outboundOrderService;
        private readonly ISplitPackageService _splitPackageService;
        private readonly IRepository<Dt_Task> _taskRepository;
        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)
        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) : base(BaseDal)
        {
            _unitOfWorkManage = unitOfWorkManage;
            _stockInfoService = stockInfoService;
@@ -49,6 +52,7 @@
            _outboundOrderDetailService = outboundOrderDetailService;
            _splitPackageService = splitPackageService;
            _outboundOrderService = outboundOrderService;
            _taskRepository = taskRepository;
        }
@@ -114,8 +118,7 @@
        }
        /// <summary>
        /// æ‰«ç æ‹£é€‰ç¡®è®¤ - ç®€åŒ–版本
        /// åªå¤„理实际拣选的库存扣减
        /// æ‰«ç æ‹£é€‰ç¡®è®¤
        /// </summary>
        public async Task<WebResponseContent> ConfirmPicking(PickingConfirmRequest request)
        {
@@ -221,19 +224,20 @@
                if (stockDetail == null)
                    return WebResponseContent.Instance.Error("无效的条码或物料编码");
                // 2. æ£€æŸ¥åº“存可用数量
                var availableQty = stockDetail.StockQuantity - stockDetail.OutboundQuantity;
                if (availableQty <= 0)
                    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)
                               x.Status == (int)OutLockStockStatusEnum.出库中 &&
                               x.AssignQuantity - x.PickedQty > 0)
                    .FirstAsync();
                if (outStockInfo == null)
                    return WebResponseContent.Instance.Error("未找到对应的拣选信息或已拣选完成");
@@ -244,36 +248,45 @@
                // 5. æ›´æ–°å‡ºåº“详情的已拣选数量
                outStockInfo.PickedQty = outStockInfo.AssignQuantity;
                outStockInfo.Status = 1;
                outStockInfo.Status = (int)OutLockStockStatusEnum.已拣选;
                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();
                //// 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();
                if (orderDetail != null)
                {
                orderDetail.OverOutQuantity += outStockInfo.AssignQuantity;
                    orderDetail.LockQuantity -= outStockInfo.AssignQuantity;
                await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync();
                }
                // 8. æ£€æŸ¥æ˜¯å¦å®Œæˆå‡ºåº“
                await CheckAndUpdateOrderStatus(orderNo);
                //查询任务表
                var task = _taskRepository.QueryData(x => x.OrderNo == orderNo && x.PalletCode == palletCode).FirstOrDefault();
                // 9. è®°å½•拣选历史
                var pickingHistory = new Dt_PickingRecord
                {
                    FactoryArea = outStockInfo.FactoryArea,
                    TaskNo = task?.TaskNum ?? 0,
                    LocationCode = task?.SourceAddress ?? "",
                    StockId = stockDetail.Id,
                    OrderNo = orderNo,
                    OrderDetailId = orderDetail?.Id ?? 0,
                    PalletCode = palletCode,
                    Barcode = barcode,
                    MaterielCode = outStockInfo.MaterielCode,
                    PickQuantity = outStockInfo.AssignQuantity,
                    PickTime = DateTime.Now,
                    Operator = App.User.UserName,
                    OutStockLockId = outStockInfo.Id
                };
                await Db.Insertable(pickingHistory).ExecuteCommandAsync();
@@ -325,7 +338,7 @@
                        .Where(x => x.OrderNo == orderNo &&
                                   x.PalletCode == palletCode &&
                                   x.CurrentBarcode == barcode &&
                                   x.Status == 1)
                                   x.Status == 2)
                        .FirstAsync();
                if (outStockInfo == null)
@@ -333,14 +346,14 @@
                // è¿˜åŽŸå‡ºåº“è¯¦æƒ…çŠ¶æ€
                outStockInfo.PickedQty = 0;
                outStockInfo.Status = 0;
                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();
                //// è¿˜åŽŸåº“å­˜å‡ºåº“æ•°é‡
                //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>()
@@ -384,10 +397,9 @@
            var list = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
                .Where(x => x.OrderNo == orderNo &&
                           x.PalletCode == palletCode &&
                           x.Status == 0 &&
                       x.RemainQuantity > 0)
                           x.Status == 1)
                .ToListAsync();
            return list;
            return list.Where(x => x.RemainQuantity > 0).ToList();
        }
        // èŽ·å–å·²æ‹£é€‰åˆ—è¡¨
@@ -396,24 +408,66 @@
            var list = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
                .Where(x => x.OrderNo == orderNo &&
                           x.PalletCode == palletCode &&
                           x.Status == 1)
                           x.Status == 2)
                .ToListAsync();
            return list;
        }
        // èŽ·å–æ‹£é€‰æ±‡æ€»
        public async Task<object> GetPickingSummary(string orderNo)
        public async Task<object> GetPickingSummary(string orderNo, string palletCode)
        {
            var summary = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
                .Where(x => x.OrderNo == orderNo && x.Status == 0)
                .Where(x => x.OrderNo == orderNo &&
                           x.PalletCode == palletCode && x.Status == 1)
                .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)
                    UnpickedQuantity = SqlFunc.AggregateSum(x.AssignQuantity) - SqlFunc.AggregateSum(x.PickedQty)
                })
                .ToListAsync();
                .FirstAsync();
            return summary;
        }
        // èŽ·å–æ‹£é€‰æ±‡æ€»
        public async Task<object> GetPickingSummary(ConfirmPickingDto dto)
        {
            var picked = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
             .WhereIF(!string.IsNullOrEmpty(dto.OrderNo), x => x.OrderNo == dto.OrderNo)
             .WhereIF(!string.IsNullOrEmpty(dto.PalletCode), x => x.PalletCode == dto.PalletCode)
             .Where(x => x.Status == 2)
             .GroupBy(x => new { x.PalletCode, x.MaterielCode })
             .Select(x => new SummaryPickingDto
             {
                 PalletCode = x.PalletCode,
                 MaterielCode = x.MaterielCode,
                 pickedCount = SqlFunc.AggregateCount(x.Id)
             }).FirstAsync();
            if (picked == null)
            {
                picked = new SummaryPickingDto { pickedCount = 0 };
            }
            var summary = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
                .WhereIF(!string.IsNullOrEmpty(dto.OrderNo), x => x.OrderNo == dto.OrderNo)
                .WhereIF(!string.IsNullOrEmpty(dto.PalletCode), x => x.PalletCode == dto.PalletCode)
                .Where(x => x.Status == 1)
                .GroupBy(x => new { x.PalletCode, x.MaterielCode })
                .Select(x => new SummaryPickingDto
                {
                    PalletCode = x.PalletCode,
                    MaterielCode = x.MaterielCode,
                    UnpickedCount = SqlFunc.AggregateCount(x.Id),
                    UnpickedQuantity = SqlFunc.AggregateSum(x.AssignQuantity) - SqlFunc.AggregateSum(x.PickedQty),
                }).FirstAsync();
            if (summary == null)
            {
                summary = new SummaryPickingDto { pickedCount = 0 };
            }
            summary.pickedCount = picked.pickedCount;
            return  summary;
        }
@@ -587,50 +641,59 @@
            {
                _unitOfWorkManage.BeginTran();
                // 1. èŽ·å–æ‰˜ç›˜åº“å­˜ä¿¡æ¯
                var stockInfo = await _stockInfoService.Db.Queryable<Dt_StockInfo>()
                    .Includes(x => x.Details)
                    .Where(x => x.PalletCode == request.PalletCode)
                    .FirstAsync();
                    .Where(x => x.PalletCode == request.PalletCode).FirstAsync();
                if (stockInfo == null)
                    return WebResponseContent.Instance.Error("未找到托盘库存信息");
                // 2. èŽ·å–ç›¸å…³çš„å‡ºåº“é”å®šä¿¡æ¯
                var lockInfos = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
                    .Where(x => x.PalletCode == request.PalletCode &&
                               x.Status == (int)OutLockStockStatusEnum.出库中)
                    .Where(x => x.OrderNo == request.OrderNo && x.PalletCode == request.PalletCode)
                    .ToListAsync();
                // 3. æ•´ä¸ªæ‰˜ç›˜å‡ºåº“ - è®¾ç½®å‡ºåº“数量等于库存数量
                foreach (var detail in stockInfo.Details)
                {
                    decimal outboundQuantity = detail.StockQuantity - detail.OutboundQuantity;
                    detail.OutboundQuantity = detail.StockQuantity; // å…¨éƒ¨å‡ºåº“
                    await _stockInfoDetailService.Db.Updateable(detail).ExecuteCommandAsync();
                }
                // 4. æ›´æ–°å‡ºåº“锁定信息
                foreach (var lockInfo in lockInfos)
                {
                    decimal unpicked = lockInfo.AssignQuantity - lockInfo.PickedQty;
                    lockInfo.PickedQty += unpicked; // æ ‡è®°ä¸ºå…¨éƒ¨æ‹£é€‰
                    if (lockInfo.Status == (int)OutLockStockStatusEnum.出库中)
                    {
                        lockInfo.PickedQty = lockInfo.AssignQuantity;
                    }
                    lockInfo.Status = (int)OutLockStockStatusEnum.已出库;
                    await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
                    // æ›´æ–°å‡ºåº“单明细
                    var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
                        .Where(x => x.Id == lockInfo.OrderDetailId)
                        .FirstAsync();
                    orderDetail.OverOutQuantity += unpicked;
                    orderDetail.LockQuantity -= unpicked;
                    if (orderDetail != null)
                    {
                        orderDetail.OverOutQuantity += lockInfo.PickedQty;
                        orderDetail.LockQuantity -= lockInfo.PickedQty;
                    orderDetail.OrderDetailStatus = (int)OrderDetailStatusEnum.Over;
                    orderDetail.LockQuantity = 0;
                    await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync();
                }
                }
                var groupDetails = lockInfos.GroupBy(x => x.OrderDetailId).Select(x => new
                {
                    OrderDetailId = x.Key,
                    TotalQuantity = x.Sum(o => o.PickedQty)
                }).ToList();
                foreach (var item in groupDetails)
                {
                    var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>().Where(x => x.Id == item.OrderDetailId).FirstAsync();
                    if (orderDetail != null)
                    {
                        orderDetail.OverOutQuantity = item.TotalQuantity;
                        orderDetail.LockQuantity = 0;
                        orderDetail.OrderDetailStatus = (int)OrderDetailStatusEnum.Over;
                        await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync();
                    }
                }
                // 5. æ›´æ–°æ‹†åŒ…记录状态
                await CheckAndUpdateOrderStatus(request.OrderNo);
                var lockInfoIds = lockInfos.Select(x => x.Id).ToList();
                var splitRecords = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>()
                    .Where(x => lockInfoIds.Contains(x.OutStockLockInfoId) &&
@@ -643,7 +706,7 @@
                    await _splitPackageService.Db.Updateable(record).ExecuteCommandAsync();
                }
                // 6. æ¸…空货位
                var location = await _locationInfoService.Db.Queryable<Dt_LocationInfo>()
                    .Where(x => x.LocationCode == stockInfo.LocationCode)
                    .FirstAsync();
@@ -653,6 +716,14 @@
                    await _locationInfoService.Db.Updateable(location).ExecuteCommandAsync();
                }
                foreach (var detail in stockInfo.Details)
                {
                    await _stockInfoDetailService.Db.Deleteable(detail).ExecuteCommandAsync();
                }
                await _stockInfoService.Db.Deleteable(stockInfo).ExecuteCommandAsync();
                _unitOfWorkManage.CommitTran();
                return WebResponseContent.Instance.OK("直接出库成功");
            }