From 569b9900086f06fbd986f69534c8d5af54c4d55b Mon Sep 17 00:00:00 2001
From: heshaofeng <heshaofeng@hnkhzn.com>
Date: 星期一, 16 三月 2026 10:51:43 +0800
Subject: [PATCH] 1

---
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_WMSServer/Controllers/Outbound/OutboundController.cs |   30 +++
 项目代码/WIDESEA_WMSClient/src/views/outbound/allocateoutboundOrder.vue                         |    2 
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_DTO/CalcOut/OutboundCompleteRequestDTO.cs            |   66 ++++++++
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_IOutboundService/IOutboundService.cs                 |    2 
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_OutboundService/OutboundService.cs                   |  295 ++++++++++++++++++++++++++++++++++++
 项目代码/WIDESEA_WMSClient/src/views/inbound/Dt_AllocateOrder.vue                               |    2 
 项目代码/WIDESEA_WMSClient/src/views/outbound/outPicking.vue                                    |   77 ++++++++-
 项目代码/WIDESEA_WMSClient/src/views/inbound/allocateinboundOrder.vue                           |    2 
 项目代码/WMS无仓储版/WIDESEA_WMSServer/WIDESEA_StockService/StockInfoDetailService.cs               |    2 
 9 files changed, 463 insertions(+), 15 deletions(-)

diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/inbound/Dt_AllocateOrder.vue" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/inbound/Dt_AllocateOrder.vue"
index 872ab5b..bf835df 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/inbound/Dt_AllocateOrder.vue"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/inbound/Dt_AllocateOrder.vue"
@@ -209,7 +209,7 @@
           title: "鍥炰紶MES鐘舵��",
           field: "returnToMESStatus",
           type: "select",
-          dataKey: "returnToMESStatus",
+          dataKey: "outboundReturnToMESStatus",
           data: [],
         },
         { title: "鐗╂枡缂栧彿", field: "materielCode", type: "like" },
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/inbound/allocateinboundOrder.vue" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/inbound/allocateinboundOrder.vue"
index 888147c..583abee 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/inbound/allocateinboundOrder.vue"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/inbound/allocateinboundOrder.vue"
@@ -94,7 +94,7 @@
           title: "鍥炰紶MES鐘舵��",
           field: "returnToMESStatus",
           type: "select",
-          dataKey: "returnToMESStatus",
+          dataKey: "outboundReturnToMESStatus",
           data: [],
         },
         { title: "鐗╂枡缂栧彿", field: "materielCode", type: "like" },
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/outbound/allocateoutboundOrder.vue" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/outbound/allocateoutboundOrder.vue"
index b06b71f..9c47fad 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/outbound/allocateoutboundOrder.vue"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/outbound/allocateoutboundOrder.vue"
@@ -103,7 +103,7 @@
           title: "鍥炰紶MES鐘舵��",
           field: "returnToMESStatus",
           type: "select",
-          dataKey: "returnToMESStatus",
+          dataKey: "outboundReturnToMESStatus",
           data: [],
         },
         { title: "鐗╂枡缂栧彿", field: "materielCode", type: "like" },
diff --git "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/outbound/outPicking.vue" "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/outbound/outPicking.vue"
index 49b205f..2ce2088 100644
--- "a/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/outbound/outPicking.vue"
+++ "b/\351\241\271\347\233\256\344\273\243\347\240\201/WIDESEA_WMSClient/src/views/outbound/outPicking.vue"
@@ -214,6 +214,19 @@
                             <el-table-column prop="createDate" label="鎷i�夋椂闂�" width="160" />
                             <el-table-column prop="originalBarcode" label="鍘熺墿鏂欑爜" width="160" />
                             <el-table-column prop="newBarcode" label="鏂扮墿鏂欑爜" width="160" />
+                            <el-table-column label="鎿嶄綔" width="100" align="center">
+                        <template #default="scope">
+                            <el-button 
+                                type="danger" 
+                                size="small" 
+                                icon="el-icon-refresh-left"
+                                @click="handleReversePicking(scope.row)"
+                                :disabled="reverseLoading"
+                            >
+                                鎾ら攢
+                            </el-button>
+                        </template>
+                    </el-table-column>
                         </el-table>
 
                         <div class="table-footer">
@@ -376,7 +389,8 @@
             loadingInstance: null,
             // 闊抽瀹炰緥锛堢紦瀛橈紝閬垮厤閲嶅鍒涘缓锛�
             successAudio: null,
