From 30dc073f49e03354e7719cc4d79a8cd7a303be03 Mon Sep 17 00:00:00 2001
From: heshaofeng <heshaofeng@hnkhzn.com>
Date: 星期一, 01 十二月 2025 21:03:49 +0800
Subject: [PATCH] Merge branch 'master' of http://115.159.85.185:8098/r/ZhongRui/ALDbanyunxiangmu

---
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundPickingService.cs | 4844 +++++++++++++++++++++++++++++++++++++----------------------
 1 files changed, 3,032 insertions(+), 1,812 deletions(-)

diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundPickingService.cs" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundPickingService.cs"
index 4deb21d..0b032a3 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundPickingService.cs"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WMS\346\227\240\344\273\223\345\202\250\347\211\210/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundPickingService.cs"
@@ -8,7 +8,9 @@
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
+using System.Text.Json;
 using System.Threading.Tasks;
+using WIDESEA_Common.CommonEnum;
 using WIDESEA_Common.LocationEnum;
 using WIDESEA_Common.OrderEnum;
 using WIDESEA_Common.StockEnum;
@@ -16,14 +18,22 @@
 using WIDESEA_Core;
 using WIDESEA_Core.BaseRepository;
 using WIDESEA_Core.BaseServices;
+using WIDESEA_Core.Enums;
 using WIDESEA_Core.Helper;
+using WIDESEA_Core.Utilities;
+using WIDESEA_DTO.Allocate;
 using WIDESEA_DTO.Basic;
 using WIDESEA_DTO.Inbound;
 using WIDESEA_DTO.Outbound;
+using WIDESEA_IAllocateService;
 using WIDESEA_IBasicService;
+using WIDESEA_ICheckService;
+using WIDESEA_IInboundService;
 using WIDESEA_IOutboundService;
 using WIDESEA_IStockService;
 using WIDESEA_Model.Models;
+using WIDESEA_Model.Models.Basic;
+using WIDESEA_Model.Models.Check;
 
 namespace WIDESEA_OutboundService
 {
@@ -47,7 +57,11 @@
         private readonly IESSApiService _eSSApiService;
         private readonly IInvokeMESService _invokeMESService;
         private readonly IDailySequenceService _dailySequenceService;
-
+        private readonly IAllocateService _allocateService;
+        private readonly IRepository<Dt_InboundOrder> _inboundOrderRepository;
+        private readonly IInboundOrderDetailService _inboundOrderDetailService;
+        private readonly IRepository<Dt_WarehouseArea> _warehouseAreaRepository;
+        private readonly IReCheckOrderService _reCheckOrderService;
         private readonly ILogger<OutboundPickingService> _logger;
 
         private Dictionary<string, string> stations = new Dictionary<string, string>
@@ -67,7 +81,7 @@
         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, IESSApiService eSSApiService, ILogger<OutboundPickingService> logger, IInvokeMESService invokeMESService, IDailySequenceService dailySequenceService) : base(BaseDal)
+            IRepository<Dt_Task> taskRepository, IESSApiService eSSApiService, ILogger<OutboundPickingService> logger, IInvokeMESService invokeMESService, IDailySequenceService dailySequenceService, IAllocateService allocateService, IRepository<Dt_InboundOrder> inboundOrderRepository, IInboundOrderDetailService inboundOrderDetailService, IRepository<Dt_WarehouseArea> warehouseAreaRepository, IReCheckOrderService reCheckOrderService) : base(BaseDal)
         {
             _unitOfWorkManage = unitOfWorkManage;
             _stockInfoService = stockInfoService;
@@ -83,1651 +97,15 @@
             _logger = logger;
             _invokeMESService = invokeMESService;
             _dailySequenceService = dailySequenceService;
+            _allocateService = allocateService;
+            _inboundOrderRepository = inboundOrderRepository;
+            _inboundOrderDetailService = inboundOrderDetailService;
+            _warehouseAreaRepository = warehouseAreaRepository;
+            _reCheckOrderService = reCheckOrderService;
         }
 
 
