1
heshaofeng
2026-01-13 1866b69e8f67e382a0a75268d63e6418c8ae02e7
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundService.cs
@@ -3,6 +3,7 @@
using Dm.filter;
using MailKit.Search;
using Mapster;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Org.BouncyCastle.Asn1.Ocsp;
@@ -18,6 +19,7 @@
using WIDESEA_Core.BaseRepository;
using WIDESEA_Core.CodeConfigEnum;
using WIDESEA_Core.Helper;
using WIDESEA_DTO.Base;
using WIDESEA_DTO.Basic;
using WIDESEA_DTO.CalcOut;
using WIDESEA_DTO.ReturnMES;
@@ -549,7 +551,7 @@
        private List<Dt_StockInfo> BuildStockQueryWithInfo(MaterielOutboundCalculationDTO materielCalc, string factoryArea)
        {
            // åŸºç¡€æŸ¥è¯¢æ¡ä»¶ï¼šç‰©æ–™ç¼–号、批次号(如果提供)、库存数量>0
            ISugarQueryable<Dt_StockInfoDetail> stockDetails = _stockDetailRepository.Db.Queryable<Dt_StockInfoDetail>().Where(x => x.MaterielCode == materielCalc.MaterielCode && x.StockQuantity > 0);
            ISugarQueryable<Dt_StockInfoDetail> stockDetails = _stockDetailRepository.Db.Queryable<Dt_StockInfoDetail>().Where(x => x.MaterielCode == materielCalc.MaterielCode && x.StockQuantity > 0 && (x.Status == (int)StockStatusEmun.入库完成 || x.Status == (int)StockStatusEmun.手动解锁));
            // æ ¹æ®æ¡ä»¶æ·»åŠ ä¾›åº”å•†ç¼–å·åŒ¹é…ï¼ˆä¸ä¸ºç©ºæ—¶æ‰éœ€è¦åŒ¹é…ï¼‰
            if (!string.IsNullOrEmpty(materielCalc.SupplyCode))
@@ -878,22 +880,6 @@
                    return WebResponseContent.Instance.Error(response.Message);
                }
                bool isMatMixed = stockInfo.Details.GroupBy(x => new
                {
                    x.MaterielCode,
                    x.MaterielName,
                    x.BatchNo,
                    x.SupplyCode,
                    x.WarehouseCode
                }).Count() > 1;
                if (isMatMixed)
                {
                    response.Success = false;
                    response.Message = $"混料托盘 {request.PalletCode} ä¸èƒ½æ•´ç®±å‡ºåº“";
                    return WebResponseContent.Instance.Error(response.Message);
                }
                // 2. æŸ¥æ‰¾å‡ºåº“单信息
                Dt_OutboundOrder outboundOrder = _outboundRepository.QueryFirst(o => o.OrderNo == request.OrderNo);
                if (outboundOrder == null)
@@ -916,6 +902,67 @@
                {
                    response.Success = false;
                    response.Message = $"该库存没有分配出库量,托盘号:{request.PalletCode}";
                    return WebResponseContent.Instance.Error(response.Message);
                }
                //bool isMatMixed = stockInfo.Details.GroupBy(x => new
                //{
                //    x.MaterielCode,
                //    x.MaterielName,
                //    x.BatchNo,
                //    x.SupplyCode,
                //    x.WarehouseCode
                //}).Count() > 1;
                bool isMatMixed = false;
                bool includeBatchNo = !string.IsNullOrEmpty(lockInfo.BatchNo);
                bool includeSupplyCode = !string.IsNullOrEmpty(lockInfo.SupplyCode);
                if (includeBatchNo && includeSupplyCode)
                {
                    isMatMixed = stockInfo.Details.GroupBy(x => new
                    {
                        x.MaterielCode,
                        x.MaterielName,
                        x.BatchNo,
                        x.SupplyCode,
                        x.WarehouseCode
                    }).Count() > 1;
                }
                else if (includeBatchNo && !includeSupplyCode)
                {
                    isMatMixed = stockInfo.Details.GroupBy(x => new
                    {
                        x.MaterielCode,
                        x.MaterielName,
                        x.BatchNo,
                        x.WarehouseCode
                    }).Count() > 1;
                }
                else if (!includeBatchNo && includeSupplyCode)
                {
                    isMatMixed = stockInfo.Details.GroupBy(x => new
                    {
                        x.MaterielCode,
                        x.MaterielName,
                        x.SupplyCode,
                        x.WarehouseCode
                    }).Count() > 1;
                }
                else
                {
                    isMatMixed = stockInfo.Details.GroupBy(x => new
                    {
                        x.MaterielCode,
                        x.MaterielName,
                        x.WarehouseCode
                    }).Count() > 1;
                }
                if (isMatMixed)
                {
                    response.Success = false;
                    response.Message = $"混料托盘 {request.PalletCode} ä¸èƒ½æ•´ç®±å‡ºåº“";
                    return WebResponseContent.Instance.Error(response.Message);
                }
