1
heshaofeng
2026-03-19 c866c43016f12a9db80095d9e5fd7bbc3dcaeb66
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_InboundService/TakeStockOrderService.cs
@@ -22,6 +22,15 @@
using WIDESEA_Common.CommonEnum;
using WIDESEA_Common.TaskEnum;
using WIDESEA_IBasicService;
using static HslCommunication.Profinet.Knx.KnxCode;
using System.Collections;
using WIDESEA_Common.AllocateEnum;
using WIDESEA_Model.Models.Basic;
using WIDESEA_IOutboundService;
using WIDESEA_DTO.CalcOut;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json;
using WIDESEA_DTO.Basic;
namespace WIDESEA_InboundService
{
@@ -34,7 +43,16 @@
        private readonly IRepository<Dt_TakeStockOrderDetail> _takeStockOrderDetail;
        private readonly IRepository<Dt_Task> _taskRepository;
        private readonly ILocationInfoService _locationInfoService;
        public TakeStockOrderService(IRepository<Dt_TakeStockOrder> BaseDal, IUnitOfWorkManage unitOfWorkManage,IRepository<Dt_TakeStockOrder> takeStockOrder,IRepository<Dt_StockInfo> stockInfoRepository,IRepository<Dt_TakeStockOrderDetail> takeStockOrderDetail,IRepository<Dt_Task> taskRepository,ILocationInfoService locationInfoService) : base(BaseDal)
        private readonly IRepository<Dt_InboundOrder> _inboundOrderRepository;
        private readonly IRepository<Dt_OutboundOrder> _outboundOrderRepository;
        private readonly IRepository<Dt_InboundOrderDetail> _inboundOrderDetailRepository;
        private readonly IRepository<Dt_OutboundOrderDetail> _outboundOrderDetailRepository;
        private readonly IOutboundPickingService _outboundPickingService;
        private readonly IRepository<Dt_StockInfoDetail> _stockInfoDetailRepository;
        private readonly IOutboundService _outboundService;
        private readonly IFeedbackMesService _feedbackMesService;
        private readonly IESSApiService _eSSApiService;
        public TakeStockOrderService(IRepository<Dt_TakeStockOrder> BaseDal, IUnitOfWorkManage unitOfWorkManage,IRepository<Dt_TakeStockOrder> takeStockOrder,IRepository<Dt_StockInfo> stockInfoRepository,IRepository<Dt_TakeStockOrderDetail> takeStockOrderDetail,IRepository<Dt_Task> taskRepository,ILocationInfoService locationInfoService, IRepository<Dt_InboundOrder> inboundOrderRepository,IRepository<Dt_OutboundOrder> outboundOrderRepository,IRepository<Dt_InboundOrderDetail> inboundOrderDetailRepository, IRepository<Dt_OutboundOrderDetail> outboundOrderDetailRepository, IOutboundPickingService outboundPickingService, IRepository<Dt_StockInfoDetail> stockInfoDetailRepository, IOutboundService outboundService,IFeedbackMesService feedbackMesService,IESSApiService eSSApiService) : base(BaseDal)
        {
            _unitOfWorkManage = unitOfWorkManage;
            _takeStockOrder = takeStockOrder;
@@ -42,8 +60,28 @@
            _takeStockOrderDetail = takeStockOrderDetail;
            _taskRepository = taskRepository;
            _locationInfoService = locationInfoService;
            _inboundOrderRepository = inboundOrderRepository;
            _outboundOrderRepository = outboundOrderRepository;
            _inboundOrderDetailRepository = inboundOrderDetailRepository;
            _outboundOrderDetailRepository = outboundOrderDetailRepository;
            _outboundPickingService = outboundPickingService;
            _stockInfoDetailRepository = stockInfoDetailRepository;
            _outboundService = outboundService;
            _feedbackMesService = feedbackMesService;
            _eSSApiService = eSSApiService;
        }
        private Dictionary<string, string> stations = new Dictionary<string, string>
        {
            {"2-1","2-9" },
            {"3-1","3-9" },
        };
        private Dictionary<string, string> movestations = new Dictionary<string, string>
        {
            {"2-1","2-5" },
            {"3-1","3-5" },
        };
        public WebResponseContent ValidateBoxNo(string orderNo, string boxNo)
        {
            try
@@ -52,14 +90,14 @@
                if (stockInfo == null) {
                    return WebResponseContent.Instance.Error("未找到该托盘库存");
                }
                if(stockInfo.StockStatus != StockStatusEmun.盘点出库完成.ObjToInt())
                if(stockInfo.StockStatus != StockStatusEmun.盘点出库完成.ObjToInt() && stockInfo.StockStatus != StockStatusEmun.盘点库存完成.ObjToInt())
                {
                    return WebResponseContent.Instance.Error("该托盘处于非盘点状态,请检查盘点任务");
                }
                Dt_TakeStockOrder takeStockOrder = _takeStockOrder.QueryFirst(x=>x.OrderNo == orderNo);
                Dt_TakeStockOrder takeStockOrder = _takeStockOrder.QueryFirst(x=>x.AllPalletCode.Contains(boxNo)&& x.TakeStockStatus == TakeStockStatusEnum.盘点中.ObjToInt());
                if (takeStockOrder == null)
                {
                    return WebResponseContent.Instance.Error("未找到该盘点单据");
                    return WebResponseContent.Instance.Error("该托盘未找到该盘点单据");
                }
                if (takeStockOrder.AllPalletCode.Contains(","))
                {
@@ -76,19 +114,11 @@
                    bool isMatch = remarkValues.Any(val => val.Equals(boxNo, StringComparison.OrdinalIgnoreCase));
                    if (!isMatch)
                    {
                        return WebResponseContent.Instance.Error($"箱号【{boxNo}】未在盘点单箱号【{takeStockOrder.Remark}】中找到匹配项");
                        return WebResponseContent.Instance.Error($"箱号【{boxNo}】未在盘点单箱号【{takeStockOrder.AllPalletCode}】中找到匹配项");
                    }
                }
                else
                {
                    bool isMatch = takeStockOrder.Remark.Trim().Equals(boxNo, StringComparison.OrdinalIgnoreCase);
                    if (!isMatch)
                    {
                        return WebResponseContent.Instance.Error($"箱号【{boxNo}】与盘点单箱号【{takeStockOrder.Remark}】不匹配");
                    }
                }
                return WebResponseContent.Instance.OK();
                var resultData = new { takeStockOrder = takeStockOrder.OrderNo };
                return WebResponseContent.Instance.OK(data:resultData);
            }
            catch(Exception ex)
            {
@@ -151,34 +181,40 @@
                {
                    TakeStockId = takeStockOrder.Id,
                    MaterielCode = stockInfoDetail.MaterielCode,
                    MaterielName = stockInfoDetail.MaterielName??"",
                    MaterielName = stockInfoDetail.MaterielName ?? "",
                    BatchNo = stockInfoDetail.BatchNo,
                    TakePalletCode = completeStockTakeDTO.boxNo,
                    TakeDetalStatus = TakeStockDetailStatusEnum.盘点完成.ObjToInt(),
                    TakeDetalStatus = TakeStockDetailStatusEnum.未进行平账处理.ObjToInt(),
                    Unit = stockInfoDetail.Unit,
                    SysQty = completeStockTakeDTO.stockQuantity,
                    Qty =completeStockTakeDTO.actualQuantity,
                    Remark = completeStockTakeDTO.stockQuantity-completeStockTakeDTO.actualQuantity>=0 ?"盘亏":"盘盈",
                    Qty = completeStockTakeDTO.actualQuantity,
                    Remark = "盘亏",
                    barcode = completeStockTakeDTO.barcode,
                    WarehouseCode = stockInfoDetail.WarehouseCode??"",
                    WarehouseCode = stockInfoDetail.WarehouseCode ?? "",
                    FactoryArea = stockInfoDetail.FactoryArea,
                    SupplyCode = stockInfoDetail.SupplyCode??"",
                    SupplyCode = stockInfoDetail.SupplyCode ?? "",
                    TakeStockNo = takeStockOrder.OrderNo,
                    DifferenceQty = completeStockTakeDTO.actualQuantity - completeStockTakeDTO.stockQuantity
                };
                stockInfoDetail.StockId = 0;
                stockInfoDetail.OrderNo = takeStockOrder.OrderNo;
                stockInfo.StockStatus = StockStatusEmun.盘点库存完成.ObjToInt();
                _unitOfWorkManage.BeginTran();
                _takeStockOrderDetail.AddData(takeStockOrderDetail);
                _stockInfoDetailRepository.UpdateData(stockInfoDetail);
                _stockInfoRepository.UpdateData(stockInfo);
                _unitOfWorkManage.CommitTran();
                return WebResponseContent.Instance.OK();
            }
            catch (Exception ex)
                return WebResponseContent.Instance.OK("盘点完成,请取走该异常料箱进行平账处理!");
            }
            catch (Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
        public WebResponseContent ReturnBox(string orderNo, string boxNo)
        public WebResponseContent ReturnBox(string orderNo, string boxNo, string sourceAddress)
        {
            WebResponseContent content = new WebResponseContent();
            try
@@ -188,7 +224,7 @@
                {
                    return content.Error("未找到该盘点单据");
                }
                var stock = _stockInfoRepository.QueryFirst(x => x.PalletCode == boxNo);
                var stock = _stockInfoRepository.Db.Queryable<Dt_StockInfo>().Where(x => x.PalletCode == boxNo).Includes(x=>x.Details).First();
                if (stock == null)
                {
@@ -196,21 +232,37 @@
                }
                var task = _taskRepository.QueryFirst(x => x.PalletCode == boxNo);
                if (task != null)
                {
                    return content.Error($"托盘{boxNo}存在任务回库失败!");
                    return content.Error($"托盘{boxNo}存在任务,回库失败!");
                }
                if(stock.StockStatus != StockStatusEmun.盘点出库完成.ObjToInt())
                if(stock.StockStatus != StockStatusEmun.盘点出库完成.ObjToInt() && stock.StockStatus != StockStatusEmun.盘点库存完成.ObjToInt())
                {
                    return content.Error("该托盘状态不对,不允许盘点入库");
                }
                stock.StockStatus = StockStatusEmun.入库确认.ObjToInt();
                var palletCodes = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
                if (!string.IsNullOrEmpty(takeStockOrder.AllPalletCode))
                {
                    palletCodes = takeStockOrder.AllPalletCode
                        .Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries)
                        .Select(p => p.Trim())
                        .ToHashSet(StringComparer.OrdinalIgnoreCase);
                }
                int overPalletCodeCount = _stockInfoRepository.QueryData(x => palletCodes.Contains(x.PalletCode) && (x.StockStatus == StockStatusEmun.出库完成.ObjToInt() || x.StockStatus == StockStatusEmun.入库完成.ObjToInt() || x.StockStatus == StockStatusEmun.出库锁定.ObjToInt()|| x.StockStatus == StockStatusEmun.入库确认.ObjToInt())).Count();
                bool hasRelatedTasks = palletCodes.Count == overPalletCodeCount + 1;
                takeStockOrder.TakeStockStatus = TakeStockStatusEnum.盘点完成.ObjToInt();
                if (hasRelatedTasks)
                {
                    takeStockOrder.TakeStockStatus = (int)TakeStockStatusEnum.盘点完成;
                }
                stock.StockStatus = StockStatusEmun.入库确认.ObjToInt();
                // åˆ†é…æ–°è´§ä½
                var newLocation = _locationInfoService.AssignLocation(stock.LocationType);
                if (newLocation == null)
                {
                    return WebResponseContent.Instance.Error("没有空闲库位可回库");
                }
                var newTask = new Dt_Task()
                {
@@ -220,24 +272,29 @@
                    NextAddress = "",
                    OrderNo = takeStockOrder.OrderNo,
                    Roadway = newLocation.RoadwayNo,
                    SourceAddress = takeStockOrder.Remark,
                    SourceAddress = stations.GetValueOrDefault(sourceAddress)??"",
                    TargetAddress = newLocation.LocationCode,
                    TaskStatus = (int)TaskStatusEnum.New,
                    TaskType = TaskTypeEnum.InInventory.ObjToInt(),
                    PalletType = stock.PalletType,
                    WarehouseId = stock.WarehouseId
                };
                if (stock.Details.Count <= 0)
                {
                    stock.PalletType = (int)PalletTypeEnum.Empty;
                    newTask.TaskType = TaskTypeEnum.InEmpty.ObjToInt();
                }
                _unitOfWorkManage.BeginTran();
                _stockInfoRepository.UpdateData(stock);
                _takeStockOrder.UpdateData(takeStockOrder);
                _taskRepository.AddData(newTask);
                _unitOfWorkManage.CommitTran();
                //var moveResult = await _eSSApiService.MoveContainerAsync(new MoveContainerRequest
                //{
                //    slotCode = movestations[station],
                //    containerCode = palletCode
                //});
                var moveResult = _eSSApiService.MoveContainerAsync(new MoveContainerRequest
                {
                    slotCode = movestations[sourceAddress],
                    containerCode = boxNo
                });
                return content.OK();
            }
