From ca3e4977395bc02c5d147dffdff7381333fdfbca Mon Sep 17 00:00:00 2001
From: heshaofeng <heshaofeng@hnkhzn.com>
Date: 星期四, 09 四月 2026 14:39:37 +0800
Subject: [PATCH] 空箱跨区域移库

---
 项目代码/WIDESEA_WMSClient/src/extension/stock/stockView.js                                 |   13 +
 项目代码/WIDESEA_WMSClient/src/views/inbound/inboundOrder.vue                               |    2 
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService_Outbound.cs          |  143 +++++++++++++++++
 项目代码/WIDESEA_WMSClient/config/buttons.js                                                |    9 +
 项目代码/WIDESEA_WMSClient/src/extension/stock/extend/CrossAreaRelocationDialog.vue         |  105 +++++++++++++
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_InboundService/InboundService.cs                 |   17 ++
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/TaskInfo/TaskController.cs |    7 
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_ITaskInfoService/ITaskService.cs                 |    2 
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_TaskInfoService/TaskService.cs                   |  134 ++++++++++++++++
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_Common/TaskEnum/TaskTypeEnum.cs                  |    8 
 10 files changed, 435 insertions(+), 5 deletions(-)

diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/config/buttons.js" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/config/buttons.js"
index 8ce07b4..9817868 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/config/buttons.js"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/config/buttons.js"
@@ -363,6 +363,15 @@
     type: 'danger',
     onClick: function () {
     }
+},
+,{
+    name: "搴撳瓨璺ㄥ尯鍩熺Щ搴�",
+    icon: '',
+    class: '',
+    value: 'SelectStockAreaIn',
+    type: 'danger',
+    onClick: function () {
+    }
 }
 ]
 
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/stock/extend/CrossAreaRelocationDialog.vue" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/stock/extend/CrossAreaRelocationDialog.vue"
new file mode 100644
index 0000000..42b2260
--- /dev/null
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/stock/extend/CrossAreaRelocationDialog.vue"
@@ -0,0 +1,105 @@
+<template>
+  <vol-box v-model="show" title="璺ㄥ尯鍩熺Щ搴�" :width="800" :height="1200">
+    <template #content>
+      <el-form ref="form" :model="form" label-width="100px">
+        <el-form-item label="鐩爣璐т綅绫诲瀷:">
+          <el-select v-model="targetLocationType" placeholder="璇烽�夋嫨鐩爣璐т綅绫诲瀷">
+            <el-option 
+              v-for="item in locationTypes" 
+              :key="item.locationType" 
+              :label="item.locationTypeDesc.toString()"
+              :value="item.locationType">
+            </el-option>
+          </el-select>
+        </el-form-item>
+      </el-form>
+    </template>
+    <template #footer>
+      <div>
+        <el-button 
+          type="danger" 
+          size="small" 
+          plain 
+          @click="submit"
+          :loading="isSubmitting"
+          :disabled="isSubmitting">
+          <i class="el-icon-check">纭绉诲簱</i>
+        </el-button>
+        <el-button 
+          size="small" 
+          type="primary" 
+          plain 
+          @click="() => { this.show = false }">
+          <i class="el-icon-close">鍏抽棴</i>
+        </el-button>
+      </div>
+    </template>
+  </vol-box>
+</template>
+
+<script>
+import VolBox from '@/components/basic/VolBox.vue'
+export default {
+  components: {
+    'vol-box': VolBox
+  },
+  data() {
+    return {
+      show: false,
+      locationTypes: [],
+      targetLocationType: "",
+      isSubmitting: false,
+      form:{}
+    }
+  },
+  methods: {
+    open() {
+      this.show = true
+      this.getData();
+    },
+    submit() {
+      // 1. 楠岃瘉蹇呭~椤�
+      if (!this.targetLocationType) {
+        this.$message.warning('璇烽�夋嫨鐩爣璐т綅绫诲瀷');
+        return;
+      }
+
+      // 2. 绂佺敤鎸夐挳
+      this.isSubmitting = true;
+
+      this.$emit('parentCall', ($vue) => {
+        // 閫変腑鐨勮〃鏍兼暟鎹�
+        let stockViews = $vue.$refs.table.getSelected();
+        
+        this.http.post(
+          `/api/Task/CrossAreaOutbound?targetLocationType=${this.targetLocationType}`,
+          stockViews,
+          '璺ㄥ尯鍩熺Щ搴撳鐞嗕腑...'
+        )
+        .then((x) => {
+          if (!x.status) {
+            this.$message.error(x.message)
+          } else {
+            this.show = false
+            this.$message.success(x.message || '璺ㄥ尯鍩熺Щ搴撲换鍔$敓鎴愭垚鍔�')
+            $vue.refresh();
+          }
+        })
+        .catch((error) => {
+          this.$message.error('璇锋眰澶辫触锛岃绋嶅悗閲嶈瘯');
+          console.error('璺ㄥ尯鍩熺Щ搴撳け璐�:', error);
+        })
+        .finally(() => {
+          this.isSubmitting = false;
+        });
+      })
+    },
+    getData() {
+      this.http.post("api/LocationInfo/GetLocationTypes", null, "鍔犺浇璐т綅绫诲瀷涓�")
+        .then((x) => {
+          this.locationTypes = x.data;
+        })
+    },
+  }
+}
+</script>
\ No newline at end of file
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/stock/stockView.js" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/stock/stockView.js"
index 56cdda1..efe09a5 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/stock/stockView.js"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/extension/stock/stockView.js"
@@ -1,9 +1,10 @@
 import { createVNode, render, h, reactive } from 'vue';
 import { ElDialog, ElForm, ElFormItem, ElSelect, ElOption, ElButton, ElMessage, ElLoading } from 'element-plus';
