From 9571956561915d24ebfc0915117e7df24ea3058d Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期五, 03 四月 2026 10:52:05 +0800
Subject: [PATCH] fix: 发货审批通过库存不扣减

---
 src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java    |   65 ++++++++--
 src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java |   32 +++-
 src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java     |  116 +++++++++++++++++--
 src/main/java/com/ruoyi/sales/service/ShippingInfoService.java              |    2 
 src/main/java/com/ruoyi/sales/pojo/SalesLedger.java                         |    4 
 src/main/java/com/ruoyi/basic/pojo/ProductModel.java                        |    2 
 src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java        |  102 ++++++++--------
 7 files changed, 232 insertions(+), 91 deletions(-)

diff --git a/src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java b/src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java
index 00a53f5..cee9249 100644
--- a/src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java
+++ b/src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java
@@ -27,11 +27,14 @@
 import com.ruoyi.purchase.service.impl.PurchaseLedgerServiceImpl;
 import com.ruoyi.sales.mapper.*;
 import com.ruoyi.sales.pojo.CommonFile;
+import com.ruoyi.sales.pojo.SalesLedger;
 import com.ruoyi.sales.pojo.SalesLedgerProduct;
 import com.ruoyi.sales.pojo.SalesQuotation;
 import com.ruoyi.sales.pojo.ShippingInfo;
+import com.ruoyi.sales.service.ShippingInfoService;
 import com.ruoyi.sales.service.impl.CommonFileServiceImpl;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 
@@ -81,6 +84,13 @@
 
     @Autowired
     private PurchaseLedgerServiceImpl purchaseLedgerServiceImpl;
+
+    @Autowired
+    private SalesLedgerMapper salesLedgerMapper;
+
+    @Autowired
+    @Lazy
+    private ShippingInfoService shippingInfoService;
 
 
     public ApproveProcess getApproveById(String id) {
@@ -232,24 +242,34 @@
             }
             salesQuotationMapper.updateById(salesQuote);
         }
