From 0e214856df682998cd52df74c851502c571ba183 Mon Sep 17 00:00:00 2001
From: wanshenmean <cathay_xy@163.com>
Date: 星期二, 28 四月 2026 23:22:23 +0800
Subject: [PATCH] feat(出库任务): 优化二深位出库的移库逻辑并添加事务支持

---
 Code/WMS/WIDESEA_WMSServer/WIDESEA_BasicService/LocationInfoService.cs |  380 +++++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 305 insertions(+), 75 deletions(-)

diff --git a/Code/WMS/WIDESEA_WMSServer/WIDESEA_BasicService/LocationInfoService.cs b/Code/WMS/WIDESEA_WMSServer/WIDESEA_BasicService/LocationInfoService.cs
index af5cc9a..d7aee6d 100644
--- a/Code/WMS/WIDESEA_WMSServer/WIDESEA_BasicService/LocationInfoService.cs
+++ b/Code/WMS/WIDESEA_WMSServer/WIDESEA_BasicService/LocationInfoService.cs
@@ -11,6 +11,7 @@
 using WIDESEA_DTO.Basic;
 using WIDESEA_DTO.Task;
 using WIDESEA_IBasicService;
+using WIDESEA_IRecordService;
 using WIDESEA_Model.Models;
 
 namespace WIDESEA_BasicService
@@ -23,6 +24,9 @@
         private readonly IMapper _mapper;
         private readonly IRepository<Dt_Task> _taskRepository;
         private readonly IRepository<Dt_StockInfo> _stockInfoRepository;
+        private readonly IRecordService _recordService;
+        private readonly IRepository<Dt_Warehouse> _warehouseRepository;
+        private readonly IUnitOfWorkManage _unitOfWorkManage;
 
         /// <summary>
         /// 鏋勯�犲嚱鏁�
@@ -30,15 +34,22 @@
         /// <param name="baseDal">鍩虹鏁版嵁璁块棶瀵硅薄</param>
         /// <param name="taskRepository">浠诲姟浠撳偍</param>
         /// <param name="stockInfoRepository">搴撳瓨淇℃伅浠撳偍</param>
+        /// <param name="unitOfWorkManage">宸ヤ綔鍗曞厓绠$悊鍣�</param>
         public LocationInfoService(
             IRepository<Dt_LocationInfo> baseDal,
             IRepository<Dt_Task> taskRepository,
             IRepository<Dt_StockInfo> stockInfoRepository,
-            IMapper mapper) : base(baseDal)
+            IRepository<Dt_Warehouse> warehouseRepository,
+            IMapper mapper,
+            IRecordService recordService,
+            IUnitOfWorkManage unitOfWorkManage) : base(baseDal)
         {
             _taskRepository = taskRepository;
             _stockInfoRepository = stockInfoRepository;
             _mapper = mapper;
+            _recordService = recordService;
+            _warehouseRepository = warehouseRepository;
+            _unitOfWorkManage = unitOfWorkManage;
         }
 
         /// <summary>
@@ -126,22 +137,43 @@
 
         /// <summary>
         /// 鏍规嵁宸烽亾鑾峰彇绌洪棽璐т綅淇℃伅
+        /// 鎺掑簭绛栫暐锛氭繁搴︿紭鍏堬紙浜屾繁浣嶄紭鍏堬級锛屽叾娆℃寜灞傘�佸垪銆佽鍗囧簭
         /// </summary>
         /// <param name="roadwayNo">宸烽亾缂栧彿</param>
