1
huangxiaoqiang
2025-12-16 7a7b559723e20de635d3888ea58eb151993c2ca2
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundService.cs
@@ -97,15 +97,31 @@
                        if (outStockLockInfo != null)
                        {
                            outStockLockInfo = item;
                            Dt_Task? task = tasks.FirstOrDefault(x => x.PalletCode == item.PalletCode);
                            if (task != null)
                            {
                                outStockLockInfo.TaskNum = task.TaskNum;
                            }
                        }
                        else
                        {
                            Dt_Task? task = tasks.FirstOrDefault(x => x.PalletCode == item.PalletCode);
                            if (task != null)
                            {
                                item.TaskNum = task.TaskNum;
                            }
                            materielCalc.OutStockLockInfos.Add(item);
                        }
                        outStockLockInfos.Add(item);
                    }
                    tasks.AddRange(materielPickedDetails.Tasks);
                    foreach (var item in materielPickedDetails.Tasks)
                    {
                        Dt_Task? task = tasks.FirstOrDefault(x => x.PalletCode == item.PalletCode);
                        if (task == null)
                        {
                            tasks.Add(item);
                        }
                    }
                    pickedDetails.AddRange(materielPickedDetails.PickedDetails);
@@ -353,9 +369,11 @@
                decimal availableQuantity = availableStockMap.GetValueOrDefault(stock.Id, 0);
                if (availableQuantity <= 0) continue;
                // è®¡ç®—该托盘可分配数量
                decimal allocateQuantity = Math.Min(remainingQuantity, availableQuantity);
                (decimal ActualAllocatedQuantity, List<Dt_OutStockLockInfo> LockInfoList) actualAllocated = AllocateStockQuantity(stock, allocateQuantity, availableQuantity, outboundOrder, firstDetail, request, lockStockMap.GetValueOrDefault(stock.Id, new List<Dt_OutStockLockInfo>()), stockDetailMap);
                // æœ¬æ¬¡åˆ†é…çš„æ•°é‡
                decimal actualAllocatedQuantity = actualAllocated.ActualAllocatedQuantity;
                if (actualAllocatedQuantity > 0)
@@ -502,7 +520,7 @@
                // è®¡ç®—总库存数量
                decimal totalQuantity = stockInfo.Details.Sum(x => x.StockQuantity);
                List<Dt_OutStockLockInfo> outStockLockInfos = allocatedData.Where(x => x.StockId == stockInfo.Id).ToList();
                List<Dt_OutStockLockInfo> outStockLockInfos = allocatedData.Where(x => x.StockId == stockInfo.Id && x.MaterielCode == materielCalc.MaterielCode).ToList();
                // è®¡ç®—已分配数量
                decimal allocatedQuantity = outStockLockInfos.Sum(x => x.AllocatedQuantity);
@@ -510,7 +528,6 @@
                lockStockMap[stockInfo.Id] = outStockLockInfos;
            }
            return (availableStockMap, lockStockMap);
        }
@@ -560,7 +577,7 @@
                    // æ›´æ–°åˆ†é…å‡ºåº“量
                    decimal beforeAssignQuantity = totalAllocatedQuantity; // æœ¬æ¬¡åˆ†é…å‰çš„æ€»ç´¯è®¡é‡
                    lockInfo.AssignQuantity += actualAllocatedQuantity; // ç´¯åŠ æœ¬æ¬¡åˆ†é…æ•°é‡
                    lockInfo.AssignQuantity += actualAllocatedQuantity; // æœ¬æ¬¡åˆ†é…æ•°é‡
                    lockInfo.AllocatedQuantity = beforeAssignQuantity; // è®°å½•本次分配前的总累计量
                    lockInfoList.Add(lockInfo);
@@ -789,16 +806,7 @@
                    return WebResponseContent.Instance.Error($"出库单 {request.OrderNo} ä¸å­˜åœ¨");
                }
                // 5. æŸ¥æ‰¾å‡ºåº“单明细信息
                List<Dt_OutboundOrderDetail> outboundOrderDetails = FindMatchingOutboundDetails(outboundOrder.Id, stockDetail);
                if (!outboundOrderDetails.Any())
                {
                    response.Success = false;
                    response.Message = $"未找到匹配的出库单明细,物料:{stockDetail.MaterielCode},批次:{stockDetail.BatchNo}";
                    return WebResponseContent.Instance.Error($"未找到匹配的出库单明细,物料:{stockDetail.MaterielCode},批次:{stockDetail.BatchNo}");
                }
                // 6. æŸ¥æ‰¾é”å®šè®°å½•
                // 5. æŸ¥æ‰¾é”å®šè®°å½•
                Dt_OutStockLockInfo lockInfo = _outboundLockInfoService.Repository.QueryFirst(x =>
                    x.OrderNo == request.OrderNo &&
                    x.StockId == stockInfo.Id &&
@@ -810,6 +818,25 @@
                    response.Success = false;
                    response.Message = $"该库存没有分配出库量,条码:{request.Barcode}";
                    return WebResponseContent.Instance.Error($"该库存没有分配出库量,条码:{request.Barcode}");
                }
                // æ‰¾å‡ºå·²åˆ†é…çš„订单明细Id
                List<int> detailIds = new List<int>();
                string[] ids = lockInfo.OrderDetailIds.Split(",");
                foreach (string id in ids)
                {
                    if (int.TryParse(id, out int detailId))
                    {
                        detailIds.Add(detailId);
                    }
                }
                // 6. æŸ¥æ‰¾å‡ºåº“单明细信息
                List<Dt_OutboundOrderDetail> outboundOrderDetails = FindMatchingOutboundDetails(outboundOrder.Id, stockDetail, detailIds);
                if (!outboundOrderDetails.Any())
                {
                    response.Success = false;
                    response.Message = $"未找到匹配的出库单明细,物料:{stockDetail.MaterielCode},批次:{stockDetail.BatchNo}";
                    return WebResponseContent.Instance.Error($"未找到匹配的出库单明细,物料:{stockDetail.MaterielCode},批次:{stockDetail.BatchNo}");
                }
                // 7. è®¡ç®—实际出库量
