From b4dfb1c5a0a3e6a682a98483e80ff372086aee8d Mon Sep 17 00:00:00 2001
From: heshaofeng <heshaofeng@hnkhzn.com>
Date: 星期三, 03 十二月 2025 10:04:31 +0800
Subject: [PATCH] Merge branch 'master' of http://115.159.85.185:8098/r/ZhongRui/ALDbanyunxiangmu

---
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService_Outbound.cs |  486 ++++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 397 insertions(+), 89 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_TaskInfoService/TaskService_Outbound.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_TaskInfoService/TaskService_Outbound.cs"
index d479cef..db099ac 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_TaskInfoService/TaskService_Outbound.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_TaskInfoService/TaskService_Outbound.cs"
@@ -6,6 +6,7 @@
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using WIDESEA_BasicService;
 using WIDESEA_Common.CommonEnum;
 using WIDESEA_Common.LocationEnum;
 using WIDESEA_Common.OrderEnum;
@@ -17,6 +18,9 @@
 using WIDESEA_DTO.Basic;
 using WIDESEA_DTO.Stock;
 using WIDESEA_Model.Models;
+using WIDESEA_Model.Models.Basic;
+using WIDESEA_Model.Models.Check;
+using WIDESEA_Model.Models.Outbound;
 
 namespace WIDESEA_TaskInfoService
 {
@@ -27,95 +31,83 @@
         /// </summary>
         /// <param name="inTask"></param>
         /// <returns></returns>
-        public async Task<WebResponseContent> PalletOutboundTask(string endStation, string palletCode = "")
+        public async Task<WebResponseContent> PalletOutboundTask(int num, int locationType)
         {
+            WebResponseContent content = new WebResponseContent();
             try
             {
-                Dt_StockInfo stockInfo;
-                if (string.IsNullOrEmpty(palletCode))
-                {
-                    stockInfo = _stockRepository.Db.Queryable<Dt_StockInfo>().Where(x => x.PalletType == PalletTypeEnum.Empty.ObjToInt() && x.StockStatus == StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt() && !string.IsNullOrWhiteSpace(x.LocationCode)).First();
-                }
-                else
-                {
-                    stockInfo = _stockRepository.Db.Queryable<Dt_StockInfo>().Where(x => x.PalletType == PalletTypeEnum.Empty.ObjToInt() && x.PalletCode == palletCode && x.StockStatus == StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt()).First();
-                }
+                var stockInfos = _stockRepository.Db.Queryable<Dt_StockInfo>().Where(x => x.PalletType == PalletTypeEnum.Empty.ObjToInt() && x.StockStatus == StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt()).WhereIF(locationType != 0, x => x.LocationType == locationType).Take(num).ToList();
 
-                if (stockInfo == null)
+                if (stockInfos.Count() == 0)
                 {
                     return WebResponseContent.Instance.Error("鏈壘鍒扮┖鎵樼洏搴撳瓨");
                 }
-                Dt_LocationInfo locationInfo = _locationInfoService.Repository.QueryFirst(x => x.LocationCode == stockInfo.LocationCode);
-                if (locationInfo == null)
+                foreach (var stockInfo in stockInfos)
                 {
-                    return WebResponseContent.Instance.Error("鏈壘鍒扮┖鎵樼洏搴撳瓨瀵瑰簲鐨勮揣浣嶄俊鎭�");
-                }
-
-                Dt_Task task = new Dt_Task()
-                {
-                    CurrentAddress = stockInfo.LocationCode,
-                    Grade = 0,
-                    NextAddress = endStation,
-                    PalletCode = stockInfo.PalletCode,
-                    Roadway = locationInfo.RoadwayNo,
-                    SourceAddress = stockInfo.LocationCode,
-                    TargetAddress = endStation,
-                    TaskStatus = TaskStatusEnum.New.ObjToInt(),
-                    TaskType = TaskTypeEnum.OutEmpty.ObjToInt(),
-                    WarehouseId = stockInfo.WarehouseId,
-                    PalletType = stockInfo.PalletType
-
-                };
-                int beforeStatus = locationInfo.LocationStatus;
-                _unitOfWorkManage.BeginTran();
-                stockInfo.StockStatus = StockStatusEmun.鍑哄簱閿佸畾.ObjToInt();
-                locationInfo.LocationStatus = LocationStatusEnum.Lock.ObjToInt();
-
-                int taskId = BaseDal.AddData(task);
-                task.TaskId = taskId;
-
-                _stockService.StockInfoService.UpdateData(stockInfo);
-
-                _locationInfoService.UpdateData(locationInfo);
-
-                _recordService.LocationStatusChangeRecordSetvice.AddLocationStatusChangeRecord(locationInfo, beforeStatus, StockChangeType.Outbound.ObjToInt(), "", task.TaskNum);
-
-                _unitOfWorkManage.CommitTran();
-
-                TaskModel esstask = new TaskModel()
-                {
-                    taskType = "carry",
-                    taskGroupCode = "",
-                    groupPriority = 0,
-                    tasks = new List<TasksType>
+                    Dt_LocationInfo locationInfo = _locationInfoService.Repository.QueryFirst(x => x.LocationCode == stockInfo.LocationCode);
+                    if (locationInfo == null)
                     {
-                            new()
-                            {
-                                taskCode=task.TaskNum.ToString(),
-                                taskPriority=0,
-                                taskDescribe=new TaskDescribeType{
-                                containerCode=stockInfo.PalletCode,
-                                containerType= "CT_KUBOT_STANDARD",
-                                fromLocationCode=stockInfo.LocationCode??"",
-                                toStationCode="",
-                                toLocationCode=endStation,
-                                deadline=0,storageTag=""
-                                }
-                            }
+                        return WebResponseContent.Instance.Error("鏈壘鍒扮┖鎵樼洏搴撳瓨瀵瑰簲鐨勮揣浣嶄俊鎭�");
                     }
-                };
-                var result = await _eSSApiService.CreateTaskAsync(esstask);
 
-                _logger.LogInformation("鍒涘缓浠诲姟PalletOutboundTask 杩斿洖:  " + result);
-                if (result)
-                {
-                    return WebResponseContent.Instance.OK(200);
-                }
-                else
-                {
-                    return WebResponseContent.Instance.Error("涓嬪彂鏈哄櫒浜轰换鍔″け璐ワ紒");
-                }
+                    Dt_Task task = new Dt_Task()
+                    {
+                        CurrentAddress = stockInfo.LocationCode,
+                        Grade = 0,
+                        NextAddress = "1-2",
+                        PalletCode = stockInfo.PalletCode,
+                        Roadway = locationInfo.RoadwayNo,
+                        SourceAddress = stockInfo.LocationCode,
+                        TargetAddress = "1-2",
+                        TaskStatus = TaskStatusEnum.New.ObjToInt(),
+                        TaskType = TaskTypeEnum.OutEmpty.ObjToInt(),
+                        WarehouseId = stockInfo.WarehouseId,
+                        PalletType = stockInfo.PalletType
 
+                    };
+                    int beforeStatus = locationInfo.LocationStatus;
+                    _unitOfWorkManage.BeginTran();
+                    stockInfo.StockStatus = StockStatusEmun.鍑哄簱閿佸畾.ObjToInt();
+                    locationInfo.LocationStatus = LocationStatusEnum.Lock.ObjToInt();
+
+                    int taskId = BaseDal.AddData(task);
+                    task.TaskId = taskId;
+
+                    _stockService.StockInfoService.UpdateData(stockInfo);
+
+                    _locationInfoService.UpdateData(locationInfo);
+
+                    _recordService.LocationStatusChangeRecordSetvice.AddLocationStatusChangeRecord(locationInfo, beforeStatus, StockChangeType.Outbound.ObjToInt(), "", task.TaskNum);
+
+                    _unitOfWorkManage.CommitTran();
+
+                    TaskModel esstask = new TaskModel()
+                    {
+                        taskType = "carry",
+                        taskGroupCode = "",
+                        groupPriority = 0,
+                        tasks = new List<TasksType>
+                        {
+                                new()
+                                {
+                                    taskCode=task.TaskNum.ToString(),
+                                    taskPriority=0,
+                                    taskDescribe=new TaskDescribeType{
+                                    containerCode=stockInfo.PalletCode,
+                                    containerType= "CT_KUBOT_STANDARD",
+                                    fromLocationCode=stockInfo.LocationCode??"",
+                                    toStationCode="",
+                                    toLocationCode="1-2",
+                                    deadline=0,storageTag=""
+                                    }
+                                }
+                        }
+                    };
+                    var result = await _eSSApiService.CreateTaskAsync(esstask);
+
+                    _logger.LogInformation("鍒涘缓浠诲姟PalletOutboundTask 杩斿洖:  " + result);
+                }
+                return content.OK("绌烘墭鍑哄簱鎴愬姛!");
             }
             catch (Exception ex)
             {
@@ -140,14 +132,22 @@
             {
                 throw new Exception("鏈壘鍒板嚭搴撳崟鏄庣粏淇℃伅");
             }
-            if (outboundOrderDetails.FirstOrDefault(x => x.OrderDetailStatus > OrderDetailStatusEnum.New.ObjToInt() && x.OrderDetailStatus != OrderDetailStatusEnum.AssignOverPartial.ObjToInt()) != null)
+            //if (outboundOrderDetails.FirstOrDefault(x => x.OrderDetailStatus > OrderDetailStatusEnum.New.ObjToInt() && x.OrderDetailStatus != OrderDetailStatusEnum.AssignOverPartial.ObjToInt()) != null)
+            //{
+            //    throw new Exception("鎵�閫夊嚭搴撳崟鏄庣粏瀛樺湪鍑哄簱涓垨宸插畬鎴�");
+            //}
+
+            if (outboundOrderDetails.FirstOrDefault(x => x.OrderDetailStatus > OrderDetailStatusEnum.Outbound.ObjToInt() && x.OrderDetailStatus != OrderDetailStatusEnum.AssignOverPartial.ObjToInt()) != null)
             {
-                throw new Exception("鎵�閫夊嚭搴撳崟鏄庣粏瀛樺湪鍑哄簱涓垨宸插畬鎴�");
+                throw new Exception("鎵�閫夊嚭搴撳崟鏄庣粏瀛樺湪宸插畬鎴愮姸鎬侊紝鏃犳硶閲嶆柊鍒嗛厤");
             }
+
             List<Dt_StockInfo>? stockInfos = null;
             List<Dt_OutboundOrderDetail>? orderDetails = null;
             List<Dt_OutStockLockInfo>? outStockLockInfos = null;
             List<Dt_LocationInfo>? locationInfos = null;
+
+            CleanupPreviousInvalidLocks(outboundOrderDetails);
 
             (List<Dt_StockInfo>, List<Dt_OutboundOrderDetail>, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>) result = _outboundOrderDetailService.AssignStockOutbound(outboundOrderDetails);
             if (result.Item1 != null && result.Item1.Count > 0)
@@ -185,7 +185,31 @@
             }
             return (tasks, stockInfos, orderDetails, outStockLockInfos, locationInfos);
         }