-        /// <returns>绌洪棽璐т綅淇℃伅锛屽鏋滄湭鎵惧埌鍒欒繑鍥瀗ull</returns>
+        /// <returns>绌洪棽璐т綅淇℃伅锛屽鏋滅┖闂茶揣浣嶄笉瓒冲垯杩斿洖null</returns>
         public async Task<Dt_LocationInfo?> GetLocationInfo(string roadwayNo)
         {
-            var locations = await BaseDal.QueryDataAsync(x =>
-                x.EnableStatus == EnableStatusEnum.Normal.GetHashCode() &&
-                x.RoadwayNo == roadwayNo &&
-                x.LocationStatus == LocationStatusEnum.Free.GetHashCode());
+            // HC 宸烽亾浣跨敤 Capacity 绫诲瀷锛屽叾浠栧贩閬撲娇鐢� ShelfCapacity 绫诲瀷
+            var locationType = roadwayNo.Contains("HC")
+                ? (int)LocationTypeEnum.Capacity
+                : (int)LocationTypeEnum.ShelfCapacity;
 
-            return locations?
+            var enableStatus = EnableStatusEnum.Normal.GetHashCode();
+            var freeStatus = LocationStatusEnum.Free.GetHashCode();
+
+            // 鏁版嵁搴撶 COUNT 妫�鏌ョ┖闂茶揣浣嶆暟閲忥紙浠呰繑鍥炰竴涓暟瀛楋紝鏃犳暟鎹紶杈撳紑閿�锛�
+            var freeCount = await BaseDal.Db.Queryable<Dt_LocationInfo>()
+                .Where(x => x.EnableStatus == enableStatus
+                    && x.RoadwayNo == roadwayNo
+                    && x.LocationStatus == freeStatus
+                    && x.LocationType == locationType)
+                .CountAsync();
+
+            // 绌洪棽璐т綅涓嶈冻鏈�浣庝繚鐣欐暟閲忔椂杩斿洖null锛岄伩鍏嶅皢宸烽亾鍒嗛厤鑰楀敖
+            const int minFreeLocationThreshold = 5;
+            if (freeCount < minFreeLocationThreshold) return null;
+
+            // 鏁版嵁搴撶鎺掑簭鍙栫涓�鏉★紙鍙紶杈撳崟琛屾暟鎹級
+            return await BaseDal.Db.Queryable<Dt_LocationInfo>()
+                .Where(x => x.EnableStatus == enableStatus
+                    && x.RoadwayNo == roadwayNo
+                    && x.LocationStatus == freeStatus
+                    && x.LocationType == locationType)
+                .OrderByDescending(x => x.Depth)
                 .OrderBy(x => x.Layer)
-                .ThenByDescending(x => x.Depth)
-                .ThenBy(x => x.Column)
-                .ThenBy(x => x.Row)
-                .FirstOrDefault();
+                .OrderBy(x => x.Column)
+                .OrderBy(x => x.Row)
+                .FirstAsync();
         }
 
         /// <summary>
@@ -166,13 +198,64 @@
         }
 
         /// <summary>
+        /// 鏍规嵁璐т綅ID鑾峰彇璐т綅淇℃伅
+        /// </summary>
+        /// <param name="id">璐т綅id</param>
+        /// <returns>璐т綅淇℃伅</returns>
+        public async Task<Dt_LocationInfo> GetLocationInfoAsync(int id)
+        {
+            return await BaseDal.QueryFirstAsync(x => x.Id == id);
+        }
+
+        /// <summary>
         /// 鏇存柊璐т綅淇℃伅
         /// </summary>
         /// <param name="locationInfo">璐т綅淇℃伅瀵硅薄</param>
         /// <returns>鏇存柊鏄惁鎴愬姛</returns>
         public async Task<bool> UpdateLocationInfoAsync(Dt_LocationInfo locationInfo)
         {
-            return await BaseDal.UpdateDataAsync(locationInfo);
+            var beforeLocation = await BaseDal.QueryFirstAsync(x => x.Id == locationInfo.Id);
+            var result = await BaseDal.UpdateDataAsync(locationInfo);
+            if (!result)
+                return false;
+
+            return beforeLocation == null
+                || await _recordService.AddLocationChangeRecordAsync(beforeLocation, locationInfo, LocationChangeType.HandUpdate, remark: "璐т綅鏇存柊");
+        }
+
+        public override WebResponseContent UpdateData(Dt_LocationInfo entity)
+        {
+            var beforeLocation = BaseDal.QueryFirst(x => x.Id == entity.Id);
+            var result = base.UpdateData(entity);
+            if (!result.Status || beforeLocation == null)
+                return result;
+
+            var saveRecordResult = _recordService.AddLocationChangeRecordAsync(beforeLocation, entity, LocationChangeType.HandUpdate, remark: "璐т綅鏇存柊").GetAwaiter().GetResult();
+            return saveRecordResult ? result : WebResponseContent.Instance.Error("璐т綅鐘舵�佸彉鏇磋褰曚繚瀛樺け璐�");
+        }
+
+        public override WebResponseContent UpdateData(List<Dt_LocationInfo> entities)
+        {
+            var beforeLocations = entities
+                .Select(entity => BaseDal.QueryFirst(x => x.Id == entity.Id))
+                .Where(location => location != null)
+                .ToDictionary(location => location!.Id, location => location!);
+
+            var result = base.UpdateData(entities);
+            if (!result.Status)
+                return result;
+
+            foreach (var entity in entities)
+            {
+                if (!beforeLocations.TryGetValue(entity.Id, out var beforeLocation))
+                    continue;
+
+                var saveRecordResult = _recordService.AddLocationChangeRecordAsync(beforeLocation, entity, LocationChangeType.HandUpdate, remark: "鎵归噺璐т綅鏇存柊").GetAwaiter().GetResult();
+                if (!saveRecordResult)
+                    return WebResponseContent.Instance.Error("璐т綅鐘舵�佸彉鏇磋褰曚繚瀛樺け璐�");
+            }
+
+            return result;
         }
 
         /// <summary>