-            errorAudio: null
+            errorAudio: null,
+            reverseLoading: false
         }
     },
     computed: {
@@ -412,7 +426,6 @@
             }
         },
 
-        // ============== 鏂板锛氭牴鎹墭鐩樺彿鑾峰彇璁㈠崟鍙凤紙鏍稿績鍔熻兘锛� ==============
         async getOrderNoByPallet(palletCode) {
             if (!palletCode) {
                 this.$message.warning('鎵樼洏鍙蜂笉鑳戒负绌�');
@@ -457,7 +470,7 @@
                 this.hideFullScreenLoading();
             }
         },
-        // ============== 鏂板缁撴潫 ==============
+        
 
         // 鎾斁鎴愬姛闊抽
         playSuccessAudio() {
@@ -485,14 +498,7 @@
         initPage() {
             // 浠庤矾鐢卞弬鏁拌幏鍙栬鍗曞彿
             this.orderNo = this.$route.query.orderNo || ''
-            // ============== 寰皟锛氭敞閲婂己鍒惰繑鍥為�昏緫锛屽吋瀹规墭鐩樺彿鏌ヨ鍗曞彿 ==============
-            // if (!this.orderNo) {
-            //     this.$message.error('璁㈠崟鍙蜂笉鑳戒负绌�')
-            //     this.$router.back()
-            //     return
-            // }
-            // ============== 寰皟缁撴潫 ==============
-
+            
             // 鍔犺浇璁㈠崟淇℃伅
             this.loadOrderInfo()
 
@@ -694,6 +700,55 @@
             });
         },
 