-        #region 鏌ヨ鍑哄簱璇︽儏鍒楄〃
-        public async Task<List<OutStockLockListResp>> GetOutStockLockListAsync(string orderNo)
-        {
-            var locks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
-                .Where(t => t.OrderNo == orderNo)
-                .ToListAsync();
-
-            return locks.Select(t => new OutStockLockListResp
-            {
-                Id = t.Id,
-                // TaskNum = t.TaskNum,
-                PalletCode = t.PalletCode,
-                CurrentBarcode = t.CurrentBarcode,
-                AssignQuantity = t.AssignQuantity,
-                PickedQty = t.PickedQty,
-                Status = t.Status,
-                //  IsSplitted = t.IsSplitted
-            }).ToList();
-        }
-        #endregion
-        public async Task<WebResponseContent> ValidateBarcode(string barcode)
-        {
-            try
-            {
-                if (string.IsNullOrEmpty(barcode))
-                {
-                    return WebResponseContent.Instance.Error("鏉$爜涓嶈兘涓虹┖");
-                }
-
-                // 鏍规嵁鏉$爜鏌ヨ搴撳瓨鏄庣粏
-                var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
-                    .Includes(x => x.StockInfo)
-                    .Where(x => x.Barcode == barcode)
-                    .FirstAsync();
-
-                if (stockDetail == null)
-                {
-                    return WebResponseContent.Instance.Error("鏉$爜涓嶅瓨鍦�");
-                }
-
-
-
-                var result = new
-                {
-                    Barcode = barcode,
-                    MaterielCode = stockDetail.MaterielCode,
-
-                    BatchNo = stockDetail.BatchNo,
-                    AvailableQuantity = stockDetail.StockQuantity - stockDetail.OutboundQuantity,
-                    LocationCode = stockDetail.StockInfo?.LocationCode,
-                    PalletCode = stockDetail.StockInfo?.PalletCode
-                };
-
-                return WebResponseContent.Instance.OK(null, result);
-            }
-            catch (Exception ex)
-            {
-                return WebResponseContent.Instance.Error($"鏉$爜楠岃瘉澶辫触: {ex.Message}");
-            }
-        }
-
-        // 妫�鏌ュ苟鏇存柊璁㈠崟鐘舵��
-        private async Task CheckAndUpdateOrderStatus(string orderNo)
-        {
-
-            var orderDetails = _stockInfoDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
-                      .LeftJoin<Dt_OutboundOrder>((o, item) => o.OrderId == item.Id) // 鍏宠仈鏉′欢锛氱埗琛� Id = 瀛愯〃 OrderId
-                      .Where((o, item) => item.OrderNo == orderNo) // 杩囨护鐖惰〃 OrderNo
-                      .Select((o, item) => o) // 鍙繑鍥炲瓙琛ㄦ暟鎹�
-                      .ToList();
-
-            //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)
-            {
-                try
-                {
-                    await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>()
-                        .SetColumns(x => x.OrderStatus == 2) // 宸插畬鎴�
-                        .Where(x => x.OrderNo == orderNo)
-                        .ExecuteCommandAsync();
-
-                    var outboundOrder = _stockInfoService.Db.Queryable<Dt_OutboundOrder>().First(x => x.OrderNo == orderNo);
-
-
-                    if (outboundOrder != null && outboundOrder.OrderStatus == OutOrderStatusEnum.鍑哄簱瀹屾垚.ObjToInt())
-                    {
-
-                        if (outboundOrder.OrderType == OutOrderTypeEnum.Allocate.ObjToInt().ObjToInt())//璋冩嫧鍑哄簱
-                        {
-
-                        }
-                        else if (outboundOrder.OrderType == OutOrderTypeEnum.ReCheck.ObjToInt()) //閲嶆鍑哄簱
-                        {
-
-                        }
-                        else
-                        {
-                            var feedmodel = new FeedbackOutboundRequestModel
-                            {
-                                reqCode = Guid.NewGuid().ToString(),
-                                reqTime = DateTime.Now.ToString(),
-                                business_type = outboundOrder.BusinessType,
-                                factoryArea = outboundOrder.FactoryArea,
-                                operationType = 1,
-                                Operator = outboundOrder.Operator,
-                                orderNo = outboundOrder.UpperOrderNo,
-                                status = outboundOrder.OrderStatus,
-                                details = new List<FeedbackOutboundDetailsModel>()
-
-                            };
-                            var lists = _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>().Where(x => x.OrderNo == orderNo && x.Status == (int)OutLockStockStatusEnum.鎷i�夊畬鎴�).ToList();
-
-                            var groupedData = lists.GroupBy(item => new { item.MaterielCode, item.lineNo, item.Unit, item.WarehouseCode })
-                               .Select(group => new FeedbackOutboundDetailsModel
-                               {
-                                   materialCode = group.Key.MaterielCode,
-                                   lineNo = group.Key.lineNo,
-                                   warehouseCode = group.Key.WarehouseCode,
-                                   currentDeliveryQty = group.Sum(x => x.OrderQuantity),
-                                   // warehouseCode= "1072",
-                                   unit = group.Key.Unit,
-                                   barcodes = group.Select(row => new WIDESEA_DTO.Outbound.BarcodesModel
-                                   {
-                                       barcode = row.CurrentBarcode,
-                                       supplyCode = row.SupplyCode,
-                                       batchNo = row.BatchNo,
-                                       unit = row.Unit,
-                                       qty = row.PickedQty
-                                   }).ToList()
-                               }).ToList();
-                            feedmodel.details = groupedData;
-
-                            var result = await _invokeMESService.FeedbackOutbound(feedmodel);
-                            if (result != null && result.code == 200)
-                            {
-                                await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>().SetColumns(x => x.ReturnToMESStatus == 1) // 宸插畬鎴�
-                                            .Where(x => x.OrderId == outboundOrder.Id).ExecuteCommandAsync();
-                                await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>() .SetColumns(x => x.ReturnToMESStatus == 1) // 宸插畬鎴�
-                                              .Where(x => x.OrderNo == orderNo) .ExecuteCommandAsync();
-                            }
-                        }
-
-                    }
-                }
-                catch (Exception ex)
-                {
-                    _logger.LogError(" OutboundPickingService  FeedbackOutbound : " + ex.Message);
-                }
-
-            }
-        }
-
-        public async Task<WebResponseContent> ConfirmPicking(string orderNo, string palletCode, string barcode)
-        {
-            try
-            {
-                _unitOfWorkManage.BeginTran();
-
-                // 1. 楠岃瘉杈撳叆鍙傛暟
-                if (string.IsNullOrEmpty(orderNo) || string.IsNullOrEmpty(palletCode) || string.IsNullOrEmpty(barcode))
-                {
-                    throw new Exception("璁㈠崟鍙枫�佹墭鐩樼爜鍜屾潯鐮佷笉鑳戒负绌�");
-                }
-
-                // 2. 鏌ユ壘鍑哄簱閿佸畾淇℃伅
-                var lockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
-                    .Where(it => it.OrderNo == orderNo &&
-                               it.Status == (int)OutLockStockStatusEnum.鍑哄簱涓� &&
-                               it.PalletCode == palletCode &&
-                               it.CurrentBarcode == barcode &&
-                               it.AssignQuantity > it.PickedQty)
-                    .FirstAsync();
-
-                if (lockInfo == null)
-                {
-                    lockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
-                        .Where(it => it.CurrentBarcode == barcode &&
-                                   it.Status == (int)OutLockStockStatusEnum.鍑哄簱涓� &&
-                                   it.AssignQuantity > it.PickedQty)
-                        .FirstAsync();
-
-                    if (lockInfo == null)
-                    {
-                        var completedLockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
-                            .Where(it => it.CurrentBarcode == barcode &&
-                                       (it.Status == (int)OutLockStockStatusEnum.鎷i�夊畬鎴� ||
-                                        it.PickedQty >= it.AssignQuantity))
-                            .FirstAsync();
-
-                        if (completedLockInfo != null)
-                            throw new Exception($"鏉$爜{barcode}宸茬粡瀹屾垚鍒嗘嫞锛屼笉鑳介噸澶嶅垎鎷�");
-                        else
-                            throw new Exception($"鏉$爜{barcode}涓嶅睘浜庢墭鐩榹palletCode}鎴栦笉瀛樺湪寰呭垎鎷h褰�");
-                    }
-                }
-
-                if (lockInfo.PalletCode != palletCode)
-                    throw new Exception($"鏉$爜{barcode}涓嶅睘浜庢墭鐩榹palletCode}");
-
-                // 妫�鏌ユ嫞閫夊巻鍙诧紝闃叉閲嶅鍒嗘嫞
-                var existingPicking = await Db.Queryable<Dt_PickingRecord>()
-                    .Where(x => x.Barcode == barcode &&
-                               x.OrderNo == orderNo &&
-                               x.PalletCode == palletCode &&
-                               x.OutStockLockId == lockInfo.Id)
-                    .FirstAsync();
-
-                if (existingPicking != null)
-                {
-                    throw new Exception($"鏉$爜{barcode}宸茬粡鍒嗘嫞杩囷紝涓嶈兘閲嶅鍒嗘嫞");
-                }
-
-                // 鑾峰彇璁㈠崟鏄庣粏骞舵鏌ユ暟閲忛檺鍒�
-                var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
-                    .FirstAsync(x => x.Id == lockInfo.OrderDetailId);
-
-                if (orderDetail == null)
-                    throw new Exception($"鏈壘鍒拌鍗曟槑缁嗭紝ID: {lockInfo.OrderDetailId}");
-
-                // 鍏抽敭淇锛氭鏌ョ疮璁℃嫞閫夋暟閲忔槸鍚︿細瓒呰繃璁㈠崟鏁伴噺
-                decimal actualQty = lockInfo.AssignQuantity - lockInfo.PickedQty;
-                decimal remainingOrderQty = orderDetail.NeedOutQuantity - orderDetail.OverOutQuantity;
-
-                if (actualQty > remainingOrderQty)
-                {
-                    // 濡傛灉鍒嗛厤鏁伴噺澶т簬鍓╀綑璁㈠崟鏁伴噺锛岃皟鏁村疄闄呮嫞閫夋暟閲�
-                    actualQty = remainingOrderQty;
-
-                    if (actualQty <= 0)
-                    {
-                        throw new Exception($"璁㈠崟{orderNo}鐨勯渶姹傛暟閲忓凡婊¤冻锛屾棤娉曠户缁垎鎷�");
-                    }
-
-                    _logger.LogWarning($"璋冩暣鍒嗘嫞鏁伴噺锛氬師鍒嗛厤{lockInfo.AssignQuantity - lockInfo.PickedQty}锛岃皟鏁翠负{actualQty}锛岃鍗曢渶姹倇orderDetail.NeedOutQuantity}锛屽凡鍑哄簱{orderDetail.OverOutQuantity}");
-                }
-
-                var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
-                    .Where(x => x.Barcode == barcode && x.StockId == lockInfo.StockId)
-                    .FirstAsync();
-
-                if (stockDetail == null)
-                    return WebResponseContent.Instance.Error("鏃犳晥鐨勬潯鐮佹垨鐗╂枡缂栫爜");
-
-                decimal stockQuantity = stockDetail.StockQuantity;
-
-                List<SplitResult> splitResults = new List<SplitResult>();
-                Dt_OutStockLockInfo finalLockInfo = lockInfo;
-                var finalBarcode = barcode;
-                var finalStockId = stockDetail.Id;
-                decimal actualPickedQty = actualQty;
-
-                if (actualQty < stockQuantity)
-                {
-                    // 鎯呭喌1: 鍒嗛厤鏁伴噺灏忎簬搴撳瓨鏁伴噺锛岄渶瑕佽嚜鍔ㄦ媶鍖�
-                    decimal remainingStockQty = stockQuantity - actualQty;
-
-                    // 鏇存柊鍘熸潯鐮佸簱瀛樹负鍓╀綑鏁伴噺
-                    stockDetail.StockQuantity = remainingStockQty;
-                    stockDetail.OutboundQuantity = remainingStockQty;
-                    await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync();
-
-                    // 鐢熸垚鏂版潯鐮佺敤浜庤褰曟嫞閫夋暟閲�
-                    var seq = await _dailySequenceService.GetNextSequenceAsync();
-                    string newBarcode = "WSLOT" + DateTime.Now.ToString("yyyyMMdd") + seq.ToString()?.PadLeft(5, '0');
-
-                    // 涓烘柊鏉$爜鍒涘缓鍑哄簱閿佸畾淇℃伅
-                    var newLockInfo = new Dt_OutStockLockInfo
-                    {
-                        OrderNo = lockInfo.OrderNo,
-                        OrderDetailId = lockInfo.OrderDetailId,
-                        BatchNo = lockInfo.BatchNo,
-                        MaterielCode = lockInfo.MaterielCode,
-                        MaterielName = lockInfo.MaterielName,
-                        StockId = lockInfo.StockId,
-                        OrderQuantity = actualQty,
-                        OriginalQuantity = actualQty,
-                        AssignQuantity = actualQty,
-                        PickedQty = actualQty,
-                        LocationCode = lockInfo.LocationCode,
-                        PalletCode = lockInfo.PalletCode,
-                        TaskNum = lockInfo.TaskNum,
-                        Status = (int)OutLockStockStatusEnum.鎷i�夊畬鎴�,
-                        Unit = lockInfo.Unit,
-                        SupplyCode = lockInfo.SupplyCode,
-                        OrderType = lockInfo.OrderType,
-                        CurrentBarcode = newBarcode,
-                        OriginalLockQuantity = actualQty,
-                        IsSplitted = 1,
-                        ParentLockId = lockInfo.Id
-                    };
-
-                    var newLockId = await _outStockLockInfoService.Db.Insertable(newLockInfo).ExecuteReturnIdentityAsync();
-                    newLockInfo.Id = newLockId;
-
-                    // 璁板綍鎷嗗寘鍘嗗彶
-                    var splitHistory = new Dt_SplitPackageRecord
-                    {
-                        FactoryArea = lockInfo.FactoryArea,
-                        TaskNum = lockInfo.TaskNum,
-                        OutStockLockInfoId = lockInfo.Id,
-                        StockId = stockDetail.StockId,
-                        Operator = App.User.UserName,
-                        IsReverted = false,
-                        OriginalBarcode = barcode,
-                        NewBarcode = newBarcode,
-                        SplitQty = actualQty,
-                        RemainQuantity = remainingStockQty,
-                        MaterielCode = lockInfo.MaterielCode,
-                        SplitTime = DateTime.Now,
-                        OrderNo = lockInfo.OrderNo,
-                        PalletCode = lockInfo.PalletCode,
-                        Status = (int)SplitPackageStatusEnum.宸叉嫞閫�
-                    };
-                    await _splitPackageService.Db.Insertable(splitHistory).ExecuteCommandAsync();
-
-                    // 鏇存柊鍘熼攣瀹氫俊鎭负鍓╀綑搴撳瓨鏁伴噺
-                    lockInfo.AssignQuantity = remainingStockQty;
-                    lockInfo.PickedQty = 0;
-                    await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
-
-                    splitResults.Add(new SplitResult
-                    {
-                        materialCode = lockInfo.MaterielCode,
-                        supplierCode = lockInfo.SupplyCode,
-                        quantityTotal = actualQty.ToString("F2"),
-                        batchNumber = newBarcode,
-                        batch = lockInfo.BatchNo,
-                        factory = lockInfo.FactoryArea,
-                        date = DateTime.Now.ToString("yyyy-MM-dd"),
-                    });
-
-                    splitResults.Add(new SplitResult
-                    {
-                        materialCode = lockInfo.MaterielCode,
-                        supplierCode = lockInfo.SupplyCode,
-                        quantityTotal = remainingStockQty.ToString("F2"),
-                        batchNumber = barcode,
-                        batch = lockInfo.BatchNo,
-                        factory = lockInfo.FactoryArea,
-                        date = DateTime.Now.ToString("yyyy-MM-dd"),
-                    });
-
-                    finalLockInfo = newLockInfo;
-                    finalBarcode = newBarcode;
-                }
-                else if (actualQty == stockQuantity)
-                {
-                    // 鎯呭喌2: 鍒嗛厤鏁伴噺绛変簬搴撳瓨鏁伴噺锛屾暣鍖呭嚭搴�
-                    stockDetail.StockQuantity = 0;
-                    stockDetail.OutboundQuantity = 0;
-                    await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync();
-
-                    lockInfo.PickedQty += actualQty;
-                    lockInfo.Status = (int)OutLockStockStatusEnum.鎷i�夊畬鎴�;
-                    await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
-                }
-                else
-                {
-                    // 鎯呭喌3: 鍒嗛厤鏁伴噺澶т簬搴撳瓨鏁伴噺锛屽簱瀛樻暣鍖呭嚭搴�
-                    decimal stockOutQty = stockQuantity;
-                    stockDetail.StockQuantity = 0;
-                    stockDetail.OutboundQuantity = 0;
-                    await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync();
-
-                    decimal remainingAssignQty = actualQty - stockQuantity;
-                    lockInfo.PickedQty += stockOutQty;
-                    lockInfo.AssignQuantity = remainingAssignQty;
-                    await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
-
-                    var relatedSplitRecords = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>()
-                        .Where(it => it.OriginalBarcode == barcode || it.NewBarcode == barcode)
-                        .Where(it => !it.IsReverted)
-                        .ToListAsync();
-
-                    foreach (var record in relatedSplitRecords)
-                    {
-                        record.Status = (int)SplitPackageStatusEnum.宸叉嫞閫�;
-                        await _splitPackageService.Db.Updateable(record).ExecuteCommandAsync();
-                    }
-
-                    actualPickedQty = stockOutQty;
-                }
-
-                // 鍏抽敭淇锛氬啀娆℃鏌ヨ鍗曟暟閲忛檺鍒�
-                decimal newOverOutQuantity = orderDetail.OverOutQuantity + actualPickedQty;
-                decimal newPickedQty = orderDetail.PickedQty + actualPickedQty;
-
-                if (newOverOutQuantity > orderDetail.NeedOutQuantity)
-                {
-                    throw new Exception($"鍒嗘嫞鍚庡皢瀵艰嚧宸插嚭搴撴暟閲�({newOverOutQuantity})瓒呰繃璁㈠崟闇�姹傛暟閲�({orderDetail.NeedOutQuantity})");
-                }
-
-                // 鏇存柊璁㈠崟鏄庣粏
-                await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
-                    .SetColumns(it => new Dt_OutboundOrderDetail
-                    {
-                        PickedQty = newPickedQty,
-                        OverOutQuantity = newOverOutQuantity
-                    })
-                    .Where(it => it.Id == lockInfo.OrderDetailId)
-                    .ExecuteCommandAsync();
-
-                await CheckAndUpdateOrderStatus(orderNo);
-
-                // 鏌ヨ浠诲姟琛�
-                var task = _taskRepository.QueryData(x => x.OrderNo == orderNo && x.PalletCode == palletCode).FirstOrDefault();
-
-                if (finalLockInfo.Id <= 0)
-                {
-                    throw new Exception($"閿佸畾淇℃伅ID鏃犳晥: {finalLockInfo.Id}锛屾棤娉曡褰曟嫞閫夊巻鍙�");
-                }
-
-                // 璁板綍鎷i�夊巻鍙�
-                var pickingHistory = new Dt_PickingRecord
-                {
-                    FactoryArea = finalLockInfo.FactoryArea,
-                    TaskNo = task?.TaskNum ?? 0,
-                    LocationCode = task?.SourceAddress ?? "",
-                    StockId = finalStockId,
-                    OrderNo = orderNo,
-                    OrderDetailId = finalLockInfo.OrderDetailId,
-                    PalletCode = palletCode,
-                    Barcode = finalBarcode,
-                    MaterielCode = finalLockInfo.MaterielCode,
-                    PickQuantity = actualPickedQty,
-                    PickTime = DateTime.Now,
-                    Operator = App.User.UserName,
-                    OutStockLockId = finalLockInfo.Id
-                };
-                await Db.Insertable(pickingHistory).ExecuteCommandAsync();
-
-                _unitOfWorkManage.CommitTran();
-
-                if (splitResults.Any())
-                {
-                    return WebResponseContent.Instance.OK("鎷i�夌‘璁ゆ垚鍔燂紝宸茶嚜鍔ㄦ媶鍖�", new { SplitResults = splitResults });
-                }
-
-                return WebResponseContent.Instance.OK("鎷i�夌‘璁ゆ垚鍔�", new { SplitResults = new List<SplitResult>() });
-
-            }
-            catch (Exception ex)
-            {
-                _unitOfWorkManage.RollbackTran();
-                _logger.LogError($"ConfirmPicking澶辫触 - OrderNo: {orderNo}, PalletCode: {palletCode}, Barcode: {barcode}, Error: {ex.Message}");
-                return WebResponseContent.Instance.Error($"鎷i�夌‘璁ゅけ璐ワ細{ex.Message}");
-            }
-        }
-
-        public async Task<WebResponseContent> CancelPicking(string orderNo, string palletCode, string barcode)
-        {
-            try
-            {
-                _unitOfWorkManage.BeginTran();
-
-                // 鏌ユ壘鎷i�夎褰�
-                var pickingRecord = await Db.Queryable<Dt_PickingRecord>()
-                    .Where(it => it.OrderNo == orderNo &&
-                               it.PalletCode == palletCode &&
-                               it.Barcode == barcode)
-                    .OrderByDescending(it => it.PickTime)
-                    .FirstAsync();
-
-                if (pickingRecord == null)
-                    return WebResponseContent.Instance.Error("鏈壘鍒板搴旂殑鎷i�夎褰�");
-
-                // 鏌ユ壘鍑哄簱閿佸畾淇℃伅
-                var lockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
-                    .Where(it => it.Id == pickingRecord.OutStockLockId)
-                    .FirstAsync();
-
-                if (lockInfo == null)
-                    return WebResponseContent.Instance.Error("鏈壘鍒板搴旂殑鍑哄簱閿佸畾淇℃伅");
-
-                // 妫�鏌ユ槸鍚﹀彲浠ュ彇娑�
-                if (lockInfo.Status != (int)OutLockStockStatusEnum.鎷i�夊畬鎴�)
-                    return WebResponseContent.Instance.Error("褰撳墠鐘舵�佷笉鍏佽鍙栨秷鍒嗘嫞");
-
-                decimal cancelQty = pickingRecord.PickQuantity;
-
-                // 鑾峰彇璁㈠崟鏄庣粏
-                var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
-                    .FirstAsync(x => x.Id == pickingRecord.OrderDetailId);
-
-                if (orderDetail == null)
-                    throw new Exception($"鏈壘鍒拌鍗曟槑缁嗭紝ID: {pickingRecord.OrderDetailId}");
-
-                // 鍏抽敭淇锛氭鏌ュ彇娑堝悗鏁伴噺涓嶄細涓鸿礋鏁�
-                decimal newOverOutQuantity = orderDetail.OverOutQuantity - cancelQty;
-                decimal newPickedQty = orderDetail.PickedQty - cancelQty;
-
-                if (newOverOutQuantity < 0 || newPickedQty < 0)
-                {
-                    throw new Exception($"鍙栨秷鍒嗘嫞灏嗗鑷村凡鍑哄簱鏁伴噺鎴栧凡鎷i�夋暟閲忎负璐熸暟");
-                }
-
-                // 澶勭悊鍙栨秷閫昏緫
-                if (lockInfo.IsSplitted == 1 && lockInfo.ParentLockId.HasValue)
-                {
-                    await HandleSplitBarcodeCancel(lockInfo, pickingRecord, cancelQty);
-                }
-                else
-                {
-                    await HandleNormalBarcodeCancel(lockInfo, pickingRecord, cancelQty);
-                }
-
-                // 鏇存柊璁㈠崟鏄庣粏
-                await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
-                    .SetColumns(it => new Dt_OutboundOrderDetail
-                    {
-                        PickedQty = newPickedQty,
-                        OverOutQuantity = newOverOutQuantity
-                    })
-                    .Where(it => it.Id == pickingRecord.OrderDetailId)
-                    .ExecuteCommandAsync();
-
-                // 鍒犻櫎鎷i�夎褰�
-                await Db.Deleteable<Dt_PickingRecord>()
-                    .Where(x => x.Id == pickingRecord.Id)
-                    .ExecuteCommandAsync();
-
-                // 閲嶆柊妫�鏌ヨ鍗曠姸鎬�
-                await CheckAndUpdateOrderStatus(orderNo);
-
-                _unitOfWorkManage.CommitTran();
-                return WebResponseContent.Instance.OK($"鍙栨秷鍒嗘嫞鎴愬姛锛屾仮澶嶆暟閲忥細{cancelQty}");
-            }
-            catch (Exception ex)
-            {
-                _unitOfWorkManage.RollbackTran();
-                _logger.LogError($"CancelPicking澶辫触 - OrderNo: {orderNo}, PalletCode: {palletCode}, Barcode: {barcode}, Error: {ex.Message}");
-                return WebResponseContent.Instance.Error($"鍙栨秷鍒嗘嫞澶辫触锛歿ex.Message}");
-            }
-        }
-
-        private async Task HandleSplitBarcodeCancel(Dt_OutStockLockInfo lockInfo, Dt_PickingRecord pickingRecord, decimal cancelQty)
-        {
-            // 鏌ユ壘鐖堕攣瀹氫俊鎭�
-            var parentLockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
-                .Where(x => x.Id == lockInfo.ParentLockId.Value)
-                .FirstAsync();
-
-            if (parentLockInfo == null)
-            {
-                throw new Exception("鏈壘鍒扮埗閿佸畾淇℃伅锛屾棤娉曞彇娑堟媶鍖呭垎鎷�");
-            }
-
-            // 鎭㈠鐖堕攣瀹氫俊鎭殑鍒嗛厤鏁伴噺
-            parentLockInfo.AssignQuantity += cancelQty;
-            await _outStockLockInfoService.Db.Updateable(parentLockInfo).ExecuteCommandAsync();
-
-            // 鎭㈠搴撳瓨
-            var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
-                .Where(x => x.Barcode == parentLockInfo.CurrentBarcode && x.StockId == parentLockInfo.StockId)
-                .FirstAsync();
-
-            if (stockDetail != null)
-            {
-                stockDetail.StockQuantity += cancelQty;
-                stockDetail.OutboundQuantity += cancelQty;
-                await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync();
-            }
-
-            // 鏇存柊鎷嗗寘璁板綍鐘舵��
-            await _splitPackageService.Db.Updateable<Dt_SplitPackageRecord>()
-                .SetColumns(x => new Dt_SplitPackageRecord
-                {
-                    Status = (int)SplitPackageStatusEnum.宸叉挙閿�,
-                    IsReverted = true
-                })
-                .Where(x => x.NewBarcode == lockInfo.CurrentBarcode && !x.IsReverted)
-                .ExecuteCommandAsync();
-
-            // 鍒犻櫎鎷嗗寘浜х敓鐨勯攣瀹氫俊鎭�
-            await _outStockLockInfoService.Db.Deleteable<Dt_OutStockLockInfo>()
-                .Where(x => x.Id == lockInfo.Id)
-                .ExecuteCommandAsync();
-        }
-
-        private async Task HandleNormalBarcodeCancel(Dt_OutStockLockInfo lockInfo, Dt_PickingRecord pickingRecord, decimal cancelQty)
-        {
-            // 鎭㈠閿佸畾淇℃伅
-            lockInfo.PickedQty -= cancelQty;
-            if (lockInfo.PickedQty < 0) lockInfo.PickedQty = 0;
-
-            lockInfo.Status = (int)OutLockStockStatusEnum.鍑哄簱涓�;
-            await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
-
-            // 鎭㈠搴撳瓨
-            var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
-                .Where(x => x.Barcode == pickingRecord.Barcode && x.StockId == pickingRecord.StockId)
-                .FirstAsync();
-
-            if (stockDetail != null)
-            {
-                stockDetail.StockQuantity += cancelQty;
-                stockDetail.OutboundQuantity += cancelQty;
-                await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync();
-            }
-        }
-
-        public async Task<WebResponseContent> ReturnRemaining(string orderNo, string palletCode, string reason)
-        {
-            try
-            {
-                _unitOfWorkManage.BeginTran();
-                        
-                if (string.IsNullOrEmpty(orderNo) || string.IsNullOrEmpty(palletCode))
-                {
-                    return WebResponseContent.Instance.Error("璁㈠崟鍙峰拰鎵樼洏鐮佷笉鑳戒负绌�");
-                }               
-                var stockInfo = await _stockInfoService.Db.Queryable<Dt_StockInfo>()
-                    .FirstAsync(x => x.PalletCode == palletCode);
-
-                if (stockInfo == null)
-                {
-                    return WebResponseContent.Instance.Error($"鏈壘鍒版墭鐩� {palletCode} 瀵瑰簲鐨勫簱瀛樹俊鎭�");
-                }             
-                var task = await GetCurrentTask(orderNo, palletCode);
-                if (task == null)
-                {
-                    return WebResponseContent.Instance.Error("鏈壘鍒板搴旂殑浠诲姟淇℃伅");
-                }
-
-                // 鍒嗘瀽闇�瑕佸洖搴撶殑璐х墿
-                var returnAnalysis = await AnalyzeReturnItems(orderNo, palletCode, stockInfo.Id);
-
-                if (!returnAnalysis.HasItemsToReturn)
-                {
-                    return await HandleNoReturnItems(orderNo, palletCode);
-                }
-
-                // 鎵ц鍥炲簱鎿嶄綔
-                await ExecuteReturnOperations(orderNo, palletCode, stockInfo, task, returnAnalysis);
-
-                //鍒涘缓鍥炲簱浠诲姟骞跺鐞咵SS
-                await CreateReturnTaskAndHandleESS(orderNo, palletCode, task, returnAnalysis);
-
-                _unitOfWorkManage.CommitTran();
-
-                // 鏇存柊璁㈠崟鐘舵�� 
-                await UpdateOrderStatusForReturn(orderNo);
-
-                return WebResponseContent.Instance.OK($"鍥炲簱鎿嶄綔鎴愬姛锛屽叡鍥炲簱鏁伴噺锛歿returnAnalysis.TotalReturnQty}");
-
-            }
-            catch (Exception ex)
-            {
-                _unitOfWorkManage.RollbackTran();
-                _logger.LogError($"ReturnRemaining澶辫触 - OrderNo: {orderNo}, PalletCode: {palletCode}, Error: {ex.Message}");
-                return WebResponseContent.Instance.Error($"鍥炲簱鎿嶄綔澶辫触: {ex.Message}");
-            }
-        }
-
-        #region 璁㈠崟鐘舵�� 
-
-        private async Task UpdateOrderStatusForReturn(string orderNo)
-        {
-            try
-            {
-                var orderDetails = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
-                    .LeftJoin<Dt_OutboundOrder>((o, item) => o.OrderId == item.Id)
-                    .Where((o, item) => item.OrderNo == orderNo)
-                    .Select((o, item) => o)
-                    .ToListAsync();
-
-                bool allCompleted = true;
-                foreach (var detail in orderDetails)
-                {
-                    if (detail.OverOutQuantity < detail.NeedOutQuantity)
-                    {
-                        allCompleted = false;
-                        break;
-                    }
-                }
-
-                var outboundOrder = await _outboundOrderService.Db.Queryable<Dt_OutboundOrder>()
-                    .FirstAsync(x => x.OrderNo == orderNo);
-
-                if (outboundOrder == null) return;
-
-                // 鍙湁褰撶姸鎬佺‘瀹炲彂鐢熷彉鍖栨椂鎵嶆洿鏂�
-                int newStatus = allCompleted ? (int)OutOrderStatusEnum.鍑哄簱瀹屾垚 : (int)OutOrderStatusEnum.鍑哄簱涓�;
-
-                if (outboundOrder.OrderStatus != newStatus)
-                {
-                    await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>()
-                        .SetColumns(x => x.OrderStatus == newStatus)
-                        .Where(x => x.OrderNo == orderNo)
-                        .ExecuteCommandAsync();
-
-                    _logger.LogInformation($"鍥炲簱鎿嶄綔鏇存柊璁㈠崟鐘舵�� - OrderNo: {orderNo}, 鏂扮姸鎬�: {newStatus}");
-                }
-            }
-            catch (Exception ex)
-            {
-                _logger.LogError($"UpdateOrderStatusForReturn澶辫触 - OrderNo: {orderNo}, Error: {ex.Message}");
-                
-            }
-        }
-
-        #endregion
-
-        #region Private Methods
-
-        private async Task<Dt_Task> GetCurrentTask(string orderNo, string palletCode)
-        {
-            // 鍏堝皾璇曢�氳繃璁㈠崟鍙峰拰鎵樼洏鍙锋煡鎵句换鍔�
-            var task = await _taskRepository.Db.Queryable<Dt_Task>()
-                .Where(x => x.OrderNo == orderNo && x.PalletCode == palletCode)
-                .FirstAsync();
-
-            if (task == null)
-            {
-                // 濡傛灉鎵句笉鍒帮紝鍐嶉�氳繃鎵樼洏鍙锋煡鎵�
-                task = await _taskRepository.Db.Queryable<Dt_Task>()
-                    .Where(x => x.PalletCode == palletCode)
-                    .FirstAsync();
-            }
-
-            return task;
-        }
-
-        private async Task<ReturnAnalysisResult> AnalyzeReturnItems(string orderNo, string palletCode, int stockId)
-        {
-            var result = new ReturnAnalysisResult();
-
-            // 鑾峰彇鏈垎鎷g殑鍑哄簱閿佸畾璁板綍
-            var remainingLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
-                .Where(it => it.OrderNo == orderNo &&
-                           it.PalletCode == palletCode &&
-                           it.Status == (int)OutLockStockStatusEnum.鍑哄簱涓�)
-                .ToListAsync();
-
-            if (remainingLocks.Any())
-            {
-                result.HasRemainingLocks = true;
-                result.RemainingLocks = remainingLocks;
-                result.RemainingLocksReturnQty = remainingLocks.Sum(x => x.AssignQuantity - x.PickedQty);
-            }
-
-            // 妫�鏌ユ墭鐩樹笂鏄惁鏈夊叾浠栧簱瀛樿揣鐗�    
-            var palletStockGoods = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
-                .Where(it => it.StockId == stockId &&
-                            (it.Status == StockStatusEmun.鍏ュ簱纭.ObjToInt() ||
-                             it.Status == StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt() ||
-                             it.Status == StockStatusEmun.鍑哄簱閿佸畾.ObjToInt()))
-                .Where(it => it.StockQuantity > 0) // 鏈夊簱瀛樼殑
-                .ToListAsync();
-
-
-            if (palletStockGoods.Any())
-            {
-                result.HasPalletStockGoods = true;
-                result.PalletStockGoods = palletStockGoods;
-                result.PalletStockReturnQty = palletStockGoods.Sum(x => x.StockQuantity);
-            }
-
-            //  妫�鏌ユ媶鍖呰褰�
-            var splitRecords = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>()
-                .Where(it => it.OrderNo == orderNo && it.PalletCode == palletCode && !it.IsReverted)
-                .ToListAsync();
-
-            if (splitRecords.Any())
-            {
-                result.HasSplitRecords = true;
-                result.SplitRecords = splitRecords;
-                result.SplitReturnQty = await CalculateSplitReturnQuantity(splitRecords, stockId);
-            }
-
-            result.TotalReturnQty = result.RemainingLocksReturnQty + result.PalletStockReturnQty + result.SplitReturnQty;
-            result.HasItemsToReturn = result.TotalReturnQty > 0;
-
-            return result;
-        }
-
-        private async Task<decimal> CalculateSplitReturnQuantity(List<Dt_SplitPackageRecord> splitRecords, int stockId)
-        {
-            decimal totalQty = 0;
-            var processedBarcodes = new HashSet<string>();
-
-            foreach (var splitRecord in splitRecords)
-            {
-                // 妫�鏌ュ師鏉$爜
-                if (!processedBarcodes.Contains(splitRecord.OriginalBarcode))
-                {
-                    var originalStock = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
-                        .Where(it => it.Barcode == splitRecord.OriginalBarcode && it.StockId == stockId)
-                        .FirstAsync();
-
-                    if (originalStock != null && originalStock.StockQuantity > 0)
-                    {
-                        totalQty += originalStock.StockQuantity;
-                        processedBarcodes.Add(splitRecord.OriginalBarcode);
-                    }
-                }
-
-                // 妫�鏌ユ柊鏉$爜
-                if (!processedBarcodes.Contains(splitRecord.NewBarcode))
-                {
-                    var newStock = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
-                        .Where(it => it.Barcode == splitRecord.NewBarcode && it.StockId == stockId)
-                        .FirstAsync();
-
-                    if (newStock != null && newStock.StockQuantity > 0)
-                    {
-                        totalQty += newStock.StockQuantity;
-                        processedBarcodes.Add(splitRecord.NewBarcode);
-                    }
-                }
-            }
-
-            return totalQty;
-        }
-
-        private async Task<WebResponseContent> HandleNoReturnItems(string orderNo, string palletCode)
-        {
-            // 妫�鏌ユ槸鍚︽墍鏈夎揣鐗╅兘宸叉嫞閫夊畬鎴�
-            var allPicked = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
-                .Where(it => it.OrderNo == orderNo && it.PalletCode == palletCode)
-                .AnyAsync(it => it.Status == (int)OutLockStockStatusEnum.鎷i�夊畬鎴�);
-
-            if (allPicked)
-            {
-                return WebResponseContent.Instance.OK("鎵�鏈夎揣鐗╁凡鎷i�夊畬鎴愶紝鎵樼洏涓虹┖");
-            }
-            else
-            {
-                return WebResponseContent.Instance.Error("娌℃湁闇�瑕佸洖搴撶殑鍓╀綑璐х墿");
-            }
-        }
-
-        private async Task ExecuteReturnOperations(string orderNo, string palletCode, Dt_StockInfo stockInfo,
-            Dt_Task task, ReturnAnalysisResult analysis)
-        {
-            // 鎯呭喌1锛氬鐞嗘湭鍒嗘嫞鐨勫嚭搴撻攣瀹氳褰�
-            if (analysis.HasRemainingLocks)
-            {
-                await HandleRemainingLocksReturn(analysis.RemainingLocks, stockInfo.Id);
-
-                // 鍏抽敭锛氭洿鏂拌鍗曟槑缁嗙殑宸叉嫞閫夋暟閲�
-                await UpdateOrderDetailsOnReturn(analysis.RemainingLocks);
-            }
-
-            // 鎯呭喌2锛氬鐞嗘墭鐩樹笂鍏朵粬搴撳瓨璐х墿
-            if (analysis.HasPalletStockGoods)
-            {
-                await HandlePalletStockGoodsReturn(analysis.PalletStockGoods);
-            }
-
-            // 鎯呭喌3锛氬鐞嗘媶鍖呰褰�
-            if (analysis.HasSplitRecords)
-            {
-                await HandleSplitRecordsReturn(analysis.SplitRecords, orderNo, palletCode);
-            }
-
-            // 鏇存柊搴撳瓨涓昏〃鐘舵��
-            await UpdateStockInfoStatus(stockInfo);
-        }
-
-        private async Task HandleRemainingLocksReturn(List<Dt_OutStockLockInfo> remainingLocks, int stockId)
-        {
-            var lockIds = remainingLocks.Select(x => x.Id).ToList();
-
-            // 鏇存柊鍑哄簱閿佸畾璁板綍鐘舵�佷负鍥炲簱涓�
-            await _outStockLockInfoService.Db.Updateable<Dt_OutStockLockInfo>()
-                .SetColumns(it => new Dt_OutStockLockInfo
-                {
-                    Status = (int)OutLockStockStatusEnum.鍥炲簱涓� 
-                })
-                .Where(it => lockIds.Contains(it.Id))
-                .ExecuteCommandAsync();
-
-            // 澶勭悊搴撳瓨璁板綍
-            foreach (var lockInfo in remainingLocks)
-            {
-                decimal returnQty = lockInfo.AssignQuantity - lockInfo.PickedQty;
-
-                // 鏌ユ壘瀵瑰簲鐨勫簱瀛樻槑缁�
-                var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
-                    .Where(it => it.Barcode == lockInfo.CurrentBarcode && it.StockId == lockInfo.StockId)
-                    .FirstAsync();
-
-                if (stockDetail != null)
-                {
-                    // 鎭㈠搴撳瓨鐘舵��
-                    stockDetail.OutboundQuantity = Math.Max(0, stockDetail.OutboundQuantity - returnQty);
-                    stockDetail.Status = StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt();
-                    await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync();
-                }
-                else
-                {
-                    // 鍒涘缓鏂扮殑搴撳瓨璁板綍锛堟媶鍖呬骇鐢熺殑鏂版潯鐮侊級
-                    var newStockDetail = new Dt_StockInfoDetail
-                    {
-                        StockId = lockInfo.StockId,
-                        MaterielCode = lockInfo.MaterielCode,
-                        MaterielName = lockInfo.MaterielName,
-                        OrderNo = lockInfo.OrderNo,
-                        BatchNo = lockInfo.BatchNo,
-                        StockQuantity = returnQty,
-                        OutboundQuantity = 0,
-                        Barcode = lockInfo.CurrentBarcode,
-                        InboundOrderRowNo = "",
-                        Status = StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt(),
-                        SupplyCode = lockInfo.SupplyCode,
-                        WarehouseCode = lockInfo.WarehouseCode,
-                        Unit = lockInfo.Unit 
-                    };
-                    await _stockInfoDetailService.Db.Insertable(newStockDetail).ExecuteCommandAsync();
-                }
-            }
-        }
-
-        private async Task UpdateOrderDetailsOnReturn(List<Dt_OutStockLockInfo> remainingLocks)
-        {
-            // 鎸夎鍗曟槑缁嗗垎缁�
-            var orderDetailGroups = remainingLocks.GroupBy(x => x.OrderDetailId);
-
-            foreach (var group in orderDetailGroups)
-            {
-                var orderDetailId = group.Key;
-                var totalReturnQty = group.Sum(x => x.AssignQuantity - x.PickedQty);
-
-                // 鑾峰彇褰撳墠璁㈠崟鏄庣粏
-                var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
-                    .FirstAsync(x => x.Id == orderDetailId);
-
-                if (orderDetail != null)
-                {
-                    // 璋冩暣宸叉嫞閫夋暟閲忓拰宸插嚭搴撴暟閲�
-                    decimal newPickedQty = Math.Max(0, orderDetail.PickedQty - totalReturnQty);
-                    decimal newOverOutQuantity = Math.Max(0, orderDetail.OverOutQuantity - totalReturnQty);
-
-                    await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
-                        .SetColumns(it => new Dt_OutboundOrderDetail
-                        {
-                            PickedQty = newPickedQty,
-                            OverOutQuantity = newOverOutQuantity
-                        })
-                        .Where(it => it.Id == orderDetailId)
-                        .ExecuteCommandAsync();
-                }
-            }
-        }
-
-        private async Task HandlePalletStockGoodsReturn(List<Dt_StockInfoDetail> palletStockGoods)
-        {
-            foreach (var stockGood in palletStockGoods)
-            {
-                // 鎭㈠搴撳瓨鐘舵��
-                stockGood.OutboundQuantity = 0;
-                stockGood.Status = StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt(); 
-                await _stockInfoDetailService.Db.Updateable(stockGood).ExecuteCommandAsync();
-            }
-        }
-
-        private async Task HandleSplitRecordsReturn(List<Dt_SplitPackageRecord> splitRecords, string orderNo, string palletCode)
-        {
-            // 鏇存柊鎷嗗寘璁板綍鐘舵��
-            await _splitPackageService.Db.Updateable<Dt_SplitPackageRecord>()
-                .SetColumns(x => new Dt_SplitPackageRecord
-                {
-                    Status = (int)SplitPackageStatusEnum.宸插洖搴�               
-                })
-                .Where(x => x.OrderNo == orderNo && x.PalletCode == palletCode && !x.IsReverted)
-                .ExecuteCommandAsync();
-        }
-
-        private async Task UpdateStockInfoStatus(Dt_StockInfo stockInfo)
-        {
-            // 鏇存柊搴撳瓨涓昏〃鐘舵��
-            stockInfo.StockStatus = StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt();  
-            await _stockInfoService.Db.Updateable(stockInfo).ExecuteCommandAsync();
-        }
-
-        private async Task CreateReturnTaskAndHandleESS(string orderNo, string palletCode, Dt_Task originalTask, ReturnAnalysisResult analysis)
-        {
-            var firstLocation = await _locationInfoService.Db.Queryable<Dt_LocationInfo>()
-                .FirstAsync(x => x.LocationCode == originalTask.SourceAddress);
-
-            // 鍒嗛厤鏂拌揣浣嶏紙鍥炲簱鍒板瓨鍌ㄤ綅锛�
-            var newLocation = _locationInfoService.AssignLocation(firstLocation.LocationType);
-
-            Dt_Task returnTask = new()
-            {
-                CurrentAddress = stations[originalTask.TargetAddress],
-                Grade = 0,
-                PalletCode = palletCode,
-                NextAddress = "",
-                OrderNo = originalTask.OrderNo,
-                Roadway = newLocation.RoadwayNo,
-                SourceAddress = stations[originalTask.TargetAddress],
-                TargetAddress = newLocation.LocationCode,
-                TaskStatus = TaskStatusEnum.New.ObjToInt(),
-                TaskType = TaskTypeEnum.InPick.ObjToInt(),
-                PalletType = originalTask.PalletType,
-                WarehouseId = originalTask.WarehouseId,
-
-            }; 
-
-            // 淇濆瓨鍥炲簱浠诲姟
-            await _taskRepository.Db.Insertable(returnTask).ExecuteCommandAsync();
-
-            // 鍒犻櫎鍘熷鍑哄簱浠诲姟
-              _taskRepository.Db.Deleteable(originalTask);
-
-            // 缁� ESS 鍙戦�佹祦鍔ㄤ俊鍙峰拰鍒涘缓浠诲姟
-            await SendESSCommands(palletCode, originalTask, returnTask);
-        }
-        private async Task SendESSCommands(string palletCode, Dt_Task originalTask, Dt_Task returnTask)
-        {
-            try
-            {
-                // 1. 鍙戦�佹祦鍔ㄤ俊鍙�
-                var moveResult = await _eSSApiService.MoveContainerAsync(new WIDESEA_DTO.Basic.MoveContainerRequest
-                {
-                    slotCode = movestations[originalTask.TargetAddress],
-                    containerCode = palletCode
-                });
-
-                if (moveResult)
-                {
-                    // 2. 鍒涘缓鍥炲簱浠诲姟
-                    var essTask = new TaskModel()
-                    {
-                        taskType = "putaway",
-                        taskGroupCode = "",
-                        groupPriority = 0,
-                        tasks = new List<TasksType>
-                {
-                    new()
-                    {
-                        taskCode = returnTask.TaskNum.ToString(),
-                        taskPriority = 0,
-                        taskDescribe = new TaskDescribeType
-                        {
-                            containerCode = palletCode,
-                            containerType = "CT_KUBOT_STANDARD",
-                            fromLocationCode = stations.GetValueOrDefault(originalTask.TargetAddress) ?? "",
-                            toStationCode = "",
-                            toLocationCode = returnTask.TargetAddress,
-                            deadline = 0,
-                            storageTag = ""
-                        }
-                    }
-                }
-                    };
-
-                    var resultTask = await _eSSApiService.CreateTaskAsync(essTask);
-                    _logger.LogInformation($"ReturnRemaining 鍒涘缓浠诲姟鎴愬姛: {resultTask}");
-                }
-            }
-            catch (Exception ex)
-            {
-                _logger.LogError($"ReturnRemaining ESS鍛戒护鍙戦�佸け璐�: {ex.Message}");
-                throw new Exception($"ESS绯荤粺閫氫俊澶辫触: {ex.Message}");
-            }
-        }
-
-        #endregion
-
-  
-
-        /// <summary>
-        /// 鍥炲簱鎿嶄綔  
-        /// </summary>
-
-        //public async Task<WebResponseContent> ReturnRemaining(string orderNo, string palletCode, string reason)
-        //{
-        //    try
-        //    {
-        //        _unitOfWorkManage.BeginTran();
-
-        //        // 鑾峰彇鎵�鏈夋湭鍒嗘嫞鐨勫嚭搴撻攣瀹氳褰曪紝鍖呮嫭鎷嗗寘浜х敓鐨勮褰�
-        //        var remainingLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
-        //            .Where(it => it.OrderNo == orderNo && it.Status == (int)OutLockStockStatusEnum.鍑哄簱涓�)
-        //            .ToListAsync();
-
-        //        var stockinfo = _stockInfoService.Db.Queryable<Dt_StockInfo>().First(x => x.PalletCode == palletCode);
-
-        //        var tasks = new List<Dt_Task>();
-
-        //        // 鏌ヨ浠诲姟琛�
-        //        var task = remainingLocks.Any()
-        //            ? _taskRepository.QueryData(x => x.TaskNum == remainingLocks.First().TaskNum).FirstOrDefault()
-        //            : _taskRepository.QueryData(x => x.PalletCode == palletCode).FirstOrDefault();
-
-        //        if (task == null)
-        //        {
-        //            return WebResponseContent.Instance.Error("鏈壘鍒板搴旂殑浠诲姟淇℃伅");
-        //        }
-
-        //        // 妫�鏌ユ墭鐩樹笂鏄惁鏈夊叾浠栭潪鍑哄簱璐х墿锛堝簱瀛樿揣鐗╋級
-        //        var palletStockGoods = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
-        //            .Where(it => it.StockId == stockinfo.Id &&
-        //                        (it.Status == StockStatusEmun.鍏ュ簱纭.ObjToInt() ||
-        //                         it.Status == StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt() ||
-        //                         it.Status == StockStatusEmun.鍑哄簱閿佸畾.ObjToInt()))
-        //            .Where(it => it.OutboundQuantity == 0 || it.OutboundQuantity < it.StockQuantity) // 鏈畬鍏ㄥ嚭搴撶殑
-        //            .ToListAsync();
-
-        //        // 妫�鏌ユ媶鍖呰褰曪紝鎵惧嚭闇�瑕佸洖搴撶殑鏉$爜
-        //        var splitRecords = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>()
-        //            .Where(it => it.OrderNo == orderNo && it.PalletCode == palletCode && !it.IsReverted)
-        //            .ToListAsync();
-
-        //        // 璁$畻闇�瑕佸洖搴撶殑鎷嗗寘鏉$爜
-        //        var splitBarcodesToReturn = new List<string>();
-        //        foreach (var splitRecord in splitRecords)
-        //        {
-        //            // 妫�鏌ュ師鏉$爜鏄惁杩樻湁搴撳瓨闇�瑕佸洖搴�
-        //            var originalStock = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
-        //                .Where(it => it.Barcode == splitRecord.OriginalBarcode && it.StockId == stockinfo.Id)
-        //                .FirstAsync();
-
-        //            if (originalStock != null && originalStock.StockQuantity > 0)
-        //            {
-        //                splitBarcodesToReturn.Add(splitRecord.OriginalBarcode);
-        //            }
-
-        //            // 妫�鏌ユ柊鏉$爜鏄惁杩樻湁搴撳瓨闇�瑕佸洖搴�
-        //            var newStock = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
-        //                .Where(it => it.Barcode == splitRecord.NewBarcode && it.StockId == stockinfo.Id)
-        //                .FirstAsync();
-
-        //            if (newStock != null && newStock.StockQuantity > 0)
-        //            {
-        //                splitBarcodesToReturn.Add(splitRecord.NewBarcode);
-        //            }
-        //        }
-
-        //        // 濡傛灉娌℃湁闇�瑕佸洖搴撶殑璐х墿锛堟棦鏃犳湭鍒嗘嫞鍑哄簱璐х墿锛屼篃鏃犲叾浠栧簱瀛樿揣鐗╋紝涔熸棤鎷嗗寘鍓╀綑璐х墿锛�
-        //        if (!remainingLocks.Any() && !palletStockGoods.Any() && !splitBarcodesToReturn.Any())
-        //        {
-        //            // 妫�鏌ユ槸鍚︽墍鏈夎揣鐗╅兘宸叉嫞閫夊畬鎴�
-        //            var allPicked = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
-        //                .Where(it => it.OrderNo == orderNo && it.PalletCode == palletCode)
-        //                .AnyAsync(it => it.Status == (int)OutLockStockStatusEnum.鎷i�夊畬鎴�);
-
-        //            if (allPicked)
-        //            {
-        //                return WebResponseContent.Instance.OK("鎵�鏈夎揣鐗╁凡鎷i�夊畬鎴愶紝鎵樼洏涓虹┖");
-        //            }
-        //            else
-        //            {
-        //                return WebResponseContent.Instance.Error("娌℃湁闇�瑕佸洖搴撶殑鍓╀綑璐х墿");
-        //            }
-        //        }
-
-        //        var firstlocation = _locationInfoService.Db.Queryable<Dt_LocationInfo>().First(x => x.LocationCode == task.SourceAddress);
-        //        decimal totalReturnQty = 0;
-
-        //        // 鎯呭喌1锛氬鐞嗘湭鍒嗘嫞鐨勫嚭搴撻攣瀹氳褰�
-        //        if (remainingLocks.Any(x => x.PalletCode == palletCode))
-        //        {
-        //            var palletLocks = remainingLocks.Where(x => x.PalletCode == palletCode).ToList();
-        //            totalReturnQty = palletLocks.Sum(x => x.AssignQuantity - x.PickedQty);
-
-        //            if (totalReturnQty > 0)
-        //            {
-        //                // 鍒嗛厤鏂拌揣浣�
-        //                var newLocation = _locationInfoService.AssignLocation(firstlocation.LocationType);
-
-        //                // 鏇存柊鍑哄簱閿佸畾璁板綍鐘舵��
-        //                var lockIds = palletLocks.Select(x => x.Id).ToList();
-        //                await _outStockLockInfoService.Db.Updateable<Dt_OutStockLockInfo>()
-        //                    .SetColumns(it => new Dt_OutStockLockInfo { Status = (int)OutLockStockStatusEnum.鍥炲簱涓� })
-        //                    .Where(it => lockIds.Contains(it.Id))
-        //                    .ExecuteCommandAsync();
-
-
-
-        //                // 澶勭悊搴撳瓨璁板綍
-        //                foreach (var lockInfo in palletLocks)
-        //                {
-        //                    decimal returnQty = lockInfo.AssignQuantity - lockInfo.PickedQty;
-
-        //                    // 妫�鏌ュ簱瀛樿褰曟槸鍚﹀瓨鍦�
-        //                    var existingStock = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
-        //                        .Where(it => it.Barcode == lockInfo.CurrentBarcode && it.StockId == lockInfo.StockId)
-        //                        .FirstAsync();
-
-        //                    if (existingStock != null)
-        //                    {
-        //                        // 搴撳瓨璁板綍瀛樺湪锛屾仮澶嶉攣瀹氭暟閲�
-        //                        existingStock.OutboundQuantity = 0;
-
-        //                        await _stockInfoDetailService.Db.Updateable(existingStock).ExecuteCommandAsync();
-        //                    }
-        //                    else
-        //                    {
-        //                        // 搴撳瓨璁板綍涓嶅瓨鍦紙鍙兘鏄媶鍖呬骇鐢熺殑鏂版潯鐮侊級锛屽垱寤烘柊鐨勫簱瀛樿褰�
-        //                        var newStockDetail = new Dt_StockInfoDetail
-        //                        {
-        //                            StockId = lockInfo.StockId,
-        //                            MaterielCode = lockInfo.MaterielCode,
-        //                            MaterielName = lockInfo.MaterielName,
-        //                            OrderNo = lockInfo.OrderNo,
-        //                            BatchNo = lockInfo.BatchNo,
-        //                            StockQuantity = returnQty,
-        //                            OutboundQuantity = 0,
-        //                            Barcode = lockInfo.CurrentBarcode,
-        //                            InboundOrderRowNo = "",
-        //                            Status = StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt(),
-        //                            SupplyCode = lockInfo.SupplyCode,
-        //                            WarehouseCode = lockInfo.WarehouseCode,
-        //                            Unit = lockInfo.Unit
-        //                        };
-        //                        await _stockInfoDetailService.Db.Insertable(newStockDetail).ExecuteCommandAsync();
-        //                    }
-        //                }
-
-        //                // 鍒涘缓鍥炲簱浠诲姟
-        //                CreateReturnTask(tasks, task, palletCode, newLocation);
-        //            }
-        //        }
-
-        //        // 鎯呭喌2锛氬鐞嗘媶鍖呭墿浣欑殑搴撳瓨璐х墿
-        //        if (splitBarcodesToReturn.Any())
-        //        {
-        //            decimal splitReturnQty = 0;
-
-        //            foreach (var barcode in splitBarcodesToReturn)
-        //            {
-        //                var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
-        //                    .Where(it => it.Barcode == barcode && it.StockId == stockinfo.Id)
-        //                    .FirstAsync();
-
-        //                if (stockDetail != null && stockDetail.StockQuantity > 0)
-        //                {
-        //                    splitReturnQty += stockDetail.StockQuantity;
-
-        //                    // 鎭㈠搴撳瓨鐘舵�佷负鍏ュ簱瀹屾垚
-        //                    stockDetail.OutboundQuantity = 0;
-
-        //                    await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync();
-        //                }
-        //            }
-
-        //            totalReturnQty += splitReturnQty;
-
-        //            // 濡傛灉娌℃湁鍒涘缓浠诲姟锛屽垱寤哄洖搴撲换鍔�
-        //            if (!tasks.Any())
-        //            {
-        //                var newLocation = _locationInfoService.AssignLocation(firstlocation.LocationType);
-        //                CreateReturnTask(tasks, task, palletCode, newLocation);
-        //            }
-        //        }
-
-        //        // 鎯呭喌3锛氬嚭搴撹揣鐗╁凡鍒嗘嫞瀹岋紝浣嗘墭鐩樹笂杩樻湁鍏朵粬搴撳瓨璐х墿闇�瑕佸洖搴�
-        //        if (palletStockGoods.Any() && !remainingLocks.Any(x => x.PalletCode == palletCode))
-        //        {
-        //            decimal otherReturnQty = palletStockGoods.Sum(x => x.StockQuantity - x.OutboundQuantity);
-        //            totalReturnQty += otherReturnQty;
-        //            // 鏇存柊杩欎簺搴撳瓨璐х墿鐨勭姸鎬�
-        //            foreach (var stockGood in palletStockGoods)
-        //            {
-        //                stockGood.OutboundQuantity = 0;
-
-        //                await _stockInfoDetailService.Db.Updateable(stockGood).ExecuteCommandAsync();
-        //            }
-        //            // 濡傛灉娌℃湁鍒涘缓浠诲姟锛屽垱寤哄洖搴撲换鍔�
-        //            if (!tasks.Any())
-        //            {
-        //                var newLocation = _locationInfoService.AssignLocation(firstlocation.LocationType);
-        //                CreateReturnTask(tasks, task, palletCode, newLocation);
-        //            }
-
-
-        //        }
-
-        //        var allSplitRecords = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>()
-        //            .Where(it => it.OrderNo == orderNo && it.PalletCode == palletCode && !it.IsReverted)
-        //            .ToListAsync();
-
-        //        foreach (var record in allSplitRecords)
-        //        {
-        //            record.Status = (int)SplitPackageStatusEnum.宸插洖搴�;
-        //            await _splitPackageService.Db.Updateable(record).ExecuteCommandAsync();
-        //        }
-        //        // 淇濆瓨浠诲姟 缁橢SS涓嬪彂浠诲姟
-        //        if (tasks.Any())
-        //        {
-        //            try
-        //            {
-        //                await _taskRepository.Db.Insertable(tasks).ExecuteCommandAsync();
-        //                var targetAddress = task.TargetAddress;
-        //                _taskRepository.DeleteData(task);
-
-        //                // 缁� ESS 娴佸姩淇″彿鍜屽垱寤轰换鍔�
-        //                try
-        //                {
-        //                    var result = await _eSSApiService.MoveContainerAsync(new WIDESEA_DTO.Basic.MoveContainerRequest
-        //                    {
-        //                        slotCode = movestations[targetAddress],
-        //                        containerCode = palletCode
-        //                    });
-
-        //                    if (result)
-        //                    {
-        //                        TaskModel esstask = new TaskModel()
-        //                        {
-        //                            taskType = "putaway",
-        //                            taskGroupCode = "",
-        //                            groupPriority = 0,
-        //                            tasks = new List<TasksType>
-        //                    {
-        //                        new()
-        //                        {
-        //                            taskCode = tasks.First().TaskNum.ToString(),
-        //                            taskPriority = 0,
-        //                            taskDescribe = new TaskDescribeType {
-        //                                containerCode = palletCode,
-        //                                containerType = "CT_KUBOT_STANDARD",
-        //                                fromLocationCode = stations.GetValueOrDefault(targetAddress) ?? "",
-        //                                toStationCode = "",
-        //                                toLocationCode = tasks.First().TargetAddress,
-        //                                deadline = 0, storageTag = ""
-        //                            }
-        //                        }
-        //                    }
-        //                        };
-
-        //                        var resulttask = await _eSSApiService.CreateTaskAsync(esstask);
-        //                        _logger.LogInformation("ReturnRemaining 鍒涘缓浠诲姟杩斿洖:  " + resulttask);
-        //                    }
-        //                }
-        //                catch (Exception ex)
-        //                {
-        //                    _logger.LogInformation("ReturnRemaining 鍒涘缓浠诲姟杩斿洖 catch err:  " + ex.Message);
-        //                }
-
-        //                _unitOfWorkManage.CommitTran();
-        //                return WebResponseContent.Instance.OK($"鍥炲簱鎿嶄綔鎴愬姛锛屽叡鍥炲簱鏁伴噺锛歿totalReturnQty}");
-        //            }
-        //            catch (Exception ex)
-        //            {
-        //                _unitOfWorkManage.RollbackTran();
-        //                return WebResponseContent.Instance.Error($"鍒涘缓鍥炲簱浠诲姟澶辫触: {ex.Message}");
-        //            }
-        //        }
-
-        //        _unitOfWorkManage.RollbackTran();
-        //        return WebResponseContent.Instance.Error("鏈垱寤轰换浣曞洖搴撲换鍔�");
-        //    }
-        //    catch (Exception ex)
-        //    {
-        //        _unitOfWorkManage.RollbackTran();
-        //        return WebResponseContent.Instance.Error($"鍥炲簱鎿嶄綔澶辫触: {ex.Message}");
-        //    }
-        //}
-
-
-        /// <summary>
-        /// 鍒涘缓鍥炲簱浠诲姟
-        /// </summary>
-        private void CreateReturnTask(List<Dt_Task> tasks, Dt_Task originalTask, string palletCode, Dt_LocationInfo newLocation)
-        {
-            Dt_Task newTask = new()
-            {
-                CurrentAddress = stations[originalTask.TargetAddress],
-                Grade = 0,
-                PalletCode = palletCode,
-                NextAddress = "",
-                OrderNo = originalTask.OrderNo,
-                Roadway = newLocation.RoadwayNo,
-                SourceAddress = stations[originalTask.TargetAddress],
-                TargetAddress = newLocation.LocationCode,
-                TaskStatus = TaskStatusEnum.New.ObjToInt(),
-                TaskType = TaskTypeEnum.InPick.ObjToInt(),
-                PalletType = originalTask.PalletType,
-                WarehouseId = originalTask.WarehouseId,
-
-            };
-            tasks.Add(newTask);
-        }
-
-        /// <summary>
-        /// 妫�鏌ユ墭鐩樻槸鍚﹂渶瑕佸洖搴撶殑杈呭姪鏂规硶
-        /// </summary>
-        public async Task<bool> CheckPalletNeedReturn(string orderNo, string palletCode)
-        {
-            // 1. 妫�鏌ユ槸鍚︽湁鏈垎鎷g殑鍑哄簱璁板綍
-            var hasUnpickedLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
-                .Where(it => it.OrderNo == orderNo && it.PalletCode == palletCode && it.Status == 1)
-                .AnyAsync();
-
-            if (hasUnpickedLocks)
-                return true;
-
-            // 2. 妫�鏌ュ嚭搴撴槸鍚﹀凡瀹屾垚浣嗘墭鐩樿繕鏈夊簱瀛樿揣鐗�
-            var outboundFinished = !await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
-                .Where(it => it.PalletCode == palletCode && it.Status == 1)
-                .AnyAsync();
-
-            var stockinfo = _stockInfoService.Db.Queryable<Dt_StockInfo>().First(x => x.PalletCode == palletCode);
-
-
-            var hasRemainingGoods = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
-                .Where(it => it.StockId == stockinfo.Id && it.Status == StockStatusEmun.鍏ュ簱纭.ObjToInt())
-                .Where(it => it.OutboundQuantity == 0 || it.OutboundQuantity < it.StockQuantity)
-                .AnyAsync();
-
-            return outboundFinished && hasRemainingGoods;
-        }
-
- 
-        /// <summary>
-        /// 鑾峰彇鎷嗗寘閾撅紙浠庡綋鍓嶆潯鐮佽拷婧埌鍘熷鏉$爜锛�
-        /// </summary>
-        // 鍦� GetSplitChain 鏂规硶涓坊鍔犳洿涓ユ牸鐨勯獙璇�
-        private async Task<List<SplitChainItem>> GetSplitChain(string currentBarcode)
-        {
-            var chain = new List<SplitChainItem>();
-            var visited = new HashSet<string>();
-
-            string current = currentBarcode;
-            int maxDepth = 10; // 闃叉鏃犻檺寰幆
-
-            while (!string.IsNullOrEmpty(current) && maxDepth > 0)
-            {
-                maxDepth--;
-
-                if (visited.Contains(current))
-                {
-                    _logger.LogWarning($"妫�娴嬪埌寰幆寮曠敤鍦ㄦ媶鍖呴摼涓�: {current}");
-                    break;
-                }
-
-                visited.Add(current);
-
-                var splitRecord = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>()
-                    .Where(it => it.NewBarcode == current && !it.IsReverted)
-                    .FirstAsync();
-
-                if (splitRecord == null)
-                    break;
-
-                // 楠岃瘉鎷嗗寘璁板綍鐨勫畬鏁存��
-                if (string.IsNullOrEmpty(splitRecord.OriginalBarcode))
-                {
-                    _logger.LogError($"鎷嗗寘璁板綍 {splitRecord.Id} 缂哄皯鍘熷鏉$爜");
-                    break;
-                }
-
-                var item = new SplitChainItem
-                {
-                    SplitRecord = splitRecord,
-                    OriginalBarcode = splitRecord.OriginalBarcode,
-                    NewBarcode = splitRecord.NewBarcode,
-                    SplitQuantity = splitRecord.SplitQty
-                };
-
-                chain.Add(item);
-
-                current = splitRecord.OriginalBarcode;
-            }
-
-            if (maxDepth <= 0)
-            {
-                _logger.LogWarning($"鎷嗗寘閾捐拷婧揪鍒版渶澶ф繁搴�: {currentBarcode}");
-            }
-
-            chain.Reverse();
-            return chain;
-        }
-        /// <summary>
-        /// 澶勭悊鎷嗗寘閾剧殑鍙栨秷鍒嗘嫞
-        /// </summary>
-        private async Task HandleSplitChainCancel(string orderNo, string palletCode, string barcode,
-            decimal cancelQty, Dt_OutStockLockInfo lockInfo, Dt_PickingRecord pickingRecord, List<SplitChainItem> splitChain)
-        {
-            if (!splitChain.Any())
-                return;
-
-            //  鎵惧埌鍘熷鏉$爜锛堥摼鐨勭涓�涓級
-            var originalSplitItem = splitChain.First();
-            var originalBarcode = originalSplitItem.OriginalBarcode;
-
-            // 鏌ユ壘鍘熷鏉$爜鐨勯攣瀹氫俊鎭拰搴撳瓨
-            var originalLockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
-                .Where(it => it.CurrentBarcode == originalBarcode && it.Status == (int)OutLockStockStatusEnum.鍑哄簱涓�)
-                .FirstAsync();
-
-            var originalStockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
-                .Where(it => it.Barcode == originalBarcode && it.StockId == originalLockInfo.StockId)
-                .FirstAsync();
-
-            if (originalLockInfo == null || originalStockDetail == null)
-                throw new Exception("鏈壘鍒板師濮嬫潯鐮佺殑閿佸畾淇℃伅鎴栧簱瀛樹俊鎭�");
-
-            // 鎭㈠鍘熷鏉$爜搴撳瓨锛堝皢鍙栨秷鐨勬暟閲忓姞鍥炲幓锛�
-            originalStockDetail.StockQuantity += cancelQty;
-            originalStockDetail.OutboundQuantity += cancelQty;
-            await _stockInfoDetailService.Db.Updateable(originalStockDetail).ExecuteCommandAsync();
-
-            // 鎭㈠鍘熷鏉$爜閿佸畾淇℃伅
-            originalLockInfo.AssignQuantity += cancelQty;
-            await _outStockLockInfoService.Db.Updateable(originalLockInfo).ExecuteCommandAsync();
-
-            //  鍒犻櫎鎷嗗寘閾句腑鎵�鏈夋柊鏉$爜鐨勯攣瀹氫俊鎭拰搴撳瓨璁板綍
-            var allNewBarcodes = splitChain.Select(x => x.NewBarcode).ToList();
-
-            // 鍒犻櫎閿佸畾淇℃伅
-            await _outStockLockInfoService.Db.Deleteable<Dt_OutStockLockInfo>()
-                .Where(it => allNewBarcodes.Contains(it.CurrentBarcode))
-                .ExecuteCommandAsync();
-
-            // 鍒犻櫎搴撳瓨璁板綍锛堝彧鍒犻櫎鎷嗗寘浜х敓鐨勬柊鏉$爜搴撳瓨锛屼繚鐣欏師濮嬫潯鐮侊級
-            await _stockInfoDetailService.Db.Deleteable<Dt_StockInfoDetail>()
-                .Where(it => allNewBarcodes.Contains(it.Barcode) && it.Barcode != originalBarcode)
-                .ExecuteCommandAsync();
-
-            // 鏇存柊鎷嗗寘閾句腑鎵�鏈夋媶鍖呰褰曠姸鎬佷负宸叉媶鍖�
-            foreach (var chainItem in splitChain)
-            {
-                chainItem.SplitRecord.Status = (int)SplitPackageStatusEnum.宸叉媶鍖�;
-                await _splitPackageService.Db.Updateable(chainItem.SplitRecord).ExecuteCommandAsync();
-            }
-
-            //  鎭㈠璁㈠崟鏄庣粏鎷i�夋暟閲忥紙浣跨敤鍘熷閿佸畾淇℃伅鐨勮鍗曟槑缁咺D锛�
-            await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
-                .SetColumns(it => it.PickedQty == it.PickedQty - cancelQty)
-                .Where(it => it.Id == originalLockInfo.OrderDetailId)
-                .ExecuteCommandAsync();
-
-            //   鎭㈠璁㈠崟鐘舵��
-            await CheckAndRevertOrderStatus(orderNo);
-
-            //  鍒犻櫎鎷i�夎褰�
-            await Db.Deleteable<Dt_PickingRecord>()
-                .Where(it => it.Id == pickingRecord.Id)
-                .ExecuteCommandAsync();
-
-            ////  璁板綍鍙栨秷鎿嶄綔鍘嗗彶
-            //await RecordCancelHistory(orderNo, palletCode, barcode, cancelQty, pickingRecord.Id,
-            //    lockInfo.MaterielCode, "鍙栨秷鎷嗗寘閾惧垎鎷�");
-        }
-
-        /// <summary>
-        /// 澶勭悊鏅�氭潯鐮佺殑鍙栨秷鍒嗘嫞
-        /// </summary>
-        private async Task HandleNormalBarcodeCancel(string orderNo, string palletCode, string barcode,
-            decimal cancelQty, Dt_OutStockLockInfo lockInfo, Dt_PickingRecord pickingRecord)
-        {
-            // 1. 鏌ユ壘搴撳瓨淇℃伅
-            var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
-                .Where(it => it.Barcode == barcode && it.StockId == lockInfo.StockId)
-                .FirstAsync();
-
-            if (stockDetail == null)
-                throw new Exception("鏈壘鍒板搴旂殑搴撳瓨淇℃伅");
-
-            // 2. 鎭㈠搴撳瓨鏁伴噺
-            if (stockDetail.StockQuantity == 0)
-            {
-                // 鏁村寘鍑哄簱鐨勬儏鍐�
-                stockDetail.StockQuantity = cancelQty;
-                stockDetail.OutboundQuantity = cancelQty;
-            }
-            else
-            {
-                // 閮ㄥ垎鍑哄簱鐨勬儏鍐�
-                stockDetail.StockQuantity += cancelQty;
-                stockDetail.OutboundQuantity += cancelQty;
-            }
-            await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync();
-
-            // 3. 鎭㈠閿佸畾淇℃伅鐘舵��
-            lockInfo.AssignQuantity += cancelQty;
-            lockInfo.PickedQty -= cancelQty;
-
-            if (lockInfo.PickedQty == 0)
-            {
-                lockInfo.Status = (int)OutLockStockStatusEnum.鍑哄簱涓�;
-            }
-            await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
-
-            // 4. 澶勭悊鐩稿叧鐨勬媶鍖呰褰曠姸鎬佹仮澶�
-            var relatedSplitRecords = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>()
-                .Where(it => it.OriginalBarcode == barcode &&
-                           it.Status == (int)SplitPackageStatusEnum.宸叉嫞閫�)
-                .ToListAsync();
-
-            foreach (var record in relatedSplitRecords)
-            {
-                record.Status = (int)SplitPackageStatusEnum.宸叉媶鍖�;
-                await _splitPackageService.Db.Updateable(record).ExecuteCommandAsync();
-            }
-
-            // 5. 鎭㈠璁㈠崟鏄庣粏鐨勬嫞閫夋暟閲�
-            await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
-                .SetColumns(it => it.PickedQty == it.PickedQty - cancelQty)
-                .Where(it => it.Id == lockInfo.OrderDetailId)
-                .ExecuteCommandAsync();
-
-            // 6. 鎭㈠璁㈠崟鐘舵��
-            await CheckAndRevertOrderStatus(orderNo);
-
-            // 7. 鍒犻櫎鎷i�夎褰�
-            await Db.Deleteable<Dt_PickingRecord>().Where(it => it.Id == pickingRecord.Id).ExecuteCommandAsync();
-
-            //// 8. 璁板綍鍙栨秷鎿嶄綔鍘嗗彶
-            //await RecordCancelHistory(orderNo, palletCode, barcode, cancelQty, pickingRecord.Id,
-            //    lockInfo.MaterielCode, "鍙栨秷鍒嗘嫞");
-        }
-
-        /// <summary>
-        /// 妫�鏌ュ苟鎭㈠璁㈠崟鐘舵��
-        /// </summary>
-        private async Task CheckAndRevertOrderStatus(string orderNo)
-        {
-            var order = await _outboundOrderService.Db.Queryable<Dt_OutboundOrder>()
-                .Where(x => x.OrderNo == orderNo)
-                .FirstAsync();
-
-            if (order != null && order.OrderStatus == OutOrderStatusEnum.鍑哄簱瀹屾垚.ObjToInt())
-            {
-                await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>()
-                    .SetColumns(x => x.OrderStatus == OutOrderStatusEnum.鍑哄簱涓�.ObjToInt())
-                    .Where(x => x.OrderNo == orderNo)
-                    .ExecuteCommandAsync();
-            }
-        }
-
- 
-
-
+        #region 鏌ヨ鏂规硶
         // 鑾峰彇鏈嫞閫夊垪琛�
         public async Task<List<Dt_OutStockLockInfo>> GetUnpickedList(string orderNo, string palletCode)
         {
@@ -1789,201 +167,2986 @@
 
             return summary;
         }