@@ -191,24 +274,29 @@
                     return content.Error("浠诲姟涓嶅瓨鍦�");
 
                 var location = await BaseDal.QueryFirstAsync(x => x.LocationCode == outboundTask.SourceAddress && x.RoadwayNo == outboundTask.Roadway);
+                if (location == null)
+                    return content.Error("鏈壘鍒版簮璐т綅淇℃伅");
 
-                // 妫�鏌ユ槸鍚﹂渶瑕佽繘琛岀Щ搴�
+                // 妫�鏌ユ槸鍚﹂渶瑕佽繘琛岀Щ搴擄紙浜屾繁浣嶅嚭搴撻渶瑕佸厛绉昏蛋涓�娣变綅锛�
                 if (CheckForInternalTransfer(location))
                 {
                     // 璁$畻瀵瑰簲浣嶇疆鐨勭浉瀵瑰簱浣嶏紙濂囨暟琛岀殑涓嬩竴琛屾垨鑰呭伓鏁拌鐨勪笂涓�琛岋級
-                    var newLocationID = GetRelativeLocationID(location);
+                    var relativeLocationCode = GetRelativeLocationID(location);
 
-                    // 鑾峰彇鏂扮殑搴撲綅鐨勪换鍔�
-                    var internalTransferTask = await _taskRepository.QueryFirstAsync(x => x.SourceAddress == newLocationID && x.Roadway == outboundTask.Roadway);
+                    // 鏌ユ壘鐩稿搴撲綅涓婄殑娲昏穬浠诲姟锛堟帓闄ゅ凡瀹屾垚銆佸凡鍙栨秷銆佸紓甯哥瓑缁堟�侊級
+                    var activeTask = await _taskRepository.QueryFirstAsync(x =>
+                        x.SourceAddress == relativeLocationCode
+                        && x.Roadway == outboundTask.Roadway
+                        && (x.TaskStatus == TaskOutStatusEnum.OutNew.GetHashCode()));   
 
-                    // 濡傛灉鏂扮殑搴撲綅娌℃湁鎵惧埌瀵瑰簲鐨勪换鍔�
-                    if (internalTransferTask == null)
+                    // 濡傛灉鐩稿搴撲綅娌℃湁娲昏穬浠诲姟锛屽皾璇曞垱寤虹Щ搴撲换鍔�
+                    if (activeTask == null)
                     {
-                        return content.OK("鑾峰彇鍒扮Щ搴撲换鍔�", await HandleNoTaskAtLocation(newLocationID, outboundTask));
+                        return await HandleNoTaskAtLocation(relativeLocationCode, outboundTask);
                     }
 
                     // 鐩存帴杩斿洖涓�娣变綅鍑哄簱浠诲姟
-                    return content.OK("鑾峰彇鍒颁竴娣变綅鍑哄簱浠诲姟", internalTransferTask);
+                    return content.OK("鑾峰彇鍒颁竴娣变綅鍑哄簱浠诲姟", activeTask);
                 }
 
                 // 杩斿洖褰撳墠搴撲綅鐨勫嚭搴撲换鍔�
@@ -240,69 +328,186 @@
         }
 
         /// <summary>