+        async handleReversePicking(row) {
+            // 1. 浜屾纭
+            try {
+                await this.$confirm(
+                    '纭畾瑕佹挙閿�杩欐潯鎷i�夎褰曞悧锛熸挙閿�鍚庡簱瀛樺皢鎭㈠锛屽嚭搴撳崟鐘舵�佷篃浼氬悓姝ユ洿鏂�', 
+                    '鎾ら攢纭', 
+                    {
+                        type: 'warning',
+                        confirmButtonText: '纭鎾ら攢',
+                        cancelButtonText: '鍙栨秷',
+                        closeOnClickModal: false
+                    }
+                );
+
+                // 2. 鎵ц鎾ら攢
+                this.reverseLoading = true;
+                this.showFullScreenLoading();
+
+                // 3. 璋冪敤鎾ら攢鎺ュ彛锛堥�傞厤浣犲悗绔殑鎾ら攢鎺ュ彛鍦板潃锛�
+                const response = await this.http.post('/api/Outbound/ReversePickingWithBarcode', {
+                    Barcode: row.originalBarcode || row.newBarcode, // 浼樺厛鍙栧師鏉$爜锛屾棤鍒欏彇鏂版潯鐮�
+                    OrderNo: this.orderNo,
+                    PalletCode: row.palletCode || this.scanForm.palletCode,
+                    Operator: this.getUserName(),
+                    OrderType: this.orderInfo?.orderType || 0 // 璁㈠崟绫诲瀷锛屾棤鍒欎紶0
+                });
+
+                // 4. 澶勭悊缁撴灉
+                if (response.status) {
+                    this.$message.success('鎾ら攢鎷i�夋垚鍔�');
+                    this.playSuccessAudio(); // 鎾斁鎴愬姛闊抽
+                    // 鍒锋柊鏁版嵁鍒楄〃
+                    await this.loadPalletData(false);
+                } else {
+                    this.$message.error(response.message || '鎾ら攢鎷i�夊け璐�');
+                    this.playErrorAudio();
+                }
+            } catch (error) {
+                // 鍙栨秷纭涓嶆姤閿�
+                if (error !== 'cancel') {
+                    this.$message.error('鎾ら攢鎷i�夊け璐ワ細' + (error.message || '缃戠粶寮傚父'));
+                    this.playErrorAudio();
+                }
+            } finally {
+                this.reverseLoading = false;
+                this.hideFullScreenLoading();
+            }
+        },
+
         handleMaterialScan() {
             if (!this.scanForm.palletCode) {
                 this.$message.warning('璇峰厛鎵弿鎵樼洏鐮�')
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_DTO/CalcOut/OutboundCompleteRequestDTO.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_DTO/CalcOut/OutboundCompleteRequestDTO.cs"
index 944df65..3820f8d 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_DTO/CalcOut/OutboundCompleteRequestDTO.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_DTO/CalcOut/OutboundCompleteRequestDTO.cs"
@@ -76,4 +76,70 @@
         public string barCode { get; set; }
 
     }
+
+    /// <summary>
+    /// 鎾ら攢鎷i�夎姹侱TO
+    /// </summary>
+    public class ReversePickingRequestDTO
+    {
+        /// <summary>
+        /// 瑕佹挙閿�鐨勬嫞閫夋潯鐮侊紙蹇呭~锛�
+        /// </summary>
+        [Required(ErrorMessage = "鏉$爜涓嶈兘涓虹┖")]
+        [MaxLength(50, ErrorMessage = "鏉$爜闀垮害涓嶈兘瓒呰繃50涓瓧绗�")]
+        public string Barcode { get; set; }
+
+        /// <summary>
+        /// 鍑哄簱鍗曞彿锛堝繀濉級
+        /// </summary>
+        [Required(ErrorMessage = "鍑哄簱鍗曞彿涓嶈兘涓虹┖")]
+        [MaxLength(50, ErrorMessage = "鍑哄簱鍗曞彿闀垮害涓嶈兘瓒呰繃50涓瓧绗�")]
+        public string OrderNo { get; set; }
+
+        /// <summary>
+        /// 鎵樼洏鍙凤紙蹇呭~锛�
+        /// </summary>
+        [Required(ErrorMessage = "鎵樼洏鍙蜂笉鑳戒负绌�")]
+        [MaxLength(50, ErrorMessage = "鎵樼洏鍙烽暱搴︿笉鑳借秴杩�50涓瓧绗�")]
+        public string PalletCode { get; set; }
+
+        /// <summary>
+        /// 鎿嶄綔鑰咃紙蹇呭~锛�
+        /// </summary>
+        [Required(ErrorMessage = "鎿嶄綔鑰呬笉鑳戒负绌�")]
+        [MaxLength(50, ErrorMessage = "鎿嶄綔鑰呴暱搴︿笉鑳借秴杩�50涓瓧绗�")]
+        public string Operator { get; set; }
+
+        /// <summary>
+        /// 璁㈠崟绫诲瀷锛堝彲閫夛紝鏅轰粨璋冩嫧涓撶敤锛�
+        /// </summary>
+        [Range(0, int.MaxValue, ErrorMessage = "璁㈠崟绫诲瀷蹇呴』涓洪潪璐熸暣鏁�")]
+        public int OrderType { get; set; }
+    }
+
+    /// <summary>
+    /// 鎾ら攢鎷i�夊搷搴擠TO
+    /// </summary>
+    public class ReversePickingResponseDTO
+    {
+        /// <summary>
+        /// 鏄惁鎴愬姛
+        /// </summary>
+        public bool Success { get; set; }
+
+        /// <summary>
+        /// 鎻愮ず淇℃伅
+        /// </summary>
+        public string Message { get; set; }
+
+        /// <summary>
+        /// 鎾ら攢鐨勬潯鐮�
+        /// </summary>
+        public string Barcode { get; set; }
+
+        /// <summary>
+        /// 鎭㈠鐨勫簱瀛樻暟閲�
+        /// </summary>
+        public decimal RestoredQuantity { get; set; }
+    }
 }
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_IOutboundService/IOutboundService.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_IOutboundService/IOutboundService.cs"
index 410afa4..0626627 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_IOutboundService/IOutboundService.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_IOutboundService/IOutboundService.cs"
@@ -69,6 +69,8 @@
         /// <returns></returns>
         WebResponseContent RecheckPicking(RecheckPickingDTO pickingDTO);
 
+        WebResponseContent ReversePicking(ReversePickingRequestDTO reversePickingRequestDTO);
+
         WebResponseContent PrintFromData(string barcode);
     }
 }
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/OutboundService.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/OutboundService.cs"
index 6a79f4c..4d08558 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/OutboundService.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/OutboundService.cs"
@@ -1970,6 +1970,7 @@
                 OperateType = "鍑哄簱瀹屾垚",
                 InsertTime = DateTime.Now,
                 StockId = stockDetail.StockId,
+                Barcode = stockDetail.Barcode,
                 MaterielCode = stockDetail.MaterielCode,
                 MaterielName = stockDetail.MaterielName,
                 OrderNo = stockDetail.OrderNo,