+import gridHeader from './extend/CrossAreaRelocationDialog.vue'
 let extension = {
   components: {
     //鏌ヨ鐣岄潰鎵╁睍缁勪欢
-    gridHeader: '',
+    gridHeader: gridHeader,
     gridBody: '',
     gridFooter: '',
     //鏂板缓銆佺紪杈戝脊鍑烘鎵╁睍缁勪欢
@@ -335,6 +336,16 @@
             });
         }
       }
+      var SelectStockAreaIn = this.buttons.find(x => x.value == "SelectStockAreaIn");
+      if (SelectStockAreaIn != null) {
+        SelectStockAreaIn.onClick = () => {
+          let rows = this.$refs.table.getSelected();
+          if (rows.length == 0) {
+              return this.$message.error("璇峰厛閫夋嫨闇�瑕佺Щ搴撶殑鏁版嵁锛�");
+            }
+          this.$refs.gridHeader.open();
+        }
+      }
     },
     onInited() {
       //妗嗘灦鍒濆鍖栭厤缃悗
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/inbound/inboundOrder.vue" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/inbound/inboundOrder.vue"
index d872169..cc67dd7 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/inbound/inboundOrder.vue"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/inbound/inboundOrder.vue"
@@ -274,7 +274,6 @@
           width: 150,
           align: "left",
           edit: { type: "" },
-          required: true,
         },
         {
           field: "batchNo",
@@ -300,6 +299,7 @@
           type: "decimal",
           width: 90,
           align: "left",
+          edit: { type: "" },
           required: true
         },
         {
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_Common/TaskEnum/TaskTypeEnum.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_Common/TaskEnum/TaskTypeEnum.cs"
index 21f0392..f0c5ab9 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_Common/TaskEnum/TaskTypeEnum.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_Common/TaskEnum/TaskTypeEnum.cs"
@@ -153,7 +153,13 @@
         /// 鍚屽尯鍩熺Щ搴�
         /// </summary>
         [Description("鍚屽尯鍩熺Щ搴�")]
-        AreaRelocation = 910
+        AreaRelocation = 910,
+
+        /// <summary>
+        /// 璺ㄥ尯鍩熺Щ搴�
+        /// </summary>
+        [Description("璺ㄥ尯鍩熺Щ搴�")]
+        CrossAreaRelocation = 920
 
     }
 
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_ITaskInfoService/ITaskService.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_ITaskInfoService/ITaskService.cs"
index 056278e..8bba5a9 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_ITaskInfoService/ITaskService.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_ITaskInfoService/ITaskService.cs"
@@ -81,5 +81,7 @@
         Task<WebResponseContent> TaskCancel(List<int> taskCodes);
 
         Task<WebResponseContent> AreaOutbound(List<StockViewDTO> stockViews);
+
+        Task<WebResponseContent> CrossAreaOutbound(List<StockViewDTO> stockViews, int targetLocationType);
     }
 }
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_InboundService/InboundService.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_InboundService/InboundService.cs"
index c08f145..e984a4e 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_InboundService/InboundService.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_InboundService/InboundService.cs"
@@ -80,7 +80,8 @@
             _allocateOrderRepository = allocateOrderRepository;
         }
 