@@ -824,6 +851,13 @@
                    response.Success = false;
                    response.Message = $"无法出库,条码:{request.Barcode},库存:{stockDetail.StockQuantity},已出库:{totalAllocatedQuantity},分配量:{lockInfo.AssignQuantity},明细剩余:{detailRemainingQuantity}";
                    return WebResponseContent.Instance.Error($"无法出库,条码:{request.Barcode},库存:{stockDetail.StockQuantity},已出库:{totalAllocatedQuantity},分配量:{lockInfo.AssignQuantity},明细剩余:{detailRemainingQuantity}");
                }
                if (actualOutboundQuantity + lockInfo.SortedQuantity > lockInfo.AssignQuantity)
                {
                    response.Success = false;
                    response.Message = $"无法出库,条码:{request.Barcode},库存:{stockDetail.StockQuantity},出库量{actualOutboundQuantity + lockInfo.SortedQuantity}大于分配量{lockInfo.AssignQuantity}";
                    return WebResponseContent.Instance.Error($"无法出库,条码:{request.Barcode},库存:{stockDetail.StockQuantity},出库量{actualOutboundQuantity + lockInfo.SortedQuantity}大于分配量{lockInfo.AssignQuantity}");
                }
                // 8. åˆ¤æ–­æ˜¯å¦éœ€è¦æ‹†åŒ…(当出库数量小于库存数量时需要拆包)
@@ -867,14 +901,21 @@
                    lockInfo.SortedQuantity = lockInfo.SortedQuantity + actualOutboundQuantity;
                    // æ›´æ–°é”å®šè®°å½•
                    _outboundLockInfoService.Repository.UpdateData(lockInfo);
                    if (lockInfo.SortedQuantity == lockInfo.AssignQuantity)
                    {
                        _outboundLockInfoService.Repository.DeleteAndMoveIntoHty(lockInfo, WIDESEA_Core.Enums.OperateTypeEnum.自动完成);
                    }
                    else
                    {
                        // æ›´æ–°é”å®šè®°å½•
                        _outboundLockInfoService.Repository.UpdateData(lockInfo);
                    }
                    // æ›´æ–°å‡ºåº“单明细的已出库数量
                    _detailService.Repository.UpdateData(updateDetails);
                    // æ›´æ–°é”å®šè®°å½•的累计已出库数量(需要更新该托盘该物料的所有相关记录)
                    UpdateLockInfoAllocatedQuantity(stockInfo.Id, stockDetail.MaterielCode, stockDetail.BatchNo, actualOutboundQuantity);
                    //UpdateLockInfoAllocatedQuantity(stockInfo.Id, stockDetail.MaterielCode, stockDetail.BatchNo, actualOutboundQuantity);
                    // æäº¤äº‹åŠ¡
                    _unitOfWorkManage.CommitTran();
@@ -904,6 +945,8 @@
                    if (CheckOutboundOrderCompleted(request.OrderNo))
                    {
                        UpdateOutboundOrderStatus(request.OrderNo, OutOrderStatusEnum.出库完成.ObjToInt());
                        //todo: å›žä¼ MES
                    }
                }
                catch (Exception ex)
@@ -929,11 +972,11 @@
        /// <param name="orderId"></param>
        /// <param name="stockDetail"></param>
        /// <returns></returns>
        private List<Dt_OutboundOrderDetail> FindMatchingOutboundDetails(int orderId, Dt_StockInfoDetail stockDetail)
        private List<Dt_OutboundOrderDetail> FindMatchingOutboundDetails(int orderId, Dt_StockInfoDetail stockDetail, List<int> detailIds)
        {
            List<Dt_OutboundOrderDetail> details = _detailService.Repository.QueryData(x =>
                x.OrderId == orderId &&
                x.MaterielCode == stockDetail.MaterielCode && x.OrderQuantity - x.MoveQty > x.OverOutQuantity);
                x.MaterielCode == stockDetail.MaterielCode && x.OrderQuantity - x.MoveQty > x.OverOutQuantity && detailIds.Contains(x.Id));
            // ç²¾ç¡®åŒ¹é…ï¼šå¤„理null值的批次、供应商、仓库
            List<Dt_OutboundOrderDetail> exactMatches = details.Where(x =>
@@ -1008,6 +1051,7 @@
            {
                // æ›´æ–°åŽŸåº“å­˜æ˜Žç»†
                stockDetail.StockQuantity = remainingQuantity;
                //stockDetail.Barcode = newBarcode;
                stockDetail.Remark = $"拆包后更新,原条码:{request.Barcode},新数量:{remainingQuantity},操作者:{request.Operator}";
                _stockDetailService.Repository.UpdateData(stockDetail);
            }