@@ -2444,6 +2445,300 @@
 
         #endregion
 
+        #region 鎾ら攢鎷i��
+        /// <summary>
+        /// 鎾ら攢鎷i�夋潯鐮侊紙鍙嶅悜鍥炴粴鍑哄簱鎷i�夋搷浣滐級
+        /// </summary>
+        /// <param name="request">鎾ら攢鎷i�夎姹傦紙鑷冲皯鍖呭惈鏉$爜銆佽鍗曞彿銆佹墭鐩樺彿锛�</param>
+        /// <returns>鎾ら攢鍝嶅簲</returns>
+        public WebResponseContent ReversePicking(ReversePickingRequestDTO request)
+        {
+            WebResponseContent content = WebResponseContent.Instance;
+            ReversePickingResponseDTO response = new ReversePickingResponseDTO();
 
+            try
+            {
+                if (string.IsNullOrWhiteSpace(request.Barcode) || string.IsNullOrWhiteSpace(request.OrderNo) || string.IsNullOrWhiteSpace(request.PalletCode))
+                {
+                    response.Success = false;
+                    response.Message = "鏉$爜銆佽鍗曞彿銆佹墭鐩樺彿涓嶈兘涓虹┖";
+                    return WebResponseContent.Instance.Error(response.Message);
+                }
+
+                Dt_StockInfo stockInfo = _stockInfoRepository.QueryFirst(x => x.PalletCode == request.PalletCode);
+                if (stockInfo == null)
+                {
+                    response.Success = false;
+                    response.Message = $"鎵樼洏鍙� {request.PalletCode} 瀵瑰簲鐨勫簱瀛樹笉瀛樺湪";
+                    return WebResponseContent.Instance.Error(response.Message);
+                }
+
+                Dt_OutboundOrder outboundOrder = _outboundRepository.QueryFirst(o => o.OrderNo == request.OrderNo);
+                if (outboundOrder == null)
+                {
+                    response.Success = false;
+                    response.Message = $"鍑哄簱鍗� {request.OrderNo} 涓嶅瓨鍦�";
+                    return WebResponseContent.Instance.Error(response.Message);
+                }
+
+                Dt_StockInfoDetail_Hty historyDetail = _stockDetailHistoryRepository.QueryFirst(x =>
+                    x.Barcode == request.Barcode &&
+                 
+                    (x.OperateType == "鍑哄簱瀹屾垚" || x.OperateType == "鎷嗗寘-鍘熷璁板綍"));
+                if (historyDetail == null)
+                {
+                    response.Success = false;
+                    response.Message = $"鏉$爜 {request.Barcode} 宸叉媶鍖咃紝鏃犳硶鎾ら攢";
+                    return WebResponseContent.Instance.Error(response.Message);
+                }
+
+                Dt_OutStockLockInfo lockInfo = _outboundLockInfoRepository.QueryFirst(x =>
+                    x.OrderNo == request.OrderNo &&
+                    x.StockId == stockInfo.Id &&
+                    x.MaterielCode == historyDetail.MaterielCode &&
+                    x.PalletCode == stockInfo.PalletCode);
+
+                _unitOfWorkManage.BeginTran();
+                try
+                {
+                    if(lockInfo == null)
+                    {
+                        return WebResponseContent.Instance.Error("璇ユ墭鐩樺凡鍏ㄩ儴鎷i�夊畬,涓嶅厑璁告挙閿�");
+                    }
+                    bool isUnpack = historyDetail.OperateType == "鎷嗗寘-鍘熷璁板綍";
+                    if (isUnpack)
+                    {
+                        return WebResponseContent.Instance.Error("璇ユ潯鐮佸凡鎷嗗寘锛屼笉鍏佽鎾ら攢");
+                    }
+                    else
+                    {
+                        ReverseFullOutboundOperation(historyDetail, stockInfo, request);
+                    }
+                    RollbackOutboundOrderDetails(historyDetail.MaterielCode, request.OrderNo, historyDetail.StockQuantity, stockInfo.Id);
+
+                    if (lockInfo != null)
+                    {
+                        lockInfo.SortedQuantity = Math.Max(0, (decimal)(lockInfo.SortedQuantity - historyDetail.StockQuantity));
+
+                        if (lockInfo.SortedQuantity == 0)
+                        {
+                            _outboundLockInfoRepository.UpdateData(lockInfo);
+                        }
+                        else
+                        {
+                            _outboundLockInfoRepository.UpdateData(lockInfo);
+                        }
+                    }
+
+                    _stockDetailHistoryRepository.DeleteData(historyDetail);
+
+                    DeleteStockChangeRecord(request.Barcode, request.OrderNo);
+
+                    if (!CheckOutboundOrderCompleted(request.OrderNo))
+                    {
+                        UpdateOutboundOrderStatus(request.OrderNo, OutOrderStatusEnum.鍑哄簱涓�.ObjToInt());
+                    }
+
+                    _unitOfWorkManage.CommitTran();
+
+                    response.Success = true;
+                    response.Message = $"鏉$爜 {request.Barcode} 鎾ら攢鎷i�夋垚鍔�";
+                    response.Barcode = request.Barcode;
+                    response.RestoredQuantity = historyDetail.StockQuantity;
+
+                    content = WebResponseContent.Instance.OK(data: response);
+                }
+                catch (Exception ex)
+                {
+                    _unitOfWorkManage.RollbackTran();
+                    response.Success = false;
+                    response.Message = $"鎾ら攢鎷i�夊け璐ワ細{ex.Message}";
+                    content = WebResponseContent.Instance.Error(response.Message);
+                }
+            }
+            catch (Exception ex)
+            {
+                response.Success = false;
+                response.Message = $"澶勭悊鎾ら攢鎷i�夊け璐ワ細{ex.Message}";
+                content = WebResponseContent.Instance.Error(response.Message);
+            }
+
+            return content;
+        }
+
+        /// <summary>
+        /// 鎾ら攢鎷嗗寘鍑哄簱鎿嶄綔锛堝弽鍚戞仮澶嶆媶鍖呭墠鐘舵�侊級
+        /// </summary>
+        private void ReverseUnpackOperation(Dt_StockInfoDetail_Hty historyDetail, Dt_StockInfo stockInfo, ReversePickingRequestDTO request, Dt_OutboundOrder outboundOrder)
+        {
+            Dt_StockInfoDetail currentDetail = _stockDetailRepository.QueryFirst(x =>
+                x.Barcode == request.Barcode &&
+                x.StockId == stockInfo.Id &&
+                x.MaterielCode == historyDetail.MaterielCode);
+
+            if (currentDetail != null)
+            {
+                currentDetail.StockQuantity = historyDetail.StockQuantity;
+                currentDetail.Remark = $"鎾ら攢鎷嗗寘鎷i�夛紝鎭㈠鍘熷鏁伴噺锛歿historyDetail.StockQuantity}锛屾搷浣滆�咃細{request.Operator}";
+                _stockDetailRepository.UpdateData(currentDetail);
+            }
+            else
+            {
+                Dt_StockInfoDetail restoreDetail = new Dt_StockInfoDetail
+                {
+                    StockId = historyDetail.StockId,
+                    MaterielCode = historyDetail.MaterielCode,
+                    MaterielName = historyDetail.MaterielName,
+                    Barcode =historyDetail.Barcode,
+                    OrderNo = historyDetail.OrderNo,
+                    BatchNo = historyDetail.BatchNo,
+                    ProductionDate = historyDetail.ProductionDate,
+                    EffectiveDate = historyDetail.EffectiveDate,
+                    SerialNumber = historyDetail.SerialNumber,
+                    StockQuantity = historyDetail.StockQuantity,
+                    OutboundQuantity = historyDetail.OutboundQuantity,
+                    Status = historyDetail.Status,
+                    Unit = historyDetail.Unit,
+                    InboundOrderRowNo = historyDetail.InboundOrderRowNo,
+                    SupplyCode = historyDetail.SupplyCode,
+                    Creater = request.Operator,
+                    CreateDate = DateTime.Now,
+                    FactoryArea = historyDetail.FactoryArea,
+                    WarehouseCode = historyDetail.WarehouseCode,
+                    Remark = $"鎾ら攢鎷嗗寘鎷i�夛紝閲嶆柊鍒涘缓搴撳瓨鏄庣粏锛屾潯鐮侊細{request.Barcode}锛屾搷浣滆�咃細{request.Operator}"
+                };
+                _stockDetailRepository.AddData(restoreDetail);
+            }
+
+            List<Dt_MaterialCodeInfo> materialCodeInfos = _basicService.MaterielCodeInfoService.Repository.QueryData(x =>
+                x.OldBarcode == request.Barcode &&
+                x.OrderNo == request.OrderNo);
+            if (materialCodeInfos.Any())
+            {
+                _basicService.MaterielCodeInfoService.Repository.DeleteData(materialCodeInfos);
+            }
+
+            if (outboundOrder.OrderType == InOrderTypeEnum.InternalAllocat.ObjToInt())
+            {
+                Dt_AllocateMaterialInfo allocateMaterialInfo = _allocateMaterialInfoRepository.QueryFirst(x =>
+                    x.Barcode == request.Barcode &&
+                    x.OrderNo == request.OrderNo);
+                if (allocateMaterialInfo != null)
+                {
+                    _allocateMaterialInfoRepository.DeleteData(allocateMaterialInfo);
+                }
+            }
+        }
+
+        /// <summary>
+        /// 鎾ら攢瀹屾暣鍑哄簱鎿嶄綔锛堟仮澶嶈鍒犻櫎鐨勫簱瀛樻槑缁嗭級
+        /// </summary>
+        private void ReverseFullOutboundOperation(Dt_StockInfoDetail_Hty historyDetail, Dt_StockInfo stockInfo, ReversePickingRequestDTO request)
+        {
+            Dt_StockInfoDetail restoreDetail = new Dt_StockInfoDetail
+            {
+             
+                StockId = historyDetail.StockId,
+                MaterielCode = historyDetail.MaterielCode,
+                MaterielName = historyDetail.MaterielName,
+                Barcode = historyDetail.Barcode,
+                OrderNo = historyDetail.OrderNo,
+                BatchNo = historyDetail.BatchNo,
+                ProductionDate = historyDetail.ProductionDate,
+                EffectiveDate = historyDetail.EffectiveDate,
+                SerialNumber = historyDetail.SerialNumber,
+                StockQuantity = historyDetail.StockQuantity,
+                OutboundQuantity = historyDetail.OutboundQuantity - historyDetail.StockQuantity,
+                Status = historyDetail.Status,
+                Unit = historyDetail.Unit,
+                InboundOrderRowNo = historyDetail.InboundOrderRowNo,
+                SupplyCode = historyDetail.SupplyCode,
+                Creater = request.Operator,
+                CreateDate = DateTime.Now,
+                FactoryArea = historyDetail.FactoryArea,
+                WarehouseCode = historyDetail.WarehouseCode,
+                Remark = $"鎾ら攢瀹屾暣鍑哄簱鎷i�夛紝鎭㈠搴撳瓨鏄庣粏锛屾潯鐮侊細{request.Barcode}锛屾搷浣滆�咃細{request.Operator}"
+            };
+
+            _stockDetailRepository.AddData(restoreDetail);
+
+            if (request.OrderType == InOrderTypeEnum.InternalAllocat.ObjToInt())
+            {
+                Dt_AllocateMaterialInfo allocateMaterialInfo = _allocateMaterialInfoRepository.QueryFirst(x =>
+                    x.Barcode == request.Barcode &&
+                    x.OrderNo == request.OrderNo);
+                if (allocateMaterialInfo != null)
+                {
+                    _allocateMaterialInfoRepository.DeleteData(allocateMaterialInfo);
+                }
+            }
+        }
+
+        /// <summary>
+        /// 鍥炴粴鍑哄簱鍗曟槑缁嗭紙鎵e噺宸插嚭搴撴暟閲忥級
+        /// </summary>
+        private void RollbackOutboundOrderDetails(string materielCode, string orderNo, decimal rollbackQuantity, int stockId)
+        {
+            Dt_OutboundOrder outboundOrder = _outboundRepository.QueryFirst(x => x.OrderNo == orderNo);
+            List<Dt_OutboundOrderDetail> details = _detailRepository.QueryData(x =>
+                x.OrderId == outboundOrder.Id &&
+                x.MaterielCode == materielCode &&
+                x.OverOutQuantity > 0);
+
+            if (!details.Any()) return;
+
+            decimal remainingRollbackQty = rollbackQuantity;
+            foreach (var detail in details)
+            {
+                if (remainingRollbackQty <= 0) break;
+
+                decimal rollbackQty = Math.Min(remainingRollbackQty, detail.OverOutQuantity);
+
+                detail.OverOutQuantity -= rollbackQty;
+                detail.CurrentDeliveryQty -= rollbackQty;
+
+                if (detail.OrderDetailStatus == (int)OrderDetailStatusEnum.Over && detail.OverOutQuantity < detail.OrderQuantity - detail.MoveQty)
+                {
+                    detail.OrderDetailStatus = (int)OrderDetailStatusEnum.New;
+                }
+
+                if (!string.IsNullOrEmpty(detail.ReturnJsonData))
+                {
+                    List<Barcodes> barcodesList = JsonConvert.DeserializeObject<List<Barcodes>>(detail.ReturnJsonData) ?? new List<Barcodes>();
+                    var targetBarcode = barcodesList.FirstOrDefault(x => x.Barcode == materielCode);
+                    if (targetBarcode != null)
+                    {
+                        barcodesList.Remove(targetBarcode);
+                        detail.ReturnJsonData = JsonConvert.SerializeObject(barcodesList, new JsonSerializerSettings
+                        {
+                            ContractResolver = new CamelCasePropertyNamesContractResolver()
+                        });
+                    }
+                }
+
+                _detailRepository.UpdateData(detail);
+                remainingRollbackQty -= rollbackQty;
+            }
+        }
+
+        /// <summary>
+        /// 鍒犻櫎搴撳瓨鍙樺姩璁板綍锛堟嫞閫夋椂鐢熸垚鐨勶級
+        /// </summary>
+        private void DeleteStockChangeRecord(string barcode, string orderNo)
+        {
+            Dt_StockQuantityChangeRecord changeRecord = _stockChangeRepository.QueryFirst(x =>
+                x.OriginalSerilNumber == barcode &&
+                x.OrderNo == orderNo &&
+                x.ChangeType == (int)StockChangeTypeEnum.Outbound);
+            if (changeRecord != null)
+            {
+                _stockChangeRepository.DeleteData(changeRecord);
+            }
+        }
+
+       
+        #endregion
+
+       
     }
 }
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_StockService/StockInfoDetailService.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_StockService/StockInfoDetailService.cs"
index 001a4fc..2c85ebd 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_StockService/StockInfoDetailService.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_StockService/StockInfoDetailService.cs"
@@ -38,7 +38,7 @@
         {
 
             var sugarQueryable = Db.Queryable<Dt_StockInfoDetail>().InnerJoin<Dt_StockInfo>((detail, item) => detail.StockId == item.Id)
-                .Where((detail, item) => item.StockStatus == StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt());
+                .Where((detail, item) => item.StockStatus == StockStatusEmun.鍏ュ簱瀹屾垚.ObjToInt() || item.StockStatus == StockStatusEmun.鍑哄簱瀹屾垚.ObjToInt());
 
             Dictionary<string, SqlSugar.OrderByType> orderbyDic = GetPageDataSort(options, TProperties);
             List<OrderByModel> orderByModels = new List<OrderByModel>();
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/Outbound/OutboundController.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/Outbound/OutboundController.cs"
index 3b155bd..fa3b447 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/Outbound/OutboundController.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/Outbound/OutboundController.cs"
@@ -64,6 +64,36 @@
             }
         }
 