-        public async Task<WebResponseContent> GroupPallet(GroupPalletDto palletDto)
+        public async Task<WebResponseContent> 
+            GroupPallet(GroupPalletDto palletDto)
         {
             WebResponseContent content = new WebResponseContent();
             try
@@ -180,6 +181,20 @@
                     stockInfo = new Dt_StockInfo() { PalletType = (int)PalletTypeEnum.None, LocationType = Convert.ToInt32(palletDto.locationType) };
                     stockInfo.Details = new List<Dt_StockInfoDetail>();
                 }
+                //else
+                //{
+                //      var allowStatus = new[]
+                //  {
+                //      (int)StockStatusEmun.缁勭洏鏆傚瓨,
+                //      (int)StockStatusEmun.鏅轰粨鍏ユ櫤浠撶粍鐩樻殏瀛�,
+                //      (int)StockStatusEmun.鎵嬪姩缁勭洏鏆傚瓨
+                //  };
+
+                //    if (!allowStatus.Contains(stockInfo.StockStatus))
+                //    {
+                //        return content.Error($"璇ユ墭鐩榹stockInfo.PalletCode}鐘舵�佷笉鍏佽缁勭洏");
+                //    }
+                //}
 
                 if (inboundOrder.BusinessType != MESDocumentType.PurchaseInbound.ToString() && stockInfo != null && stockInfo.Details.Count > 0 && stockInfo.Details.FirstOrDefault()?.WarehouseCode != palletDto.WarehouseType)
                 {
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.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.cs"
index 9b7fa57..d195df9 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.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.cs"
@@ -311,7 +311,7 @@
             stockInfo.StockStatus = StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt();
             stockInfo.Details.ForEach(x =>
             {
-                x.Status = StockStatusEmun.鍏ュ簱纭.ObjToInt();
+                x.Status = inboundOrders.FirstOrDefault().CreateType == (int)OrderCreateTypeEnum.CreateInSystem ? StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt():StockStatusEmun.鍏ュ簱纭.ObjToInt();
             });
             _stockService.StockInfoService.Repository.UpdateData(stockInfo);
             _stockService.StockInfoDetailService.Repository.UpdateData(stockInfo.Details);
@@ -2711,6 +2711,138 @@
                 return await Task.FromResult(WebResponseContent.Instance.Error($"绉诲簱浠诲姟澶勭悊澶辫触锛歿ex.Message}"));
             }
         }