@@ -247,6 +304,388 @@
                return content.Error(ex.Message);
            }
        }
        public WebResponseContent ManualReconciliation(int id)
        {
            try
            {
                Dt_TakeStockOrderDetail takeStockOrderDetail = _takeStockOrderDetail.QueryFirst(x=>x.Id == id);
                if(takeStockOrderDetail == null)
                {
                    return WebResponseContent.Instance.Error("未找到该盘点差异记录");
                }
                else
                {
                    if(takeStockOrderDetail.TakeDetalStatus != TakeStockDetailStatusEnum.未进行平账处理.ObjToInt())
                    {
                        return WebResponseContent.Instance.Error("该记录已经进行了平账操作");
                    }
                    takeStockOrderDetail.DifferenceQty = 0;
                    takeStockOrderDetail.TakeDetalStatus = TakeStockDetailStatusEnum.已进行平账处理.ObjToInt();
                }
                _takeStockOrderDetail.UpdateData(takeStockOrderDetail);
                return WebResponseContent.Instance.OK();
            }
            catch(Exception ex)
            {
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
        public WebResponseContent SelectOrder(string remark, int id)
        {
            try
            {
                Dt_TakeStockOrderDetail takeStockOrderDetail = _takeStockOrderDetail.QueryFirst(x => x.Id == id);
                if (takeStockOrderDetail == null)
                {
                    return WebResponseContent.Instance.Error("未找到该盘点差异记录");
                }
                else
                {
                    //查杂收单
                    if (takeStockOrderDetail.Remark == "盘盈")
                    {
                        List<Dt_InboundOrderDetail> inboundOrderDetails = new List<Dt_InboundOrderDetail>();
                        List<Dt_InboundOrder> inboundOrders = _inboundOrderRepository.Db.Queryable<Dt_InboundOrder>().Where(x => x.BusinessType == "12" && x.OrderStatus != InOrderStatusEnum.入库完成.ObjToInt()).Includes(x => x.Details).ToList();
                        foreach (var inboundOrder in inboundOrders)
                        {
                            var matchedDetails = inboundOrder.Details
                                .Where(detail => !string.IsNullOrEmpty(detail.MaterielCode)
                                              && detail.MaterielCode == takeStockOrderDetail.MaterielCode && detail.OrderDetailStatus != OrderDetailStatusEnum.Over.ObjToInt())
                                .WhereIF(!string.IsNullOrEmpty(takeStockOrderDetail.FactoryArea),
                                         detail => !string.IsNullOrEmpty(inboundOrder.FactoryArea)
                                              && inboundOrder.FactoryArea == takeStockOrderDetail.FactoryArea)
                                .WhereIF(!string.IsNullOrEmpty(takeStockOrderDetail.WarehouseCode),
                                         detail => !string.IsNullOrEmpty(detail.WarehouseCode)
                                         && detail.WarehouseCode == takeStockOrderDetail.WarehouseCode)
                                .WhereIF(!string.IsNullOrEmpty(takeStockOrderDetail.BatchNo),
                                         detail => !string.IsNullOrEmpty(detail.BatchNo)
                                         && detail.BatchNo == takeStockOrderDetail.BatchNo)
                                .ToList();
                            // å°†åŒ¹é…çš„æ˜Žç»†æ·»åŠ åˆ°æ€»åˆ—è¡¨
                            if (matchedDetails.Any())
                            {
                                inboundOrderDetails.AddRange(matchedDetails);
                            }
                        }
                        return WebResponseContent.Instance.OK("成功",data: inboundOrderDetails);
                    }
                    else
                    {
                        List<Dt_OutboundOrderDetail> outboundOrderDetails = new List<Dt_OutboundOrderDetail>();
                        List<Dt_OutboundOrder> outboundOrders = _outboundOrderRepository.Db.Queryable<Dt_OutboundOrder>().Where(x => x.BusinessType == "23" && x.OrderStatus != OutOrderStatusEnum.出库完成.ObjToInt()).Includes(x => x.Details).ToList();
                        foreach (var outboundOrder in outboundOrders)
                        {
                            var matchedDetails = outboundOrder.Details
                                .Where(detail => !string.IsNullOrWhiteSpace(detail.MaterielCode)
                                              && detail.MaterielCode == takeStockOrderDetail.MaterielCode && detail.OrderQuantity-detail.MoveQty-detail.OverOutQuantity>0)
                                .WhereIF(!string.IsNullOrWhiteSpace(takeStockOrderDetail.FactoryArea),
                                         detail => !string.IsNullOrWhiteSpace(outboundOrder.FactoryArea)
                                              && outboundOrder.FactoryArea == takeStockOrderDetail.FactoryArea)
                                .WhereIF(!string.IsNullOrWhiteSpace(takeStockOrderDetail.WarehouseCode),
                                         detail => !string.IsNullOrWhiteSpace(detail.WarehouseCode)
                                              && detail.WarehouseCode == takeStockOrderDetail.WarehouseCode)
                                .Where(detail => string.IsNullOrWhiteSpace(detail.BatchNo)||
                                         detail.BatchNo == takeStockOrderDetail.BatchNo)
                                .Where(detail => string.IsNullOrWhiteSpace(detail.SupplyCode) ||
                                         detail.SupplyCode == takeStockOrderDetail.SupplyCode)
                                .ToList();
                            if (matchedDetails.Any())
                            {
                                outboundOrderDetails.AddRange(matchedDetails);
                            }
                        }
                        return WebResponseContent.Instance.OK("成功", data: outboundOrderDetails);
                    }
                }
            }
            catch (Exception ex)
            {
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
        public WebResponseContent DocumentReconciliation(string barcode)
        {
            WebResponseContent webResponseContent = new WebResponseContent();
            try
            {
                Dt_TakeStockOrderDetail takeStockOrderDetail = _takeStockOrderDetail.QueryFirst(x => x.barcode == barcode);
                if (takeStockOrderDetail == null)
                {
                    return WebResponseContent.Instance.Error("未找到该盘点差异数据");
                }
                Dt_OutboundOrderDetail outboundOrderDetail = _outboundOrderDetailRepository.QueryFirst(x => x.Remark == takeStockOrderDetail.TakeStockNo && (x.OrderQuantity-x.LockQuantity-x.MoveQty)>0);
                if (outboundOrderDetail == null)
                {
                    return WebResponseContent.Instance.Error("未找到选择的杂发平账单据");
                }
                if(outboundOrderDetail.MaterielCode != takeStockOrderDetail.MaterielCode)
                {
                    return WebResponseContent.Instance.Error("与杂发平账单据物料编码不匹配");
                }
                if (!string.IsNullOrWhiteSpace(outboundOrderDetail.BatchNo)&& outboundOrderDetail.BatchNo != takeStockOrderDetail.BatchNo)
                {
                    return WebResponseContent.Instance.Error("与杂发平账单据物料批次不匹配");
                }
                if (!string.IsNullOrWhiteSpace(outboundOrderDetail.SupplyCode) && outboundOrderDetail.SupplyCode != takeStockOrderDetail.SupplyCode)
                {
                    return WebResponseContent.Instance.Error("与杂发平账单据供应商不匹配");
                }
                Dt_OutboundOrder outboundOrder = _outboundOrderRepository.Db.Queryable<Dt_OutboundOrder>().Where(x => x.Id == outboundOrderDetail.OrderId).Includes(x => x.Details).First();
                takeStockOrderDetail.TakeDetalStatus = TakeStockDetailStatusEnum.杂收杂发平账处理.ObjToInt();
                OutboundCompleteRequestDTO request = new OutboundCompleteRequestDTO()
                {
                    OrderNo = outboundOrder.OrderNo,
                    PalletCode = takeStockOrderDetail.TakePalletCode,
                    Barcode = takeStockOrderDetail.barcode,
                    Operator = App.User.UserName
                };
                webResponseContent = CompleteOutboundWithBarcode(request,outboundOrderDetail.Id);
                takeStockOrderDetail.DifferenceQty = 0;
                _takeStockOrderDetail.UpdateData(takeStockOrderDetail);
                return WebResponseContent.Instance.OK(data: webResponseContent);
            }
            catch(Exception ex)
            {
                _unitOfWorkManage.RollbackTran();
                return WebResponseContent.Instance.Error(ex.Message);
            }
        }
        public WebResponseContent CompleteOutboundWithBarcode(OutboundCompleteRequestDTO request ,int orderDetailId)
        {
            WebResponseContent content = WebResponseContent.Instance;
            OutboundCompleteResponseDTO response = new();
            try
            {
                // 1. æ ¹æ®æ‰˜ç›˜å·æŸ¥æ‰¾åº“存信息
                Dt_StockInfo stockInfo = _stockInfoRepository.QueryFirst(x => x.PalletCode == request.PalletCode);
                if (stockInfo == null)
                {
                    response.Success = false;
                    response.Message = $"托盘号 {request.PalletCode} å¯¹åº”的库存不存在";
                    return WebResponseContent.Instance.Error($"托盘号 {request.PalletCode} å¯¹åº”的库存不存在");
                }
                // 2. æ ¹æ®æ¡ç æŸ¥æ‰¾åº“存明细
                Dt_StockInfoDetail stockDetail = _stockInfoDetailRepository.QueryFirst(x => x.Barcode == request.Barcode);
                if (stockDetail == null)
                {
                    response.Success = false;
                    response.Message = $"条码 {request.Barcode} å¯¹åº”的库存明细不存在";
                    return WebResponseContent.Instance.Error($"条码 {request.Barcode} å¯¹åº”的库存明细不存在");
                }
                // 4. æŸ¥æ‰¾å‡ºåº“单信息
                Dt_OutboundOrder outboundOrder = _outboundOrderRepository.QueryFirst(o => o.OrderNo == request.OrderNo);
                if (outboundOrder == null)
                {
                    response.Success = false;
                    response.Message = $"出库单 {request.OrderNo} ä¸å­˜åœ¨";
                    return WebResponseContent.Instance.Error($"出库单 {request.OrderNo} ä¸å­˜åœ¨");
                }
                Dt_OutboundOrderDetail outboundOrderDetail = _outboundOrderDetailRepository.QueryFirst(x => x.Id == orderDetailId);
                if (outboundOrderDetail == null)
                {
                    return WebResponseContent.Instance.Error("未找到出库单明细");
                }
                // å®žé™…出库量
                decimal actualOutboundQuantity = outboundOrderDetail.OrderQuantity-outboundOrderDetail.LockQuantity-outboundOrderDetail.MoveQty;
                // 8. åˆ¤æ–­æ˜¯å¦éœ€è¦æ‹†åŒ…(当出库数量小于库存数量时需要拆包)
                bool isUnpacked = actualOutboundQuantity < stockDetail.StockQuantity;
                List<MaterialCodeReturnDTO> returnDTOs = new List<MaterialCodeReturnDTO>();
                string newBarcode = string.Empty;
                // 9. å¼€å¯äº‹åŠ¡
                _unitOfWorkManage.BeginTran();
                try
                {
                    decimal beforeQuantity = stockDetail.StockQuantity; // åŽŸå§‹åº“å­˜é‡
                    Dt_AllocateMaterialInfo allocateMaterialInfo = new Dt_AllocateMaterialInfo();
                    // æ ¹æ®æ˜¯å¦æ‹†åŒ…执行不同的操作
                    if (isUnpacked)
                    {
                        (string NewBarcode, List<MaterialCodeReturnDTO> MaterialCodeReturnDTOs) result = _outboundService.PerformUnpackOperation(stockDetail, stockInfo, actualOutboundQuantity, request, beforeQuantity, 0, outboundOrder.Id, outboundOrder.OrderNo);
                        returnDTOs = result.MaterialCodeReturnDTOs;
                        newBarcode = result.NewBarcode;
                        MaterialCodeReturnDTO returnDTO = returnDTOs.First(x => x.Barcode == newBarcode);
                        if (outboundOrder.OrderType != 0)
                        {
                            allocateMaterialInfo = new Dt_AllocateMaterialInfo()
                            {
                                Barcode = returnDTO.Barcode,
                                BatchNo = returnDTO.BatchNo,
                                FactoryArea = returnDTO.FactoryArea,
                                MaterialCode = returnDTO.MaterialCode,
                                MaterialName = returnDTO.MaterialName,
                                OrderId = outboundOrder.Id,
                                OrderNo = outboundOrder.OrderNo,
                                Quantity = returnDTO.Quantity,
                                SupplyCode = returnDTO.SuplierCode,
                                Unit = stockDetail.Unit
                            };
                        }
                    }
                    else
                    {
                       _outboundService.PerformFullOutboundOperation(stockDetail, stockInfo, actualOutboundQuantity, request, beforeQuantity, 0);
                        if (outboundOrder.OrderType != 0)
                        {
                            allocateMaterialInfo = new Dt_AllocateMaterialInfo()
                            {
                                Barcode = stockDetail.Barcode,
                                BatchNo = stockDetail.BatchNo,
                                FactoryArea = stockDetail.FactoryArea,
                                MaterialCode = stockDetail.MaterielCode,
                                MaterialName = stockDetail.MaterielName,
                                OrderId = outboundOrder.Id,
                                OrderNo = outboundOrder.OrderNo,
                                Quantity = stockDetail.StockQuantity,
                                SupplyCode = stockDetail.SupplyCode,
                                Unit = stockDetail.Unit
                            };
                        }
                    }
                    List<Dt_OutboundOrderDetail> outboundOrderDetails = new List<Dt_OutboundOrderDetail>();
                    outboundOrderDetails.Add(outboundOrderDetail);
                    decimal allocatedQuantity = actualOutboundQuantity;
                    List<Dt_OutboundOrderDetail> updateDetails = new();
                    foreach (var item in outboundOrderDetails)
                    {
                        if (allocatedQuantity <= 0) break;
                        decimal barcodeQuantity = allocatedQuantity;
                        if (item.LockQuantity - item.OverOutQuantity >= allocatedQuantity)
                        {
                            item.OverOutQuantity += allocatedQuantity;
                            item.CurrentDeliveryQty += allocatedQuantity;
                            allocatedQuantity = 0;
                        }
                        else
                        {
                            barcodeQuantity = allocatedQuantity;
                            allocatedQuantity -= (item.LockQuantity - item.OverOutQuantity);
                            item.OverOutQuantity = allocatedQuantity;
                            item.LockQuantity = allocatedQuantity;
                            item.CurrentDeliveryQty = allocatedQuantity;
                        }
                        updateDetails.Add(item);
                        List<Barcodes> barcodesList = new List<Barcodes>();
                        Barcodes barcodes = new Barcodes
                        {
                            Barcode = isUnpacked ? newBarcode : stockDetail?.Barcode,
                            Qty = barcodeQuantity,
                            SupplyCode = stockDetail?.SupplyCode ?? "",
                            BatchNo = stockDetail?.BatchNo ?? "",
                            Unit = stockDetail?.Unit ?? ""
                        };
                        if (!string.IsNullOrEmpty(item.ReturnJsonData))
                        {
                            barcodesList = JsonConvert.DeserializeObject<List<Barcodes>>(item.ReturnJsonData) ?? new List<Barcodes>();
                        }
                        barcodesList.Add(barcodes);
                        JsonSerializerSettings settings = new JsonSerializerSettings
                        {
                            ContractResolver = new CamelCasePropertyNamesContractResolver()
                        };
                        item.ReturnJsonData = JsonConvert.SerializeObject(barcodesList, settings);
                    }
                    // æ›´æ–°å‡ºåº“单明细的已出库数量
                    _outboundOrderDetailRepository.UpdateData(updateDetails);
                    // æ›´æ–°é”å®šè®°å½•的累计已出库数量(需要更新该托盘该物料的所有相关记录)
                    //UpdateLockInfoAllocatedQuantity(stockInfo.Id, stockDetail.MaterielCode, stockDetail.BatchNo, actualOutboundQuantity);
                    // æäº¤äº‹åŠ¡
                    _unitOfWorkManage.CommitTran();
                    // æž„建返回信息
                    ScannedStockDetailDTO scannedDetail = new ScannedStockDetailDTO
                    {
                        StockDetailId = stockDetail.Id,
                        PalletCode = stockInfo.PalletCode,
                        MaterielCode = stockDetail.MaterielCode,
                        MaterielName = stockDetail.MaterielName,
                        BatchNo = stockDetail.BatchNo,
                        OriginalBarcode = request.Barcode,
                        BeforeQuantity = beforeQuantity,
                        AfterQuantity = isUnpacked ? actualOutboundQuantity : 0,
                        ChangeQuantity = -actualOutboundQuantity,
                        IsUnpacked = isUnpacked,
                        MaterialCodes = returnDTOs
                    };
                    response.Success = true;
                    response.Message = "出库完成";
                    response.ScannedDetail = scannedDetail;
                    response.UpdatedDetails = updateDetails;
                    if (!string.IsNullOrEmpty(newBarcode))
                    {
                        // ç‰©æ–™æ–°æ¡ç å›žä¼ 
                        _feedbackMesService.BarcodeFeedback(newBarcode);
                    }
                    List<Dt_OutboundOrderDetail> details = _outboundOrderDetailRepository.QueryData(x => x.OrderId == outboundOrder.Id);
                    if(details.All(x => x.OverOutQuantity >= x.OrderQuantity - x.MoveQty))
                    {
                        _feedbackMesService.OutboundFeedback(outboundOrder.OrderNo);
                        outboundOrder.OrderStatus = OutOrderStatusEnum.出库完成.ObjToInt();
                        _outboundOrderRepository.UpdateData(outboundOrder);
                    }
                }
                catch (Exception ex)
                {
                    _unitOfWorkManage.RollbackTran();
                    response.Success = false;
                    response.Message = $"出库处理失败:{ex.Message}";
                    return WebResponseContent.Instance.Error(ex.Message);
                }
                content = WebResponseContent.Instance.OK(data: response);
            }
            catch (Exception ex)
            {
                content = WebResponseContent.Instance.Error("处理出库完成失败:" + ex.Message);
            }
            return content;
        }
        public WebResponseContent StockTakeGroupPallet(string barcode, string boxNo)
        {
            throw new NotImplementedException();
        }
    }
    
}