+
+        #endregion
+
+        #region 鏍稿績涓氬姟娴佺▼
         /// <summary>
-        /// 鑾峰彇鎷i�夊巻鍙�
+        /// 鎷i��
         /// </summary>
-        public async Task<List<Dt_PickingRecord>> GetPickingHistory(int orderId)
-        {
-            // 閫氳繃鍑哄簱鍗旾D鏌ヨ鐩稿叧鐨勬嫞閫夊巻鍙�
-            // 娉ㄦ剰锛欴t_PickingRecord 涓病鏈夌洿鎺ュ瓨鍌∣rderId锛岄渶瑕侀�氳繃鍑哄簱鍗曟槑缁嗗叧鑱�
-            var detailIds = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
-                .Where(d => d.OrderId == orderId)
-                .Select(d => d.Id)
-                .ToListAsync();
-
-            return await Db.Queryable<Dt_PickingRecord>()
-                .Where(p => detailIds.Contains(p.OrderDetailId))
-                .OrderByDescending(p => p.PickTime)
-                .ToListAsync();
-        }
-
-
-        /// <summary>
-        /// 鑾峰彇鎵樼洏鐨勫嚭搴撶姸鎬佷俊鎭�
-        /// </summary>
-        public async Task<WebResponseContent> GetPalletOutboundStatus(string palletCode)
-        {
-            // 鑾峰彇鎵樼洏鐨勯攣瀹氫俊鎭�
-            var lockInfos = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
-                .Where(x => x.PalletCode == palletCode)
-                .ToListAsync();
-
-            // 鑾峰彇鎵樼洏搴撳瓨淇℃伅
-            var stockInfo = await _stockInfoService.Db.Queryable<Dt_StockInfo>()
-                .Includes(x => x.Details)
-                .Where(x => x.PalletCode == palletCode)
-                .FirstAsync();
-
-            if (stockInfo == null)
-                return WebResponseContent.Instance.Error("鏈壘鍒版墭鐩樹俊鎭�");
-
-            // 璁$畻鍚勭鏁伴噺
-            var totalStockQuantity = stockInfo.Details.Sum(x => x.StockQuantity);
-            var totalOutboundQuantity = stockInfo.Details.Sum(x => x.OutboundQuantity);
-            var totalLockedQuantity = lockInfos.Where(x => x.Status == (int)OutLockStockStatusEnum.鍑哄簱涓�)
-                .Sum(x => x.AssignQuantity - x.PickedQty);
-            var totalPickedQuantity = lockInfos.Sum(x => x.PickedQty);
-
-            var result = new
-            {
-                PalletCode = palletCode,
-                LocationCode = stockInfo.LocationCode,
-                StockStatus = stockInfo.StockStatus,
-                TotalStockQuantity = totalStockQuantity,
-                TotalOutboundQuantity = totalOutboundQuantity,
-                TotalLockedQuantity = totalLockedQuantity,
-                TotalPickedQuantity = totalPickedQuantity,
-                AvailableQuantity = totalStockQuantity - totalOutboundQuantity,
-                LockInfos = lockInfos.Select(x => new
-                {
-                    x.Id,
-                    x.MaterielCode,
-                    x.OrderDetailId,
-                    x.AssignQuantity,
-                    x.PickedQty,
-                    x.Status,
-                    x.CurrentBarcode,
-                    x.IsSplitted
-                }).ToList(),
-                StockDetails = stockInfo.Details.Select(x => new
-                {
-                    x.Barcode,
-                    x.MaterielCode,
-                    StockQuantity = x.StockQuantity,
-                    OutboundQuantity = x.OutboundQuantity,
-                    AvailableQuantity = x.StockQuantity - x.OutboundQuantity
-                }).ToList()
-            };
-
-            return WebResponseContent.Instance.OK(null, result);
-        }
-
-        /// <summary>
-        /// 鐩存帴鍑哄簱 - 鏁翠釜鎵樼洏鍑哄簱锛屾竻绌哄簱瀛�
-        /// </summary>
-        public async Task<WebResponseContent> DirectOutbound(DirectOutboundRequest request)
+        /// <param name="orderNo"></param>
+        /// <param name="palletCode"></param>
+        /// <param name="barcode"></param>
+        /// <returns></returns>
+        public async Task<WebResponseContent> ConfirmPicking(string orderNo, string palletCode, string barcode)
         {
             try
             {
                 _unitOfWorkManage.BeginTran();
 
-                var stockInfo = await _stockInfoService.Db.Queryable<Dt_StockInfo>()
-                    .Includes(x => x.Details)
-                    .Where(x => x.PalletCode == request.PalletCode).FirstAsync();
+                var validationResult = await ValidatePickingRequest(orderNo, palletCode, barcode);
+                if (!validationResult.IsValid)
+                    return WebResponseContent.Instance.Error(validationResult.ErrorMessage);
 
-                if (stockInfo == null)
-                    return WebResponseContent.Instance.Error("鏈壘鍒版墭鐩樺簱瀛樹俊鎭�");
+                var (lockInfo, orderDetail, stockDetail) = validationResult.Data;
 
+                // 璁$畻瀹為檯鎷i�夋暟閲�
+                var quantityResult = await CalculateActualPickingQuantity(lockInfo, orderDetail, stockDetail);
+                if (!quantityResult.IsValid)
+                    return WebResponseContent.Instance.Error(quantityResult.ErrorMessage);
 
-                var lockInfos = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
-                    .Where(x => x.OrderNo == request.OrderNo && x.PalletCode == request.PalletCode)
-                    .ToListAsync();
+                var (actualQty, adjustedReason) = quantityResult.Data;
 
-
-                foreach (var lockInfo in lockInfos)
+                var overPickingValidation = await ValidateOverPicking(orderDetail.Id, actualQty);
+                if (!overPickingValidation.IsValid)
                 {
-                    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();
-                    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();
-                    }
+                    return WebResponseContent.Instance.Error(overPickingValidation.ErrorMessage);
                 }
 
-                await CheckAndUpdateOrderStatus(request.OrderNo);
+                // 鎵ц鍒嗘嫞閫昏緫锛堝彧澶勭悊搴撳瓨鍜岄攣瀹氾紝涓嶅鐞嗚鍗曪級
+                var pickingResult = await ExecutePickingLogic(lockInfo, orderDetail, stockDetail, orderNo, palletCode, barcode, actualQty);
 
-                var lockInfoIds = lockInfos.Select(x => x.Id).ToList();
-                var splitRecords = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>()
-                    .Where(x => lockInfoIds.Contains(x.OutStockLockInfoId) &&
-                               x.Status == (int)SplitPackageStatusEnum.宸叉媶鍖�)
-                    .ToListAsync();
+                // 缁熶竴鏇存柊璁㈠崟鏁版嵁锛堟墍鏈夊垎鏀兘鍦ㄨ繖閲屾洿鏂帮級
+                await UpdateOrderRelatedData(orderDetail.Id, pickingResult.ActualPickedQty, orderNo);
 
-                foreach (var record in splitRecords)
-                {
-                    record.Status = (int)SplitPackageStatusEnum.宸叉嫞閫�;
-                    await _splitPackageService.Db.Updateable(record).ExecuteCommandAsync();
-                }
-
-
-                var location = await _locationInfoService.Db.Queryable<Dt_LocationInfo>()
-                    .Where(x => x.LocationCode == stockInfo.LocationCode)
-                    .FirstAsync();
-                if (location != null)
-                {
-                    location.LocationStatus = (int)LocationStatusEnum.Free;
-                    await _locationInfoService.Db.Updateable(location).ExecuteCommandAsync();
-                }
-
-                foreach (var detail in stockInfo.Details)
-                {
-                    await _stockInfoDetailService.Db.Deleteable(detail).ExecuteCommandAsync();
-                }
-                await _stockInfoService.Db.Deleteable(stockInfo).ExecuteCommandAsync();
-
-
+                // 璁板綍鎿嶄綔鍘嗗彶
+                await RecordPickingHistory(pickingResult, orderNo, palletCode);
 
                 _unitOfWorkManage.CommitTran();
-                return WebResponseContent.Instance.OK("鐩存帴鍑哄簱鎴愬姛");
+
+                return CreatePickingResponse(pickingResult, adjustedReason);
             }
             catch (Exception ex)
             {
                 _unitOfWorkManage.RollbackTran();
-                return WebResponseContent.Instance.Error($"鐩存帴鍑哄簱澶辫触: {ex.Message}");
+                _logger.LogError($"ConfirmPicking澶辫触 - OrderNo: {orderNo}, PalletCode: {palletCode}, Barcode: {barcode}, Error: {ex.Message}");
+                return WebResponseContent.Instance.Error($"鎷i�夌‘璁ゅけ璐ワ細{ex.Message}");
             }