+
+
+        /// <summary>
+        /// 璺ㄥ尯鍩熺Щ搴撲换鍔″畬鎴�
+        /// </summary>
+        /// <param name="task"></param>
+        /// <returns></returns>
+        public async Task<WebResponseContent> CrossAreaRelocationTaskCompleted(Dt_Task task)
+        {
+            WebResponseContent content = new WebResponseContent();
+            try
+            {
+                if (task == null || string.IsNullOrEmpty(task.PalletCode) || string.IsNullOrEmpty(task.TargetAddress))
+                {
+                    return WebResponseContent.Instance.Error("璺ㄥ尯鍩熺Щ搴撲换鍔′俊鎭笉瀹屾暣锛堟墭鐩樺彿/鐩爣璐т綅涓虹┖锛�");
+                }
+
+                // 2. 鏌ヨ鎵樼洏搴撳瓨淇℃伅
+                Dt_StockInfo stockInfo = await _stockRepository.Db.Queryable<Dt_StockInfo>()
+                    .Includes(x => x.Details)
+                    .Where(x => x.PalletCode == task.PalletCode)
+                    .FirstAsync();
+
+                if (stockInfo == null)
+                {
+                    return WebResponseContent.Instance.Error($"鏈壘鍒版墭鐩榌{task.PalletCode}]瀵瑰簲鐨勫簱瀛樹俊鎭�");
+                }
+
+                // 闈炵┖鎵樼洏蹇呴』鏈夋槑缁�
+                if (stockInfo.Details.Count == 0 && stockInfo.PalletType != PalletTypeEnum.Empty.ObjToInt())
+                {
+                    _logger.LogInformation($"CrossAreaRelocationTaskCompleted: 鏈壘鍒拌鎵樼洏搴撳瓨鏄庣粏淇℃伅.{task.TaskNum}");
+                    return WebResponseContent.Instance.Error($"鏈壘鍒拌鎵樼洏[{task.PalletCode}]搴撳瓨鏄庣粏淇℃伅");
+                }
+
+                // 3. 鏌ヨ鐩爣璐т綅 + 鍘熻揣浣嶄俊鎭�
+                Dt_LocationInfo targetLocationInfo = _locationInfoService.Repository.QueryFirst(x => x.LocationCode == task.TargetAddress);
+                if (targetLocationInfo == null)
+                {
+                    return content.Error($"鏈壘鍒板搴旂殑缁堢偣璐т綅[{task.TargetAddress}]淇℃伅");
+                }
+
+                // 鍘熻揣浣嶄俊鎭�
+                Dt_LocationInfo oldLocationInfo = null;
+                if (!string.IsNullOrEmpty(stockInfo.LocationCode))
+                {
+                    oldLocationInfo = _locationInfoService.Repository.QueryFirst(x => x.LocationCode == stockInfo.LocationCode);
+                    if (oldLocationInfo == null)
+                    {
+                        return content.Error($"鏈壘鍒板師璐т綅[{stockInfo.LocationCode}]淇℃伅");
+                    }
+                }
+
+                // 4. 璐т綅鐘舵�佹牎楠�
+                if (targetLocationInfo.LocationStatus == LocationStatusEnum.InStock.ObjToInt())
+                {
+                    return WebResponseContent.Instance.Error($"鐩爣璐т綅[{task.TargetAddress}]鐘舵�佷笉姝g‘锛堝綋鍓嶄负宸插崰鐢級");
+                }
+
+                // 5. 寮�鍚簨鍔″鐞嗘牳蹇冮�昏緫
+                _unitOfWorkManage.BeginTran();
+
+                // 5.1 鐩爣璐т綅鏇存柊涓哄崰鐢�
+                var beforeTargetLocationStatus = targetLocationInfo.LocationStatus;
+                targetLocationInfo.LocationStatus = stockInfo.PalletType == PalletTypeEnum.Empty.ObjToInt()
+                        ? LocationStatusEnum.Pallet.ObjToInt()
+                        : LocationStatusEnum.InStock.ObjToInt();
+                _locationInfoService.Repository.UpdateData(targetLocationInfo);
+
+                // 5.2 鍘熻揣浣嶉噴鏀剧┖闂�
+                int beforeOldLocationStatus = 0;
+                if (oldLocationInfo != null)
+                {
+                    beforeOldLocationStatus = oldLocationInfo.LocationStatus;
+                    oldLocationInfo.LocationStatus = LocationStatusEnum.Free.ObjToInt();
+                    _locationInfoService.Repository.UpdateData(oldLocationInfo);
+                }
+
+                // 5.3 鏇存柊搴撳瓨锛氱粦瀹氭柊璐т綅 + 鎭㈠姝e父鐘舵��
+                string oldLocationCode = stockInfo.LocationCode;
+                stockInfo.LocationCode = targetLocationInfo.LocationCode;
+                stockInfo.StockStatus = StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt();
+                stockInfo.LocationType = targetLocationInfo.LocationType;
+                _stockRepository.UpdateData(stockInfo);
+
+                // 5.4 浠诲姟鏍囪涓哄畬鎴�
+                task.TaskStatus = TaskStatusEnum.Finish.ObjToInt();
+                var result = _task_HtyService.DeleteAndMoveIntoHty(task, OperateTypeEnum.鑷姩瀹屾垚);
+
+                // 鎻愪氦浜嬪姟
+                _unitOfWorkManage.CommitTran();
+
+                // 浠诲姟褰掓。澶辫触鍒欏垹闄�
+                if (!result)
+                {
+                    await Db.Deleteable(task).ExecuteCommandAsync();
+                }
+
+                // 璁板綍璐т綅鐘舵�佸彉鏇存棩蹇�
+                try
+                {
+                    _locationStatusChangeRecordService.AddLocationStatusChangeRecord(
+                        targetLocationInfo,
+                        beforeTargetLocationStatus,
+                        StockChangeType.Inbound.ObjToInt(),
+                        $"璺ㄥ尯鍩熺Щ搴撳叆搴擄紙鍘熻揣浣嶏細{oldLocationCode}锛�",
+                        task.TaskNum);
+
+                    if (oldLocationInfo != null)
+                    {
+                        _locationStatusChangeRecordService.AddLocationStatusChangeRecord(
+                            oldLocationInfo,
+                            beforeOldLocationStatus,
+                            StockChangeType.Outbound.ObjToInt(),
+                            $"璺ㄥ尯鍩熺Щ搴撳嚭搴擄紙鐩爣璐т綅锛歿targetLocationInfo.LocationCode}锛�",
+                            task.TaskNum);
+                    }
+                }
+                catch (Exception ex)
+                {
+                    _logger.LogInformation($"CrossAreaRelocationTaskCompleted 璁板綍鏃ュ織寮傚父锛歿ex.Message}");
+                }
+
+                return content.OK("璺ㄥ尯鍩熺Щ搴撲换鍔″畬鎴�");
+            }
+            catch (Exception ex)
+            {
+                _unitOfWorkManage.RollbackTran();
+                _logger.LogError($"CrossAreaRelocationTaskCompleted 澶勭悊澶辫触锛歿ex.Message}", ex);
+                return await Task.FromResult(WebResponseContent.Instance.Error($"璺ㄥ尯鍩熺Щ搴撲换鍔″鐞嗗け璐ワ細{ex.Message}"));
+            }
+        }
     }
 }
 
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 37dcbc7..10ebb01 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"
@@ -1441,6 +1441,149 @@
                 }
             }
         }