-        /// 澶勭悊娌℃湁浠诲姟鐨勫簱浣嶆儏鍐�
+        /// 澶勭悊娌℃湁娲昏穬浠诲姟鐨勫簱浣嶆儏鍐�
+        /// 鍒ゆ柇鏄惁鏈夊簱瀛橈紝鏈夊垯鐢熸垚绉诲簱浠诲姟锛屾棤鍒欑洿鎺ヨ繑鍥炲嚭搴撲换鍔�
         /// </summary>
-        /// <param name="newLocationID">鏂扮殑搴撲綅ID</param>
-        /// <param name="outboundTask">鍑哄簱浠诲姟</param>
-        /// <returns>鐢熸垚鐨勭Щ搴撲换鍔℃垨鍘熷鍑哄簱浠诲姟</returns>
-        private async Task<Dt_Task> HandleNoTaskAtLocation(string newLocationID, Dt_Task outboundTask)
+        /// <param name="newLocationID">鐩稿搴撲綅缂栫爜</param>
+        /// <param name="outboundTask">鍘熷鍑哄簱浠诲姟</param>
+        /// <returns>鎿嶄綔缁撴灉锛堝寘鍚Щ搴撲换鍔℃垨鍘熷鍑哄簱浠诲姟锛�</returns>
+        private async Task<WebResponseContent> HandleNoTaskAtLocation(string newLocationID, Dt_Task outboundTask)
         {
             // 鍒ゆ柇璇ヤ綅缃槸鍚︽湁搴撳瓨
             var stockInfo = await _stockInfoRepository.QueryDataNavFirstAsync(x =>
                             x.LocationCode == newLocationID &&
-                            x.StockStatus == StockStatusEmun.鍏ュ簱瀹屾垚.GetHashCode() &&
+                            (x.StockStatus == StockStatusEmun.鍏ュ簱瀹屾垚.GetHashCode() || x.StockStatus == StockStatusEmun.绌烘墭鐩樺簱瀛�.GetHashCode()) &&
                             x.LocationDetails.LocationStatus == LocationStatusEnum.InStock.GetHashCode());
             if (stockInfo == null)
             {
                 // 濡傛灉娌℃湁搴撳瓨锛岀洿鎺ヨ繑鍥炲綋鍓嶅嚭搴撲换鍔�
-                return outboundTask;
+                return WebResponseContent.Instance.OK("褰撳墠鍑哄簱浠诲姟", outboundTask);
             }
 
-            // 濡傛灉鏈夊簱瀛橈紝鐢熸垚绉诲簱浠诲姟
-            var emptyLocation = await GetTransferLocationEmptyAsync(outboundTask.Roadway);
-            var taskNo = await _taskRepository.GetTaskNo();
-
-            var newTransferTask = new Dt_Task
+            // 鏈夊簱瀛樻椂锛屽湪浜嬪姟涓垱寤虹Щ搴撲换鍔″苟閿佸畾鐩稿叧璧勬簮
+            return await _unitOfWorkManage.BeginTranAsync(async () =>
             {
-                CreateDate = DateTime.Now,
-                Creater = App.User.UserName ?? "system",
-                CurrentAddress = newLocationID,
-                Grade = 99,
-                NextAddress = emptyLocation.LocationCode,
-                PalletCode = stockInfo.PalletCode,
-                Remark = "绉诲簱",
-                Roadway = stockInfo.LocationDetails.RoadwayNo,
-                SourceAddress = newLocationID,
-                TaskNum = taskNo,
-                TargetAddress = emptyLocation.LocationCode,
-                TaskType = TaskRelocationTypeEnum.Relocation.GetHashCode(),
-                TaskStatus = TaskRelocationStatusEnum.RelocationNew.GetHashCode(),
-                WarehouseId = stockInfo.WarehouseId
+                // 浜嬪姟鍐呭啀娆$‘璁ゆ病鏈夋椿璺冧换鍔★紙闃叉骞跺彂閲嶅鍒涘缓绉诲簱浠诲姟锛�
+                var existingTask = await _taskRepository.QueryFirstAsync(x =>
+                    x.SourceAddress == newLocationID
+                    && x.Roadway == outboundTask.Roadway
+                    && (x.TaskStatus == TaskOutStatusEnum.OutNew.GetHashCode()));
+                if (existingTask != null)
+                {
+                    return WebResponseContent.Instance.OK("鑾峰彇鍒板凡鏈変换鍔�", existingTask);
+                }
+
+                // 鑾峰彇鐩爣绌哄簱浣�
+                var emptyLocation = await GetTransferLocationEmptyAsync(outboundTask.Roadway);
+                if (emptyLocation == null)
+                {
+                    return WebResponseContent.Instance.Error("鏈壘鍒板彲鐢ㄧ殑绌哄簱浣嶇敤浜庣Щ搴�");
+                }
+
+                var taskNo = await _taskRepository.GetTaskNo();
+                var newTransferTask = new Dt_Task
+                {
+                    CreateDate = DateTime.Now,
+                    Creater = App.User.UserName ?? "system",
+                    CurrentAddress = newLocationID,
+                    Grade = 99,
+                    NextAddress = emptyLocation.LocationCode,
+                    PalletCode = stockInfo.PalletCode,
+                    Remark = "绉诲簱",
+                    Roadway = stockInfo.LocationDetails.RoadwayNo,
+                    SourceAddress = newLocationID,
+                    TaskNum = taskNo,
+                    TargetAddress = emptyLocation.LocationCode,
+                    TaskType = TaskRelocationTypeEnum.Relocation.GetHashCode(),
+                    TaskStatus = TaskRelocationStatusEnum.RelocationNew.GetHashCode(),
+                    WarehouseId = stockInfo.WarehouseId
+                };
+
+                var createdTask = await _taskRepository.Db.Insertable(newTransferTask).ExecuteReturnEntityAsync();
+                var beforeStock = CloneStockSnapshot(stockInfo);
+                var beforeSourceLocation = stockInfo.LocationDetails == null ? null : CloneLocationSnapshot(stockInfo.LocationDetails);
+                var beforeTargetLocation = CloneLocationSnapshot(emptyLocation);
+
+                // 鍒涘缓绉诲簱浠诲姟鍚庯紝绔嬪嵆閿佸畾搴撳瓨鍜岀浉鍏宠揣浣�
+                stockInfo.StockStatus = StockStatusEmun.绉诲簱閿佸畾.GetHashCode();
+                var updateStockResult = await _stockInfoRepository.UpdateDataAsync(stockInfo);
+
+                var locationsToUpdate = new List<Dt_LocationInfo>();
+                if (stockInfo.LocationDetails != null)
+                {
+                    stockInfo.LocationDetails.LocationStatus = LocationStatusEnum.InStockLock.GetHashCode();
+                    locationsToUpdate.Add(stockInfo.LocationDetails);
+                }
+
+                emptyLocation.LocationStatus = LocationStatusEnum.FreeLock.GetHashCode();
+                locationsToUpdate.Add(emptyLocation);
+
+                var updateLocationResult = await BaseDal.UpdateDataAsync(locationsToUpdate);
+                if (!updateStockResult || !updateLocationResult)
+                {
+                    return WebResponseContent.Instance.Error("鍒涘缓绉诲簱浠诲姟鍚庢洿鏂板簱瀛樼姸鎬佹垨璐т綅鐘舵�佸け璐�");
+                }
+
+                var saveStockRecordResult = await _recordService.AddStockChangeRecordAsync(
+                    beforeStock,
+                    stockInfo,
+                    StockChangeTypeEnum.Relocation,
+                    createdTask.TaskNum,
+                    createdTask.OrderNo,
+                    "绉诲簱浠诲姟棰勫崰搴撳瓨");
+                if (!saveStockRecordResult)
+                {
+                    return WebResponseContent.Instance.Error("鍒涘缓绉诲簱浠诲姟鍚庤褰曞簱瀛樺彉鏇村け璐�");
+                }
+
+                if (beforeSourceLocation != null && stockInfo.LocationDetails != null)
+                {
+                    var saveSourceLocationRecordResult = await _recordService.AddLocationChangeRecordAsync(
+                        beforeSourceLocation,
+                        stockInfo.LocationDetails,
+                        LocationChangeType.RelocationAssignLocation,
+                        createdTask.TaskNum,
+                        createdTask.OrderNo,
+                        null,
+                        "绉诲簱浠诲姟閿佸畾婧愯揣浣�");
+                    if (!saveSourceLocationRecordResult)
+                    {
+                        return WebResponseContent.Instance.Error("鍒涘缓绉诲簱浠诲姟鍚庤褰曟簮璐т綅鍙樻洿澶辫触");
+                    }
+                }
+
+                var saveTargetLocationRecordResult = await _recordService.AddLocationChangeRecordAsync(
+                    beforeTargetLocation,
+                    emptyLocation,
+                    LocationChangeType.RelocationAssignLocation,
+                    createdTask.TaskNum,
+                    createdTask.OrderNo,
+                    null,
+                    "绉诲簱浠诲姟閿佸畾鐩爣璐т綅");
+                if (!saveTargetLocationRecordResult)
+                {
+                    return WebResponseContent.Instance.Error("鍒涘缓绉诲簱浠诲姟鍚庤褰曠洰鏍囪揣浣嶅彉鏇村け璐�");
+                }
+
+                return WebResponseContent.Instance.OK("鑾峰彇鍒扮Щ搴撲换鍔�", createdTask);
+            });
+        }
+
+        private static Dt_LocationInfo CloneLocationSnapshot(Dt_LocationInfo location)
+        {
+            return new Dt_LocationInfo
+            {
+                Id = location.Id,
+                WarehouseId = location.WarehouseId,
+                LocationCode = location.LocationCode,
+                LocationName = location.LocationName,
+                RoadwayNo = location.RoadwayNo,
+                Row = location.Row,
+                Column = location.Column,
+                Layer = location.Layer,
+                Depth = location.Depth,
+                LocationType = location.LocationType,
+                LocationStatus = location.LocationStatus,
+                EnableStatus = location.EnableStatus,
+                Remark = location.Remark
             };
+        }
 