+        /// <summary>
+        /// 娓呯悊涔嬪墠鐨勬棤鏁堥攣瀹氳褰�
+        /// </summary>
+        private void CleanupPreviousInvalidLocks(List<Dt_OutboundOrderDetail> orderDetails)
+        {
+            var orderIds = orderDetails.Select(x => x.OrderId).Distinct().ToList();
+            var orderNos = _outboundOrderService.Db.Queryable<Dt_OutboundOrder>()
+                .Where(x => orderIds.Contains(x.Id))
+                .Select(x => x.OrderNo)
+                .ToList();
 
+            // 娓呯悊鐘舵�佷负"宸查噴鏀�"鎴�"鍥炲簱涓�"鐨勬棫閿佸畾璁板綍
+            foreach (var orderNo in orderNos)
+            {
+                _outStockLockInfoService.Db.Updateable<Dt_OutStockLockInfo>()
+                     .SetColumns(x => new Dt_OutStockLockInfo
+                     {
+                         Status = (int)OutLockStockStatusEnum.宸查噴鏀�
+                     })
+                     .Where(x => x.OrderNo == orderNo &&
+                                (x.Status == (int)OutLockStockStatusEnum.鍥炲簱涓� ||
+                                 x.Status == (int)OutLockStockStatusEnum.宸查噴鏀�))
+                     .ExecuteCommand();
+            }
+        }
 
         /// <summary>
         /// 鐢熸垚鍑哄簱浠诲姟鍚庢暟鎹洿鏂板埌鏁版嵁搴�
@@ -222,7 +246,7 @@
                     {
                         outboundOrder.OrderStatus = OutOrderStatusEnum.鍑哄簱涓�.ObjToInt();
                     }
-                    outboundOrder.Operator = App.User.UserName;                
+                    outboundOrder.Operator = App.User.UserName;
                     _outboundOrderService.Repository.UpdateData(outboundOrder);
                     WebResponseContent content = _outboundOrderDetailService.LockOutboundStockDataUpdate(stockInfos, outboundOrderDetails, outStockLockInfos, locationInfos, tasks: tasks);
 
@@ -441,20 +465,70 @@
             }
         }
 
+        /// <summary>
+        /// 鏅轰粨璋冩櫤浠�
+        /// </summary>
+        /// <param name="orderDetailId"></param>
+        /// <param name="stockSelectViews"></param>
+        /// <param name="station"></param>
+        /// <returns></returns>
+        public async Task<WebResponseContent> GenerateAllocatOutboundTask(int orderDetailId, List<StockSelectViewDTO> stockSelectViews, string station = null)
+        {
+            try
+            {
+                var allocorder = _allocateOrderRepository.Db.Queryable<Dt_AllocateOrder>().Includes(x => x.Details).Where(x => x.Details.Any(o => o.Id == orderDetailId)).First();
+                //var allocorder = _allocateOrderDetailRepository.Db.Queryable<Dt_AllocateOrderDetail>()
+                //               .LeftJoin<Dt_AllocateOrder>((detail, order) => detail.OrderId == order.Id)
+                //               .Where((detail, order) => order.Id == orderDetailId)
+                //               .Select((detail, order) => order)
+                //               .First();
+                if (allocorder == null)
+                {
+                    return WebResponseContent.Instance.Error("鎵句笉鍒板崟鎹�");
+                }
+                var outboundOrder = _outboundOrderService.Db.Queryable<Dt_OutboundOrder>().Includes(x => x.Details).First(x => x.OrderNo == allocorder.OrderNo);
+                if (outboundOrder == null)
+                {
+                    return WebResponseContent.Instance.Error("鎵句笉鍒板嚭搴撳崟鎹�");
+                }
+        
+                var orderdetail = outboundOrder.Details.Where(outItem => allocorder.Details .Any(allocItem => allocItem.MaterielCode == outItem.MaterielCode  && allocItem.LineNo == outItem.lineNo 
+                 && allocItem.BarcodeQty==outItem.BarcodeQty && allocItem.WarehouseCode==outItem.WarehouseCode && allocItem.BarcodeUnit==outItem.BarcodeUnit) ) .First();
+                if (orderdetail == null)
+                {
+                    return WebResponseContent.Instance.Error("鎵句笉鍒板嚭搴撴槑缁嗗崟鎹�");
+                }
 
+                (List<Dt_Task>, List<Dt_StockInfo>?, List<Dt_OutboundOrderDetail>?, List<Dt_OutStockLockInfo>?, List<Dt_LocationInfo>?) result = OutboundTaskDataHandle(outboundOrder.Details.First().Id, stockSelectViews,station);
+
+                WebResponseContent content =await GenerateOutboundTaskDataUpdate(result.Item1, result.Item2, result.Item3, result.Item4, result.Item5);
+
+                return content;
+            }
+            catch (Exception ex)
+            {
+                return WebResponseContent.Instance.Error(ex.Message);
+            }
+        }
         /// <summary>
         /// 鐢熸垚鍑哄簱浠诲姟
         /// </summary>
         /// <param name="orderDetailId"></param>
         /// <param name="stockSelectViews"></param>
         /// <returns></returns>