-        // 鍑哄簱瀹℃壒淇敼
+        // 鍑哄簱瀹℃壒淇敼 (璁㈠崟绾у埆)
         if(approveProcess.getApproveType().equals(7)){
             String[] split = approveProcess.getApproveReason().split(":");
-            ShippingInfo shippingInfo = shippingInfoMapper.selectOne(new LambdaQueryWrapper<ShippingInfo>()
-                    .eq(ShippingInfo::getShippingNo, split[1])
-                    .orderByDesc(ShippingInfo::getCreateTime)
-                    .last("limit 1"));
-            if(shippingInfo != null){
-                if(status.equals(2)){
-                    shippingInfo.setStatus("瀹℃牳閫氳繃");
-                }else if(status.equals(3)){
-                    shippingInfo.setStatus("瀹℃牳鎷掔粷");
-                }else if(status.equals(1)){
-                    shippingInfo.setStatus("瀹℃牳涓�");
+            if (split.length > 1) {
+                String identifier = split[1];
+                // 鏌ユ壘閿�鍞彴璐�
+                SalesLedger salesLedger = salesLedgerMapper.selectOne(new LambdaQueryWrapper<SalesLedger>()
+                        .eq(SalesLedger::getSalesContractNo, identifier)
+                        .last("limit 1"));
+                
+                if (salesLedger != null) {
+                    if(status.equals(2)){
+                        // 瀹℃壒瀹屾垚 -> 鑷姩鎵i櫎搴撳瓨
+                        try {
+                            shippingInfoService.deductStockByOrder(salesLedger.getId(), null);
+                        } catch (IOException e) {
+                            throw new RuntimeException("鑷姩鎵i櫎搴撳瓨澶辫触: " + e.getMessage());
+                        }
+                    } else if(status.equals(3)){
+                        updateSalesLedgerDeliveryStatus(salesLedger.getId(), 3);
+                        // 鏇存柊鍏宠仈鐨勫彂璐ц褰曚负瀹℃牳鎷掔粷
+                        updateShippingInfoStatusByOrder(salesLedger.getId(), "瀹℃牳鎷掔粷");
+                    } else if(status.equals(1)){
+                        updateSalesLedgerDeliveryStatus(salesLedger.getId(), 2);
+                        updateShippingInfoStatusByOrder(salesLedger.getId(), "瀹℃牳涓�");
+                    }
                 }
-                shippingInfoMapper.updateById(shippingInfo);
             }
-
         }
         // 缁戝畾闄勪欢
         if(!CollectionUtils.isEmpty(approveNode.getTempFileIds()) && approveNode.getApproveNodeStatus() == 1){
@@ -257,6 +277,23 @@
         }
     }
 
+    private void updateShippingInfoStatusByOrder(Long salesLedgerId, String statusText) {
+        if (salesLedgerId == null) return;
+        shippingInfoMapper.update(null, new UpdateWrapper<ShippingInfo>()
+                .lambda()
+                .set(ShippingInfo::getStatus, statusText)
+                .eq(ShippingInfo::getSalesLedgerId, salesLedgerId));
+    }
+
+    private void updateSalesLedgerDeliveryStatus(Long salesLedgerId, Integer status) {
+        if (salesLedgerId == null) return;
+        SalesLedger salesLedger = salesLedgerMapper.selectById(salesLedgerId);
+        if (salesLedger != null) {
+            salesLedger.setDeliveryStatus(status);
+            salesLedgerMapper.updateById(salesLedger);
+        }
+    }
+
     @Override
     public void updateApproveNode(ApproveNode approveNode) throws IOException {
         // 瀹℃壒鑺傜偣鐘舵��:1鍚屾剰锛�2鎷掔粷锛�0灏氭湭瀹℃牳
diff --git a/src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java b/src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java
index a624661..e42726f 100644
--- a/src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java
+++ b/src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java
@@ -29,6 +29,8 @@
 import com.ruoyi.purchase.pojo.PurchaseLedger;
 import com.ruoyi.sales.mapper.CommonFileMapper;
 import com.ruoyi.sales.mapper.ShippingInfoMapper;
+import com.ruoyi.sales.mapper.SalesLedgerMapper;
+import com.ruoyi.sales.pojo.SalesLedger;
 import com.ruoyi.sales.pojo.CommonFile;
 import com.ruoyi.sales.pojo.ShippingInfo;
 import com.ruoyi.sales.service.impl.CommonFileServiceImpl;
@@ -79,6 +81,9 @@
     private  CommonFileServiceImpl commonFileService;
     @Autowired
     private  ISysNoticeService sysNoticeService;
+
+    @Autowired
+    private SalesLedgerMapper salesLedgerMapper;
 
     @Override
     public void addApprove(ApproveProcessVO approveProcessVO) throws Exception {
@@ -191,19 +196,28 @@
 
             //  鍙戣揣瀹℃壒鏌ヨ
             else if (record.getApproveType() == 7) {
-                String reason = record.getApproveReason(); // 鏍煎紡涓� "xx:...-..."
+                String reason = record.getApproveReason(); // 鏍煎紡涓� "xx:CONTRACT_NO"
                 if (StringUtils.hasText(reason) && reason.contains(":")) {
-                    // 鎻愬彇鍐掑彿鍚庨潰鐨勫彂璐у崟鍙�
-                    String shippingNo = reason.split(":")[1];
-                    // 鏍规嵁鍙戣揣鍗曞彿鏌ヨ鍙戣揣鍙拌处璁板綍
-                    ShippingInfo shippingInfo = shippingInfoMapper.selectOne(new LambdaQueryWrapper<ShippingInfo>()
-                            .eq(ShippingInfo::getShippingNo, shippingNo)
+                    // 鎻愬彇鍐掑彿鍚庨潰鐨勬爣璇嗙 (鍙兘鏄悎鍚屽彿鎴栧彂璐у崟鍙�)
+                    String identifier = reason.split(":")[1];
+                    // 1. 浼樺厛灏濊瘯鎵鹃攢鍞彴璐� (鏂伴�昏緫锛氬悎鍚屽彿鍚屾瀹℃壒)
+                    SalesLedger ledger = salesLedgerMapper.selectOne(new LambdaQueryWrapper<SalesLedger>()
+                            .eq(SalesLedger::getSalesContractNo, identifier)
                             .last("limit 1"));
-                    if (shippingInfo != null) {
-                        // 浣跨敤鍙戣揣鍙拌处鐨� 閿�鍞彴璐D 鍘绘煡闄勪欢
+                    if (ledger != null) {
                         allFiles = commonFileMapper.selectList(new LambdaQueryWrapper<CommonFile>()
-                                .eq(CommonFile::getCommonId, shippingInfo.getSalesLedgerId())
+                                .eq(CommonFile::getCommonId, ledger.getId())
                                 .eq(CommonFile::getType, FileNameType.SALE.getValue()));
+                    } else {
+                        // 2. 鍥為��鍒版棫閫昏緫锛氬彂璐у崟鍙�
+                        ShippingInfo shippingInfo = shippingInfoMapper.selectOne(new LambdaQueryWrapper<ShippingInfo>()
+                                .eq(ShippingInfo::getShippingNo, identifier)
+                                .last("limit 1"));
+                        if (shippingInfo != null) {
+                            allFiles = commonFileMapper.selectList(new LambdaQueryWrapper<CommonFile>()
+                                    .eq(CommonFile::getCommonId, shippingInfo.getSalesLedgerId())
+                                    .eq(CommonFile::getType, FileNameType.SALE.getValue()));
+                        }
                     }
                 }
             }
diff --git a/src/main/java/com/ruoyi/basic/pojo/ProductModel.java b/src/main/java/com/ruoyi/basic/pojo/ProductModel.java
index 11aac74..7369e19 100644
--- a/src/main/java/com/ruoyi/basic/pojo/ProductModel.java
+++ b/src/main/java/com/ruoyi/basic/pojo/ProductModel.java
@@ -39,7 +39,7 @@
     /**
      * 鍗曚綅
      */
-//    @Excel(name = "鍗曚綅")
+    @Excel(name = "鍗曚綅")
     private String unit;
 
     /**
diff --git a/src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java b/src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java
index 1be6dce..4f00394 100644
--- a/src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java
+++ b/src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java
@@ -1,18 +1,22 @@
 package com.ruoyi.sales.controller;
 
-// import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 // import com.ruoyi.approve.mapper.ApproveProcessMapper;
 // import com.ruoyi.approve.service.impl.ApproveProcessServiceImpl;
 // import com.ruoyi.approve.vo.ApproveProcessVO;
 // import com.ruoyi.common.enums.FileNameType;
+import com.ruoyi.approve.service.IApproveProcessService;
+import com.ruoyi.approve.vo.ApproveProcessVO;
 import com.ruoyi.common.utils.OrderUtils;
 // import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.framework.aspectj.lang.annotation.Log;
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
 // import com.ruoyi.framework.security.LoginUser;
+import com.ruoyi.framework.security.LoginUser;
 import com.ruoyi.framework.web.controller.BaseController;
 import com.ruoyi.framework.web.domain.AjaxResult;
 // import com.ruoyi.other.service.impl.TempFileServiceImpl;
@@ -38,7 +42,7 @@
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 // import java.time.LocalDate;
-import java.util.ArrayList;
+import java.time.LocalDate;
 import java.util.List;
 
 /**
@@ -56,8 +60,8 @@
     // @Autowired
     // private CommonFileServiceImpl commonFileService;
 
-    // @Autowired
-    // private ApproveProcessServiceImpl approveProcessService;
+     @Autowired
+     private IApproveProcessService approveProcessService;
 
     // @Autowired
     // private StockUtils stockUtils;
@@ -67,6 +71,9 @@
 
     @Autowired
     private ISalesLedgerService salesLedgerService;
+
+    @Autowired
+    private com.ruoyi.sales.mapper.SalesLedgerProductMapper salesLedgerProductMapper;
 
 
     @GetMapping("/listPage")
@@ -81,65 +88,56 @@
     @Transactional(rollbackFor = Exception.class)
     @Log(title = "鍙戣揣淇℃伅绠$悊", businessType = BusinessType.INSERT)
     public AjaxResult add(@RequestBody ShippingInfoDto req) throws Exception {
-        // LoginUser loginUser = SecurityUtils.getLoginUser();
-        String sh = OrderUtils.countTodayByCreateTime(shippingInfoMapper, "SH");
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        
+        if (req.getSalesLedgerId() == null) {
+            return AjaxResult.error("鍏宠仈璁㈠崟 ID 涓嶈兘涓虹┖");
+        }
 
-        /* // 鍘熸湁鐨勫崟浜у搧鍙戣揣鍙婂鎵归�昏緫
-        // 鍙戣揣瀹℃壒
+        SalesLedger salesLedger = salesLedgerService.getById(req.getSalesLedgerId());
+        if (salesLedger == null) {
+            return AjaxResult.error("鍏宠仈璁㈠崟涓嶅瓨鍦�");
+        }
+
+        // 妫�鏌ユ槸鍚﹀凡缁忓湪瀹℃壒涓垨宸插彂璐�
+        if (salesLedger.getDeliveryStatus() != null && salesLedger.getDeliveryStatus() >= 2 && !salesLedger.getDeliveryStatus().equals(3)) {
+             return AjaxResult.error("璇ヨ鍗曞凡鍦ㄥ鎵逛腑鎴栧凡鍙戣揣锛屾棤娉曢噸澶嶅彂璧�");
+        }
+
+        String shNo = OrderUtils.countTodayByCreateTime(shippingInfoMapper, "SH");
+
+        //  鍙戣捣璁㈠鎵�
         ApproveProcessVO approveProcessVO = new ApproveProcessVO();
         approveProcessVO.setApproveType(7);
         approveProcessVO.setApproveDeptId(loginUser.getCurrentDeptId());
-        approveProcessVO.setApproveReason(req.getType() + ":" +sh);
+        // 瀹℃壒鐞嗙敱鍖呭惈鍚堝悓鍙凤紝鐢ㄤ簬鍚庣画瀹℃壒閫氳繃鍚庢壘鍥炶鍗�
+        approveProcessVO.setApproveReason("鍙戣揣瀹℃壒:" + salesLedger.getSalesContractNo());
         approveProcessVO.setApproveUserIds(req.getApproveUserIds());
         approveProcessVO.setApproveUser(loginUser.getUserId());
         approveProcessVO.setApproveTime(LocalDate.now().toString());
         approveProcessService.addApprove(approveProcessVO);
-        // 娣诲姞鍙戣揣娑堟伅
-        req.setShippingNo(sh);
-        req.setStatus("寰呭鏍�");
-        boolean save = shippingInfoService.save(req);
-        return save ? AjaxResult.success() : AjaxResult.error();
-        */
 
-        //  鎸夋暣涓鍗曞彂璐э紝涓嶉渶瀹℃壒
-        if (req.getSalesLedgerId() == null) {
-            return AjaxResult.error("璇烽�夋嫨鍙戣揣璁㈠崟");
+        //  鏇存柊閿�鍞彴璐︾姸鎬佷负 2 (瀹℃壒涓�)
+        salesLedger.setDeliveryStatus(2);
+        salesLedgerService.updateById(salesLedger);
+
+        //  涓鸿鍗曚笅鐨勬瘡涓�涓骇鍝佺敓鎴愬彂璐у彴璐﹁褰� (鏄剧ず鍗曚釜浜у搧)
+        List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(new LambdaQueryWrapper<SalesLedgerProduct>()
+                .eq(SalesLedgerProduct::getSalesLedgerId, salesLedger.getId()));
+        
+        if (CollectionUtils.isNotEmpty(products)) {
+            for (SalesLedgerProduct product : products) {
+                ShippingInfo si = new ShippingInfo();
+                si.setSalesLedgerId(salesLedger.getId());
+                si.setSalesLedgerProductId(product.getId());
+                si.setShippingNo(shNo);
+                si.setStatus("寰呭鏍�");
+                si.setType(req.getType()); // 鏉ユ簮/绫诲瀷
+                shippingInfoService.save(si);
+            }
         }
 
-        // 鑾峰彇璇ヨ鍗曚笅鐨勬墍鏈変骇鍝�
-        SalesLedgerProduct query = new SalesLedgerProduct();
-        query.setSalesLedgerId(req.getSalesLedgerId());
-        List<SalesLedgerProduct> productList = salesLedgerProductService.selectSalesLedgerProductList(query);
-
-        if (CollectionUtils.isEmpty(productList)) {
-            return AjaxResult.error("璇ヨ鍗曚笅鏃犲緟鍙戣揣浜у搧");
-        }
-
-        // 涓烘瘡涓骇鍝佸垱寤哄彂璐т俊鎭�
-        List<ShippingInfo> shippingInfoList = new ArrayList<>();
-        for (SalesLedgerProduct product : productList) {
-            ShippingInfo shippingInfo = new ShippingInfo();
-            shippingInfo.setSalesLedgerId(req.getSalesLedgerId());
-            shippingInfo.setSalesLedgerProductId(product.getId());
-            shippingInfo.setShippingNo(sh);
-            shippingInfo.setStatus("瀹℃牳閫氳繃"); // 鐩存帴璁句负瀹℃牳閫氳繃锛岃烦杩囧鎵�
-            shippingInfo.setType(req.getType());
-            shippingInfo.setExpressCompany(req.getExpressCompany());
-            shippingInfo.setExpressNumber(req.getExpressNumber());
-            shippingInfo.setShippingDate(req.getShippingDate());
-            shippingInfo.setShippingCarNumber(req.getShippingCarNumber());
-            shippingInfoList.add(shippingInfo);
-        }
-
-        boolean save = shippingInfoService.saveBatch(shippingInfoList);
-        if (save) {
-            // 鏇存柊閿�鍞彴璐︾殑鍙戣揣鐘舵�佷负宸插彂璐�
-            SalesLedger salesLedger = new SalesLedger();
-            salesLedger.setId(req.getSalesLedgerId());
-            salesLedger.setDeliveryStatus(1);
-            salesLedgerService.updateById(salesLedger);
-        }
-        return save ? AjaxResult.success() : AjaxResult.error();
+        return AjaxResult.success("鍙戣揣瀹℃壒宸插彂璧�");
     }
 
     @ApiOperation("鍙戣揣鎵e簱瀛�")
diff --git a/src/main/java/com/ruoyi/sales/pojo/SalesLedger.java b/src/main/java/com/ruoyi/sales/pojo/SalesLedger.java
index 93766d9..e8ca9d4 100644
--- a/src/main/java/com/ruoyi/sales/pojo/SalesLedger.java
+++ b/src/main/java/com/ruoyi/sales/pojo/SalesLedger.java
@@ -143,9 +143,9 @@
     private LocalDate deliveryDate;
 
     /**
-     * 鍙戣揣鐘舵�侊細0-鏈彂璐э紝1-宸插彂璐�
+     * 鍙戣揣鐘舵�侊細1-鏈彂璐э紝2-瀹℃壒涓紝3-瀹℃壒涓嶉�氳繃锛�4-宸插彂璐�
      */
-    @ApiModelProperty("鍙戣揣鐘舵�侊細0-鏈彂璐э紝1-宸插彂璐�")
+    @ApiModelProperty("鍙戣揣鐘舵�侊細1-鏈彂璐э紝2-瀹℃壒涓紝3-瀹℃壒涓嶉�氳繃锛�4-宸插彂璐�")
     private Integer deliveryStatus;
 
     @TableField(exist = false)
diff --git a/src/main/java/com/ruoyi/sales/service/ShippingInfoService.java b/src/main/java/com/ruoyi/sales/service/ShippingInfoService.java
index 2aa1a13..65a761d 100644
--- a/src/main/java/com/ruoyi/sales/service/ShippingInfoService.java
+++ b/src/main/java/com/ruoyi/sales/service/ShippingInfoService.java
@@ -21,6 +21,8 @@
 
     boolean deductStock(ShippingInfoDto req) throws IOException;
 
+    boolean deductStockByOrder(Long salesLedgerId, ShippingInfoDto req) throws IOException;
+
     boolean delete(List<Long> ids);
 
     List<SalesLedgerProductDto> getReturnManagementDtoById( Long shippingId);
diff --git a/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java
index c9651a7..4cade95 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java
@@ -14,9 +14,19 @@
 import com.ruoyi.sales.dto.ShippingInfoDto;
 import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
 import com.ruoyi.sales.mapper.ShippingInfoMapper;
+import com.ruoyi.sales.pojo.SalesLedger;
 import com.ruoyi.sales.pojo.SalesLedgerProduct;
 import com.ruoyi.sales.pojo.ShippingInfo;
 import com.ruoyi.sales.service.ShippingInfoService;
+import com.ruoyi.sales.mapper.SalesLedgerMapper;
+import com.ruoyi.stock.mapper.StockInventoryMapper;
+import com.ruoyi.stock.pojo.StockInventory;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import org.springframework.transaction.annotation.Transactional;
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections4.CollectionUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -49,6 +59,12 @@
     @Autowired
     private ApproveProcessServiceImpl approveProcessService;
 
+    @Autowired
+    private SalesLedgerMapper salesLedgerMapper;
+
+    @Autowired
+    private StockInventoryMapper stockInventoryMapper;
+
     @Override
     public IPage<ShippingInfoDto> listPage(Page page, ShippingInfo req) {
         IPage<ShippingInfoDto> listPage = shippingInfoMapper.listPage(page, req);
@@ -59,27 +75,101 @@
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public boolean deductStock(ShippingInfoDto req) throws IOException {
         ShippingInfo byId = this.getById(req.getId());
         if (byId == null) {
             throw new RuntimeException("鍙戣揣淇℃伅涓嶅瓨鍦�");
         }
-        //鎵e噺搴撳瓨
-        if(!"宸插彂璐�".equals(byId.getStatus())){
-            SalesLedgerProduct salesLedgerProduct = salesLedgerProductMapper.selectById(byId.getSalesLedgerProductId());
-            stockUtils.substractStock(salesLedgerProduct.getProductModelId(), salesLedgerProduct.getQuantity(), StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode(), req.getId());
+        return deductStockByOrder(byId.getSalesLedgerId(), req);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean deductStockByOrder(Long salesLedgerId, ShippingInfoDto req) throws IOException {
+        if (salesLedgerId == null) {
+            throw new RuntimeException("鍏宠仈璁㈠崟涓嶅彲涓虹┖");
         }
-        byId.setExpressNumber(req.getExpressNumber());
-        byId.setExpressCompany(req.getExpressCompany());
-        byId.setStatus("宸插彂璐�");
-        byId.setShippingCarNumber(req.getShippingCarNumber());
-        byId.setShippingDate(req.getShippingDate());
-        boolean update = this.updateById(byId);
-        // 杩佺Щ鏂囦欢
-        if(CollectionUtils.isNotEmpty(req.getTempFileIds())){
+
+        SalesLedger salesLedger = salesLedgerMapper.selectById(salesLedgerId);
+        if (salesLedger == null) {
+            throw new RuntimeException("鍏宠仈璁㈠崟涓嶅瓨鍦�");
+        }
+
+        // 妫�鏌ヨ璁㈠崟涓嬫槸鍚﹁繕鏈夋湭鍙戣揣鐨勮褰�
+        List<ShippingInfo> unsentShippings = this.list(new LambdaQueryWrapper<ShippingInfo>()
+                .eq(ShippingInfo::getSalesLedgerId, salesLedgerId)
+                .ne(ShippingInfo::getStatus, "宸插彂璐�"));
+
+        // 浠呭湪瀛樺湪鏈彂璐ц褰曟椂鎵ц搴撳瓨鎵e噺
+        if (CollectionUtils.isNotEmpty(unsentShippings)) {
+            // 鑾峰彇璇ヨ鍗曚笅鎵�鏈夌殑浜у搧淇℃伅杩涜姹囨�绘墸鍑�
+            List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(new LambdaQueryWrapper<SalesLedgerProduct>()
+                    .eq(SalesLedgerProduct::getSalesLedgerId, salesLedgerId));
+
+            if (CollectionUtils.isEmpty(products)) {
+                throw new RuntimeException("璇ヨ鍗曚笅鏃犱骇鍝佷俊鎭紝鏃犳硶鎵e噺搴撳瓨");
+            }
+
+            //  姹囨�婚渶姹傚苟鏍¢獙搴撳瓨
+            Map<Long, BigDecimal> modelQtyMap = new HashMap<>();
+            for (SalesLedgerProduct p : products) {
+                if (p.getProductModelId() == null) continue;
+                modelQtyMap.put(p.getProductModelId(), modelQtyMap.getOrDefault(p.getProductModelId(), BigDecimal.ZERO).add(p.getQuantity()));
+            }
+
+            for (Map.Entry<Long, BigDecimal> entry : modelQtyMap.entrySet()) {
+                Long modelId = entry.getKey();
+                BigDecimal totalNeeded = entry.getValue();
+
+                StockInventory stock = stockInventoryMapper.selectOne(new LambdaQueryWrapper<StockInventory>()
+                        .eq(StockInventory::getProductModelId, modelId));
+
+                if (stock == null) {
+                    throw new RuntimeException("浜у搧瑙勬牸ID:" + modelId + " 搴撳瓨璁板綍涓嶅瓨鍦�");
+                }
+
+                BigDecimal locked = stock.getLockedQuantity() == null ? BigDecimal.ZERO : stock.getLockedQuantity();
+                BigDecimal available = stock.getQualitity().subtract(locked);
+
+                if (totalNeeded.compareTo(available) > 0) {
+                    throw new RuntimeException("浜у搧瑙勬牸ID:" + modelId + " 鎬昏闇�姹� " + totalNeeded + "锛屽彲鐢ㄥ簱瀛� " + available + "锛屽簱瀛樺厖瓒虫牎楠屾湭閫氳繃");
+                }
+            }
+
+            //  鎵ц璁㈠崟涓嬫墍鏈変骇鍝佺殑搴撳瓨鎵e噺
+            for (SalesLedgerProduct p : products) {
+                if (p.getProductModelId() == null) continue;
+                // 浣跨敤 businessId = salesLedgerId 鎴栧綋鍓� req.getId()
+                stockUtils.substractStock(p.getProductModelId(), p.getQuantity(), StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode(), salesLedgerId);
+            }
+        }
+
+        //  鏇存柊璇ヨ鍗曚笅鎵�鏈夌殑鍙戣揣璁板綍鐘舵�佷负宸插彂璐�
+        LambdaUpdateWrapper<ShippingInfo> updateWrapper = new LambdaUpdateWrapper<>();
+        updateWrapper.set(ShippingInfo::getStatus, "宸插彂璐�")
+                .eq(ShippingInfo::getSalesLedgerId, salesLedgerId);
+        
+        if (req != null) {
+            if (req.getExpressNumber() != null) updateWrapper.set(ShippingInfo::getExpressNumber, req.getExpressNumber());
+            if (req.getExpressCompany() != null) updateWrapper.set(ShippingInfo::getExpressCompany, req.getExpressCompany());
+            if (req.getShippingCarNumber() != null) updateWrapper.set(ShippingInfo::getShippingCarNumber, req.getShippingCarNumber());
+            if (req.getShippingDate() != null) updateWrapper.set(ShippingInfo::getShippingDate, req.getShippingDate());
+        }
+        this.update(updateWrapper);
+
+        //  鏇存柊璁㈠崟鐘舵�佷负 4-宸插彂璐�
+        if (!Integer.valueOf(4).equals(salesLedger.getDeliveryStatus())) {
+            salesLedger.setDeliveryStatus(4);
+            salesLedgerMapper.updateById(salesLedger);
+        }
+
+        //  杩佺Щ褰撳墠璁板綍娑夊強鐨勬枃浠�
+        if (req != null && req.getId() != null && CollectionUtils.isNotEmpty(req.getTempFileIds())) {
             tempFileService.migrateTempFilesToFormal(req.getId(), req.getTempFileIds(), FileNameType.SHIP.getValue());
         }
-        return update ;
+
+        return true;
     }
 
     @Override

--
Gitblit v1.9.3