-            var createdTask = await _taskRepository.Db.Insertable(newTransferTask).ExecuteReturnEntityAsync();
-
-            // 鍒涘缓绉诲簱浠诲姟鍚庯紝绔嬪嵆閿佸畾搴撳瓨鍜岀浉鍏宠揣浣嶏紝閬垮厤骞跺彂閲嶅鍒嗛厤
-            stockInfo.StockStatus = StockStatusEmun.绉诲簱閿佸畾.GetHashCode();
-            var updateStockResult = await _stockInfoRepository.UpdateDataAsync(stockInfo);
-
-            var locationsToUpdate = new List<Dt_LocationInfo>();
-            if (stockInfo.LocationDetails != null)
+        private static Dt_StockInfo CloneStockSnapshot(Dt_StockInfo stockInfo)
+        {
+            return new Dt_StockInfo
             {
-                stockInfo.LocationDetails.LocationStatus = LocationStatusEnum.InStockLock.GetHashCode();
-                locationsToUpdate.Add(stockInfo.LocationDetails);
-            }
-
-            emptyLocation.LocationStatus = LocationStatusEnum.FreeLock.GetHashCode();
-            locationsToUpdate.Add(emptyLocation);
-
-            var updateLocationResult = await BaseDal.UpdateDataAsync(locationsToUpdate);
-            if (!updateStockResult || !updateLocationResult)
-            {
-                throw new Exception("鍒涘缓绉诲簱浠诲姟鍚庢洿鏂板簱瀛樼姸鎬佹垨璐т綅鐘舵�佸け璐�");
-            }
-
-            return createdTask;
+                Id = stockInfo.Id,
+                PalletCode = stockInfo.PalletCode,
+                PalletType = stockInfo.PalletType,
+                LocationId = stockInfo.LocationId,
+                LocationCode = stockInfo.LocationCode,
+                WarehouseId = stockInfo.WarehouseId,
+                StockStatus = stockInfo.StockStatus,
+                Remark = stockInfo.Remark,
+                OutboundDate = stockInfo.OutboundDate,
+                Details = stockInfo.Details?.Select(detail => new Dt_StockInfoDetail
+                {
+                    Id = detail.Id,
+                    StockId = detail.StockId,
+                    MaterielCode = detail.MaterielCode,
+                    MaterielName = detail.MaterielName,
+                    OrderNo = detail.OrderNo,
+                    BatchNo = detail.BatchNo,
+                    ProductionDate = detail.ProductionDate,
+                    EffectiveDate = detail.EffectiveDate,
+                    SerialNumber = detail.SerialNumber,
+                    StockQuantity = detail.StockQuantity,
+                    OutboundQuantity = detail.OutboundQuantity,
+                    Status = detail.Status,
+                    Unit = detail.Unit,
+                    InboundOrderRowNo = detail.InboundOrderRowNo,
+                    Remark = detail.Remark
+                }).ToList()
+            };
         }
 
         /// <summary>