+
+        /// <summary>
+        /// 閫夊畾搴撳瓨璺ㄥ尯鍩熺Щ搴�
+        /// </summary>
+        /// <param name="stockViews"></param>
+        /// <param name="targetLocationType">鐩爣璐т綅绫诲瀷</param>
+        /// <returns></returns>
+        public async Task<WebResponseContent> CrossAreaOutbound(List<StockViewDTO> stockViews, int targetLocationType)
+        {
+            WebResponseContent content = new WebResponseContent();
+            try
+            {
+                if(targetLocationType == (int)LocationTypeEnum.Electronic)
+                {
+                    return content.Error("鐢靛瓙浠撲笉鍏佽璺ㄥ尯鍩熺Щ搴�");
+                }
+                List<int> ids = stockViews.Select(x => x.StockId).ToList();
+                List<Dt_StockInfo> stockInfos = _stockRepository.Db.Queryable<Dt_StockInfo>().Where(x => ids.Contains(x.Id)).Includes(x => x.Details).ToList();
+
+                if (stockInfos.Count != stockViews.Count)
+                {
+                    StockViewDTO? stockViewDTO = stockViews.FirstOrDefault(x => !stockInfos.Select(x => x.PalletCode).Contains(x.PalletCode));
+                    return content.Error($"鏈壘鍒皗stockViewDTO?.PalletCode}搴撳瓨");
+                }
+
+                List<string> locStrs = stockInfos.Select(x => x.LocationCode).ToList();
+                List<Dt_LocationInfo> locationInfos = _locationInfoService.Db.Queryable<Dt_LocationInfo>().Where(x => locStrs.Contains(x.LocationCode)).ToList();
+
+                if (stockInfos.Count != locationInfos.Count)
+                {
+                    string? locStr = locStrs.FirstOrDefault(x => !locationInfos.Select(x => x.LocationCode).Contains(x));
+                    return content.Error($"鏈壘鍒皗locStr}璐т綅鏁版嵁");
+                }
+
+                foreach (var item in stockInfos)
+                {
+                    if (item.PalletType != PalletTypeEnum.Empty.ObjToInt())
+                    {
+                        return content.Error($"鎵樼洏銆恵item.PalletCode}銆戦潪绌虹锛屼粎绌虹鍏佽璺ㄥ尯鍩熺Щ搴擄紒");
+                    }
+                    Dt_LocationInfo? locationInfo = locationInfos.FirstOrDefault(x => x.LocationCode == item.LocationCode);
+                    if (locationInfo == null || locationInfo.EnableStatus != EnableStatusEnum.Normal.ObjToInt() || item.StockStatus != StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt())
+                    {
+                        return content.Error($"{item.PalletCode}璐т綅鎴栧簱瀛樼姸鎬佷笉婊¤冻鍑哄簱鏉′欢");
+                    }
+                }
+
+                List<Dt_Task> tasks = CrossAreaGetTasks(stockInfos, targetLocationType, TaskTypeEnum.CrossAreaRelocation);
+
+                if (tasks == null || tasks.Count <= 0)
+                {
+                    return content.Error("鐢熸垚璺ㄥ尯鍩熺Щ搴撲换鍔″け璐�");
+                }
+
+                stockInfos.ForEach(x =>
+                {
+                    x.StockStatus = StockStatusEmun.鍑哄簱閿佸畾.ObjToInt();
+                });
+
+                tasks.ForEach(x =>
+                {
+                    x.OrderNo = "璺ㄥ尯鍩熺Щ搴�";
+                });
+
+                locationInfos.ForEach(x =>
+                {
+                    x.LocationStatus = LocationStatusEnum.Lock.ObjToInt();
+                });
+
+                _unitOfWorkManage.BeginTran();
+                _stockRepository.UpdateData(stockInfos);
+                BaseDal.AddData(tasks);
+                _locationInfoService.UpdateData(locationInfos);
+                _unitOfWorkManage.CommitTran();
+
+                content.OK();
+            }
+            catch (Exception ex)
+            {
+                _unitOfWorkManage.RollbackTran();
+                return await Task.FromResult(WebResponseContent.Instance.Error(ex.Message));
+            }
+            return content;
+        }
+
+
+        /// <summary>
+        /// 鐢熸垚璺ㄥ尯鍩熺Щ搴撲换鍔�
+        /// </summary>
+        /// <param name="stockInfos">搴撳瓨鍒楄〃</param>
+        /// <param name="targetAreaCode">鐩爣鍖哄煙缂栫爜</param>
+        /// <param name="taskType">浠诲姟绫诲瀷</param>
+        /// <returns></returns>
+        public List<Dt_Task> CrossAreaGetTasks(List<Dt_StockInfo> stockInfos, int targetLocationType, TaskTypeEnum taskType)
+        {
+            using (var scope = new TransactionScope(TransactionScopeOption.Required,
+                new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted }))
+            {
+                try
+                {
+                    List<Dt_Task> tasks = new List<Dt_Task>();
+
+                    foreach (var stockInfo in stockInfos)
+                    {
+                        Dt_LocationInfo newLocation = _locationInfoService.AssignLocation(targetLocationType);
+
+                        if (newLocation == null)
+                        {
+                            throw new Exception($"{stockInfo.PalletCode} 娌℃湁绌洪棽璐т綅鍙繘琛岃法鍖哄煙绉诲簱");
+                        }
+
+                        if (!tasks.Exists(x => x.PalletCode == stockInfo.PalletCode))
+                        {
+                            Dt_Task task = new()
+                            {
+                                CurrentAddress = stockInfo.LocationCode,
+                                Grade = 0,
+                                PalletCode = stockInfo.PalletCode,
+                                NextAddress = "",
+                                Roadway = newLocation.RoadwayNo,
+                                SourceAddress = stockInfo.LocationCode,
+                                TargetAddress = newLocation.LocationCode,
+                                TaskStatus = TaskStatusEnum.New.ObjToInt(),
+                                TaskType = taskType.ObjToInt(),
+                                PalletType = stockInfo.PalletType,
+                                WarehouseId = stockInfo.WarehouseId,
+                            };
+                            tasks.Add(task);
+                        }
+
+                        newLocation.LocationStatus = LocationStatusEnum.Lock.ObjToInt();
+                        _locationInfoService.UpdateData(newLocation);
+                    }
+
+                    scope.Complete();
+                    return tasks;
+                }
+                catch (Exception ex)
+                {
+                    throw new Exception(ex.Message);
+                }
+            }
+        }
     }
 
 }
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_WMSServer/Controllers/TaskInfo/TaskController.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_WMSServer/Controllers/TaskInfo/TaskController.cs"
index 22cc2ac..68dcacb 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_WMSServer/Controllers/TaskInfo/TaskController.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_WMSServer/Controllers/TaskInfo/TaskController.cs"
@@ -144,5 +144,12 @@
         {
             return await Service.AreaOutbound(stockViews);
         }
+
+
+        [HttpPost, HttpGet, Route("CrossAreaOutbound"), AllowAnonymous]
+        public async Task<WebResponseContent> CrossAreaOutbound([FromBody] List<StockViewDTO> stockViews,int targetLocationType)
+        {
+            return await Service.CrossAreaOutbound(stockViews,targetLocationType);
+        }
     }
 }

--
Gitblit v1.9.3