+        /// <summary>
+        /// 鎾ら攢鎷i�夋潯鐮佹帴鍙o紙鍙嶅悜鍥炴粴鎷i�夋搷浣滐級
+        /// </summary>
+        /// <param name="request">鎾ら攢鎷i�夎姹傚弬鏁�</param>
+        /// <returns>鎺ュ彛鍝嶅簲缁撴灉</returns>
+        [HttpPost, Route("ReversePickingWithBarcode"), AllowAnonymous]
+        public WebResponseContent ReversePickingWithBarcode([FromBody] ReversePickingRequestDTO request)
+        {
+            try
+            {
+                lock (lockObj)
+                {
+                    if (!ModelState.IsValid)
+                    {
+                        string errorMsg = string.Join("; ", ModelState.Values
+                            .SelectMany(v => v.Errors)
+                            .Select(e => e.ErrorMessage));
+                        return WebResponseContent.Instance.Error(errorMsg);
+                    }
+
+                    return _outboundService.ReversePicking(request);
+                }
+            }
+            catch (Exception ex)
+            {
+                return WebResponseContent.Instance.Error($"鎾ら攢鎷i�夋搷浣滃け璐�: {ex.Message}");
+            }
+        }
+
+
         [HttpPost, Route("CompleteOutboundWithPallet"), AllowAnonymous]
         public WebResponseContent CompleteOutboundWithPallet([FromBody] OutboundCompletePalletRequestDTO request)
         {

--
Gitblit v1.9.3