@@ -316,13 +521,30 @@
         }
 
         /// <summary>
-        /// 鏍规嵁宸烽亾鑾峰彇浜屾繁浣嶇殑绌哄簱浣�
+        /// 鏍规嵁宸烽亾鑾峰彇绌哄簱浣嶇敤浜庣Щ搴擄紙浼樺厛浜屾繁浣嶏紝鏃犲垯闄嶇骇鍙栦竴娣变綅锛�
         /// </summary>
         /// <param name="roadway">宸烽亾缂栧彿</param>
-        /// <returns>璐т綅瀵硅薄</returns>
-        private async Task<Dt_LocationInfo> GetTransferLocationEmptyAsync(string roadway)
+        /// <returns>璐т綅瀵硅薄锛屾湭鎵惧埌鍒欒繑鍥瀗ull</returns>
+        private async Task<Dt_LocationInfo?> GetTransferLocationEmptyAsync(string roadway)
         {
-            return await BaseDal.QueryFirstAsync(x => x.Depth == 2 && x.LocationStatus == LocationStatusEnum.Free.GetHashCode() && x.RoadwayNo == roadway);
+            var freeStatus = LocationStatusEnum.Free.GetHashCode();
+
+            // 浼樺厛鑾峰彇浜屾繁浣嶇┖搴撲綅
+            var location = await BaseDal.QueryFirstAsync(x =>
+                x.Depth == 2
+                && x.LocationStatus == freeStatus
+                && x.RoadwayNo == roadway);
+
+            // 浜屾繁浣嶆棤绌洪棽鏃堕檷绾ц幏鍙栦竴娣变綅
+            if (location == null)
+            {
+                location = await BaseDal.QueryFirstAsync(x =>
+                    x.Depth == 1
+                    && x.LocationStatus == freeStatus
+                    && x.RoadwayNo == roadway);
+            }
+
+            return location;
         }
 
         /// <summary>