-        public WebResponseContent GenerateOutboundTask(int orderDetailId, List<StockSelectViewDTO> stockSelectViews)
+        public async Task<WebResponseContent> GenerateOutboundTask(int orderDetailId, List<StockSelectViewDTO> stockSelectViews,string station=null)
         {
             try
             {
-                (List<Dt_Task>, List<Dt_StockInfo>?, List<Dt_OutboundOrderDetail>?, List<Dt_OutStockLockInfo>?, List<Dt_LocationInfo>?) result = OutboundTaskDataHandle(orderDetailId, stockSelectViews);
+                var orderNo = _reCheckOrderRepository.Db.Queryable<Dt_ReCheckOrder>().First(x => x.Id == orderDetailId)?.OrderNo;
+                var outboundOrder = _outboundOrderService.Db.Queryable<Dt_OutboundOrder>().Includes(x => x.Details).First(x => x.UpperOrderNo == orderNo);
+                if (outboundOrder == null)
+                {
+                    return WebResponseContent.Instance.Error("鎵句笉鍒板崟鎹�");
+                }
+                (List<Dt_Task>, List<Dt_StockInfo>?, List<Dt_OutboundOrderDetail>?, List<Dt_OutStockLockInfo>?, List<Dt_LocationInfo>?) result = OutboundTaskDataHandle(outboundOrder.Details.First().Id, stockSelectViews,station);
 
-                WebResponseContent content = GenerateOutboundTaskDataUpdate(result.Item1, result.Item2, result.Item3, result.Item4, result.Item5);
+                WebResponseContent content =await GenerateOutboundTaskDataUpdate(result.Item1, result.Item2, result.Item3, result.Item4, result.Item5);
 
                 return content;
             }
@@ -471,7 +545,7 @@
         /// <param name="stockSelectViews"></param>
         /// <returns></returns>
         /// <exception cref="Exception"></exception>
-        public (List<Dt_Task>, List<Dt_StockInfo>?, List<Dt_OutboundOrderDetail>?, List<Dt_OutStockLockInfo>?, List<Dt_LocationInfo>?) OutboundTaskDataHandle(int orderDetailId, List<StockSelectViewDTO> stockSelectViews)
+        public (List<Dt_Task>, List<Dt_StockInfo>?, List<Dt_OutboundOrderDetail>?, List<Dt_OutStockLockInfo>?, List<Dt_LocationInfo>?) OutboundTaskDataHandle(int orderDetailId, List<StockSelectViewDTO> stockSelectViews,string station=null)
         {
             List<Dt_Task> tasks = new List<Dt_Task>();
             Dt_OutboundOrderDetail outboundOrderDetail = _outboundOrderDetailService.Repository.QueryFirst(x => x.Id == orderDetailId);
@@ -494,15 +568,15 @@
                 (List<Dt_StockInfo>, Dt_OutboundOrderDetail, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>) result = _outboundOrderDetailService.AssignStockOutbound(outboundOrderDetail, stockSelectViews);
                 if (result.Item1 != null && result.Item1.Count > 0)
                 {
-                    Dt_OutboundOrder outboundOrder = _outboundOrderService.Repository.QueryFirst(x => x.Id == outboundOrderDetail.OrderId);
+                    Dt_OutboundOrder outboundOrder = _outboundOrderService.Repository.QueryFirst(x => x.Id == outboundOrderDetail.OrderId);                    
                     TaskTypeEnum typeEnum = outboundOrder.OrderType switch
                     {
                         (int)OutOrderTypeEnum.Issue => TaskTypeEnum.Outbound,
                         (int)OutOrderTypeEnum.Allocate => TaskTypeEnum.OutAllocate,
                         (int)OutOrderTypeEnum.Quality => TaskTypeEnum.OutQuality,
-                        _ => new TaskTypeEnum()
+                        _ => TaskTypeEnum.Outbound
                     };
-                    tasks = GetTasks(result.Item1, typeEnum);
+                    tasks = GetTasks(result.Item1, typeEnum,station);
                     result.Item2.OrderDetailStatus = OrderDetailStatusEnum.Outbound.ObjToInt();
                     result.Item3.ForEach(x =>
                     {
@@ -541,7 +615,7 @@
         /// <param name="outStockLockInfos"></param>
         /// <param name="locationInfos"></param>
         /// <returns></returns>
-        public WebResponseContent GenerateOutboundTaskDataUpdate(List<Dt_Task> tasks, List<Dt_StockInfo>? stockInfos = null, List<Dt_OutboundOrderDetail>? outboundOrderDetails = null, List<Dt_OutStockLockInfo>? outStockLockInfos = null, List<Dt_LocationInfo>? locationInfos = null)
+        public async Task< WebResponseContent> GenerateOutboundTaskDataUpdate(List<Dt_Task> tasks, List<Dt_StockInfo>? stockInfos = null, List<Dt_OutboundOrderDetail>? outboundOrderDetails = null, List<Dt_OutStockLockInfo>? outStockLockInfos = null, List<Dt_LocationInfo>? locationInfos = null)
         {
             try
             {
@@ -586,7 +660,46 @@
                 }
                 _unitOfWorkManage.CommitTran();
                 //PushTasksToWCS(tasks);
-                return WebResponseContent.Instance.OK();
+                TaskModel esstask = new TaskModel()
+                {
+                    taskType = "carry",
+                    taskGroupCode = "",
+                    groupPriority = 0,
+                    tasks = new List<TasksType>()
+                };
+
+                foreach (var task in tasks)
+                {
+                    esstask.
+                       tasks.Add(new TasksType
+                       {
+                           taskCode = task.TaskNum.ToString(),
+                           taskPriority = 0,
+                           taskDescribe = new TaskDescribeType
+                           {
+                               containerCode = task.PalletCode,
+                               containerType = "CT_KUBOT_STANDARD",
+                               fromLocationCode = task.SourceAddress ?? "",
+                               toStationCode = "",
+                               toLocationCode = task.TargetAddress,
+                               deadline = 0,
+                               storageTag = ""
+                           }
+                       }
+                   );
+                }
+                var result = await _eSSApiService.CreateTaskAsync(esstask);
+
+                _logger.LogInformation("鍒涘缓浠诲姟PalletOutboundTask 杩斿洖:  " + result);
+                if (result)
+                {
+                    return WebResponseContent.Instance.OK();
+                }
+                else
+                {
+                    return WebResponseContent.Instance.Error("涓嬪彂鏈哄櫒浜轰换鍔″け璐ワ紒");
+                }
+               
             }
             catch (Exception ex)
             {
@@ -596,5 +709,200 @@
 
         }
 
+
+        #region 鍒嗘壒鍒嗛厤搴撳瓨
+
+        /// <summary>
+        /// 鍒嗘壒鍒嗛厤搴撳瓨
+        /// </summary>
+        public async Task<WebResponseContent> GenerateOutboundBatchTasksAsync(int orderDetailId, decimal batchQuantity, string outStation)
+        {
+            try
+            {
+                List<Dt_Task> tasks = new List<Dt_Task>();
+                List<Dt_StockInfo> stockInfos = new List<Dt_StockInfo>();
+                List<Dt_OutboundOrderDetail> outboundOrderDetails = new List<Dt_OutboundOrderDetail>();
+                List<Dt_OutStockLockInfo> outStockLockInfos = new List<Dt_OutStockLockInfo>();
+                List<Dt_LocationInfo> locationInfos = new List<Dt_LocationInfo>();
+
+                (List<Dt_Task>, List<Dt_StockInfo>?, List<Dt_OutboundOrderDetail>?, List<Dt_OutStockLockInfo>?, List<Dt_LocationInfo>?) result = await BatchAllocateStockDataHandle(orderDetailId, batchQuantity, outStation);
+
+                if (result.Item2 != null && result.Item2.Count > 0)
+                {
+                    stockInfos.AddRange(result.Item2);
+                }
+                if (result.Item3 != null && result.Item3.Count > 0)
+                {
+                    outboundOrderDetails.AddRange(result.Item3);
+                }
+                if (result.Item4 != null && result.Item4.Count > 0)
+                {
+                    outStockLockInfos.AddRange(result.Item4);
+                }
+                if (result.Item5 != null && result.Item5.Count > 0)
+                {
+                    locationInfos.AddRange(result.Item5);
+                }
+                if (result.Item1 != null && result.Item1.Count > 0)
+                {
+                    tasks.AddRange(result.Item1);
+                }
+
+                WebResponseContent content = await GenerateOutboundTaskDataUpdateAsync(tasks, stockInfos, outboundOrderDetails, outStockLockInfos, locationInfos);
+                return content;
+            }
+            catch (Exception ex)
+            {
+                _unitOfWorkManage.RollbackTran();
+                _logger.LogError($"鍒嗘壒鍒嗛厤搴撳瓨澶辫触 -  OrderDetailId: {orderDetailId}, Quantity: {batchQuantity}, Error: {ex.Message}");
+                return WebResponseContent.Instance.Error($"鍒嗘壒鍒嗛厤澶辫触锛歿ex.Message}");
+            }
+        }
+
+        /// <summary>
+        /// 鍒嗘壒鍒嗛厤搴撳瓨鏁版嵁澶勭悊
+        /// </summary>
+        public async Task<(List<Dt_Task>, List<Dt_StockInfo>?, List<Dt_OutboundOrderDetail>?, List<Dt_OutStockLockInfo>?, List<Dt_LocationInfo>?)>
+            BatchAllocateStockDataHandle(int orderDetailId, decimal batchQuantity, string outStation)
+        {
+            List<Dt_Task> tasks = new List<Dt_Task>();
+
+            // 鑾峰彇璁㈠崟鏄庣粏
+            var outboundOrderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>()
+                .FirstAsync(x => x.Id == orderDetailId);
+
+            if (outboundOrderDetail == null)
+            {
+                throw new Exception("鏈壘鍒板嚭搴撳崟鏄庣粏淇℃伅");
+            }
+            var outboundOrder = await _outboundOrderService.Db.Queryable<Dt_OutboundOrder>().FirstAsync(x => x.Id == outboundOrderDetail.OrderId);
+            if (outboundOrder == null)
+            {
+                throw new Exception("鏈壘鍒板嚭搴撳崟淇℃伅");
+            }
+            // 楠岃瘉璁㈠崟鏄庣粏鐘舵��
+            if (outboundOrderDetail.OrderDetailStatus > OrderDetailStatusEnum.Outbound.ObjToInt() &&
+                outboundOrderDetail.OrderDetailStatus != OrderDetailStatusEnum.AssignOverPartial.ObjToInt())
+            {
+                throw new Exception("鎵�閫夊嚭搴撳崟鏄庣粏瀛樺湪鍑哄簱涓垨宸插畬鎴�");
+            }
+
+            // 楠岃瘉鍒嗛厤鏁伴噺
+            decimal allocatedQty = outboundOrderDetail.AllocatedQuantity;
+            decimal overOutQty = outboundOrderDetail.OverOutQuantity;
+            decimal needOutQty = outboundOrderDetail.NeedOutQuantity;
+            decimal availableQty = needOutQty - allocatedQty - overOutQty;
+
+            if (availableQty <= 0)
+                throw new Exception("鏃犲彲鍒嗛厤鏁伴噺");
+
+            if (batchQuantity > availableQty)
+                throw new Exception($"鍒嗛厤鏁伴噺涓嶈兘瓒呰繃鍙垎閰嶆暟閲弡availableQty}");
+
+            List<Dt_StockInfo>? stockInfos = null;
+            List<Dt_OutboundOrderDetail>? orderDetails = null;
+            List<Dt_OutStockLockInfo>? outStockLockInfos = null;
+            List<Dt_LocationInfo>? locationInfos = null;
+
+            // 鐢熸垚鎵规鍙�
+            string batchNo = await GenerateBatchNo();
+
+            // 鍒嗛厤搴撳瓨
+            (List<Dt_StockInfo>, List<Dt_OutboundOrderDetail>, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>) allocateResult =
+                await _outboundOrderDetailService.AssignStockForBatch(outboundOrderDetail, batchQuantity, batchNo);
+
+            if (allocateResult.Item1 != null && allocateResult.Item1.Count > 0)
+            {
+                // 鍒涘缓鍒嗘壒璁板綍
+                await CreateBatchRecord(outboundOrder.OrderNo, orderDetailId, batchQuantity, batchNo);
+
+                TaskTypeEnum typeEnum = outboundOrder.OrderType switch
+                {
+                    (int)OutOrderTypeEnum.Issue => TaskTypeEnum.Outbound,
+                    (int)OutOrderTypeEnum.Allocate => TaskTypeEnum.OutAllocate,
+                    (int)OutOrderTypeEnum.Quality => TaskTypeEnum.OutQuality,
+                    _ => TaskTypeEnum.Outbound
+                };
+
+                tasks = GetTasks(allocateResult.Item1, typeEnum, outStation);
+                tasks.ForEach(x =>
+                {
+                    x.OrderNo = outboundOrder.OrderNo;
+                });
+
+                allocateResult.Item2.ForEach(x =>
+                {
+                    x.OrderDetailStatus = OrderDetailStatusEnum.Outbound.ObjToInt();
+                });
+
+                allocateResult.Item3.ForEach(x =>
+                {
+                    x.Status = OutLockStockStatusEnum.鍑哄簱涓�.ObjToInt();
+                });
+
+                stockInfos = allocateResult.Item1;
+                orderDetails = allocateResult.Item2;
+                outStockLockInfos = allocateResult.Item3;
+                locationInfos = allocateResult.Item4;
+            }
+            else
+            {
+                throw new Exception("鏃犲簱瀛�");
+            }
+
+            return (tasks, stockInfos, orderDetails, outStockLockInfos, locationInfos);
+        }
+
+
+
+
+
+        /// <summary>
+        /// 鏇存柊璁㈠崟鏄庣粏鐘舵��
+        /// </summary>
+        private void UpdateOrderDetailStatus(List<Dt_OutboundOrderDetail> details, decimal allocatedQuantity, decimal needQuantity)
+        {
+            foreach (var detail in details)
+            {
+                // 鏍规嵁鍒嗛厤鎯呭喌鏇存柊鐘舵��
+                if (allocatedQuantity >= needQuantity)
+                {
+                    detail.OrderDetailStatus = OrderDetailStatusEnum.Outbound.ObjToInt();
+                }
+                else
+                {
+                    detail.OrderDetailStatus = OrderDetailStatusEnum.AssignOverPartial.ObjToInt();
+                }
+            }
+        }
+
+
+
+        private async Task<string> GenerateBatchNo()
+        {
+            var batchNo = UniqueValueGenerator.Generate();
+
+            return $"Out{batchNo} ";
+        }
+
+        private async Task<Dt_OutboundBatch> CreateBatchRecord(string orderNo, int orderDetailId, decimal batchQuantity, string batchNo)
+        {
+            var batchRecord = new Dt_OutboundBatch
+            {
+                BatchNo = batchNo,
+                OrderNo = orderNo,
+                OrderDetailId = orderDetailId,
+                BatchQuantity = batchQuantity,
+                BatchStatus = (int)BatchStatusEnum.鍒嗛厤涓�,
+                Operator = App.User.UserName
+            };
+
+            await _OutboundBatchRepository.Db.Insertable(batchRecord).ExecuteCommandAsync();
+            return batchRecord;
+        }
+
+        #endregion
+
+
     }
 }

--
Gitblit v1.9.3