+        }
+
+        /// <summary>
+        /// 鍙栨秷鎷i��
+        /// </summary>
+        /// <param name="orderNo"></param>
+        /// <param name="palletCode"></param>
+        /// <param name="barcode"></param>
+        /// <returns></returns>
+        public async Task<WebResponseContent> CancelPicking(string orderNo, string palletCode, string barcode)
+        {
+            try
+            {
+                if (await IsPalletReturned(palletCode))
+                {
+                    return WebResponseContent.Instance.Error($"鎵樼洏{palletCode}宸茬粡鍥炲簱锛屼笉鑳藉彇娑堝垎鎷�");
+                }
+                _unitOfWorkManage.BeginTran();
+
+                // 鍓嶇疆楠岃瘉
+                var validationResult = await ValidateCancelRequest(orderNo, palletCode, barcode);
+                if (!validationResult.IsValid)
+                    return WebResponseContent.Instance.Error(validationResult.ErrorMessage);
+
+                var (pickingRecord, lockInfo, orderDetail) = validationResult.Data;
+
+                //鎵ц鍙栨秷閫昏緫
+                await ExecuteCancelLogic(lockInfo, pickingRecord, orderDetail, orderNo);
+
+                _unitOfWorkManage.CommitTran();
+
+                return WebResponseContent.Instance.OK($"鍙栨秷鍒嗘嫞鎴愬姛");
+            }
+            catch (Exception ex)
+            {
+                _unitOfWorkManage.RollbackTran();
+                _logger.LogError($"CancelPicking澶辫触 - OrderNo: {orderNo}, PalletCode: {palletCode}, Barcode: {barcode}, Error: {ex.Message}");
+                return WebResponseContent.Instance.Error($"鍙栨秷鍒嗘嫞澶辫触锛歿ex.Message}");
+            }
+        }
+        /// <summary>
+        /// 鍥炲簱
+        /// </summary>
+        /// <param name="orderNo"></param>
+        /// <param name="palletCode"></param>
+        /// <param name="reason"></param>
+        /// <returns></returns>
+        public async Task<WebResponseContent> ReturnRemaining(string orderNo, string palletCode, string reason)
+        {
+            try
+            {
+                _unitOfWorkManage.BeginTran();
+
+
+                if (string.IsNullOrEmpty(orderNo) || string.IsNullOrEmpty(palletCode))
+                    return WebResponseContent.Instance.Error("璁㈠崟鍙峰拰鎵樼洏鐮佷笉鑳戒负绌�");
+
+                //  鑾峰彇搴撳瓨鍜屼换鍔′俊鎭�
+                var stockInfo = await _stockInfoService.Db.Queryable<Dt_StockInfo>().FirstAsync(x => x.PalletCode == palletCode);
+
+                if (stockInfo == null)
+                    return WebResponseContent.Instance.Error($"鏈壘鍒版墭鐩� {palletCode} 瀵瑰簲鐨勫簱瀛樹俊鎭�");
+
+                var task = await GetCurrentTask(orderNo, palletCode);
+                if (task == null)
+                    return WebResponseContent.Instance.Error("鏈壘鍒板搴旂殑浠诲姟淇℃伅");
+
+                //鍒嗘瀽闇�瑕佸洖搴撶殑璐х墿
+                //var returnAnalysis = await AnalyzeReturnItems(orderNo, palletCode, stockInfo.Id);
+                //if (!returnAnalysis.HasItemsToReturn)
+                //    return await HandleNoReturnItems(orderNo, palletCode, task);
+
+                var statusAnalysis = await AnalyzePalletStatus(orderNo, palletCode, stockInfo.Id);
+                if (!statusAnalysis.HasItemsToReturn)
+                    return await HandleNoReturnItems(orderNo, palletCode, task, stockInfo.Id);
+
+                // 4. 妫�鏌ユ槸鍚︽湁杩涜涓殑浠诲姟
+                if (statusAnalysis.HasActiveTasks)
+                {
+                    return WebResponseContent.Instance.Error($"鎵樼洏 {palletCode} 鏈夎繘琛屼腑鐨勪换鍔★紝涓嶈兘鎵ц鍥炲簱鎿嶄綔");
+                }
+
+                //鎵ц鍥炲簱鎿嶄綔
+                await ExecuteReturnOperations(orderNo, palletCode, stockInfo, task, statusAnalysis);
+
+                await ReleaseAllLocksForReallocation(orderNo, palletCode, statusAnalysis);
+
+                _unitOfWorkManage.CommitTran();
+
+
+                // 鍒涘缓鍥炲簱浠诲姟
+                await CreateReturnTaskAndHandleESS(orderNo, palletCode, task, TaskTypeEnum.InPick, task.PalletType);
+
+                // 鏇存柊璁㈠崟鐘舵�侊紙涓嶈Е鍙慚ES鍥炰紶锛�
+                await UpdateOrderStatusForReturn(orderNo);
+
+                return WebResponseContent.Instance.OK($"鍥炲簱鎿嶄綔鎴愬姛");
+                //return WebResponseContent.Instance.OK($"鍥炲簱鎿嶄綔鎴愬姛锛屽叡鍥炲簱鏁伴噺锛歿statusAnalysis.TotalReturnQty}");
+            }
+            catch (Exception ex)
+            {
+                _unitOfWorkManage.RollbackTran();
+                _logger.LogError($"ReturnRemaining澶辫触 - OrderNo: {orderNo}, PalletCode: {palletCode}, Error: {ex.Message}");
+                return WebResponseContent.Instance.Error($"鍥炲簱鎿嶄綔澶辫触: {ex.Message}");
+            }
+        }
+
+        /// <summary>
+        /// 绌烘墭鐩樺彇璧版帴鍙o紙甯﹁鍗曞彿锛�
+        /// 楠岃瘉鎵樼洏鏄惁鐪熺殑涓虹┖锛屾竻鐞嗘暟鎹紝鏇存柊璁㈠崟鐘舵�侊紝鍒涘缓鍙栨墭鐩樹换鍔�
+        /// </summary>
+        public async Task<WebResponseContent> RemoveEmptyPallet(string orderNo, string palletCode)
+        {
+            try
+            {
+                _unitOfWorkManage.BeginTran();
+
+                if (string.IsNullOrEmpty(orderNo) || string.IsNullOrEmpty(palletCode))
+                    return WebResponseContent.Instance.Error("璁㈠崟鍙峰拰鎵樼洏鐮佷笉鑳戒负绌�");
+
+                // 妫�鏌ヨ鍗曟槸鍚﹀瓨鍦�
+                var order = await _outboundOrderService.Db.Queryable<Dt_OutboundOrder>()
+                    .Where(x => x.OrderNo == orderNo)
+                    .FirstAsync();
+
+                if (order == null)
+                    return WebResponseContent.Instance.Error($"鏈壘鍒拌鍗� {orderNo}");
+
+                //妫�鏌ユ墭鐩樻槸鍚﹀瓨鍦ㄤ笖灞炰簬璇ヨ鍗�
+                var stockInfo = await _stockInfoService.Db.Queryable<Dt_StockInfo>()
+                    .Where(x => x.PalletCode == palletCode)
+                    .FirstAsync();
+
+                if (stockInfo == null)
+                    return WebResponseContent.Instance.Error($"鏈壘鍒版墭鐩� {palletCode} 瀵瑰簲鐨勫簱瀛樹俊鎭�");
+
+                var statusAnalysis = await AnalyzePalletStatus(orderNo, palletCode, stockInfo.Id);
+
+                if (!statusAnalysis.CanRemove)
+                {
+                    if (!statusAnalysis.IsEmptyPallet)
+                    {
+                        return WebResponseContent.Instance.Error($"鎵樼洏 {palletCode} 涓婅繕鏈夎揣鐗╋紝涓嶈兘鍙栬蛋");
+                    }
+                    if (statusAnalysis.HasActiveTasks)
+                    {
+                        return WebResponseContent.Instance.Error($"鎵樼洏 {palletCode} 杩樻湁杩涜涓殑浠诲姟锛屼笉鑳藉彇璧�");
+                    }
+                }
+                // 娓呯悊闆跺簱瀛樻暟鎹�
+                await CleanupZeroStockData(stockInfo.Id);
+
+                // 鍒犻櫎鎴栧彇娑堢浉鍏充换鍔�
+                await HandleTaskCleanup(orderNo, palletCode);
+
+                // 鏇存柊璁㈠崟鐩稿叧鏁版嵁
+                await UpdateOrderData(orderNo, palletCode);
+
+
+                _unitOfWorkManage.CommitTran();
+
+                _logger.LogInformation($"绌烘墭鐩樺彇璧版搷浣滄垚鍔� - 璁㈠崟: {orderNo}, 鎵樼洏: {palletCode}, 鎿嶄綔浜�: {App.User.UserName}");
+
+                return WebResponseContent.Instance.OK("绌烘墭鐩樺彇璧版搷浣滄垚鍔�");
+            }
+            catch (Exception ex)
+            {
+                _unitOfWorkManage.RollbackTran();
+                _logger.LogError($"RemoveEmptyPallet澶辫触 - OrderNo: {orderNo}, PalletCode: {palletCode}, Error: {ex.Message}");
+                return WebResponseContent.Instance.Error($"绌烘墭鐩樺彇璧板け璐�: {ex.Message}");
+            }
+        }
+        #endregion
+
+        #region 鍒嗘嫞纭绉佹湁鏂规硶
+
+        private async Task<ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail)>> ValidatePickingRequest(string orderNo, string palletCode, string barcode)
+        {
+            // 1. 鍩虹鍙傛暟楠岃瘉
+            if (string.IsNullOrEmpty(orderNo) || string.IsNullOrEmpty(palletCode) || string.IsNullOrEmpty(barcode))
+                return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail)>.Error("璁㈠崟鍙枫�佹墭鐩樼爜鍜屾潯鐮佷笉鑳戒负绌�");
+
+            // 2. 鏌ユ壘鏈夋晥鐨勯攣瀹氫俊鎭�
+            var lockInfo = await FindValidLockInfo(orderNo, palletCode, barcode);
+            if (lockInfo == null)
+                return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail)>.Error($"鏈壘鍒版湁鏁堢殑閿佸畾淇℃伅");
+
+            // 3. 妫�鏌ヨ鍗曠姸鎬�
+            var order = await _outboundOrderService.Db.Queryable<Dt_OutboundOrder>()
+                .Where(x => x.OrderNo == orderNo)
+                .FirstAsync();
+
+            if (order?.OrderStatus == (int)OutOrderStatusEnum.鍑哄簱瀹屾垚)
+                return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail)>.Error($"璁㈠崟{orderNo}宸插畬鎴愶紝涓嶈兘缁х画鍒嗘嫞");
+
+            // 4. 鑾峰彇璁㈠崟鏄庣粏
+            var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
+                .FirstAsync(x => x.Id == lockInfo.OrderDetailId);
+
+            if (orderDetail == null)
+                return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail)>.Error($"鏈壘鍒拌鍗曟槑缁�");
+
+            // 5. 妫�鏌ヨ鍗曟槑缁嗘暟閲�
+            if (orderDetail.OverOutQuantity >= orderDetail.NeedOutQuantity)
+                return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail)>.Error($"璁㈠崟鏄庣粏闇�姹傛暟閲忓凡婊¤冻");
+
+            // 6. 鑾峰彇搴撳瓨鏄庣粏
+            var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+                .Where(x => x.Barcode == barcode && x.StockId == lockInfo.StockId &&
+                   x.Status != StockStatusEmun.鍏ュ簱纭.ObjToInt())
+                .FirstAsync();
+
+            if (stockDetail == null)
+                return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail)>.Error($"鏃犳晥鐨勬潯鐮佹垨鐗╂枡缂栫爜");
+
+            // 7. 妫�鏌ュ簱瀛樼姸鎬佸拰鏁伴噺
+            if (stockDetail.StockQuantity <= 0)
+                return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail)>.Error($"鏉$爜{barcode}搴撳瓨涓嶈冻");
+
+            if (stockDetail.Status != StockStatusEmun.鍑哄簱閿佸畾.ObjToInt())
+                return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail)>.Error($"鏉$爜{barcode}鐘舵�佷笉姝g‘锛屾棤娉曞垎鎷�");
+
+            // 8. 妫�鏌ユ槸鍚﹂噸澶嶅垎鎷�
+            var existingPicking = await Db.Queryable<Dt_PickingRecord>()
+                .Where(x => x.Barcode == barcode && x.OrderNo == orderNo && x.PalletCode == palletCode && x.OutStockLockId == lockInfo.Id)
+                .FirstAsync();
+
+            if (existingPicking != null)
+                return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail)>.Error($"鏉$爜{barcode}宸茬粡鍒嗘嫞杩�");
+
+            return ValidationResult<(Dt_OutStockLockInfo, Dt_OutboundOrderDetail, Dt_StockInfoDetail)>.Success((lockInfo, orderDetail, stockDetail));
+        }
+
+        private async Task<Dt_OutStockLockInfo> FindValidLockInfo(string orderNo, string palletCode, string barcode)
+        {
+            // 浼樺厛鏌ユ壘绮剧‘鍖归厤鐨勮褰�
+            var lockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+                .Where(it => it.OrderNo == orderNo &&
+                           it.Status == (int)OutLockStockStatusEnum.鍑哄簱涓� &&
+                           it.PalletCode == palletCode &&
+                           it.CurrentBarcode == barcode &&
+                           it.AssignQuantity > it.PickedQty).FirstAsync();
+
+            if (lockInfo == null)
+            {
+                // 鏌ユ壘鍚屼竴璁㈠崟涓嬬殑璁板綍
+                lockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+                    .Where(it => it.OrderNo == orderNo && it.CurrentBarcode == barcode && it.Status == (int)OutLockStockStatusEnum.鍑哄簱涓� && it.AssignQuantity > it.PickedQty).FirstAsync();
+
+                if (lockInfo == null)
+                {
+                    // 妫�鏌ユ槸鍚﹀凡缁忓畬鎴愬垎鎷�
+                    var completedLockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+                        .Where(it => it.CurrentBarcode == barcode &&
+                                   (it.Status == (int)OutLockStockStatusEnum.鎷i�夊畬鎴� ||
+                                    it.PickedQty >= it.AssignQuantity)).FirstAsync();
+
+                    if (completedLockInfo != null)
+                        throw new Exception($"鏉$爜{barcode}宸茬粡瀹屾垚鍒嗘嫞锛屼笉鑳介噸澶嶅垎鎷�");
+                    else
+                        return null;
+                }
+            }
+
+            return lockInfo;
+        }
+
+        private async Task<ValidationResult<(decimal, string)>> CalculateActualPickingQuantity(
+            Dt_OutStockLockInfo lockInfo, Dt_OutboundOrderDetail orderDetail, Dt_StockInfoDetail stockDetail)
+        {
+            decimal plannedQty = lockInfo.AssignQuantity - lockInfo.PickedQty;
+            decimal remainingOrderQty = orderDetail.NeedOutQuantity - orderDetail.OverOutQuantity;
+            decimal stockQuantity = stockDetail.StockQuantity;
+
+            if (plannedQty <= 0)
+            {
+                return ValidationResult<(decimal, string)>.Error($"璁″垝鎷i�夋暟閲忓繀椤诲ぇ浜�0锛屽綋鍓�: {plannedQty}");
+            }
+
+            if (remainingOrderQty <= 0)
+            {
+                return ValidationResult<(decimal, string)>.Error($"璁㈠崟鍓╀綑闇�姹傛暟閲忓繀椤诲ぇ浜�0锛屽綋鍓�: {remainingOrderQty}");
+            }
+
+            if (stockQuantity <= 0)
+            {
+                return ValidationResult<(decimal, string)>.Error($"搴撳瓨鏁伴噺蹇呴』澶т簬0锛屽綋鍓�: {stockQuantity}");
+            }
+            // 涓夐噸妫�鏌ワ細鍙栨渶灏忓��
+            decimal actualQty = plannedQty;
+            string adjustedReason = null;
+
+            if (plannedQty > remainingOrderQty)
+            {
+                actualQty = remainingOrderQty;
+                adjustedReason = $"璁㈠崟鏁伴噺闄愬埗锛氫粠{plannedQty}璋冩暣涓簕actualQty}";
+            }
+            if (actualQty > stockQuantity)
+            {
+                actualQty = stockQuantity;
+                adjustedReason = adjustedReason != null
+                    ? $"{adjustedReason}锛屽簱瀛樻暟閲忛檺鍒讹細杩涗竴姝ヨ皟鏁翠负{actualQty}"
+                    : $"搴撳瓨鏁伴噺闄愬埗锛氫粠{plannedQty}璋冩暣涓簕actualQty}";
+            }
+            if (actualQty <= 0)
+            {
+                return ValidationResult<(decimal, string)>.Error($"鏃犳硶鍒嗘嫞锛氳绠楀悗鐨勫疄闄呮暟閲忎负{actualQty}");
+            }
+            decimal projectedOverOut = orderDetail.OverOutQuantity + actualQty;
+            if (projectedOverOut > orderDetail.NeedOutQuantity)
+            {
+                // 濡傛灉浼氳秴鎷o紝璋冩暣涓哄垰濂芥弧瓒抽渶姹傜殑鏁伴噺
+                actualQty = orderDetail.NeedOutQuantity - orderDetail.OverOutQuantity;
+                adjustedReason = adjustedReason != null
+                    ? $"{adjustedReason}锛岄槻瓒呮嫞闄愬埗锛氭渶缁堣皟鏁翠负{actualQty}"
+                    : $"闃茶秴鎷i檺鍒讹細浠巤plannedQty}璋冩暣涓簕actualQty}";
+            }
+
+            if (adjustedReason != null)
+            {
+                _logger.LogWarning($"鍒嗘嫞鏁伴噺璋冩暣锛歿adjustedReason}锛岃鍗晎orderDetail.NeedOutQuantity}锛屽凡鍑哄簱{orderDetail.OverOutQuantity}锛屽簱瀛榹stockQuantity}");
+            }
+
+            return ValidationResult<(decimal, string)>.Success((actualQty, adjustedReason));
+        }
+
+        /// <summary>
+        /// 涓撻棬楠岃瘉鏄惁浼氬彂鐢熻秴鎷�
+        /// </summary>
+        private async Task<ValidationResult<bool>> ValidateOverPicking(int orderDetailId, decimal pickingQty)
+        {
+            var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
+                .FirstAsync(x => x.Id == orderDetailId);
+
+            if (orderDetail == null)
+                return ValidationResult<bool>.Error("鏈壘鍒拌鍗曟槑缁�");
+
+            decimal projectedOverOut = orderDetail.OverOutQuantity + pickingQty;
+
+            if (projectedOverOut > orderDetail.NeedOutQuantity)
+            {
+                return ValidationResult<bool>.Error(
+                    $"鍒嗘嫞鍚庡皢瀵艰嚧瓒呮嫞锛氬綋鍓嶅凡鍑哄簱{orderDetail.OverOutQuantity}锛屾湰娆″垎鎷pickingQty}锛屽悎璁projectedOverOut}锛岃秴杩囬渶姹倇orderDetail.NeedOutQuantity}");
+            }
+
+            return ValidationResult<bool>.Success(true);
+        }
+
+
+        private async Task<PickingResult> ExecutePickingLogic(
+         Dt_OutStockLockInfo lockInfo, Dt_OutboundOrderDetail orderDetail, Dt_StockInfoDetail stockDetail,
+         string orderNo, string palletCode, string barcode, decimal actualQty)
+        {
+            decimal stockQuantity = stockDetail.StockQuantity;
+            var result = new PickingResult
+            {
+                FinalLockInfo = lockInfo,
+                FinalBarcode = barcode,
+                FinalStockId = stockDetail.Id,
+                ActualPickedQty = actualQty
+            };
+
+            if (actualQty < stockQuantity)
+            {
+                await HandleSplitPacking(lockInfo, stockDetail, actualQty, stockQuantity, result);
+                // 鎷嗗寘鍦烘櫙杩斿洖瀹為檯鎷i�夋暟閲�
+                result.ActualPickedQty = actualQty;
+            }
+            else if (actualQty == stockQuantity)
+            {
+                await HandleFullPicking(lockInfo, stockDetail, actualQty, result);
+                // 鏁村寘鎷i�夎繑鍥炲疄闄呮嫞閫夋暟閲�
+                result.ActualPickedQty = actualQty;
+            }
+            else
+            {
+                await HandlePartialPicking(lockInfo, stockDetail, actualQty, stockQuantity, result);
+                // 閮ㄥ垎鎷i�夎繑鍥炶皟鏁村悗鐨勬暟閲�
+                result.ActualPickedQty = result.ActualPickedQty; // 宸茬粡鍦ㄦ柟娉曞唴璋冩暣
+            }
+
+            return result;
+        }
+        private async Task HandleSplitPacking(Dt_OutStockLockInfo lockInfo, Dt_StockInfoDetail stockDetail,
+       decimal actualQty, decimal stockQuantity, PickingResult result)
+        {
+            decimal remainingStockQty = stockQuantity - actualQty;
+
+            // 鏇存柊鍘熸潯鐮佸簱瀛�
+            stockDetail.StockQuantity = remainingStockQty;
+            stockDetail.OutboundQuantity = remainingStockQty;
+            await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync();
+
+            // 鐢熸垚鏂版潯鐮�
+            string newBarcode = await GenerateNewBarcode();
+
+            // 鍒涘缓鏂伴攣瀹氫俊鎭�
+            var newLockInfo = await CreateSplitLockInfo(lockInfo, actualQty, newBarcode);
+
+            // 璁板綍鎷嗗寘鍘嗗彶
+            await RecordSplitHistory(lockInfo, stockDetail, actualQty, remainingStockQty, newBarcode);
+
+            // 鏇存柊鍘熼攣瀹氫俊鎭�
+            lockInfo.AssignQuantity = remainingStockQty;
+            lockInfo.PickedQty = 0;
+            lockInfo.Operator = App.User.UserName;
+            await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
+
+            // 璁剧疆缁撴灉
+            result.FinalLockInfo = newLockInfo;
+            result.FinalBarcode = newBarcode;
+            result.SplitResults.AddRange(CreateSplitResults(lockInfo, actualQty, remainingStockQty, newBarcode, stockDetail.Barcode));
+
+
+
+            _logger.LogInformation($"鎷嗗寘鍒嗘嫞瀹屾垚 - OrderDetailId: {lockInfo.OrderDetailId}, 鍒嗘嫞鏁伴噺: {actualQty}");
+        }
+        private async Task HandleFullPicking(Dt_OutStockLockInfo lockInfo, Dt_StockInfoDetail stockDetail,
+            decimal actualQty, PickingResult result)
+        {
+            // 1. 鏇存柊搴撳瓨
+            stockDetail.StockQuantity = 0;
+            stockDetail.OutboundQuantity = 0;
+            stockDetail.Status = StockStatusEmun.鍑哄簱瀹屾垚.ObjToInt();
+            await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync();
+
+            // 2. 鏇存柊閿佸畾淇℃伅
+            lockInfo.PickedQty += actualQty;
+            lockInfo.Status = (int)OutLockStockStatusEnum.鎷i�夊畬鎴�;
+            lockInfo.Operator = App.User.UserName;
+            await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
+        }
+
+        private async Task HandlePartialPicking(Dt_OutStockLockInfo lockInfo, Dt_StockInfoDetail stockDetail,
+            decimal actualQty, decimal stockQuantity, PickingResult result)
+        {
+            decimal stockOutQty = stockQuantity;
+            decimal remainingAssignQty = actualQty - stockQuantity;
+
+            // 1. 鏇存柊搴撳瓨
+            stockDetail.StockQuantity = 0;
+            stockDetail.OutboundQuantity = 0;
+            stockDetail.Status = StockStatusEmun.鍑哄簱瀹屾垚.ObjToInt();
+            await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync();
+
+            // 2. 鏇存柊閿佸畾淇℃伅
+            lockInfo.PickedQty += stockOutQty;
+            lockInfo.AssignQuantity = remainingAssignQty;
+            lockInfo.Operator = App.User.UserName;
+            await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
+
+            // 3. 鏇存柊鎷嗗寘璁板綍鐘舵��
+            await UpdateSplitRecordsStatus(stockDetail.Barcode);
+
+            result.ActualPickedQty = stockOutQty;
+        }
+
+        private async Task UpdateOrderRelatedData(int orderDetailId, decimal pickedQty, string orderNo)
+        {
+            // 鑾峰彇鏈�鏂扮殑璁㈠崟鏄庣粏鏁版嵁
+            var currentOrderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
+                .FirstAsync(x => x.Id == orderDetailId);
+
+            decimal newOverOutQuantity = currentOrderDetail.OverOutQuantity + pickedQty;
+            decimal newPickedQty = currentOrderDetail.PickedQty + pickedQty;
+
+            if (newOverOutQuantity > currentOrderDetail.NeedOutQuantity)
+            {
+                _logger.LogError($"闃茶秴鎷f鏌ュけ璐� - OrderDetailId: {orderDetailId}, 宸插嚭搴�: {newOverOutQuantity}, 闇�姹�: {currentOrderDetail.NeedOutQuantity}, 鏈鍒嗘嫞: {pickedQty}");
+
+                decimal adjustedQty = currentOrderDetail.NeedOutQuantity - currentOrderDetail.OverOutQuantity;
+
+                if (adjustedQty > 0)
+                {
+                    _logger.LogWarning($"鑷姩璋冩暣鍒嗘嫞鏁伴噺闃叉瓒呮嫞锛氫粠{pickedQty}璋冩暣涓簕adjustedQty}");
+                    newOverOutQuantity = currentOrderDetail.NeedOutQuantity;
+                    newPickedQty = currentOrderDetail.PickedQty + adjustedQty;
+                    pickedQty = adjustedQty; // 鏇存柊瀹為檯鎷i�夋暟閲�
+                }
+                else
+                {
+                    throw new Exception($"鍒嗘嫞鍚庡皢瀵艰嚧宸插嚭搴撴暟閲�({newOverOutQuantity})瓒呰繃璁㈠崟闇�姹傛暟閲�({currentOrderDetail.NeedOutQuantity})锛屼笖鏃犳硶鑷姩璋冩暣");
+                }
+            }
+
+            // 鏇存柊璁㈠崟鏄庣粏鏁伴噺鍜岀姸鎬�
+            await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
+                .SetColumns(it => new Dt_OutboundOrderDetail
+                {
+                    PickedQty = newPickedQty,
+                    OverOutQuantity = newOverOutQuantity,
+                    OrderDetailStatus = newOverOutQuantity >= currentOrderDetail.NeedOutQuantity ?
+                        OrderDetailStatusEnum.Over.ObjToInt() :
+                        OrderDetailStatusEnum.Outbound.ObjToInt()
+                })
+                .Where(it => it.Id == orderDetailId)
+                .ExecuteCommandAsync();
+
+            // 鏇存柊閿佸畾鏁伴噺
+            await UpdateOrderDetailLockQuantity(orderDetailId);
+
+            // 妫�鏌ュ苟鏇存柊璁㈠崟鐘舵��
+            await CheckAndUpdateOrderStatus(orderNo);
+        }
+
+        private async Task RecordPickingHistory(PickingResult result, string orderNo, string palletCode)
+        {
+            var task = await _taskRepository.Db.Queryable<Dt_Task>()
+                .Where(x => x.OrderNo == orderNo && x.PalletCode == palletCode)
+                .FirstAsync();
+
+            if (result.FinalLockInfo.Id <= 0)
+            {
+                throw new Exception($"閿佸畾淇℃伅ID鏃犳晥: {result.FinalLockInfo.Id}锛屾棤娉曡褰曟嫞閫夊巻鍙�");
+            }
+
+            var pickingHistory = new Dt_PickingRecord
+            {
+                FactoryArea = result.FinalLockInfo.FactoryArea,
+                TaskNo = task?.TaskNum ?? 0,
+                LocationCode = task?.SourceAddress ?? "",
+                StockId = result.FinalStockId,
+                OrderNo = orderNo,
+                OrderDetailId = result.FinalLockInfo.OrderDetailId,
+                PalletCode = palletCode,
+                Barcode = result.FinalBarcode,
+                MaterielCode = result.FinalLockInfo.MaterielCode,
+                PickQuantity = result.ActualPickedQty,
+                PickTime = DateTime.Now,
+                Operator = App.User.UserName,
+                OutStockLockId = result.FinalLockInfo.Id,
+                BarcodeUnit = result.FinalLockInfo.BarcodeUnit,
+                BarcodeQty = result.FinalLockInfo.BarcodeQty,
+                BatchNo = result.FinalLockInfo.BatchNo,
+                lineNo = result.FinalLockInfo.lineNo,
+                SupplyCode = result.FinalLockInfo.SupplyCode,
+                WarehouseCode = result.FinalLockInfo.WarehouseCode,
+
+
+            };
+
+            await Db.Insertable(pickingHistory).ExecuteCommandAsync();
+        }
+
+        #endregion
+
+        #region 鍙栨秷鍒嗘嫞绉佹湁鏂规硶
+        private async Task<ValidationResult<bool>> ValidateDataConsistencyBeforeCancel(CancelPickingContext context)
+        {
+            try
+            {
+                //  楠岃瘉璁㈠崟鏄庣粏鏁版嵁
+                var currentOrderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
+                    .FirstAsync(x => x.Id == context.OrderDetail.Id);
+
+                if (currentOrderDetail.OverOutQuantity < context.PickingRecord.PickQuantity)
+                    return ValidationResult<bool>.Error($"璁㈠崟鏄庣粏宸插嚭搴撴暟閲�({currentOrderDetail.OverOutQuantity})灏忎簬鍙栨秷鏁伴噺({context.PickingRecord.PickQuantity})");
+
+                if (currentOrderDetail.PickedQty < context.PickingRecord.PickQuantity)
+                    return ValidationResult<bool>.Error($"璁㈠崟鏄庣粏宸叉嫞閫夋暟閲�({currentOrderDetail.PickedQty})灏忎簬鍙栨秷鏁伴噺({context.PickingRecord.PickQuantity})");
+
+                //  楠岃瘉閿佸畾淇℃伅鏁版嵁
+                var currentLockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+                    .FirstAsync(x => x.Id == context.LockInfo.Id);
+
+                if (currentLockInfo.PickedQty < context.PickingRecord.PickQuantity)
+                    return ValidationResult<bool>.Error($"閿佸畾淇℃伅宸叉嫞閫夋暟閲�({currentLockInfo.PickedQty})灏忎簬鍙栨秷鏁伴噺({context.PickingRecord.PickQuantity})");
+
+                ////// 楠岃瘉搴撳瓨鏁版嵁
+                ////var currentStockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+                ////    .FirstAsync(x => x.Barcode == context.PickingRecord.Barcode && x.StockId == context.PickingRecord.StockId);
+
+                ////if (currentStockDetail == null)
+                ////    return ValidationResult<bool>.Error($"鏈壘鍒板搴旂殑搴撳瓨鏄庣粏璁板綍");
+
+                ////if (currentStockDetail.Status == StockStatusEmun.鍏ュ簱纭.ObjToInt() ||
+                ////    currentStockDetail.Status == StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt())
+                ////    return ValidationResult<bool>.Error($"鏉$爜{context.PickingRecord.Barcode}宸茬粡鍥炲簱锛屾棤娉曞彇娑堝垎鎷�");
+
+                // 楠岃瘉鐘舵�佹祦杞殑鍚堟硶鎬�
+                if (!await CanCancelPicking(currentLockInfo, null))
+                    return ValidationResult<bool>.Error($"褰撳墠鐘舵�佷笉鍏佽鍙栨秷鍒嗘嫞");
+
+                return ValidationResult<bool>.Success(true);
+            }
+            catch (Exception ex)
+            {
+                _logger.LogError($"鍙栨秷鍒嗘嫞鏁版嵁涓�鑷存�ч獙璇佸け璐�: {ex.Message}");
+                return ValidationResult<bool>.Error($"鏁版嵁楠岃瘉澶辫触: {ex.Message}");
+            }
+        }
+
+        private async Task<bool> CanCancelPicking(Dt_OutStockLockInfo lockInfo, Dt_StockInfoDetail stockDetail)
+        {
+            // 閿佸畾淇℃伅鐘舵�佹鏌�
+            if (lockInfo.Status != (int)OutLockStockStatusEnum.鎷i�夊畬鎴�)
+                return false;
+
+            ////// 搴撳瓨鐘舵�佹鏌�
+            ////if (stockDetail.Status == StockStatusEmun.鍑哄簱瀹屾垚.ObjToInt())
+            ////    return false;
+
+            // 濡傛灉鏄媶鍖呰褰曪紝杩橀渶瑕佹鏌ョ埗閿佸畾淇℃伅鐘舵��
+            if (lockInfo.IsSplitted == 1 && lockInfo.ParentLockId.HasValue)
+            {
+                var parentLock = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+                    .FirstAsync(x => x.Id == lockInfo.ParentLockId.Value);
+
+                if (parentLock == null || parentLock.Status == (int)OutLockStockStatusEnum.鍥炲簱涓�)
+                    return false;
+            }
+
+            return true;
+        }
+        private async Task<ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>> ValidateCancelRequest(string orderNo, string palletCode, string barcode)
+        {
+            // 鍩虹鍙傛暟楠岃瘉
+            if (string.IsNullOrEmpty(orderNo) || string.IsNullOrEmpty(palletCode) || string.IsNullOrEmpty(barcode))
+                return ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>.Error("璁㈠崟鍙枫�佹墭鐩樼爜鍜屾潯鐮佷笉鑳戒负绌�");
+
+            // 鏌ユ壘鎷i�夎褰�
+            var pickingRecord = await Db.Queryable<Dt_PickingRecord>()
+                .Where(it => it.OrderNo == orderNo &&
+                           it.PalletCode == palletCode &&
+                           it.Barcode == barcode)
+                .OrderByDescending(it => it.PickTime)
+                .FirstAsync();
+
+            if (pickingRecord == null)
+                return ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>.Error("鏈壘鍒板搴旂殑鎷i�夎褰�");
+
+            if (pickingRecord.PickQuantity <= 0)
+            {
+                return ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>.Error($"鎷i�夎褰曟暟閲忔棤鏁�: {pickingRecord.PickQuantity}");
+            }
+            // 鏌ユ壘閿佸畾淇℃伅
+            var lockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+                .Where(it => it.Id == pickingRecord.OutStockLockId)
+                .FirstAsync();
+
+            if (lockInfo == null)
+                return ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>.Error("鏈壘鍒板搴旂殑鍑哄簱閿佸畾淇℃伅");
+
+            if (lockInfo.PickedQty < pickingRecord.PickQuantity)
+            {
+                return ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>.Error(
+                    $"鍙栨秷鏁伴噺({pickingRecord.PickQuantity})瓒呰繃閿佸畾淇℃伅鐨勫凡鎷i�夋暟閲�({lockInfo.PickedQty})");
+            }
+            // 妫�鏌ョ姸鎬佹槸鍚﹀厑璁稿彇娑�
+            if (lockInfo.Status != (int)OutLockStockStatusEnum.鎷i�夊畬鎴�)
+                return ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>.Error("褰撳墠鐘舵�佷笉鍏佽鍙栨秷鍒嗘嫞");
+
+            var order = await _outboundOrderService.Db.Queryable<Dt_OutboundOrder>().FirstAsync(x => x.OrderNo == orderNo);
+
+            if (order?.OrderStatus == (int)OutOrderStatusEnum.鍑哄簱瀹屾垚)
+                return ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>.Error("璁㈠崟宸插嚭搴撳畬鎴愶紝涓嶅厑璁稿彇娑堝垎鎷�");
+
+            var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>().FirstAsync(x => x.Id == pickingRecord.OrderDetailId);
+
+            if (orderDetail == null)
+                return ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>.Error($"鏈壘鍒拌鍗曟槑缁嗭紝ID: {pickingRecord.OrderDetailId}");
+
+            // 妫�鏌ヨ鍗曟槑缁嗙殑宸叉嫞閫夋暟閲忔槸鍚﹁冻澶熷彇娑�
+            if (orderDetail.PickedQty < pickingRecord.PickQuantity)
+            {
+                return ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>.Error($"鍙栨秷鏁伴噺({pickingRecord.PickQuantity})瓒呰繃璁㈠崟鏄庣粏鐨勫凡鎷i�夋暟閲�({orderDetail.PickedQty})");
+            }
+
+            // 妫�鏌ヨ鍗曟槑缁嗙殑宸插嚭搴撴暟閲忔槸鍚﹁冻澶熷彇娑�
+            if (orderDetail.OverOutQuantity < pickingRecord.PickQuantity)
+            {
+                return ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>.Error($"鍙栨秷鏁伴噺({pickingRecord.PickQuantity})瓒呰繃璁㈠崟鏄庣粏鐨勫凡鍑哄簱鏁伴噺({orderDetail.OverOutQuantity})");
+            }
+
+            var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>().FirstAsync(it => it.Barcode == barcode && it.StockId == pickingRecord.StockId);
+
+            if (stockDetail != null)
+            {
+                // 妫�鏌ュ簱瀛樼姸鎬� - 濡傛灉鐘舵�佹槸鍏ュ簱纭鎴栧叆搴撳畬鎴愶紝璇存槑宸茬粡鍥炲簱
+                if (stockDetail.Status == StockStatusEmun.鍏ュ簱纭.ObjToInt() ||
+                    stockDetail.Status == StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt())
+                {
+                    return ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>.Error($"鏉$爜{barcode}宸茬粡鍥炲簱锛屼笉鑳藉彇娑堝垎鎷�");
+                }
+            }
+
+            return ValidationResult<(Dt_PickingRecord, Dt_OutStockLockInfo, Dt_OutboundOrderDetail)>.Success((pickingRecord, lockInfo, orderDetail));
+        }
+        /// <summary>
+        /// 妫�鏌ユ潯鐮佹槸鍚﹀凡缁忓洖搴�
+        /// </summary>
+        private async Task<bool> IsBarcodeReturned(string barcode, int stockId)
+        {
+            var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+                .Where(it => it.Barcode == barcode && it.StockId == stockId)
+                .FirstAsync();
+
+            if (stockDetail == null)
+                return false;
+
+            // 濡傛灉鐘舵�佹槸鍏ュ簱纭鎴栧叆搴撳畬鎴愶紝璇存槑宸茬粡鍥炲簱
+            return stockDetail.Status == StockStatusEmun.鍏ュ簱纭.ObjToInt() ||
+                   stockDetail.Status == StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt();
+        }
+
+        /// <summary>
+        /// 妫�鏌ラ攣瀹氫俊鎭搴旂殑鏉$爜鏄惁宸茬粡鍥炲簱
+        /// </summary>
+        private async Task<bool> IsLockInfoReturned(Dt_OutStockLockInfo lockInfo)
+        {
+            var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+                .Where(it => it.Barcode == lockInfo.CurrentBarcode && it.StockId == lockInfo.StockId)
+                .FirstAsync();
+
+            if (stockDetail == null)
+                return false;
+
+            return stockDetail.Status == StockStatusEmun.鍏ュ簱纭.ObjToInt() ||
+                   stockDetail.Status == StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt();
+        }
+        private async Task ExecuteCancelLogic(Dt_OutStockLockInfo lockInfo, Dt_PickingRecord pickingRecord,
+        Dt_OutboundOrderDetail orderDetail, string orderNo)
+        {
+            decimal cancelQty = pickingRecord.PickQuantity;
+
+            // 鏁版嵁涓�鑷存�ч獙璇�
+            var context = new CancelPickingContext
+            {
+                LockInfo = lockInfo,
+                PickingRecord = pickingRecord,
+                OrderDetail = orderDetail,
+                OrderNo = orderNo,
+                CancelQuantity = cancelQty
+            };
+
+            var validationResult = await ValidateDataConsistencyBeforeCancel(context);
+            if (!validationResult.IsValid)
+                throw new Exception(validationResult.ErrorMessage);
+
+            // 澶勭悊涓嶅悓绫诲瀷鐨勫彇娑�
+            if (lockInfo.IsSplitted == 1 && lockInfo.ParentLockId.HasValue)
+            {
+                await HandleSplitBarcodeCancel(lockInfo, pickingRecord, cancelQty);
+            }
+            else
+            {
+                await HandleNormalBarcodeCancel(lockInfo, pickingRecord, cancelQty);
+            }
+
+            //  鏇存柊璁㈠崟鏄庣粏
+            await UpdateOrderDetailOnCancel(pickingRecord.OrderDetailId, cancelQty);
+
+            //  鍒犻櫎鎷i�夎褰�
+            var deleteResult = await Db.Deleteable<Dt_PickingRecord>()
+                .Where(x => x.Id == pickingRecord.Id)
+                .ExecuteCommandAsync();
+
+            if (deleteResult <= 0)
+                throw new Exception("鍒犻櫎鎷i�夎褰曞け璐�");
+
+            _logger.LogInformation($"鍒犻櫎鎷i�夎褰� - 璁板綍ID: {pickingRecord.Id}, 鏉$爜: {pickingRecord.Barcode}");
+
+            // 閲嶆柊妫�鏌ヨ鍗曠姸鎬�
+            await UpdateOrderStatusForReturn(orderNo);
+
+
+        }
+
+        private async Task HandleSplitBarcodeCancel(Dt_OutStockLockInfo lockInfo, Dt_PickingRecord pickingRecord, decimal cancelQty)
+        {
+            // 鏌ユ壘鐖堕攣瀹氫俊鎭�
+            var parentLockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+                .Where(x => x.Id == lockInfo.ParentLockId.Value)
+                .FirstAsync();
+
+            if (parentLockInfo == null)
+                throw new Exception("鏈壘鍒扮埗閿佸畾淇℃伅锛屾棤娉曞彇娑堟媶鍖呭垎鎷�");
+
+            // 妫�鏌ョ埗鏉$爜鍜屾媶鍖呮潯鐮佺殑鐘舵��
+            if (await IsLockInfoReturned(parentLockInfo))
+                throw new Exception($"鐖舵潯鐮亄parentLockInfo.CurrentBarcode}宸茬粡鍥炲簱锛屾棤娉曞彇娑堟媶鍖呭垎鎷�");
+
+            if (await IsLockInfoReturned(lockInfo))
+                throw new Exception($"鎷嗗寘鏉$爜{lockInfo.CurrentBarcode}宸茬粡鍥炲簱锛屾棤娉曞彇娑堟媶鍖呭垎鎷�");
+
+            // 鎭㈠鐖堕攣瀹氫俊鎭殑鍒嗛厤鏁伴噺
+            parentLockInfo.AssignQuantity += cancelQty;
+            parentLockInfo.Status = (int)OutLockStockStatusEnum.鍑哄簱涓�; // 鎭㈠涓哄嚭搴撲腑鐘舵��
+            await _outStockLockInfoService.Db.Updateable(parentLockInfo).ExecuteCommandAsync();
+
+            // 鎭㈠鐖舵潯鐮佸簱瀛�
+            var parentStockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+                .Where(x => x.Barcode == parentLockInfo.CurrentBarcode && x.StockId == parentLockInfo.StockId)
+                .FirstAsync();
+
+            if (parentStockDetail != null)
+            {
+                parentStockDetail.StockQuantity += cancelQty;
+                parentStockDetail.OutboundQuantity = parentStockDetail.StockQuantity;
+                parentStockDetail.Status = StockStatusEmun.鍑哄簱閿佸畾.ObjToInt();
+                await _stockInfoDetailService.Db.Updateable(parentStockDetail).ExecuteCommandAsync();
+
+                _logger.LogInformation($"鎭㈠鐖舵潯鐮佸簱瀛� - 鏉$爜: {parentStockDetail.Barcode}, 鎭㈠鏁伴噺: {cancelQty}, 鏂板簱瀛�: {parentStockDetail.StockQuantity}");
+            }
+
+            // 澶勭悊鎷嗗寘浜х敓鐨勬柊鏉$爜搴撳瓨
+            var splitStockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+                .Where(x => x.Barcode == lockInfo.CurrentBarcode && x.StockId == lockInfo.StockId)
+                .FirstAsync();
+
+            if (splitStockDetail != null)
+            {
+                // 鍒犻櫎鎷嗗寘浜х敓鐨勬柊鏉$爜搴撳瓨璁板綍
+                await _stockInfoDetailService.Db.Deleteable(splitStockDetail).ExecuteCommandAsync();
+                _logger.LogInformation($"鍒犻櫎鎷嗗寘鏂版潯鐮佸簱瀛� - 鏉$爜: {splitStockDetail.Barcode}");
+            }
+
+            // 鏇存柊鎷嗗寘璁板綍鐘舵��
+            var updateCount = await _splitPackageService.Db.Updateable<Dt_SplitPackageRecord>()
+                .SetColumns(x => new Dt_SplitPackageRecord
+                {
+                    Status = (int)SplitPackageStatusEnum.宸叉挙閿�,
+                    IsReverted = true,
+                    Operator = App.User.UserName,
+                    RevertTime = DateTime.Now
+                })
+                .Where(x => x.NewBarcode == lockInfo.CurrentBarcode && !x.IsReverted)
+                .ExecuteCommandAsync();
+
+            _logger.LogInformation($"鏇存柊鎷嗗寘璁板綍鐘舵�� - 鏇存柊璁板綍鏁�: {updateCount}");
+
+            // 鍒犻櫎鎷嗗寘浜х敓鐨勯攣瀹氫俊鎭�
+            await _outStockLockInfoService.Db.Deleteable<Dt_OutStockLockInfo>()
+                .Where(x => x.Id == lockInfo.Id)
+                .ExecuteCommandAsync();
+
+            _logger.LogInformation($"鍒犻櫎鎷嗗寘閿佸畾淇℃伅 - 閿佸畾ID: {lockInfo.Id}, 鏉$爜: {lockInfo.CurrentBarcode}");
+        }
+        private async Task HandleNormalBarcodeCancel(Dt_OutStockLockInfo lockInfo, Dt_PickingRecord pickingRecord, decimal cancelQty)
+        {
+            if (await IsLockInfoReturned(lockInfo))
+                throw new Exception($"鏉$爜{lockInfo.CurrentBarcode}宸茬粡鍥炲簱锛屾棤娉曞彇娑堝垎鎷�");
+
+            // 鎭㈠閿佸畾淇℃伅
+            lockInfo.PickedQty -= cancelQty;
+            if (lockInfo.PickedQty < 0) lockInfo.PickedQty = 0;
+
+            // 鍙湁褰撴嫞閫夋暟閲忓畬鍏ㄥ彇娑堟椂鎵嶆仮澶嶇姸鎬�
+            if (lockInfo.PickedQty == 0)
+            {
+                lockInfo.Status = (int)OutLockStockStatusEnum.鍑哄簱涓�;
+            }
+
+            lockInfo.Operator = App.User.UserName;
+            await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync();
+
+            _logger.LogInformation($"鎭㈠閿佸畾淇℃伅 - 閿佸畾ID: {lockInfo.Id}, 鎵e噺鎷i�夋暟閲�: {cancelQty}, 鏂板凡鎷i�夋暟閲�: {lockInfo.PickedQty}");
+
+            // 鎭㈠搴撳瓨
+            var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+                .Where(x => x.Barcode == pickingRecord.Barcode && x.StockId == pickingRecord.StockId)
+                .FirstAsync();
+
+            if (stockDetail != null)
+            {
+                stockDetail.StockQuantity += cancelQty;
+                stockDetail.OutboundQuantity = stockDetail.StockQuantity;
+
+                // 鎭㈠搴撳瓨鐘舵��
+                if (stockDetail.Status == StockStatusEmun.鍑哄簱瀹屾垚.ObjToInt())
+                {
+                    stockDetail.Status = StockStatusEmun.鍑哄簱閿佸畾.ObjToInt();
+                }
+
+                await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync();
+
+                _logger.LogInformation($"鎭㈠搴撳瓨 - 鏉$爜: {stockDetail.Barcode}, 鎭㈠鏁伴噺: {cancelQty}, " +
+                                      $"鏂板簱瀛�: {stockDetail.StockQuantity}, 鏂扮姸鎬�: {stockDetail.Status}");
+            }
+            else
+            {
+                _logger.LogWarning($"鏈壘鍒板簱瀛樿褰� - 鏉$爜: {pickingRecord.Barcode}, 搴撳瓨ID: {pickingRecord.StockId}");
+            }
+        }
+        private async Task UpdateOrderDetailOnCancel(int orderDetailId, decimal cancelQty)
+        {
+            // 鑾峰彇鏈�鏂扮殑璁㈠崟鏄庣粏鏁版嵁锛堝甫閿侊級
+            var currentOrderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
+                .With(SqlWith.RowLock)
+                .FirstAsync(x => x.Id == orderDetailId);
+
+            decimal newOverOutQuantity = currentOrderDetail.OverOutQuantity - cancelQty;
+            decimal newPickedQty = currentOrderDetail.PickedQty - cancelQty;
+
+            // 涓ユ牸妫�鏌ュ彇娑堝悗鏁伴噺涓嶄細涓鸿礋鏁�
+            if (newOverOutQuantity < 0)
+                throw new Exception($"鍙栨秷鍒嗘嫞灏嗗鑷村凡鍑哄簱鏁伴噺({newOverOutQuantity})涓鸿礋鏁�");
+
+            if (newPickedQty < 0)
+                throw new Exception($"鍙栨秷鍒嗘嫞灏嗗鑷村凡鎷i�夋暟閲�({newPickedQty})涓鸿礋鏁�");
+
+            // 纭畾鏂扮殑鐘舵��
+            int newStatus;
+            if (newOverOutQuantity >= currentOrderDetail.NeedOutQuantity)
+            {
+                newStatus = OrderDetailStatusEnum.Over.ObjToInt();
+            }
+            else if (newOverOutQuantity > 0)
+            {
+                newStatus = OrderDetailStatusEnum.Outbound.ObjToInt();
+            }
+            else
+            {
+                newStatus = OrderDetailStatusEnum.New.ObjToInt();
+            }
+
+            // 鏇存柊璁㈠崟鏄庣粏
+            var updateResult = await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
+                .SetColumns(it => new Dt_OutboundOrderDetail
+                {
+                    PickedQty = newPickedQty,
+                    OverOutQuantity = newOverOutQuantity,
+                    OrderDetailStatus = newStatus
+                })
+                .Where(it => it.Id == orderDetailId)
+                .ExecuteCommandAsync();
+
+            if (updateResult <= 0)
+                throw new Exception("鏇存柊璁㈠崟鏄庣粏澶辫触");
+
+            // 鏇存柊閿佸畾鏁伴噺
+            await UpdateOrderDetailLockQuantity(orderDetailId);
+
+            _logger.LogInformation($"鏇存柊璁㈠崟鏄庣粏 - OrderDetailId: {orderDetailId}, " +
+                                  $"鎵e噺宸插嚭搴�: {cancelQty}, 鏂板凡鍑哄簱: {newOverOutQuantity}, " +
+                                  $"鎵e噺宸叉嫞閫�: {cancelQty}, 鏂板凡鎷i��: {newPickedQty}, " +
+                                  $"鏂扮姸鎬�: {newStatus}");
+        }
+        #endregion
+
+        #region 鍥炲簱鎿嶄綔绉佹湁鏂规硶
+
+        private async Task<Dt_StockInfo> GetStockInfo(string palletCode)
+        {
+            return await _stockInfoService.Db.Queryable<Dt_StockInfo>()
+                .FirstAsync(x => x.PalletCode == palletCode);
+        }
+        /// <summary>
+        /// 妫�鏌ユ暣涓墭鐩樻槸鍚﹀凡缁忓洖搴�
+        /// </summary>
+        private async Task<bool> IsPalletReturned(string palletCode)
+        {
+            var stockInfo = await _stockInfoService.Db.Queryable<Dt_StockInfo>()
+                .Where(x => x.PalletCode == palletCode)
+                .FirstAsync();
+
+            if (stockInfo == null)
+                return false;
+
+            // 濡傛灉鎵樼洏鐘舵�佹槸鍏ュ簱纭鎴栧叆搴撳畬鎴愶紝璇存槑宸茬粡鍥炲簱
+            return stockInfo.StockStatus == StockStatusEmun.鍏ュ簱纭.ObjToInt() ||
+                   stockInfo.StockStatus == StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt();
+        }
+        private async Task<Dt_Task> GetCurrentTask(string orderNo, string palletCode)
+        {
+            // 鍏堝皾璇曢�氳繃璁㈠崟鍙峰拰鎵樼洏鍙锋煡鎵句换鍔�
+            var task = await _taskRepository.Db.Queryable<Dt_Task>()
+                .Where(x => x.OrderNo == orderNo && x.PalletCode == palletCode)
+                .FirstAsync();
+
+            if (task == null)
+            {
+                // 濡傛灉鎵句笉鍒帮紝鍐嶉�氳繃鎵樼洏鍙锋煡鎵�
+                task = await _taskRepository.Db.Queryable<Dt_Task>()
+                    .Where(x => x.PalletCode == palletCode)
+                    .FirstAsync();
+            }
+
+            return task;
+        }
+
+        private async Task<decimal> CalculateSplitReturnQuantity(List<Dt_SplitPackageRecord> splitRecords, int stockId)
+        {
+            decimal totalQty = 0;
+            var processedBarcodes = new HashSet<string>();
+
+            foreach (var splitRecord in splitRecords)
+            {
+                if (splitRecord.Status != (int)SplitPackageStatusEnum.宸叉挙閿�)
+                    continue;
+                // 妫�鏌ュ師鏉$爜
+                if (!processedBarcodes.Contains(splitRecord.OriginalBarcode))
+                {
+                    var originalStock = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+                        .Where(it => it.Barcode == splitRecord.OriginalBarcode && it.StockId == stockId &&
+                           it.Status != StockStatusEmun.鍑哄簱瀹屾垚.ObjToInt())
+                        .FirstAsync();
+
+                    if (originalStock != null && originalStock.StockQuantity > 0)
+                    {
+                        totalQty += originalStock.StockQuantity;
+                        processedBarcodes.Add(splitRecord.OriginalBarcode);
+                    }
+                }
+
+                // 妫�鏌ユ柊鏉$爜
+                if (!processedBarcodes.Contains(splitRecord.NewBarcode))
+                {
+                    var newStock = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+                        .Where(it => it.Barcode == splitRecord.NewBarcode && it.StockId == stockId && it.Status != StockStatusEmun.鍑哄簱瀹屾垚.ObjToInt())
+                        .FirstAsync();
+
+                    if (newStock != null && newStock.StockQuantity > 0)
+                    {
+                        totalQty += newStock.StockQuantity;
+                        processedBarcodes.Add(splitRecord.NewBarcode);
+                    }
+                }
+            }
+
+            return totalQty;
+        }
+
+        private async Task<WebResponseContent> HandleNoReturnItems(string orderNo, string palletCode, Dt_Task originalTask, int stockInfoId)
+        {
+            // 妫�鏌ユ槸鍚︽墍鏈夎揣鐗╅兘宸叉嫞閫夊畬鎴�
+            //var allPicked = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+            //    .Where(it => it.OrderNo == orderNo && it.PalletCode == palletCode)
+            //    .AnyAsync(it => it.Status == (int)OutLockStockStatusEnum.鎷i�夊畬鎴�);
+
+            //if (allPicked)
+            //{
+            //    // 鍒犻櫎鍘熷鍑哄簱浠诲姟 缁勭┖鐩�   绌虹洏鍥炲簱 
+            //    //await _taskRepository.Db.Deleteable(originalTask).ExecuteCommandAsync();
+            //    return WebResponseContent.Instance.OK("鎵�鏈夎揣鐗╁凡鎷i�夊畬鎴愶紝鎵樼洏涓虹┖");
+            //}
+            //else
+            //{
+            //    // 鍒犻櫎鍘熷鍑哄簱浠诲姟
+            //    //await _taskRepository.Db.Deleteable(originalTask).ExecuteCommandAsync();
+            //    return WebResponseContent.Instance.Error("娌℃湁闇�瑕佸洖搴撶殑鍓╀綑璐х墿");
+            //}
+            try
+            {
+                var locationtype = 0;
+                var stockInfo = await _stockInfoService.Db.Queryable<Dt_StockInfo>()
+                        .Where(x => x.PalletCode == palletCode)
+                        .FirstAsync();
+
+                if (stockInfo == null)
+                {
+                    var firstLocation = await _locationInfoService.Db.Queryable<Dt_LocationInfo>().FirstAsync(x => x.LocationCode == originalTask.SourceAddress);
+                    locationtype = firstLocation?.LocationType ?? 1;
+                }
+                else
+                {
+                    locationtype = stockInfo.LocationType;
+                    _stockInfoService.DeleteData(stockInfo);
+                }
+
+                var targetAddress = originalTask.TargetAddress;
+
+                await CleanupZeroStockData(stockInfoId);
+
+
+                var emptystockInfo = new Dt_StockInfo() { PalletType = PalletTypeEnum.Empty.ObjToInt(), StockStatus = StockStatusEmun.缁勭洏鏆傚瓨.ObjToInt(), PalletCode = palletCode, LocationType = locationtype };
+                emptystockInfo.Details = new List<Dt_StockInfoDetail>();
+                _stockInfoService.AddMaterielGroup(emptystockInfo);
+                //绌烘墭鐩樺浣曞鐞�  杩樻湁涓�涓嚭搴撲换鍔¤澶勭悊銆�
+                originalTask.PalletType = PalletTypeEnum.Empty.ObjToInt();
+
+                await CreateReturnTaskAndHandleESS(orderNo, palletCode, originalTask, TaskTypeEnum.InEmpty, PalletTypeEnum.Empty.ObjToInt());
+
+            }
+            catch (Exception ex)
+            {
+                _logger.LogError($" HandleNoReturnItems  澶辫触: {ex.Message}");
+                return WebResponseContent.Instance.Error($" 鍥炲簱绌烘墭鐩樺け璐ワ紒");
+            }
+            return WebResponseContent.Instance.OK("绌烘墭鐩樺洖搴撲换鍔″垱寤烘垚鍔�");
+
+        }
+
+        private async Task ExecuteReturnOperations(string orderNo, string palletCode, Dt_StockInfo stockInfo,
+            Dt_Task task, PalletStatusAnalysis analysis)
+        {
+            // 鎯呭喌1锛氬鐞嗘湭鍒嗘嫞鐨勫嚭搴撻攣瀹氳褰�
+            if (analysis.HasRemainingLocks)
+            {
+                await HandleRemainingLocksReturn(analysis.RemainingLocks, stockInfo.Id);
+
+                // await UpdateOrderDetailsOnReturn(analysis.RemainingLocks);
+            }
+
+            // 澶勭悊鎵樼洏涓婂叾浠栧簱瀛樿揣鐗�
+            if (analysis.HasPalletStockGoods)
+            {
+                var validStockGoods = analysis.PalletStockGoods
+            .Where(x => x.Status != StockStatusEmun.鍑哄簱瀹屾垚.ObjToInt())
+            .ToList();
+
+                if (validStockGoods.Any())
+                {
+                    await HandlePalletStockGoodsReturn(analysis.PalletStockGoods);
+                }
+                else
+                {
+                    _logger.LogInformation("娌℃湁鏈夋晥鐨勫簱瀛樿揣鐗╅渶瑕佸洖搴�");
+                }
+            }
+
+            // 澶勭悊鎷嗗寘璁板綍
+            if (analysis.HasSplitRecords)
+            {
+                var validSplitRecords = analysis.SplitRecords
+            .Where(x => x.Status != (int)SplitPackageStatusEnum.宸叉嫞閫�)
+            .ToList();
+
+                if (validSplitRecords.Any())
+                {
+                    await HandleSplitRecordsReturn(analysis.SplitRecords, orderNo, palletCode);
+                }
+                else
+                {
+                    _logger.LogInformation("娌℃湁鏈夋晥鐨勬媶鍖呰褰曢渶瑕佸鐞�");
+                }
+            }
+
+            // 鏇存柊搴撳瓨涓昏〃鐘舵��
+            await UpdateStockInfoStatus(stockInfo);
+        }
+
+        /// <summary>
+        /// 瀹屽叏閲婃斁閿佸畾锛屽厑璁搁噸鏂板垎閰嶅簱瀛�
+        /// </summary>
+        private async Task ReleaseAllLocksForReallocation(string orderNo, string palletCode, PalletStatusAnalysis analysis)
+        {
+            _logger.LogInformation($"寮�濮嬮噴鏀鹃攣瀹氫互渚块噸鏂板垎閰� - 璁㈠崟: {orderNo}, 鎵樼洏: {palletCode}");
+
+            // 1. 澶勭悊鏈垎鎷g殑鍑哄簱閿佸畾璁板綍 - 瀹屽叏閲婃斁
+            if (analysis.HasRemainingLocks)
+            {
+                await ReleaseRemainingLocks(analysis.RemainingLocks);
+            }
+
+            // 2. 澶勭悊宸插洖搴撶殑閿佸畾璁板綍 - 鍒犻櫎鎴栨爣璁颁负鏃犳晥
+            await CleanupReturnedLocks(orderNo, palletCode);
+
+            // 3. 閲嶇疆璁㈠崟鏄庣粏鐨勯攣瀹氭暟閲�
+            await ResetOrderDetailLockQuantities(analysis);
+
+            _logger.LogInformation($"閿佸畾閲婃斁瀹屾垚 - 璁㈠崟: {orderNo}, 鎵樼洏: {palletCode}");
+        }
+
+        /// <summary>
+        /// 閲婃斁鏈垎鎷g殑閿佸畾璁板綍
+        /// </summary>
+        private async Task ReleaseRemainingLocks(List<Dt_OutStockLockInfo> remainingLocks)
+        {
+            var lockIds = remainingLocks.Select(x => x.Id).ToList();
+
+            // 灏嗛攣瀹氳褰曠姸鎬佹敼涓�"宸查噴鏀�"锛屾垨鑰呯洿鎺ュ垹闄�
+            //  鏍囪涓哄凡閲婃斁 
+            await _outStockLockInfoService.Db.Updateable<Dt_OutStockLockInfo>()
+                .SetColumns(it => new Dt_OutStockLockInfo
+                {
+                    Status = (int)OutLockStockStatusEnum.宸查噴鏀�, // 闇�瑕佹柊澧炶繖涓姸鎬�
+                                                              // ReleaseTime = DateTime.Now,
+                    Operator = App.User.UserName
+                })
+                .Where(it => lockIds.Contains(it.Id))
+                .ExecuteCommandAsync();
+
+            //  鐩存帴鍒犻櫎锛堟洿褰诲簳锛�
+            // await _outStockLockInfoService.Db.Deleteable<Dt_OutStockLockInfo>()
+            //     .Where(it => lockIds.Contains(it.Id))
+            //     .ExecuteCommandAsync();
+
+            _logger.LogInformation($"閲婃斁{remainingLocks.Count}鏉℃湭鍒嗘嫞閿佸畾璁板綍");
+        }
+
+        /// <summary>
+        /// 娓呯悊宸插洖搴撶殑閿佸畾璁板綍
+        /// </summary>
+        private async Task CleanupReturnedLocks(string orderNo, string palletCode)
+        {
+            // 鏌ユ壘鎵�鏈夌姸鎬佷负鍥炲簱涓殑閿佸畾璁板綍骞堕噴鏀�
+            var returnedLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+                .Where(it => it.OrderNo == orderNo &&
+                           it.PalletCode == palletCode &&
+                           it.Status == (int)OutLockStockStatusEnum.鍥炲簱涓�)
+                .ToListAsync();
+
+            if (returnedLocks.Any())
+            {
+                var returnedLockIds = returnedLocks.Select(x => x.Id).ToList();
+
+                await _outStockLockInfoService.Db.Updateable<Dt_OutStockLockInfo>()
+                    .SetColumns(it => new Dt_OutStockLockInfo
+                    {
+                        Status = (int)OutLockStockStatusEnum.宸查噴鏀�,
+                        //ReleaseTime = DateTime.Now,
+                        Operator = App.User.UserName
+                    })
+                    .Where(it => returnedLockIds.Contains(it.Id))
+                    .ExecuteCommandAsync();
+
+                _logger.LogInformation($"娓呯悊{returnedLocks.Count}鏉″洖搴撲腑閿佸畾璁板綍");
+            }
+        }
+
+        /// <summary>
+        /// 閲嶇疆璁㈠崟鏄庣粏鐨勯攣瀹氭暟閲�
+        /// </summary>
+        private async Task ResetOrderDetailLockQuantities(PalletStatusAnalysis analysis)
+        {
+            // 鏀堕泦鎵�鏈夊彈褰卞搷鐨勮鍗曟槑缁咺D
+            var affectedOrderDetailIds = new HashSet<int>();
+
+            if (analysis.HasRemainingLocks)
+            {
+                foreach (var lockInfo in analysis.RemainingLocks)
+                {
+                    affectedOrderDetailIds.Add(lockInfo.OrderDetailId);
+                }
+            }
+
+            // 閲嶇疆杩欎簺璁㈠崟鏄庣粏鐨勯攣瀹氭暟閲�
+            foreach (var orderDetailId in affectedOrderDetailIds)
+            {
+                await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
+                    .SetColumns(it => new Dt_OutboundOrderDetail
+                    {
+                        LockQuantity = 0, // 閲嶇疆閿佸畾鏁伴噺
+                        OrderDetailStatus = OrderDetailStatusEnum.New.ObjToInt() // 閲嶇疆鐘舵�佷负鏂板缓
+                    })
+                    .Where(it => it.Id == orderDetailId)
+                    .ExecuteCommandAsync();
+            }
+
+            _logger.LogInformation($"閲嶇疆{affectedOrderDetailIds.Count}涓鍗曟槑缁嗙殑閿佸畾鏁伴噺");
+        }
+        private async Task HandleRemainingLocksReturn(List<Dt_OutStockLockInfo> remainingLocks, int stockId)
+        {
+            var lockIds = remainingLocks.Select(x => x.Id).ToList();
+
+            // 鏇存柊鍑哄簱閿佸畾璁板綍鐘舵�佷负鍥炲簱涓�
+            await _outStockLockInfoService.Db.Updateable<Dt_OutStockLockInfo>()
+                .SetColumns(it => new Dt_OutStockLockInfo
+                {
+                    Status = (int)OutLockStockStatusEnum.鍥炲簱涓�,
+                })
+                .Where(it => lockIds.Contains(it.Id))
+                .ExecuteCommandAsync();
+
+            // 澶勭悊搴撳瓨璁板綍
+            foreach (var lockInfo in remainingLocks)
+            {
+                decimal returnQty = lockInfo.AssignQuantity - lockInfo.PickedQty;
+                if (returnQty <= 0)
+                {
+                    _logger.LogWarning($"閿佸畾璁板綍{lockInfo.Id}鏃犻渶鍥炲簱锛屽垎閰嶆暟閲�: {lockInfo.AssignQuantity}, 宸叉嫞閫�: {lockInfo.PickedQty}");
+                    continue;
+                }
+
+                _logger.LogInformation($"澶勭悊閿佸畾璁板綍鍥炲簱 - 閿佸畾ID: {lockInfo.Id}, 鏉$爜: {lockInfo.CurrentBarcode}, 鍥炲簱鏁伴噺: {returnQty}");
+                // 鏌ユ壘瀵瑰簲鐨勫簱瀛樻槑缁�
+                var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+                    .Where(it => it.Barcode == lockInfo.CurrentBarcode && it.StockId == lockInfo.StockId)
+                    .FirstAsync();
+
+                if (stockDetail != null)
+                {
+                    stockDetail.StockQuantity += returnQty;
+                    // 鎭㈠搴撳瓨鐘舵��
+                    stockDetail.OutboundQuantity = Math.Max(0, stockDetail.OutboundQuantity - returnQty);
+                    stockDetail.Status = StockStatusEmun.鍏ュ簱纭.ObjToInt();
+                    await _stockInfoDetailService.Db.Updateable(stockDetail).ExecuteCommandAsync();
+                }
+                else
+                {
+                    _logger.LogWarning($"鏈壘鍒板搴旂殑搴撳瓨鏄庣粏 - 鏉$爜: {lockInfo.CurrentBarcode}, 搴撳瓨ID: {lockInfo.StockId}");
+                    // 鍒涘缓鏂扮殑搴撳瓨璁板綍
+                    //var newStockDetail = new Dt_StockInfoDetail
+                    //{
+                    //    StockId = lockInfo.StockId,
+                    //    MaterielCode = lockInfo.MaterielCode,
+                    //    MaterielName = lockInfo.MaterielName,
+                    //    OrderNo = lockInfo.OrderNo,
+                    //    BatchNo = lockInfo.BatchNo,
+                    //    StockQuantity = returnQty,
+                    //    OutboundQuantity = 0,
+                    //    Barcode = lockInfo.CurrentBarcode,
+                    //    InboundOrderRowNo = "",
+                    //    Status = StockStatusEmun.鍏ュ簱纭.ObjToInt(),
+                    //    SupplyCode = lockInfo.SupplyCode,
+                    //    WarehouseCode = lockInfo.WarehouseCode,
+                    //    Unit = lockInfo.Unit,
+                    //};
+                    //await _stockInfoDetailService.Db.Insertable(newStockDetail).ExecuteCommandAsync();
+                }
+                try
+                {
+                    var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
+                        .FirstAsync(x => x.Id == lockInfo.OrderDetailId);
+
+                    if (orderDetail != null)
+                    {
+                        decimal newLockQuantity = Math.Max(0, orderDetail.LockQuantity - returnQty);
+
+                        await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
+                            .SetColumns(it => new Dt_OutboundOrderDetail
+                            {
+                                LockQuantity = newLockQuantity
+                            })
+                            .Where(it => it.Id == lockInfo.OrderDetailId)
+                            .ExecuteCommandAsync();
+
+                        _logger.LogInformation($"鏇存柊璁㈠崟鏄庣粏閿佸畾鏁伴噺 - OrderDetailId: {lockInfo.OrderDetailId}, " +
+                                             $"鎵e噺閿佸畾: {returnQty}, 鏂伴攣瀹氭暟閲�: {newLockQuantity}");
+                    }
+                }
+                catch (Exception ex)
+                {
+                    _logger.LogError($"鏇存柊璁㈠崟鏄庣粏閿佸畾鏁伴噺澶辫触 - OrderDetailId: {lockInfo.OrderDetailId}, Error: {ex.Message}");
+                }
+            }
+
+
+        }
+
+        private async Task UpdateOrderDetailsOnReturn(List<Dt_OutStockLockInfo> remainingLocks)
+        {
+            // 鎸夎鍗曟槑缁嗗垎缁�
+            var orderDetailGroups = remainingLocks.GroupBy(x => x.OrderDetailId);
+
+            foreach (var group in orderDetailGroups)
+            {
+                var orderDetailId = group.Key;
+                var totalReturnQty = group.Sum(x => x.AssignQuantity - x.PickedQty);
+
+                // 鑾峰彇褰撳墠璁㈠崟鏄庣粏
+                var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
+                    .FirstAsync(x => x.Id == orderDetailId);
+
+                if (orderDetail != null)
+                {
+                    // 璋冩暣宸叉嫞閫夋暟閲忓拰宸插嚭搴撴暟閲�
+                    decimal newPickedQty = Math.Max(0, orderDetail.PickedQty - totalReturnQty);
+                    decimal newOverOutQuantity = Math.Max(0, orderDetail.OverOutQuantity - totalReturnQty);
+
+                    await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
+                        .SetColumns(it => new Dt_OutboundOrderDetail
+                        {
+                            PickedQty = newPickedQty,
+                            OverOutQuantity = newOverOutQuantity,
+                        })
+                        .Where(it => it.Id == orderDetailId)
+                        .ExecuteCommandAsync();
+                }
+            }
+        }
+
+        private async Task HandlePalletStockGoodsReturn(List<Dt_StockInfoDetail> palletStockGoods)
+        {
+            _logger.LogInformation($"鍥炲簱鎿嶄綔锛氬彂鐜皗palletStockGoods.Count}涓簱瀛樻槑缁嗛渶瑕佸洖搴擄紝绛夊緟AGV鎼繍");
+            foreach (var stockGood in palletStockGoods)
+            {
+                _logger.LogInformation($"寰呭洖搴撹揣鐗� - 鏉$爜: {stockGood.Barcode}, 鏁伴噺: {stockGood.StockQuantity}, 褰撳墠鐘舵��: {stockGood.Status}");
+
+                if (stockGood.Status != StockStatusEmun.鍑哄簱瀹屾垚.ObjToInt())
+                {
+                    stockGood.OutboundQuantity = 0;
+                    stockGood.Status = StockStatusEmun.鍏ュ簱纭.ObjToInt();
+                    await _stockInfoDetailService.Db.Updateable(stockGood).ExecuteCommandAsync();
+
+                    _logger.LogInformation($"搴撳瓨璐х墿鍥炲簱瀹屾垚 - 鏉$爜: {stockGood.Barcode}, 鏂扮姸鎬�: {stockGood.Status}");
+                }
+                else
+                {
+                    _logger.LogWarning($"璺宠繃宸插嚭搴撳畬鎴愮殑璐х墿 - 鏉$爜: {stockGood.Barcode}");
+                }
+            }
+        }
+
+        private async Task HandleSplitRecordsReturn(List<Dt_SplitPackageRecord> splitRecords, string orderNo, string palletCode)
+        {
+            var validRecords = splitRecords.Where(x => x.Status != (int)SplitPackageStatusEnum.宸叉嫞閫�).ToList();
+
+            if (!validRecords.Any())
+            {
+                _logger.LogInformation("娌℃湁闇�瑕佸洖搴撶殑鎷嗗寘璁板綍");
+                return;
+            }
+
+            _logger.LogInformation($"鏇存柊{validRecords.Count}鏉℃媶鍖呰褰曠姸鎬佷负宸插洖搴�");
+
+            // 鏇存柊鎷嗗寘璁板綍鐘舵��
+            await _splitPackageService.Db.Updateable<Dt_SplitPackageRecord>()
+                .SetColumns(x => new Dt_SplitPackageRecord
+                {
+                    Status = (int)SplitPackageStatusEnum.宸插洖搴�,
+                    Operator = App.User.UserName
+                })
+                .Where(x => validRecords.Select(r => r.Id).Contains(x.Id))
+                .ExecuteCommandAsync();
+        }
+
+        private async Task UpdateStockInfoStatus(Dt_StockInfo stockInfo)
+        {
+            _logger.LogInformation($"鍥炲簱鎿嶄綔锛氭墭鐩榹stockInfo.PalletCode}绛夊緟AGV鍥炲簱鎼繍");
+            // 鏇存柊搴撳瓨涓昏〃鐘舵��
+            stockInfo.StockStatus = StockStatusEmun.鍏ュ簱纭.ObjToInt();
+            await _stockInfoService.Db.Updateable(stockInfo).ExecuteCommandAsync();
+        }
+        /// <summary>
+        /// 鍒涘缓鍥炲簱浠诲姟
+        /// </summary>
+        /// <param name="orderNo"></param>
+        /// <param name="palletCode"></param>
+        /// <param name="originalTask"></param>
+        /// <param name="analysis"></param>
+        /// <returns></returns>
+        private async Task CreateReturnTaskAndHandleESS(string orderNo, string palletCode, Dt_Task originalTask, TaskTypeEnum taskTypeEnum, int palletType)
+        {
+            var firstLocation = await _locationInfoService.Db.Queryable<Dt_LocationInfo>()
+                .FirstAsync(x => x.LocationCode == originalTask.SourceAddress);
+
+            // 鍒嗛厤鏂拌揣浣�
+            var newLocation = _locationInfoService.AssignLocation(firstLocation.LocationType);
+
+            Dt_Task returnTask = new()
+            {
+                CurrentAddress = stations[originalTask.TargetAddress],
+                Grade = 0,
+                PalletCode = palletCode,
+                NextAddress = "",
+                // OrderNo = originalTask.OrderNo,
+                OrderNo = orderNo,
+                Roadway = newLocation.RoadwayNo,
+                SourceAddress = stations[originalTask.TargetAddress],
+                TargetAddress = newLocation.LocationCode,
+                TaskStatus = TaskStatusEnum.New.ObjToInt(),
+                TaskType = taskTypeEnum.ObjToInt(),
+                PalletType = palletType,
+                WarehouseId = originalTask.WarehouseId
+
+            };
+            // 淇濆瓨鍥炲簱浠诲姟
+            await _taskRepository.Db.Insertable(returnTask).ExecuteCommandAsync();
+            var targetAddress = originalTask.TargetAddress;
+
+            // 鍒犻櫎鍘熷鍑哄簱浠诲姟
+            _taskRepository.DeleteAndMoveIntoHty(originalTask, OperateTypeEnum.鑷姩瀹屾垚);
+            await _taskRepository.Db.Deleteable(originalTask).ExecuteCommandAsync();
+
+
+
+            // 缁� ESS 鍙戦�佹祦鍔ㄤ俊鍙峰拰鍒涘缓浠诲姟
+            await SendESSCommands(palletCode, targetAddress, returnTask);
+        }
+        /// <summary>
+        /// 缁橢SS涓嬩换鍔�
+        /// </summary>
+        /// <param name="palletCode"></param>
+        /// <param name="targetAddress"></param>
+        /// <param name="returnTask"></param>
+        /// <returns></returns>
+        /// <exception cref="Exception"></exception>
+        private async Task SendESSCommands(string palletCode, string targetAddress, Dt_Task returnTask)
+        {
+            try
+            {
+                // 1. 鍙戦�佹祦鍔ㄤ俊鍙�
+                var moveResult = await _eSSApiService.MoveContainerAsync(new WIDESEA_DTO.Basic.MoveContainerRequest
+                {
+                    slotCode = movestations[targetAddress],
+                    containerCode = palletCode
+                });
+
+                //if (moveResult)
+                //{
+                // 2. 鍒涘缓鍥炲簱浠诲姟
+                var essTask = new TaskModel()
+                {
+                    taskType = "putaway",
+                    taskGroupCode = "",
+                    groupPriority = 0,
+                    tasks = new List<TasksType>{  new() {
+                            taskCode = returnTask.TaskNum.ToString(),
+                            taskPriority = 0,
+                            taskDescribe = new TaskDescribeType
+                            {
+                                containerCode = palletCode,
+                                containerType = "CT_KUBOT_STANDARD",
+                                fromLocationCode = stations.GetValueOrDefault(targetAddress) ?? "",
+                                toStationCode = "",
+                                toLocationCode = returnTask.TargetAddress,
+                                deadline = 0,
+                                storageTag = ""
+                            }
+                        } }
+                };
+
+                var resultTask = await _eSSApiService.CreateTaskAsync(essTask);
+                _logger.LogInformation($"ReturnRemaining 鍒涘缓浠诲姟鎴愬姛: {resultTask}");
+                //}
+            }
+            catch (Exception ex)
+            {
+                _logger.LogError($"ReturnRemaining ESS鍛戒护鍙戦�佸け璐�: {ex.Message}");
+                throw new Exception($"ESS绯荤粺閫氫俊澶辫触: {ex.Message}");
+            }
+        }
+
+        #endregion
+
+        #region 璁㈠崟鐘舵�佺鐞�
+
+        private async Task CheckAndUpdateOrderStatus(string orderNo)
+        {
+            try
+            {
+                var orderDetails = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
+                    .LeftJoin<Dt_OutboundOrder>((o, item) => o.OrderId == item.Id)
+                    .Where((o, item) => item.OrderNo == orderNo)
+                    .Select((o, item) => o)
+                    .ToListAsync();
+
+                bool allCompleted = true;
+                bool hasPartial = false;
+                bool hasLocked = false;
+
+                foreach (var detail in orderDetails)
+                {
+                    if (detail.OverOutQuantity < detail.NeedOutQuantity)
+                    {
+                        allCompleted = false;
+                    }
+
+                    if (detail.OrderDetailStatus == OrderDetailStatusEnum.Outbound.ObjToInt())
+                    {
+                        hasPartial = true;
+                    }
+
+                    //if (detail.OrderDetailStatus == OrderDetailStatusEnum.Locked.ObjToInt())
+                    //{
+                    //    hasLocked = true;
+                    //}
+                }
+
+                var outboundOrder = await _outboundOrderService.Db.Queryable<Dt_OutboundOrder>()
+                    .FirstAsync(x => x.OrderNo == orderNo);
+
+                if (outboundOrder == null) return;
+
+                int newStatus;
+                if (allCompleted)
+                {
+                    newStatus = (int)OutOrderStatusEnum.鍑哄簱瀹屾垚;
+                }
+                else if (hasPartial)
+                {
+                    newStatus = (int)OutOrderStatusEnum.鍑哄簱涓�;
+                }
+                else
+                {
+                    newStatus = (int)OutOrderStatusEnum.鏈紑濮�;
+                }
+
+                if (outboundOrder.OrderStatus != newStatus)
+                {
+                    await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>()
+                        .SetColumns(x => new Dt_OutboundOrder
+                        {
+                            OrderStatus = newStatus,
+                            Operator = App.User.UserName,
+                        })
+                        .Where(x => x.OrderNo == orderNo)
+                        .ExecuteCommandAsync();
+
+                    _logger.LogInformation($"璁㈠崟鐘舵�佹洿鏂� - OrderNo: {orderNo}, 鏃х姸鎬�: {outboundOrder.OrderStatus}, 鏂扮姸鎬�: {newStatus}");
+
+                    // 鍙湁姝e父鍒嗘嫞瀹屾垚鏃舵墠鍚慚ES鍙嶉
+                    if (allCompleted && newStatus == (int)OutOrderStatusEnum.鍑哄簱瀹屾垚)
+                    {
+                        await HandleOrderCompletion(outboundOrder, orderNo);
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                _logger.LogError($"CheckAndUpdateOrderStatus澶辫触 - OrderNo: {orderNo}, Error: {ex.Message}");
+            }
+        }
+
+        /// <summary>
+        /// 鏇存柊璁㈠崟鏄庣粏鐘舵�侊紙鍩轰簬宸插嚭搴撴暟閲忥級
+        /// </summary>
+        private async Task UpdateOrderDetailStatus(int orderDetailId)
+        {
+            var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
+                .FirstAsync(x => x.Id == orderDetailId);
+
+            if (orderDetail == null) return;
+
+            int newStatus = orderDetail.OrderDetailStatus;
+
+            if (orderDetail.OverOutQuantity >= orderDetail.NeedOutQuantity)
+            {
+                // 宸插嚭搴撴暟閲� >= 闇�姹傛暟閲忥紝鏍囪涓哄畬鎴�
+                newStatus = OrderDetailStatusEnum.Over.ObjToInt();
+            }
+            else if (orderDetail.OverOutQuantity > 0)
+            {
+                // 鏈夐儴鍒嗗嚭搴擄紝浣嗘湭瀹屾垚
+                newStatus = OrderDetailStatusEnum.Outbound.ObjToInt();
+            }
+            else if (orderDetail.LockQuantity > 0)
+            {
+                // 鏈夐攣瀹氭暟閲忥紝浣嗘湭鍑哄簱
+                //newStatus = OrderDetailStatusEnum.Locked.ObjToInt();
+            }
+            else
+            {
+                // 鏂板缓鐘舵��
+                newStatus = OrderDetailStatusEnum.New.ObjToInt();
+            }
+
+            // 鍙湁鐘舵�佸彂鐢熷彉鍖栨椂鎵嶆洿鏂�
+            if (orderDetail.OrderDetailStatus != newStatus)
+            {
+                await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
+                    .SetColumns(it => new Dt_OutboundOrderDetail
+                    {
+                        OrderDetailStatus = newStatus,
+
+                    })
+                    .Where(it => it.Id == orderDetailId)
+                    .ExecuteCommandAsync();
+            }
+        }
+        /// <summary>
+        /// 鏇存柊璁㈠崟鏄庣粏閿佸畾鏁伴噺
+        /// </summary>
+        private async Task UpdateOrderDetailLockQuantity(int orderDetailId)
+        {
+            var totalLockedQty = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+                .Where(x => x.OrderDetailId == orderDetailId &&
+                           x.Status == (int)OutLockStockStatusEnum.鍑哄簱涓�)
+                .SumAsync(x => x.AssignQuantity - x.PickedQty);
+
+            await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
+                .SetColumns(it => new Dt_OutboundOrderDetail
+                {
+                    LockQuantity = totalLockedQty
+                })
+                .Where(it => it.Id == orderDetailId)
+                .ExecuteCommandAsync();
+        }
+        private async Task UpdateOrderStatusForReturn(string orderNo)
+        {
+            try
+            {
+                var orderDetails = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
+                    .LeftJoin<Dt_OutboundOrder>((o, item) => o.OrderId == item.Id)
+                    .Where((o, item) => item.OrderNo == orderNo)
+                    .Select((o, item) => o)
+                    .ToListAsync();
+
+                bool allCompleted = true;
+                foreach (var detail in orderDetails)
+                {
+                    if (detail.OverOutQuantity < detail.NeedOutQuantity)
+                    {
+                        allCompleted = false;
+                        break;
+                    }
+                }
+
+                var outboundOrder = await _outboundOrderService.Db.Queryable<Dt_OutboundOrder>()
+                    .FirstAsync(x => x.OrderNo == orderNo);
+
+                if (outboundOrder == null) return;
+
+                int newStatus = allCompleted ? (int)OutOrderStatusEnum.鍑哄簱瀹屾垚 : (int)OutOrderStatusEnum.鍑哄簱涓�;
+
+                if (outboundOrder.OrderStatus != newStatus)
+                {
+                    await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>()
+                          .SetColumns(x => new Dt_OutboundOrder
+                          {
+                              OrderStatus = newStatus,
+                              Operator = App.User.UserName,
+                          })
+                        .Where(x => x.OrderNo == orderNo)
+                        .ExecuteCommandAsync();
+
+                    _logger.LogInformation($"鍥炲簱鎿嶄綔鏇存柊璁㈠崟鐘舵�� - OrderNo: {orderNo}, 鏂扮姸鎬�: {newStatus}");
+                }
+            }
+            catch (Exception ex)
+            {
+                _logger.LogError($"UpdateOrderStatusForReturn澶辫触 - OrderNo: {orderNo}, Error: {ex.Message}");
+            }
+        }
+
+        private async Task HandleOrderCompletion(Dt_OutboundOrder outboundOrder, string orderNo)
+        {
+            // 璋冩嫧鍑哄簱鍜岄噸妫�鍑哄簱涓嶉渶瑕佸弽棣圡ES
+            if (outboundOrder.OrderType == OutOrderTypeEnum.Allocate.ObjToInt())
+            {
+                var allocate = _allocateService.Repository.QueryData(x => x.UpperOrderNo == outboundOrder.UpperOrderNo).First();
+                var allocatefeedmodel = new AllocateDto
+                {
+                    ReqCode = Guid.NewGuid().ToString(),
+                    ReqTime = DateTime.Now.ToString(),
+                    BusinessType = "3",
+
+                    FactoryArea = outboundOrder.FactoryArea,
+                    OperationType = 1,
+                    Operator = App.User.UserName,
+                    OrderNo = outboundOrder.UpperOrderNo,
+                    // documentsNO = outboundOrder.OrderNo,
+                    // status = outboundOrder.OrderStatus,
+                    fromWarehouse = allocate?.FromWarehouse ?? "",
+                    toWarehouse = allocate?.ToWarehouse ?? "",
+                    Details = new List<AllocateDtoDetail>()
+
+                };
+                // 鍙幏鍙栧凡鎷i�夊畬鎴愮殑閿佸畾璁板綍
+                var lists = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+                    .Where(x => x.OrderNo == orderNo && x.Status == (int)OutLockStockStatusEnum.鎷i�夊畬鎴�)
+                    .ToListAsync();
+
+                var groupedData = lists.GroupBy(item => new { item.MaterielCode, item.lineNo, item.Unit, item.WarehouseCode })
+                   .Select(group => new AllocateDtoDetail
+                   {
+                       MaterialCode = group.Key.MaterielCode,
+                       LineNo = group.Key.lineNo,
+                       WarehouseCode = group.Key.WarehouseCode,
+                       Qty = group.Sum(x => x.PickedQty),
+
+                       Unit = group.Key.Unit,
+                       Barcodes = group.Select(row => new BarcodeInfo
+                       {
+                           Barcode = row.CurrentBarcode,
+                           SupplyCode = row.SupplyCode,
+                           BatchNo = row.BatchNo,
+                           Unit = row.Unit,
+                           Qty = row.PickedQty
+                       }).ToList()
+
+
+                   }).ToList();
+                allocatefeedmodel.Details = groupedData;
+
+                var result = await _invokeMESService.FeedbackAllocate(allocatefeedmodel);
+                if (result != null && result.code == 200)
+                {
+                    await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
+                           .SetColumns(x => x.ReturnToMESStatus == 1)
+                           .Where(x => x.OrderId == outboundOrder.Id).ExecuteCommandAsync();
+
+                    await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>()
+                          .SetColumns(x => new Dt_OutboundOrder
+                          {
+                              ReturnToMESStatus = 1,
+                              Operator = App.User.UserName,
+                          }).Where(x => x.OrderNo == orderNo).ExecuteCommandAsync();
+                }
+            }
+            else if (outboundOrder.OrderType == OutOrderTypeEnum.ReCheck.ObjToInt())
+            {
+
+            }
+            else
+            {
+                try
+                {
+                    var feedmodel = new FeedbackOutboundRequestModel
+                    {
+                        reqCode = Guid.NewGuid().ToString(),
+                        reqTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
+                        business_type = outboundOrder.BusinessType,
+                        factoryArea = outboundOrder.FactoryArea,
+                        operationType = 1,
+                        Operator = App.User.UserName,
+                        orderNo = outboundOrder.UpperOrderNo,
+                        documentsNO = outboundOrder.OrderNo,
+                        status = outboundOrder.OrderStatus,
+                        details = new List<FeedbackOutboundDetailsModel>()
+                    };
+
+                    // 鍙幏鍙栧凡鎷i�夊畬鎴愮殑閿佸畾璁板綍
+                    var lists = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+                        .Where(x => x.OrderNo == orderNo && x.Status == (int)OutLockStockStatusEnum.鎷i�夊畬鎴�)
+                        .ToListAsync();
+
+                    var groupedData = lists.GroupBy(item => new { item.MaterielCode, item.lineNo, item.BarcodeUnit, item.WarehouseCode })
+                       .Select(group => new FeedbackOutboundDetailsModel
+                       {
+                           materialCode = group.Key.MaterielCode,
+                           lineNo = group.Key.lineNo,
+                           warehouseCode = group.Key.WarehouseCode,
+                           qty = group.Sum(x => x.BarcodeQty),
+                           currentDeliveryQty = group.Sum(x => x.BarcodeQty),
+                           unit = group.Key.BarcodeUnit,
+                           barcodes = group.Select(row => new WIDESEA_DTO.Outbound.BarcodesModel
+                           {
+                               barcode = row.CurrentBarcode,
+                               supplyCode = row.SupplyCode,
+                               batchNo = row.BatchNo,
+                               unit = row.BarcodeUnit,
+                               qty = row.BarcodeQty
+                           }).ToList()
+                       }).ToList();
+
+                    feedmodel.details = groupedData;
+
+                    var result = await _invokeMESService.FeedbackOutbound(feedmodel);
+                    if (result != null && result.code == 200)
+                    {
+                        await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
+                            .SetColumns(x => x.ReturnToMESStatus == 1)
+                            .Where(x => x.OrderId == outboundOrder.Id)
+                            .ExecuteCommandAsync();
+
+                        await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>()
+                              .SetColumns(x => new Dt_OutboundOrder
+                              {
+                                  ReturnToMESStatus = 1,
+                                  Operator = App.User.UserName,
+                              })
+
+                            .Where(x => x.OrderNo == orderNo)
+                            .ExecuteCommandAsync();
+                    }
+
+                    _logger.LogError($"FeedbackOutbound鎴愬姛 - OrderNo: {orderNo}, {JsonSerializer.Serialize(result)}");
+                }
+                catch (Exception ex)
+                {
+                    _logger.LogError($"FeedbackOutbound澶辫触 - OrderNo: {orderNo}, Error: {ex.Message}");
+                }
+            }
+        }
+
+        #endregion
+
+        #region 绌烘墭鐩�
+
+        /// <summary>
+        /// 娓呯悊闆跺簱瀛樻暟鎹�
+        /// </summary>
+        private async Task CleanupZeroStockData(int stockId)
+        {
+            try
+            {
+                // 1. 鍒犻櫎搴撳瓨鏁伴噺涓�0鐨勬槑缁嗚褰�
+                var deleteDetailCount = await _stockInfoDetailService.Db.Deleteable<Dt_StockInfoDetail>()
+                    .Where(x => x.StockId == stockId && x.StockQuantity == 0 && (x.Status == StockStatusEmun.鍑哄簱瀹屾垚.ObjToInt() || x.Status ==
+                                          StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt()))
+                    .ExecuteCommandAsync();
+
+                await _stockInfoService.Db.Deleteable<Dt_StockInfo>()
+                   .Where(x => x.Id == stockId).ExecuteCommandAsync();
+
+                _logger.LogInformation($"娓呯悊闆跺簱瀛樻槑缁嗚褰� - StockId: {stockId}, 鍒犻櫎璁板綍鏁�: {deleteDetailCount}");
+
+
+
+            }
+            catch (Exception ex)
+            {
+                _logger.LogWarning($"娓呯悊闆跺簱瀛樻暟鎹け璐� - StockId: {stockId}, Error: {ex.Message}");
+                // 娉ㄦ剰锛氭竻鐞嗗け璐ヤ笉搴旇褰卞搷涓绘祦绋�
+            }
+        }
+        /// <summary>
+        /// 澶勭悊浠诲姟娓呯悊锛堟寜璁㈠崟鍜屾墭鐩橈級
+        /// </summary>
+        private async Task HandleTaskCleanup(string orderNo, string palletCode)
+        {
+            try
+            {
+                // 1. 鏌ユ壘鎵�鏈変笌璇ヨ鍗曞拰鎵樼洏鐩稿叧鐨勪换鍔�
+                var tasks = await _taskRepository.Db.Queryable<Dt_Task>().Where(x => x.OrderNo == orderNo && x.PalletCode == palletCode).ToListAsync();
+
+                if (tasks.Any())
+                {
+                    foreach (var task in tasks)
+                    {
+                        task.TaskStatus = (int)TaskStatusEnum.Finish;
+                    }
+                    // await _taskRepository.Db.Updateable(tasks).ExecuteCommandAsync();
+
+                    _taskRepository.DeleteAndMoveIntoHty(tasks, OperateTypeEnum.鑷姩瀹屾垚);
+                    _logger.LogInformation($"瀹屾垚{tasks.Count}涓墭鐩樹换鍔� - 璁㈠崟: {orderNo}, 鎵樼洏: {palletCode}");
+                }
+
+            }
+            catch (Exception ex)
+            {
+                _logger.LogWarning($"澶勭悊浠诲姟娓呯悊澶辫触 - OrderNo: {orderNo}, PalletCode: {palletCode}, Error: {ex.Message}");
+                throw new Exception($"浠诲姟娓呯悊澶辫触: {ex.Message}");
+            }
+        }
+        /// <summary>
+        /// 鏇存柊璁㈠崟鐩稿叧鏁版嵁
+        /// </summary>
+        private async Task UpdateOrderData(string orderNo, string palletCode)
+        {
+            try
+            {
+                // 妫�鏌ヨ鍗曟槸鍚﹁繕鏈夊叾浠栨墭鐩樺湪澶勭悊涓�
+                var otherActivePallets = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+                    .Where(x => x.OrderNo == orderNo &&
+                               x.PalletCode != palletCode &&
+                             (x.Status == (int)OutLockStockStatusEnum.鍑哄簱涓� || x.Status == (int)OutLockStockStatusEnum.鍥炲簱涓�))
+                    .AnyAsync();
+
+                var otherActiveTasks = await _taskRepository.Db.Queryable<Dt_Task>()
+                    .Where(x => x.OrderNo == orderNo &&
+                               x.PalletCode != palletCode
+                    // && x.TaskStatus.In((int)TaskStatusEnum.寰呮墽琛�, (int)TaskStatusEnum.鎵ц涓�)
+                     )
+                    .AnyAsync();
+
+                // 濡傛灉娌℃湁鍏朵粬鎵樼洏鍦ㄥ鐞嗭紝妫�鏌ヨ鍗曟槸鍚﹀簲璇ュ畬鎴�
+                if (!otherActivePallets && !otherActiveTasks)
+                {
+                    await CheckAndUpdateOrderCompletion(orderNo);
+                }
+                else
+                {
+                    _logger.LogInformation($"璁㈠崟 {orderNo} 杩樻湁鍏朵粬鎵樼洏鍦ㄥ鐞嗭紝涓嶆洿鏂拌鍗曠姸鎬�");
+                }
+
+                // 3. 鏇存柊鎷i�夎褰曠姸鎬侊紙鍙�夛級
+                await UpdatePickingRecordsStatus(orderNo, palletCode);
+
+            }
+            catch (Exception ex)
+            {
+                _logger.LogWarning($"鏇存柊璁㈠崟鏁版嵁澶辫触 - OrderNo: {orderNo}, PalletCode: {palletCode}, Error: {ex.Message}");
+                throw new Exception($"鏇存柊璁㈠崟鏁版嵁澶辫触: {ex.Message}");
+            }
+        }
+
+        /// <summary>
+        /// 妫�鏌ュ苟鏇存柊璁㈠崟瀹屾垚鐘舵��
+        /// </summary>
+        private async Task CheckAndUpdateOrderCompletion(string orderNo)
+        {
+            var orderDetails = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
+                .LeftJoin<Dt_OutboundOrder>((o, item) => o.OrderId == item.Id)
+                .Where((o, item) => item.OrderNo == orderNo)
+                .Select((o, item) => o)
+                .ToListAsync();
+
+            bool allCompleted = true;
+            foreach (var detail in orderDetails)
+            {
+                if (detail.OverOutQuantity < detail.NeedOutQuantity)
+                {
+                    allCompleted = false;
+                    break;
+                }
+            }
+
+            var outboundOrder = await _outboundOrderService.Db.Queryable<Dt_OutboundOrder>()
+                .FirstAsync(x => x.OrderNo == orderNo);
+
+            if (outboundOrder != null && allCompleted && outboundOrder.OrderStatus != (int)OutOrderStatusEnum.鍑哄簱瀹屾垚)
+            {
+                outboundOrder.OrderStatus = (int)OutOrderStatusEnum.鍑哄簱瀹屾垚;
+                outboundOrder.Operator = App.User.UserName;
+                await _outboundOrderService.Db.Updateable(outboundOrder).ExecuteCommandAsync();
+
+                _logger.LogInformation($"璁㈠崟 {orderNo} 宸叉爣璁颁负鍑哄簱瀹屾垚");
+
+                // 鍚慚ES鍙嶉璁㈠崟瀹屾垚锛堝鏋滈渶瑕侊級
+                await HandleOrderCompletion(outboundOrder, orderNo);
+            }
+        }
+
+        /// <summary>
+        /// 鏇存柊鎷i�夎褰曠姸鎬�
+        /// </summary>
+        private async Task UpdatePickingRecordsStatus(string orderNo, string palletCode)
+        {
+            try
+            {
+                // 鍙互灏嗙浉鍏崇殑鎷i�夎褰曟爣璁颁负宸插畬鎴�
+                var pickingRecords = await Db.Queryable<Dt_PickingRecord>()
+                    .Where(x => x.OrderNo == orderNo && x.PalletCode == palletCode)
+                    .ToListAsync();
+
+                // 杩欓噷鍙互鏍规嵁闇�瑕佹洿鏂版嫞閫夎褰曠殑鐘舵�佸瓧娈�
+                // 渚嬪锛歱ickingRecord.Status = (int)PickingStatusEnum.宸插畬鎴�;
+
+                _logger.LogInformation($"鎵惧埌{pickingRecords.Count}鏉℃嫞閫夎褰� - 璁㈠崟: {orderNo}, 鎵樼洏: {palletCode}");
+
+            }
+            catch (Exception ex)
+            {
+                _logger.LogWarning($"鏇存柊鎷i�夎褰曠姸鎬佸け璐�: {ex.Message}");
+            }
+        }
+        #endregion
+
+
+
+        #region 杈呭姪鏂规硶
+        /// <summary>
+        /// 缁熶竴鍒嗘瀽鎵樼洏鐘舵�� - 杩斿洖鎵樼洏鐨勫畬鏁寸姸鎬佷俊鎭�
+        /// </summary>
+        private async Task<PalletStatusAnalysis> AnalyzePalletStatus(string orderNo, string palletCode, int stockId)
+        {
+            var result = new PalletStatusAnalysis
+            {
+                OrderNo = orderNo,
+                PalletCode = palletCode,
+                StockId = stockId
+            };
+
+            // 鍒嗘瀽鏈垎鎷g殑鍑哄簱閿佸畾璁板綍
+            var remainingLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+                .Where(it => it.OrderNo == orderNo &&
+                           it.PalletCode == palletCode &&
+                           it.Status == (int)OutLockStockStatusEnum.鍑哄簱涓�)
+                .ToListAsync();
+
+            if (remainingLocks.Any())
+            {
+                result.HasRemainingLocks = true;
+                result.RemainingLocks = remainingLocks;
+                result.RemainingLocksReturnQty = remainingLocks.Sum(x => x.AssignQuantity - x.PickedQty);
+                _logger.LogInformation($"鍙戠幇{remainingLocks.Count}鏉℃湭鍒嗘嫞閿佸畾璁板綍锛屾�绘暟閲�: {result.RemainingLocksReturnQty}");
+            }
+
+            // 鍒嗘瀽鎵樼洏涓婄殑搴撳瓨璐х墿
+            var palletStockGoods = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>()
+                .Where(it => it.StockId == stockId &&
+                     (it.Status == StockStatusEmun.鍏ュ簱纭.ObjToInt() ||
+                      it.Status == StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt() ||
+                      it.Status == StockStatusEmun.鍑哄簱閿佸畾.ObjToInt()))
+                .Where(it => it.StockQuantity > 0)
+                .ToListAsync();
+
+            if (palletStockGoods.Any())
+            {
+                result.HasPalletStockGoods = true;
+                result.PalletStockGoods = palletStockGoods;
+                result.PalletStockReturnQty = palletStockGoods.Sum(x => x.StockQuantity);
+                _logger.LogInformation($"鍙戠幇{palletStockGoods.Count}涓簱瀛樿揣鐗╋紝鎬绘暟閲�: {result.PalletStockReturnQty}");
+
+                // 璁板綍璇︾粏鐘舵�佸垎甯�
+                var statusGroups = palletStockGoods.GroupBy(x => x.Status);
+                foreach (var group in statusGroups)
+                {
+                    _logger.LogInformation($"搴撳瓨鐘舵�亄group.Key}: {group.Count()}涓揣鐗╋紝鏁伴噺: {group.Sum(x => x.StockQuantity)}");
+                }
+            }
+
+            //鍒嗘瀽鎷嗗寘璁板綍
+            var splitRecords = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>()
+                .Where(it => it.OrderNo == orderNo &&
+                           it.PalletCode == palletCode &&
+                           !it.IsReverted && it.Status != (int)SplitPackageStatusEnum.宸叉嫞閫� &&
+                           it.Status != (int)SplitPackageStatusEnum.宸插洖搴�)
+                .ToListAsync();
+
+            if (splitRecords.Any())
+            {
+                result.HasSplitRecords = true;
+                result.SplitRecords = splitRecords;
+                result.SplitReturnQty = await CalculateSplitReturnQuantity(splitRecords, stockId);
+
+                _logger.LogInformation($"鍙戠幇{splitRecords.Count}鏉℃湭鎷i�夋媶鍖呰褰曪紝鎬绘暟閲�: {result.SplitReturnQty}");
+            }
+
+            // 4. 璁$畻鎬诲洖搴撴暟閲忓拰绌烘墭鐩樼姸鎬�
+            result.TotalReturnQty = result.RemainingLocksReturnQty + result.PalletStockReturnQty + result.SplitReturnQty;
+            result.HasItemsToReturn = result.TotalReturnQty > 0;
+            result.IsEmptyPallet = !result.HasItemsToReturn;
+
+            // 5. 妫�鏌ユ槸鍚︽湁杩涜涓殑浠诲姟
+            result.HasActiveTasks = await _taskRepository.Db.Queryable<Dt_Task>()
+                .Where(x => x.OrderNo == orderNo && x.TaskType == TaskTypeEnum.InPick.ObjToInt() &&
+                           x.PalletCode == palletCode &&
+                           x.TaskStatus == (int)TaskStatusEnum.New)
+                .AnyAsync();
+
+            _logger.LogInformation($"鎵樼洏鐘舵�佸垎鏋愬畬鎴� - 璁㈠崟: {orderNo}, 鎵樼洏: {palletCode}, " +
+                                  $"鎬诲洖搴撴暟閲�: {result.TotalReturnQty}, 鏄惁绌烘墭鐩�: {result.IsEmptyPallet}, " +
+                                  $"鏈夎繘琛屼腑浠诲姟: {result.HasActiveTasks}");
+
+            return result;
+        }
+
+        /// <summary>
+        /// 妫�鏌ユ墭鐩樻槸鍚︿负绌� 
+        /// </summary>
+        private async Task<bool> IsPalletEmpty(string orderNo, string palletCode)
+        {
+            try
+            {
+                // 鑾峰彇搴撳瓨淇℃伅
+                var stockInfo = await _stockInfoService.Db.Queryable<Dt_StockInfo>()
+                    .Where(x => x.PalletCode == palletCode)
+                    .FirstAsync();
+
+                if (stockInfo == null)
+                    return false;
+
+                // 浣跨敤缁熶竴鐨勭姸鎬佸垎鏋�
+                var statusAnalysis = await AnalyzePalletStatus(orderNo, palletCode, stockInfo.Id);
+                return statusAnalysis.IsEmptyPallet;
+            }
+            catch (Exception ex)
+            {
+                _logger.LogWarning($"妫�鏌ユ墭鐩樻槸鍚︿负绌哄け璐� - OrderNo: {orderNo}, PalletCode: {palletCode}, Error: {ex.Message}");
+                return false;
+            }
+        }
+        /// <summary>
+        /// 妫�鏌ュ苟澶勭悊绌烘墭鐩� 
+        /// </summary>
+        private async Task<bool> CheckAndHandleEmptyPallet(string orderNo, string palletCode)
+        {
+            try
+            {
+                // 1. 鑾峰彇搴撳瓨淇℃伅
+                var stockInfo = await _stockInfoService.Db.Queryable<Dt_StockInfo>()
+                    .Where(x => x.PalletCode == palletCode)
+                    .FirstAsync();
+
+                if (stockInfo == null)
+                {
+                    _logger.LogWarning($"鏈壘鍒版墭鐩� {palletCode} 鐨勫簱瀛樹俊鎭�");
+                    return false;
+                }
+
+                // 2. 浣跨敤缁熶竴鐨勭姸鎬佸垎鏋�
+                var statusAnalysis = await AnalyzePalletStatus(orderNo, palletCode, stockInfo.Id);
+
+                // 3. 妫�鏌ユ槸鍚︿负绌烘墭鐩樹笖娌℃湁杩涜涓殑浠诲姟
+                if (!statusAnalysis.IsEmptyPallet || statusAnalysis.HasActiveTasks)
+                {
+                    return false;
+                }
+
+                _logger.LogInformation($"妫�娴嬪埌绌烘墭鐩橈紝寮�濮嬭嚜鍔ㄥ鐞� - 璁㈠崟: {orderNo}, 鎵樼洏: {palletCode}");
+
+                //// 娓呯悊闆跺簱瀛樻暟鎹�
+                //await CleanupZeroStockData(stockInfo.Id);
+
+                //// 鏇存柊搴撳瓨涓昏〃鐘舵�佷负绌烘墭鐩�
+                //await UpdateStockInfoAsEmpty(stockInfo);
+
+                //// 澶勭悊鍑哄簱閿佸畾璁板綍
+                //await HandleOutStockLockRecords(orderNo, palletCode);
+
+                //// 澶勭悊浠诲姟鐘舵��
+                //await HandleTaskStatusForEmptyPallet(orderNo, palletCode);
+
+                //// 鏇存柊璁㈠崟鏁版嵁
+                //await UpdateOrderDataForEmptyPallet(orderNo, palletCode);
+
+                ////璁板綍鎿嶄綔鍘嗗彶
+                //await RecordAutoEmptyPalletOperation(orderNo, palletCode);
+
+                _logger.LogInformation($"绌烘墭鐩樿嚜鍔ㄥ鐞嗗畬鎴� - 璁㈠崟: {orderNo}, 鎵樼洏: {palletCode}");
+
+                return true;
+            }
+            catch (Exception ex)
+            {
+                _logger.LogError($"鑷姩澶勭悊绌烘墭鐩樺け璐� - OrderNo: {orderNo}, PalletCode: {palletCode}, Error: {ex.Message}");
+                return false;
+            }
+        }
+
+        private async Task<string> GenerateNewBarcode()
+        {
+            var seq = await _dailySequenceService.GetNextSequenceAsync();
+            return "WSLOT" + DateTime.Now.ToString("yyyyMMdd") + seq.ToString()?.PadLeft(5, '0');
+        }
+
+        private async Task<Dt_OutStockLockInfo> CreateSplitLockInfo(Dt_OutStockLockInfo originalLock, decimal quantity, string newBarcode)
+        {
+            var newLockInfo = new Dt_OutStockLockInfo
+            {
+                OrderNo = originalLock.OrderNo,
+                OrderDetailId = originalLock.OrderDetailId,
+                BatchNo = originalLock.BatchNo,
+                MaterielCode = originalLock.MaterielCode,
+                MaterielName = originalLock.MaterielName,
+                StockId = originalLock.StockId,
+                OrderQuantity = quantity,
+                OriginalQuantity = quantity,
+                AssignQuantity = quantity,
+                PickedQty = quantity,
+                LocationCode = originalLock.LocationCode,
+                PalletCode = originalLock.PalletCode,
+                TaskNum = originalLock.TaskNum,
+                Status = (int)OutLockStockStatusEnum.鎷i�夊畬鎴�,
+                Unit = originalLock.Unit,
+                SupplyCode = originalLock.SupplyCode,
+                OrderType = originalLock.OrderType,
+                CurrentBarcode = newBarcode,
+                OriginalLockQuantity = quantity,
+                IsSplitted = 1,
+                ParentLockId = originalLock.Id,
+                Operator = App.User.UserName,
+                FactoryArea = originalLock.FactoryArea,
+                lineNo = originalLock.lineNo,
+                WarehouseCode = originalLock.WarehouseCode,
+                BarcodeQty = originalLock.BarcodeQty,
+                BarcodeUnit = originalLock.BarcodeUnit,
+
+            };
+
+            var newLockId = await _outStockLockInfoService.Db.Insertable(newLockInfo).ExecuteReturnIdentityAsync();
+            newLockInfo.Id = newLockId;
+            return newLockInfo;
+        }
+
+        private async Task RecordSplitHistory(Dt_OutStockLockInfo lockInfo, Dt_StockInfoDetail stockDetail,
+            decimal splitQty, decimal remainQty, string newBarcode)
+        {
+            var splitHistory = new Dt_SplitPackageRecord
+            {
+                FactoryArea = lockInfo.FactoryArea,
+                TaskNum = lockInfo.TaskNum,
+                OutStockLockInfoId = lockInfo.Id,
+                StockId = stockDetail.StockId,
+                Operator = App.User.UserName,
+                IsReverted = false,
+                OriginalBarcode = stockDetail.Barcode,
+                NewBarcode = newBarcode,
+                SplitQty = splitQty,
+                RemainQuantity = remainQty,
+                MaterielCode = lockInfo.MaterielCode,
+                SplitTime = DateTime.Now,
+                OrderNo = lockInfo.OrderNo,
+                PalletCode = lockInfo.PalletCode,
+                Status = (int)SplitPackageStatusEnum.宸叉嫞閫�
+            };
+
+            await _splitPackageService.Db.Insertable(splitHistory).ExecuteCommandAsync();
+        }
+
+        private List<SplitResult> CreateSplitResults(Dt_OutStockLockInfo lockInfo, decimal splitQty, decimal remainQty, string newBarcode, string originalBarcode)
+        {
+            return new List<SplitResult>
+        {
+            new SplitResult
+            {
+                materialCode = lockInfo.MaterielCode,
+                supplierCode = lockInfo.SupplyCode,
+                quantityTotal = splitQty.ToString("F2"),
+                batchNumber = newBarcode,
+                batch = lockInfo.BatchNo,
+                factory = lockInfo.FactoryArea,
+                date = DateTime.Now.ToString("yyyy-MM-dd"),
+            },
+            new SplitResult
+            {
+                materialCode = lockInfo.MaterielCode,
+                supplierCode = lockInfo.SupplyCode,
+                quantityTotal = remainQty.ToString("F2"),
+                batchNumber = originalBarcode,
+                batch = lockInfo.BatchNo,
+                factory = lockInfo.FactoryArea,
+                date = DateTime.Now.ToString("yyyy-MM-dd"),
+            }
+        };
+        }
+
+        private async Task UpdateSplitRecordsStatus(string barcode)
+        {
+            var relatedSplitRecords = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>()
+                .Where(it => it.OriginalBarcode == barcode || it.NewBarcode == barcode)
+                .Where(it => !it.IsReverted)
+                .ToListAsync();
+
+            foreach (var record in relatedSplitRecords)
+            {
+                record.Status = (int)SplitPackageStatusEnum.宸叉嫞閫�;
+                await _splitPackageService.Db.Updateable(record).ExecuteCommandAsync();
+            }
+        }
+
+        private async Task<int> GenerateTaskNumber()
+        {
+            return await _dailySequenceService.GetNextSequenceAsync();
+        }
+
+        private WebResponseContent CreatePickingResponse(PickingResult result, string adjustedReason)
+        {
+            //if (result.SplitResults.Any())
+            //{
+            //    var responseData = new { SplitResults = result.SplitResults, AdjustedReason = "" };
+            //    if (!string.IsNullOrEmpty(adjustedReason))
+            //    {
+            //        responseData = new { SplitResults = result.SplitResults, AdjustedReason = adjustedReason };
+            //    }
+            //    return WebResponseContent.Instance.OK("鎷i�夌‘璁ゆ垚鍔燂紝宸茶嚜鍔ㄦ媶鍖�", responseData);
+            //}
+
+            //if (!string.IsNullOrEmpty(adjustedReason))
+            //{
+            //    return WebResponseContent.Instance.OK($"鎷i�夌‘璁ゆ垚鍔燂紙{adjustedReason}锛�");
+            //}
+
+            //return WebResponseContent.Instance.OK("鎷i�夌‘璁ゆ垚鍔�");
+
+            if (result.SplitResults.Any())
+            {
+                return WebResponseContent.Instance.OK("鎷i�夌‘璁ゆ垚鍔燂紝宸茶嚜鍔ㄦ媶鍖�", new { SplitResults = result.SplitResults });
+            }
+            return WebResponseContent.Instance.OK("鎷i�夌‘璁ゆ垚鍔�", new { SplitResults = new List<SplitResult>() });
+        }
+
+
+
+        #region 铏氭嫙鍑哄叆搴�
+        public WebResponseContent GetAvailablePurchaseOrders()
+        {
+            List<Dt_InboundOrder> InOders = _inboundOrderRepository.QueryData().Where(x => x.OrderStatus != InOrderStatusEnum.鍏ュ簱瀹屾垚.ObjToInt()).ToList();
+            List<string> InOderCodes = InOders.Select(x => x.UpperOrderNo).ToList();
+            return WebResponseContent.Instance.OK("鎴愬姛", data: InOderCodes);
+        }
+
+        public WebResponseContent GetAvailablePickingOrders()
+        {
+            List<Dt_OutboundOrder> outOders = _outboundOrderService.Db.Queryable<Dt_OutboundOrder>().Where(x => x.OrderStatus != OutOrderStatusEnum.鍑哄簱瀹屾垚.ObjToInt()).ToList();
+
+            List<string> outOderCodes = outOders.Select(x => x.UpperOrderNo).ToList();
+            return WebResponseContent.Instance.OK("鎴愬姛", data: outOderCodes);
+
+        }
+        public WebResponseContent BarcodeValidate(NoStockOutModel noStockOut)
+        {
+            try
+            {
+                Dt_InboundOrder inboundOrder = Db.Queryable<Dt_InboundOrder>().Where(x => x.UpperOrderNo == noStockOut.inOder && x.OrderStatus != InOrderStatusEnum.鍏ュ簱瀹屾垚.ObjToInt()).Includes(x => x.Details).First();
+                if (inboundOrder == null)
+                {
+                    return WebResponseContent.Instance.Error($"鏈壘鍒伴噰璐崟锛歿noStockOut.inOder}");
+                }
+                var matchedDetail = inboundOrder.Details.FirstOrDefault(detail => detail.Barcode == noStockOut.barCode && detail.OrderDetailStatus != OrderDetailStatusEnum.Over.ObjToInt());
+
+                if (matchedDetail == null)
+                {
+                    return WebResponseContent.Instance.Error($"鍦ㄩ噰璐崟 {noStockOut.inOder} 涓湭鎵惧埌鏉$爜涓� {noStockOut.barCode} 鐨勬槑缁嗐��");
+                }
+                matchedDetail.NoStockOutQty = 0;
+
+                Dt_OutboundOrder outboundOrder = Db.Queryable<Dt_OutboundOrder>().Where(x => x.UpperOrderNo == noStockOut.outOder && x.OrderStatus != OutOrderStatusEnum.鍑哄簱瀹屾垚.ObjToInt()).Includes(x => x.Details).First();
+                if (outboundOrder == null)
+                {
+                    return WebResponseContent.Instance.Error($"鏈壘鍒板嚭搴撳崟锛歿noStockOut.inOder}");
+                }
+                var matchedCode = outboundOrder.Details.FirstOrDefault(detail => detail.MaterielCode == matchedDetail.MaterielCode && detail.OrderDetailStatus != OrderDetailStatusEnum.Over.ObjToInt());
+
+                if (matchedCode == null)
+                {
+                    return WebResponseContent.Instance.Error($"鍦ㄥ嚭搴撳崟鐨勭墿鏂欑紪鐮佷腑鏈壘鍒颁笌閲囪喘鍗曚腑鐨剓matchedDetail.MaterielCode} 瀵瑰簲鐨勭墿鏂欍��");
+                }
+                matchedCode.NoStockOutQty = 0;
+
+                //鍓╀綑鍏ュ簱鏁伴噺鍗宠櫄鎷熷嚭鍏ュ簱鍓╀綑鍙嚭鏁伴噺
+                decimal outQuantity = matchedDetail.OrderQuantity - matchedDetail.ReceiptQuantity;
+                if (outQuantity == 0)
+                {
+                    return WebResponseContent.Instance.Error($"璇ラ噰璐崟涓殑鏉$爜瀵瑰簲鐨勫彲鍑烘暟閲忎负0");
+                }
+                if (matchedCode.OrderQuantity < outQuantity)
+                {
+                    return WebResponseContent.Instance.Error($"璇ラ噰璐崟涓殑鏉$爜瀵瑰簲鐨勫彲鍑烘暟閲忚秴鍑哄嚭搴撳崟鍑哄簱鏁伴噺{matchedDetail.OrderQuantity - matchedCode.OrderQuantity},涓嶆弧瓒虫暣鍖呭嚭搴�");
+                }
+                //鍗曟嵁鍑哄簱閿佸畾鏁伴噺
+                matchedDetail.NoStockOutQty += outQuantity;
+                matchedCode.NoStockOutQty += outQuantity;
+
+                if ((matchedCode.LockQuantity + matchedCode.NoStockOutQty) > matchedCode.OrderQuantity)
+                {
+                    return WebResponseContent.Instance.Error($"鍑哄簱鍗曟槑缁嗘暟閲忔孩鍑簕matchedCode.LockQuantity - matchedCode.OrderQuantity}");
+                }
+                matchedDetail.OrderDetailStatus = OrderDetailStatusEnum.Inbounding.ObjToInt();
+                matchedCode.OrderDetailStatus = OrderDetailStatusEnum.AssignOver.ObjToInt();
+
+                _unitOfWorkManage.BeginTran();
+                _inboundOrderDetailService.UpdateData(matchedDetail);
+                _outboundOrderDetailService.UpdateData(matchedCode);
+                _unitOfWorkManage.CommitTran();
+                return WebResponseContent.Instance.OK();
+            }
+            catch (Exception ex)
+            {
+                _unitOfWorkManage.RollbackTran();
+                return WebResponseContent.Instance.Error(ex.Message);
+            }
+        }
+
+
+        public WebResponseContent DeleteBarcode(NoStockOutModel noStockOut)
+        {
+            try
+            {
+                Dt_InboundOrder inboundOrder = Db.Queryable<Dt_InboundOrder>().Where(x => x.UpperOrderNo == noStockOut.inOder && x.OrderStatus != InOrderStatusEnum.鍏ュ簱瀹屾垚.ObjToInt()).Includes(x => x.Details).First();
+                if (inboundOrder == null)
+                {
+                    return WebResponseContent.Instance.Error($"鏈壘鍒伴噰璐崟锛歿noStockOut.inOder}");
+                }
+                var matchedDetail = inboundOrder.Details.FirstOrDefault(detail => detail.Barcode == noStockOut.barCode && detail.OrderDetailStatus != OrderDetailStatusEnum.Over.ObjToInt());
+
+                if (matchedDetail == null)
+                {
+                    return WebResponseContent.Instance.Error($"鍦ㄩ噰璐崟 {noStockOut.inOder} 涓湭鎵惧埌鏉$爜涓� {noStockOut.barCode} 鐨勬槑缁嗐��");
+                }
+                matchedDetail.NoStockOutQty = 0;
+
+                if (matchedDetail.ReceiptQuantity == 0 && matchedDetail.OverInQuantity == 0)
+                {
+                    matchedDetail.OrderDetailStatus = OrderDetailStatusEnum.New.ObjToInt();
+                }
+
+                Dt_OutboundOrder outboundOrder = Db.Queryable<Dt_OutboundOrder>().Where(x => x.UpperOrderNo == noStockOut.outOder && x.OrderStatus != OutOrderStatusEnum.鍑哄簱瀹屾垚.ObjToInt()).Includes(x => x.Details).First();
+                if (outboundOrder == null)
+                {
+                    return WebResponseContent.Instance.Error($"鏈壘鍒板嚭搴撳崟锛歿noStockOut.inOder}");
+                }
+                var matchedCode = outboundOrder.Details.FirstOrDefault(detail => detail.MaterielCode == matchedDetail.MaterielCode && detail.OrderDetailStatus != OrderDetailStatusEnum.Over.ObjToInt());
+
+                if (matchedCode == null)
+                {
+                    return WebResponseContent.Instance.Error($"鍦ㄥ嚭搴撳崟鐨勭墿鏂欑紪鐮佷腑鏈壘鍒颁笌閲囪喘鍗曚腑鐨剓matchedDetail.MaterielCode} 瀵瑰簲鐨勭墿鏂欍��");
+                }
+                matchedCode.NoStockOutQty = 0;
+                if (matchedCode.LockQuantity == 0 && matchedCode.OverOutQuantity == 0)
+                {
+                    matchedCode.OrderDetailStatus = OrderDetailStatusEnum.New.ObjToInt();
+                }
+                _unitOfWorkManage.BeginTran();
+                _inboundOrderDetailService.UpdateData(matchedDetail);
+                _outboundOrderDetailService.UpdateData(matchedCode);
+                _unitOfWorkManage.CommitTran();
+                return WebResponseContent.Instance.OK();
+
+            }
+            catch (Exception ex)
+            {
+                _unitOfWorkManage.RollbackTran();
+                return WebResponseContent.Instance.Error(ex.Message);
+            }
+        }
+
+        public async Task<WebResponseContent> NoStockOutSubmit(NoStockOutSubmit noStockOutSubmit)
+        {
+            try
+            {
+                Dt_InboundOrder inboundOrder = _inboundOrderRepository.Db.Queryable<Dt_InboundOrder>().Where(x => x.UpperOrderNo == noStockOutSubmit.InOderSubmit && x.OrderStatus != InOrderStatusEnum.鍏ュ簱瀹屾垚.ObjToInt()).Includes(x => x.Details).First();
+                if (inboundOrder == null)
+                {
+                    return WebResponseContent.Instance.Error($"鏈壘鍒伴噰璐崟锛歿noStockOutSubmit.InOderSubmit}");
+                }
+                Dt_OutboundOrder outboundOrder = _inboundOrderRepository.Db.Queryable<Dt_OutboundOrder>().Where(x => x.UpperOrderNo == noStockOutSubmit.OutOderSubmit && x.OrderStatus != OutOrderStatusEnum.鍑哄簱瀹屾垚.ObjToInt()).Includes(x => x.Details).First();
+                if (outboundOrder == null)
+                {
+                    return WebResponseContent.Instance.Error($"鏈壘鍒板嚭搴撳崟锛歿noStockOutSubmit.OutOderSubmit}");
+                }
+                List<Dt_InboundOrderDetail> inboundOrderDetails = new List<Dt_InboundOrderDetail>();
+                List<Dt_OutboundOrderDetail> outboundOrderDetails = new List<Dt_OutboundOrderDetail>();
+                foreach (var BarCode in noStockOutSubmit.BarCodeSubmit)
+                {
+                    var inboundOrderDetail = inboundOrder.Details.FirstOrDefault(detail => detail.Barcode == BarCode && detail.OrderDetailStatus != OrderDetailStatusEnum.Over.ObjToInt());
+
+                    if (inboundOrderDetail == null)
+                    {
+                        return WebResponseContent.Instance.Error($"鍦ㄩ噰璐崟 {noStockOutSubmit.InOderSubmit} 涓湭鎵惧埌鏉$爜涓� {BarCode} 鐨勬槑缁嗐��");
+                    }
+                    var outboundOrderDetail = outboundOrder.Details.FirstOrDefault(detail => detail.MaterielCode == inboundOrderDetail.MaterielCode && detail.OrderDetailStatus != OrderDetailStatusEnum.Over.ObjToInt());
+
+                    if (outboundOrderDetail == null)
+                    {
+                        return WebResponseContent.Instance.Error($"鍦ㄥ嚭搴撳崟鐨勭墿鏂欑紪鐮佷腑鏈壘鍒颁笌閲囪喘鍗曚腑鐨剓inboundOrderDetail.MaterielCode} 瀵瑰簲鐨勭墿鏂欍��");
+                    }
+                    inboundOrderDetail.ReceiptQuantity += inboundOrderDetail.NoStockOutQty;
+                    inboundOrderDetail.OverInQuantity = inboundOrderDetail.ReceiptQuantity;
+                    inboundOrderDetail.OrderDetailStatus = OrderDetailStatusEnum.Over.ObjToInt();
+                    inboundOrderDetails.Add(inboundOrderDetail);
+
+                    outboundOrderDetail.LockQuantity += outboundOrderDetail.NoStockOutQty;
+                    outboundOrderDetail.OverOutQuantity = outboundOrderDetail.LockQuantity;
+                    if (outboundOrderDetail.OrderQuantity == outboundOrderDetail.OverOutQuantity)
+                    {
+                        outboundOrderDetail.OrderDetailStatus = OrderDetailStatusEnum.Over.ObjToInt();
+                    }
+                    outboundOrderDetails.Add(outboundOrderDetail);
+
+                }
+                //鍒ゆ柇鍏ュ簱鍗曟嵁鏄庣粏鏄惁鍏ㄩ儴鏄畬鎴愮姸鎬�
+                int e = inboundOrder.Details.Count();
+                int w = inboundOrder.Details.Where(x => x.OrderDetailStatus == OrderDetailStatusEnum.Over.ObjToInt()).Count();
+                bool inoderOver = inboundOrder.Details.Count() == inboundOrder.Details.Where(x => x.OrderDetailStatus == OrderDetailStatusEnum.Over.ObjToInt()).Count();
+                if (inoderOver)
+                {
+                    inboundOrder.OrderStatus = InOrderStatusEnum.鍏ュ簱瀹屾垚.ObjToInt();
+                }
+                else
+                {
+                    inboundOrder.OrderStatus = InOrderStatusEnum.鍏ュ簱涓�.ObjToInt();
+                }
+                //鍒ゆ柇鍑哄簱鍗曟嵁鏄庣粏鏄惁鍏ㄩ儴鏄畬鎴愮姸鎬�
+                bool outOderOver = outboundOrder.Details.Count() == outboundOrder.Details.Where(x => x.OrderDetailStatus == OrderDetailStatusEnum.Over.ObjToInt()).Count();
+                if (outOderOver)
+                {
+                    outboundOrder.OrderStatus = OutOrderStatusEnum.鍑哄簱瀹屾垚.ObjToInt();
+                }
+                else
+                {
+                    outboundOrder.OrderStatus = OutOrderStatusEnum.鍑哄簱涓�.ObjToInt();
+                }
+                //鏁版嵁澶勭悊
+                _unitOfWorkManage.BeginTran();
+                _inboundOrderDetailService.UpdateData(inboundOrderDetails);
+                _outboundOrderDetailService.UpdateData(outboundOrderDetails);
+                _inboundOrderRepository.UpdateData(inboundOrder);
+                _outboundOrderService.UpdateData(outboundOrder);
+                _unitOfWorkManage.CommitTran();
+
+                if (inboundOrder.OrderStatus == InOrderStatusEnum.鍏ュ簱瀹屾垚.ObjToInt())
+                {
+                    var feedmodel = new FeedbackInboundRequestModel
+                    {
+                        reqCode = Guid.NewGuid().ToString(),
+                        reqTime = DateTime.Now.ToString(),
+                        business_type = inboundOrder.BusinessType,
+                        factoryArea = inboundOrder.FactoryArea,
+                        operationType = 1,
+                        Operator = inboundOrder.Operator,
+                        orderNo = inboundOrder.UpperOrderNo,
+                        status = inboundOrder.OrderStatus,
+                        details = new List<FeedbackInboundDetailsModel>()
+
+                    };
+
+                    var groupedData = inboundOrder.Details.GroupBy(item => new { item.MaterielCode, item.SupplyCode, item.BatchNo, item.lineNo, item.BarcodeUnit, item.WarehouseCode })
+                       .Select(group => new FeedbackInboundDetailsModel
+                       {
+                           materialCode = group.Key.MaterielCode,
+                           supplyCode = group.Key.SupplyCode,
+                           batchNo = group.Key.BatchNo,
+                           lineNo = group.Key.lineNo,
+                           warehouseCode = group.Key.WarehouseCode,
+                           qty = group.Sum(x => x.BarcodeQty),
+                           // warehouseCode= "1072",
+                           unit = group.Key.BarcodeUnit,
+                           barcodes = group.Select(row => new FeedbackBarcodesModel
+                           {
+                               barcode = row.Barcode,
+                               qty = row.BarcodeQty
+                           }).ToList()
+                       }).ToList();
+                    feedmodel.details = groupedData;
+
+                    var result = await _invokeMESService.FeedbackInbound(feedmodel);
+                    if (result != null && result.code == 200)
+                    {
+                        _inboundOrderRepository.Db.Updateable<Dt_InboundOrder>().SetColumns(it => new Dt_InboundOrder { ReturnToMESStatus = 1 })
+                        .Where(it => it.Id == inboundOrder.Id).ExecuteCommand();
+                        _inboundOrderDetailService.Db.Updateable<Dt_InboundOrderDetail>().SetColumns(it => new Dt_InboundOrderDetail { ReturnToMESStatus = 1 })
+                        .Where(it => it.OrderId == inboundOrder.Id).ExecuteCommand();
+                    }
+                }
+                if (outboundOrder.OrderStatus == OutOrderStatusEnum.鍑哄簱瀹屾垚.ObjToInt())
+                {
+                    var feedmodel = new FeedbackOutboundRequestModel
+                    {
+                        reqCode = Guid.NewGuid().ToString(),
+                        reqTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
+                        business_type = outboundOrder.BusinessType,
+                        factoryArea = outboundOrder.FactoryArea,
+                        operationType = 1,
+                        Operator = outboundOrder.Operator,
+                        orderNo = outboundOrder.UpperOrderNo,
+                        documentsNO = outboundOrder.OrderNo,
+                        status = outboundOrder.OrderStatus,
+                        details = new List<FeedbackOutboundDetailsModel>()
+                    };
+
+
+                    foreach (var detail in outboundOrder.Details)
+                    {
+                        // 鑾峰彇璇ユ槑缁嗗搴旂殑鏉$爜淇℃伅锛堜粠閿佸畾璁板綍锛�
+                        var detailLocks = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>()
+                            .Where(x => x.OrderNo == outboundOrder.OrderNo &&
+                                       x.OrderDetailId == detail.Id &&
+                                       x.Status == (int)OutLockStockStatusEnum.鎷i�夊畬鎴�)
+                            .ToListAsync();
+
+                        var detailModel = new FeedbackOutboundDetailsModel
+                        {
+                            materialCode = detail.MaterielCode,
+                            lineNo = detail.lineNo,
+                            warehouseCode = detail.WarehouseCode,
+                            qty = detail.BarcodeQty, // 浣跨敤璁㈠崟鏄庣粏鐨勫凡鍑哄簱鏁伴噺
+                            currentDeliveryQty = detail.BarcodeQty,
+                            unit = detail.BarcodeUnit,
+                            barcodes = detailLocks.Select(lockInfo => new WIDESEA_DTO.Outbound.BarcodesModel
+                            {
+                                barcode = lockInfo.CurrentBarcode,
+                                supplyCode = lockInfo.SupplyCode,
+                                batchNo = lockInfo.BatchNo,
+                                unit = lockInfo.BarcodeUnit,
+                                qty = lockInfo.BarcodeQty //  
+                            }).ToList()
+                        };
+
+                        feedmodel.details.Add(detailModel);
+                    }
+                    var result = await _invokeMESService.FeedbackOutbound(feedmodel);
+                    if (result != null && result.code == 200)
+                    {
+                        await _outboundOrderDetailService.Db.Updateable<Dt_OutboundOrderDetail>()
+                            .SetColumns(x => x.ReturnToMESStatus == 1)
+                            .Where(x => x.OrderId == outboundOrder.Id)
+                            .ExecuteCommandAsync();
+
+                        await _outboundOrderService.Db.Updateable<Dt_OutboundOrder>()
+                            .SetColumns(x => x.ReturnToMESStatus == 1)
+                            .Where(x => x.Id == outboundOrder.Id)
+                            .ExecuteCommandAsync();
+                    }
+                }
+
+
+                return WebResponseContent.Instance.OK();
+            }
+            catch (Exception ex)
+            {
+                _unitOfWorkManage.RollbackTran();
+                return WebResponseContent.Instance.Error(ex.Message);
+            }
+        }
+        #endregion
+
+        public WebResponseContent UnPalletQuantity(string orderNo)
+        {
+            // 鍒濆鍖栬繑鍥濪TO锛堥粯璁ゅ�奸兘涓�0锛岄伩鍏峮ull锛�
+            var resultDTO = new PalletSumQuantityDTO
+            {
+                StockSumQuantity = 0,
+                StockCount = 0,
+                UniqueUnit = ""
+            };
+            WebResponseContent content = new WebResponseContent();
+            try
+            {
+                if (string.IsNullOrWhiteSpace(orderNo))
+                {
+                    return content.Error("浼犲叆鐨勮鍗曞彿orderNo涓虹┖鎴栫┖鐧�");
+                }
+                var orderDetail = Db.Queryable<Dt_PickingRecord>().Where(s => s.OrderNo == orderNo).ToList();
+                if (orderDetail == null)
+                {
+                    return content.Error("鏈壘鍒板崟鎹�");
+                }
+                var unitGroups = orderDetail.GroupBy(d => d.BarcodeUnit).ToList();
+                if (unitGroups.Count == 1)
+                {
+                    resultDTO.UniqueUnit = unitGroups.First().Key;
+                }
+                else
+                {
+                    resultDTO.UniqueUnit = "";
+                }
+                var validDetails = _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>().Where(s => s.OrderNo == orderNo).ToList();
+                resultDTO.StockSumQuantity = orderDetail.Sum(d => d.PickQuantity);
+                resultDTO.StockCount = orderDetail.Count;
+                if (validDetails.Any())
+                {
+                    resultDTO.StockSumQuantity -= validDetails.Sum(d => d.StockQuantity);
+                    // 鏄庣粏璁板綍鏁帮細绗﹀悎鏉′欢鐨勬湁鏁堣褰曟潯鏁�
+                    resultDTO.StockCount -= validDetails.Count;
+                }
+                return content.OK("", resultDTO);
+            }
+            catch (Exception ex)
+            {
+                return content.Error("SumQuantity 缁熻搴撳瓨鏁伴噺澶辫触锛岃鍗曞彿锛歿OrderNo}");
+            }
+        }
+
+        public WebResponseContent BarcodeMaterielGroup(BarcodeMaterielGroupDTO materielGroupDTO)
+        {
+
+            WebResponseContent content = new WebResponseContent();
+            try
+            {
+                (bool, string, object?) result2 = ModelValidate.ValidateModelData(materielGroupDTO);
+                if (!result2.Item1) return content = WebResponseContent.Instance.Error(result2.Item2);
+
+                //  materielGroupDTO.WarehouseCode
+                var code = _warehouseAreaRepository.Db.Queryable<Dt_WarehouseArea>().Where(x => x.Code == materielGroupDTO.WarehouseType).Select(x => x.Code).First();
+                if (string.IsNullOrEmpty(code))
+                {
+                    return content = WebResponseContent.Instance.Error($"浠撳簱涓病鏈夎{materielGroupDTO.WarehouseType}缂栧彿銆�");
+                }
+
+                if (materielGroupDTO.orderTypes == InOrderTypeEnum.ReCheck.ObjToInt())
+                {
+                    var dborder = _reCheckOrderService.Db.Queryable<Dt_ReCheckOrder>().First(x => x.OrderNo == materielGroupDTO.OrderNo);
+                    if (dborder != null && dborder.SignSeq == 0)
+                    {
+                        return content.Error("鍙湁鎷垮埌閲嶆缁撴灉鎵嶈兘鍏ュ簱锛�");
+                    }
+                    else
+                    {
+                        return content.Error("娌℃湁鎵惧埌閲嶆鍗曟嵁鏁版嵁銆�");
+                    }
+                }
+                //  Dt_InboundOrder inboundOrder = GetInboundOrder(materielGroupDTO.OrderNo);
+
+                var dbinboundOrderDetails = Db.Queryable<Dt_PickingRecord>().Where(x => x.OrderNo == materielGroupDTO.OrderNo && !x.IsCancelled && x.Barcode == materielGroupDTO.Barcodes).ToList();
+
+                if (dbinboundOrderDetails != null && !dbinboundOrderDetails.Any())
+                {
+                    return content = WebResponseContent.Instance.Error($"鍗曟嵁涓病鏈夎{materielGroupDTO.Barcodes}鏉$爜鏁版嵁銆�");
+                }
+
+                List<string?> materielCodes = dbinboundOrderDetails.GroupBy(x => x.Barcode).Select(x => x.Key).ToList();
+
+                Dt_StockInfo? stockInfo = _stockService.StockInfoService.GetStockByPalletCode(materielGroupDTO.PalletCode);
+
+
+
+                (bool, string, object?) result = CheckMaterielGroupParam(materielGroupDTO, materielCodes, stockInfo);
+                if (!result.Item1) return content = WebResponseContent.Instance.Error(result.Item2);
+
+                if (stockInfo == null)
+                {
+                    stockInfo = new Dt_StockInfo() { PalletType = (int)PalletTypeEnum.None, LocationType = materielGroupDTO.locationType.ObjToInt() };
+                    stockInfo.Details = new List<Dt_StockInfoDetail>();
+                }
+                var inboindId = 0; Dt_InboundOrder dt_InboundOrder = null;
+                var dbinbound = _inboundOrderRepository.QueryData(x => x.InboundOrderNo == dbinboundOrderDetails.First().OrderNo).First();
+                if (dbinbound == null)
+                {
+                    dt_InboundOrder = new Dt_InboundOrder
+                    {
+                        WarehouseId = 0,
+                        InboundOrderNo = dbinboundOrderDetails.First()?.OrderNo,
+                        UpperOrderNo = dbinboundOrderDetails.First()?.OrderNo,
+                        SupplierId = dbinboundOrderDetails.First()?.SupplyCode,
+                        OrderType = materielGroupDTO.orderTypes,
+
+                        BusinessType = materielGroupDTO.orderTypes.ToString(),
+
+                        FactoryArea = dbinboundOrderDetails.First()?.FactoryArea,
+                        Remark = "",
+                        Details = new List<Dt_InboundOrderDetail>()
+                    };
+                    inboindId = _inboundOrderRepository.AddData(dt_InboundOrder);
+                }
+                else
+                {
+                    dt_InboundOrder = new Dt_InboundOrder { Details = new List<Dt_InboundOrderDetail>() };
+                    inboindId = dbinbound.Id;
+                }
+
+                foreach (var item in dbinboundOrderDetails)
+                {
+                    stockInfo.Details.Add(new Dt_StockInfoDetail
+                    {
+                        StockId = stockInfo == null ? 0 : stockInfo.Id,
+                        Barcode = item.Barcode,
+                        MaterielCode = item.MaterielCode,
+                        BatchNo = item.BatchNo,
+                        Unit = item.BarcodeUnit,
+                        InboundOrderRowNo = item.lineNo,
+                        SupplyCode = item.SupplyCode,
+                        WarehouseCode = materielGroupDTO.WarehouseType,
+                        StockQuantity = item.PickQuantity,
+                        BarcodeQty = item.BarcodeQty,
+                        BarcodeUnit = item.BarcodeUnit,
+                        FactoryArea = item.FactoryArea,
+                        Status = 0,
+                        OrderNo = item.OrderNo,
+                        BusinessType = InOrderTypeEnum.InternalAllocat.ObjToInt().ToString()
+
+                    });
+                    item.WarehouseCode = item.WarehouseCode;
+
+                    dt_InboundOrder.Details.Add(new Dt_InboundOrderDetail
+                    {
+                        OrderId = inboindId,
+                        MaterielCode = item.MaterielCode,
+                        MaterielName = "",
+                        BatchNo = item.BatchNo,
+                        OrderQuantity = item.PickQuantity,
+                        ReceiptQuantity = 0,
+                        OverInQuantity = 0,
+                        Unit = item.BarcodeUnit,
+                        RowNo = 0,
+                        lineNo = item.lineNo,
+                        SupplyCode = item.SupplyCode,
+                        WarehouseCode = item.WarehouseCode,
+                        Barcode = item.Barcode,
+                        OutBoxbarcodes = "",
+                        BarcodeQty = (decimal)item.BarcodeQty,
+                        BarcodeUnit = item.BarcodeUnit
+                    });
+                }
+
+                _inboundOrderDetailService.Db.Insertable<Dt_InboundOrderDetail>(dt_InboundOrder.Details);
+                if (stockInfo.Id == 0)
+                {
+                    stockInfo.PalletCode = materielGroupDTO.PalletCode;
+                    stockInfo.StockStatus = StockStatusEmun.缁勭洏鏆傚瓨.ObjToInt();
+                }
+                stockInfo.PalletType = (int)PalletTypeEnum.None;
+
+                List<int> updateDetailIds = dbinboundOrderDetails.Select(x => x.Id).ToList();
+
+                try
+                {
+                    _unitOfWorkManage.BeginTran();
+
+                    _stockService.StockInfoService.AddMaterielGroup(stockInfo);
+                    _unitOfWorkManage.CommitTran();
+                    return WebResponseContent.Instance.OK();
+                }
+                catch (Exception ex)
+                {
+                    _unitOfWorkManage.RollbackTran();
+                    return WebResponseContent.Instance.Error(ex.Message);
+                }
+            }
+            catch (Exception ex)
+            {
+                content = WebResponseContent.Instance.Error(ex.Message);
+            }
+            finally
+            {
+
+            }
+            return content;
+
+        }
+
+
+        public (bool, string, object?) CheckMaterielGroupParam(BarcodeMaterielGroupDTO materielGroupDTO, List<string> barcodeCodes, Dt_StockInfo stockInfo)
+        {
+            (bool, string, object?) result = ModelValidate.ValidateModelData(materielGroupDTO);
+            if (!result.Item1) return result;
+
+            if (_taskRepository.QueryFirst(x => x.PalletCode == materielGroupDTO.PalletCode) != null)
+            {
+                return (false, "璇ユ墭鐩樺彿宸叉湁浠诲姟", materielGroupDTO);
+            }
+
+            if (stockInfo != null && !string.IsNullOrEmpty(stockInfo.LocationCode) && stockInfo.StockStatus != StockStatusEmun.缁勭洏鏆傚瓨.ObjToInt())
+            {
+                return (false, "宸蹭笂鏋剁殑鎵樼洏涓嶈兘鍐嶆缁勭洏", materielGroupDTO);
+            }
+
+            if (_stockService.StockInfoDetailService.ExistBarcodes(barcodeCodes))
+            {
+                return (false, $"{barcodeCodes[0]} 鏉$爜鍦ㄥ簱瀛樹腑宸插瓨鍦�", materielGroupDTO);
+            }
+
+
+
+            return (true, "鎴愬姛", materielGroupDTO);
+        }
+
+
+        #endregion
+    }
+
+
+
+    #region 鏀寔绫诲畾涔�
+
+    public class ValidationResult<T>
+    {
+        public bool IsValid { get; set; }
+        public T Data { get; set; }
+        public string ErrorMessage { get; set; }
+
+        public static ValidationResult<T> Success(T data)
+        {
+            return new ValidationResult<T>
+            {
+                IsValid = true,
+                Data = data
+            };
+        }
+
+        public static ValidationResult<T> Error(string message)
+        {
+            return new ValidationResult<T>
+            {
+                IsValid = false,
+                ErrorMessage = message
+            };
         }
     }
 
-
-    #region 杩斿洖
-    /// <summary>
-    /// 鎷嗗寘閾鹃」
-    /// </summary>
-    public class SplitChainItem
+    public class PickingResult
     {
-        public Dt_SplitPackageRecord SplitRecord { get; set; }
-        public string OriginalBarcode { get; set; }
-        public string NewBarcode { get; set; }
-        public decimal SplitQuantity { get; set; }
+        public Dt_OutStockLockInfo FinalLockInfo { get; set; }
+        public string FinalBarcode { get; set; }
+        public int FinalStockId { get; set; }
+        public decimal ActualPickedQty { get; set; }
+        public List<SplitResult> SplitResults { get; set; } = new List<SplitResult>();
     }
-    public  class ReturnAnalysisResult
+
+    public class ReturnAnalysisResult
     {
         public bool HasItemsToReturn { get; set; }
         public bool HasRemainingLocks { get; set; }
@@ -1997,7 +3160,64 @@
         public List<Dt_StockInfoDetail> PalletStockGoods { get; set; } = new List<Dt_StockInfoDetail>();
         public List<Dt_SplitPackageRecord> SplitRecords { get; set; } = new List<Dt_SplitPackageRecord>();
     }
+    public class PalletStatusAnalysis
+    {
+        public string OrderNo { get; set; }
+        public string PalletCode { get; set; }
+        public int StockId { get; set; }
 
+        // 鍥炲簱鐩稿叧灞炴��
+        public bool HasItemsToReturn { get; set; }
+        public bool HasRemainingLocks { get; set; }
+        public bool HasPalletStockGoods { get; set; }
+        public bool HasSplitRecords { get; set; }
+        public decimal RemainingLocksReturnQty { get; set; }
+        public decimal PalletStockReturnQty { get; set; }
+
+        public decimal SplitReturnQty { get; set; }
+        public decimal TotalReturnQty { get; set; }
+
+        // 鏈垎閰嶇殑閿佸畾璁板綍锛堝鑷姩鎷嗗寘浜х敓鐨勶級
+        public bool HasUnallocatedLocks { get; set; }
+        public List<Dt_OutStockLockInfo> UnallocatedLocks { get; set; } = new List<Dt_OutStockLockInfo>();
+        public decimal UnallocatedLocksReturnQty { get; set; }
+
+        public List<Dt_OutStockLockInfo> RemainingLocks { get; set; } = new List<Dt_OutStockLockInfo>();
+        public List<Dt_StockInfoDetail> PalletStockGoods { get; set; } = new List<Dt_StockInfoDetail>();
+        public List<Dt_SplitPackageRecord> SplitRecords { get; set; } = new List<Dt_SplitPackageRecord>();
+
+        public List<string> AllBarcodes { get; set; } = new List<string>();
+        // 绌烘墭鐩樼浉鍏冲睘鎬�
+        public bool IsEmptyPallet { get; set; }
+        public bool HasActiveTasks { get; set; }
+
+        // 渚垮埄鏂规硶
+        public bool CanReturn => HasItemsToReturn && !HasActiveTasks;
+        public bool CanRemove => IsEmptyPallet && !HasActiveTasks;
+    }
+    public class PickingContext
+    {
+        public string OrderNo { get; set; }
+        public string PalletCode { get; set; }
+        public string Barcode { get; set; }
+        public string Operator { get; set; }
+        public Dt_OutStockLockInfo LockInfo { get; set; }
+        public Dt_OutboundOrderDetail OrderDetail { get; set; }
+        public Dt_StockInfoDetail StockDetail { get; set; }
+        public decimal ActualQuantity { get; set; }
+        public string AdjustedReason { get; set; }
+    }
+    public class CancelPickingContext
+    {
+        public string OrderNo { get; set; }
+        public string PalletCode { get; set; }
+        public string Barcode { get; set; }
+        public string Operator { get; set; }
+
+        public decimal CancelQuantity { get; set; }
+        public Dt_PickingRecord PickingRecord { get; set; }
+        public Dt_OutStockLockInfo LockInfo { get; set; }
+        public Dt_OutboundOrderDetail OrderDetail { get; set; }
+    }
     #endregion
-
 }

--
Gitblit v1.9.3