@@ -351,11 +573,18 @@
         /// <param name="layer">灞傛暟</param>
         /// <param name="depth">娣卞害</param>
         /// <returns>璐т綅淇℃伅瀵硅薄</returns>
-        private static Dt_LocationInfo CreateLocationInfo(string roadwayNo, int row, int col, int layer, int depth)
+        private Dt_LocationInfo CreateLocationInfo(string roadwayNo, int row, int col, int layer, int depth)
         {
+            var warehouse = _warehouseRepository.QueryData(x => x.WarehouseCode == roadwayNo).FirstOrDefault();
+
+            if (warehouse == null)
+            {
+                throw new InvalidOperationException($"鏈壘鍒板贩閬撶紪鍙蜂负 {roadwayNo} 鐨勪粨搴撲俊鎭�");
+            }
+
             return new Dt_LocationInfo
             {
-                WarehouseId = 0,
+                WarehouseId = warehouse.WarehouseId,
                 Row = row,
                 Column = col,
                 Layer = layer,
@@ -364,6 +593,7 @@
                 EnableStatus = EnableStatusEnum.Normal.GetHashCode(),
                 LocationStatus = LocationStatusEnum.Free.GetHashCode(),
                 LocationType = LocationTypeEnum.Undefined.GetHashCode(),
+                //LocationCode = $"{roadwayNo}-{row:D3}-{col:D3}-{layer:D3}",
                 LocationCode = $"{row:D3}-{col:D3}-{layer:D3}",
                 LocationName = $"{roadwayNo}宸烽亾{row:D3}琛寋col:D3}鍒梴layer:D3}灞倇depth:D2}娣�"
             };
@@ -371,4 +601,4 @@
 
         #endregion 绉佹湁鏂规硶
     }
-}
+}
\ No newline at end of file

--
Gitblit v1.9.3