@@ -1017,18 +1064,23 @@
                        List<Dt_StockInfoDetail> stockInfoDetails = stockInfo.Details.Where((x => x.StockQuantity > x.OutboundQuantity)).ToList();
                        decimal itemQuantity = item.LockQuantity - item.OverOutQuantity;
                        decimal unitbarcodeQuantity;
                        foreach (var stockDetail in stockInfoDetails)
                        {
                            if (itemQuantity >= stockDetail.StockQuantity - stockDetail.OutboundQuantity)
                            {
                                unitbarcodeQuantity = stockDetail.StockQuantity - stockDetail.OutboundQuantity;
                                UnitConvertResultDTO currentResult = _basicService.UnitQuantityConvert(item.MaterielCode, item.Unit, item.BarcodeUnit, unitbarcodeQuantity);
                                Barcodes barcodes = new Barcodes
                                {
                                    Barcode = stockDetail.Barcode,
                                    Qty = stockDetail.StockQuantity - stockDetail.OutboundQuantity,
                                    Qty = currentResult.ToQuantity,
                                    SupplyCode = stockDetail?.SupplyCode ?? "",
                                    BatchNo = stockDetail?.BatchNo ?? "",
                                    Unit = stockDetail?.Unit ?? ""
                                    Unit = currentResult.ToUnit ?? ""
                                };
                                itemQuantity -= (stockDetail.StockQuantity - stockDetail.OutboundQuantity);
@@ -1039,13 +1091,14 @@
                            }
                            else
                            {
                                UnitConvertResultDTO currentResult = _basicService.UnitQuantityConvert(item.MaterielCode, item.Unit, item.BarcodeUnit, itemQuantity);
                                Barcodes barcodes = new Barcodes
                                {
                                    Barcode = stockDetail.Barcode,
                                    Qty = itemQuantity,
                                    Qty = currentResult.ToQuantity,
                                    SupplyCode = stockDetail?.SupplyCode ?? "",
                                    BatchNo = stockDetail?.BatchNo ?? "",
                                    Unit = stockDetail?.Unit ?? ""
                                    Unit = currentResult.ToUnit ?? ""
                                };
                                stockDetail.OutboundQuantity += itemQuantity;
                                barcodesList.Add(barcodes);
@@ -1402,7 +1455,6 @@
                    {
                        if (allocatedQuantity <= 0) break;
                        //if (item.OrderQuantity - item.MoveQty - item.OverOutQuantity >= allocatedQuantity)
                        //{
                        //    item.OverOutQuantity += allocatedQuantity;
@@ -1433,13 +1485,15 @@
                        updateDetails.Add(item);
                        List<Barcodes> barcodesList = new List<Barcodes>();
                        UnitConvertResultDTO currentResult = _basicService.UnitQuantityConvert(item.MaterielCode, item.Unit, item.BarcodeUnit, barcodeQuantity);
                        Barcodes barcodes = new Barcodes
                        {
                            Barcode = newBarcode,
                            Qty = barcodeQuantity,
                            Barcode = isUnpacked ? newBarcode : stockDetail?.Barcode,
                            Qty = currentResult.ToQuantity,
                            SupplyCode = stockDetail?.SupplyCode ?? "",
                            BatchNo = stockDetail?.BatchNo ?? "",
                            Unit = stockDetail?.Unit ?? ""
                            Unit = currentResult.ToUnit ?? ""
                        };
                        if (!string.IsNullOrEmpty(item.ReturnJsonData))
                        {
@@ -1455,7 +1509,7 @@
                    lockInfo.SortedQuantity = lockInfo.SortedQuantity + actualOutboundQuantity;
                    if (lockInfo.SortedQuantity == lockInfo.AssignQuantity)
                    if (lockInfo.SortedQuantity >= lockInfo.AssignQuantity)
                    {
                        _outboundLockInfoRepository.DeleteAndMoveIntoHty(lockInfo, WIDESEA_Core.Enums.OperateTypeEnum.自动完成);
                    }
@@ -1501,6 +1555,22 @@
                        _feedbackMesService.BarcodeFeedback(newBarcode);
                    }
                    // åˆ é™¤é”å®šè®°å½•(如果出库明细全部完成) ä¸ŽCalculateActualOutboundQuantity方法里面注释代码2选1使用
                    if (CheckOutboundOrderDetailCompletedByMatCode(request.OrderNo, lockInfo.MaterielCode, outboundOrderDetails.First()))
                    {
                        Func<Dt_OutStockLockInfo, bool> supWhere = x => string.IsNullOrEmpty(outboundOrderDetails.First().SupplyCode) ? true : x.SupplyCode == outboundOrderDetails.First().SupplyCode;
                        Func<Dt_OutStockLockInfo, bool> wareWhere = x => string.IsNullOrEmpty(outboundOrderDetails.First().WarehouseCode) ? true : x.WarehouseCode == outboundOrderDetails.First().WarehouseCode;
                        List<Dt_OutStockLockInfo> stockLockInfos = _outboundLockInfoRepository.QueryData(x =>
                                x.OrderNo == request.OrderNo &&
                                x.MaterielCode == stockDetail.MaterielCode).Where(supWhere).Where(wareWhere).ToList();
                        if (stockLockInfos != null && stockLockInfos.Any())
                        {
                            _outboundLockInfoRepository.DeleteAndMoveIntoHty(stockLockInfos, WIDESEA_Core.Enums.OperateTypeEnum.自动删除);
                        }
                    }
                    // æ£€æŸ¥å‡ºåº“单是否完成
                    if (CheckOutboundOrderCompleted(request.OrderNo))
                    {
@@ -1511,6 +1581,7 @@
                            _feedbackMesService.OutboundFeedback(outboundOrder.OrderNo);
                        }
                    }
                }
                catch (Exception ex)
                {
@@ -1558,6 +1629,8 @@
        /// </summary>
        private decimal CalculateActualOutboundQuantity(Dt_StockInfoDetail stockDetail, List<Dt_OutboundOrderDetail> outboundDetails, Dt_OutStockLockInfo lockInfo)
        {
            // decimal availableOutboundQuantity = lockInfo.AssignQuantity - lockInfo.SortedQuantity;
            decimal availableOutboundQuantity = lockInfo.AssignQuantity;
            decimal detailRemainingQuantity = outboundDetails.Sum(x => x.OrderQuantity - x.OverOutQuantity - x.MoveQty);//outboundDetail.OrderQuantity - outboundDetail.OverOutQuantity;
@@ -1576,7 +1649,7 @@
        /// <param name="beforeQuantity"></param>
        /// <param name="taskNum"></param>
        /// <returns></returns>
        private (string NewBarcode, List<MaterialCodeReturnDTO> MaterialCodeReturnDTOs) PerformUnpackOperation(Dt_StockInfoDetail stockDetail, Dt_StockInfo stockInfo,
        public (string NewBarcode, List<MaterialCodeReturnDTO> MaterialCodeReturnDTOs) PerformUnpackOperation(Dt_StockInfoDetail stockDetail, Dt_StockInfo stockInfo,
            decimal actualOutboundQuantity, OutboundCompleteRequestDTO request, decimal beforeQuantity, int taskNum, int orderId, string orderNo)
        {
            string newBarcode = GenerateNewBarcode();
@@ -1654,7 +1727,7 @@
        /// <summary>
        /// æ‰§è¡Œå®Œæ•´å‡ºåº“操作(不拆包)
        /// </summary>
        private void PerformFullOutboundOperation(Dt_StockInfoDetail stockDetail, Dt_StockInfo stockInfo,
        public void PerformFullOutboundOperation(Dt_StockInfoDetail stockDetail, Dt_StockInfo stockInfo,
            decimal actualOutboundQuantity, OutboundCompleteRequestDTO request, decimal beforeQuantity, int taskNum)
        {
            // ä¿å­˜åº“存明细到历史记录
@@ -1834,6 +1907,20 @@
            return details.All(x => x.OverOutQuantity >= x.OrderQuantity - x.MoveQty);
        }
        /// <summary>
        /// æ£€æŸ¥å‡ºåº“单明细是否完成
        /// </summary>
        public bool CheckOutboundOrderDetailCompletedByMatCode(string orderNo, string materialCode, Dt_OutboundOrderDetail outboundOrderDetail)
        {
            Dt_OutboundOrder outboundOrder = _outboundRepository.QueryFirst(x => x.OrderNo == orderNo);
            if (outboundOrder == null) return false;
            List<Dt_OutboundOrderDetail> details = _detailRepository.QueryData(x => x.OrderId == outboundOrder.Id && x.MaterielCode == materialCode && (string.IsNullOrEmpty(outboundOrderDetail.SupplyCode) || x.SupplyCode == outboundOrderDetail.SupplyCode) && (string.IsNullOrEmpty(outboundOrderDetail.WarehouseCode) || x.WarehouseCode == outboundOrderDetail.WarehouseCode));
            // æ£€æŸ¥æ‰€æœ‰æ˜Žç»†çš„已出数量是否都等于单据数量
            return details.All(x => x.OverOutQuantity >= x.OrderQuantity - x.MoveQty);
        }
        #endregion
        #region å–空箱