From 2cab2f69fe7efff3f1f014022be707a6648754e3 Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期一, 13 四月 2026 14:14:42 +0800
Subject: [PATCH] fix: 改为补充发货信息才扣减库存、销售订单缺失审批通过状态、审批流程编号重复

---
 src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java |   12 +-
 src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java  |  107 ++++++--------------------
 src/main/java/com/ruoyi/approve/utils/DailyRedisCounter.java             |   63 +++++++++------
 src/main/java/com/ruoyi/sales/service/ShippingInfoService.java           |    1 
 src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java   |    4 
 src/main/java/com/ruoyi/sales/pojo/SalesLedger.java                      |    4 
 doc/河南鹤壁天沐钢化玻璃厂.sql                                                      |    5 +
 7 files changed, 75 insertions(+), 121 deletions(-)

diff --git "a/doc/\346\262\263\345\215\227\351\271\244\345\243\201\345\244\251\346\262\220\351\222\242\345\214\226\347\216\273\347\222\203\345\216\202.sql" "b/doc/\346\262\263\345\215\227\351\271\244\345\243\201\345\244\251\346\262\220\351\222\242\345\214\226\347\216\273\347\222\203\345\216\202.sql"
index 68b67e0..863106f 100644
--- "a/doc/\346\262\263\345\215\227\351\271\244\345\243\201\345\244\251\346\262\220\351\222\242\345\214\226\347\216\273\347\222\203\345\216\202.sql"
+++ "b/doc/\346\262\263\345\215\227\351\271\244\345\243\201\345\244\251\346\262\220\351\222\242\345\214\226\347\216\273\347\222\203\345\216\202.sql"
@@ -87,4 +87,7 @@
     ADD COLUMN `regions_id` bigint NULL COMMENT '鍦板尯ID' AFTER `regions`;
 
 ALTER TABLE `sales_ledger`
-    ADD COLUMN `delivery_status` tinyint(1) NOT NULL DEFAULT 0 COMMENT '鍙戣揣鐘舵�侊細0-鏈彂璐э紝1-宸插彂璐�' AFTER `delivery_date`;
\ No newline at end of file
+    ADD COLUMN `delivery_status` tinyint(1) NOT NULL DEFAULT 0 COMMENT '鍙戣揣鐘舵�侊細0-鏈彂璐э紝1-宸插彂璐�' AFTER `delivery_date`;
+
+ALTER TABLE `product-inventory-management-hbtmblc`.`sales_ledger`
+    MODIFY COLUMN `delivery_status` tinyint(1) NOT NULL DEFAULT 0 COMMENT '鍙戣揣鐘舵�侊細1-鏈彂璐э紝2-瀹℃壒涓紝3-瀹℃壒涓嶉�氳繃锛�4-瀹℃壒閫氳繃锛�5-宸插彂璐�' AFTER `delivery_date`;
\ No newline at end of file
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 cee9249..84aea4e 100644
--- a/src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java
+++ b/src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java
@@ -251,15 +251,12 @@
                 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());
-                        }
+                        // 瀹℃壒瀹屾垚 -> 淇敼鐘舵�佷负瀹℃牳閫氳繃锛屼笉鎵i櫎搴撳瓨 (鎵i櫎搴撳瓨绉昏嚦鍙戣揣鍙拌处琛ュ厖淇℃伅闃舵)
+                        updateSalesLedgerDeliveryStatus(salesLedger.getId(), 4);
+                        updateShippingInfoStatusByOrder(salesLedger.getId(), "瀹℃牳閫氳繃");
                     } else if(status.equals(3)){
                         updateSalesLedgerDeliveryStatus(salesLedger.getId(), 3);
                         // 鏇存柊鍏宠仈鐨勫彂璐ц褰曚负瀹℃牳鎷掔粷
@@ -271,6 +268,7 @@
                 }
             }
         }
+
         // 缁戝畾闄勪欢
         if(!CollectionUtils.isEmpty(approveNode.getTempFileIds()) && approveNode.getApproveNodeStatus() == 1){
             tempFileService.migrateTempFilesToFormal(approveNode.getId(), approveNode.getTempFileIds(), FileNameType.ApproveNode.getValue());
diff --git a/src/main/java/com/ruoyi/approve/utils/DailyRedisCounter.java b/src/main/java/com/ruoyi/approve/utils/DailyRedisCounter.java
index f1348db..3f9aeca 100644
--- a/src/main/java/com/ruoyi/approve/utils/DailyRedisCounter.java
+++ b/src/main/java/com/ruoyi/approve/utils/DailyRedisCounter.java
@@ -10,7 +10,9 @@
 
 import javax.annotation.Resource;
 import java.text.SimpleDateFormat;
+import java.time.Duration;
 import java.time.LocalDate;
+import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.Calendar;
 import java.util.Date;
@@ -75,29 +77,41 @@
      * @return 浠婃棩鑷鍚庣殑璁℃暟鍊�
      */
     public long incrementAndGetByDb() {
-        String approveId = redisTemplate.opsForValue().get(approvalNumberPrefix + ":approveNum");
-        if(approveId == null){
-            StartAndEndDateDto dateTime = getDateTime();
-            LambdaQueryWrapper<ApproveProcess> approveProcessLambdaQueryWrapper = new LambdaQueryWrapper<>();
-            approveProcessLambdaQueryWrapper
-                    .eq(ApproveProcess::getApproveDelete,0)
-                    .gt(ApproveProcess::getCreateTime,dateTime.getStartDate())
-                    .lt(ApproveProcess::getCreateTime,dateTime.getEndDate());
-            Long aLong = approveProcessMapper.selectCount(approveProcessLambdaQueryWrapper);
-            if(aLong == null){
-                redisTemplate.opsForValue().set(approvalNumberPrefix + ":approveNum","1",1L, TimeUnit.HOURS);
-                return 1;
-            }else{
-                aLong += 1;
-                redisTemplate.opsForValue().set(approvalNumberPrefix + ":approveNum",aLong.toString(),1L, TimeUnit.HOURS);
-                return aLong;
+        String today = LocalDate.now().format(DATE_FORMAT);
+        String key = approvalNumberPrefix + ":approveNum:" + today;
+        String lockKey = "lock:" + key;
+
+        if (Boolean.FALSE.equals(redisTemplate.hasKey(key))) {
+            Boolean acquired = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 10, TimeUnit.SECONDS);
+            if (Boolean.TRUE.equals(acquired)) {
+                try {
+                    if (Boolean.FALSE.equals(redisTemplate.hasKey(key))) {
+                        StartAndEndDateDto dateTime = getDateTime();
+                        LambdaQueryWrapper<ApproveProcess> approveProcessLambdaQueryWrapper = new LambdaQueryWrapper<>();
+                        approveProcessLambdaQueryWrapper
+                                .eq(ApproveProcess::getApproveDelete, 0)
+                                .gt(ApproveProcess::getCreateTime, dateTime.getStartDate())
+                                .lt(ApproveProcess::getCreateTime, dateTime.getEndDate());
+                        Long count = approveProcessMapper.selectCount(approveProcessLambdaQueryWrapper);
+                        long initialCount = (count == null) ? 0 : count;
+
+                        redisTemplate.opsForValue().set(key, String.valueOf(initialCount), 24, TimeUnit.HOURS);
+                    }
+                } finally {
+                    // 閲婃斁閿�
+                    redisTemplate.delete(lockKey);
+                }
+            } else {
+                try {
+                    Thread.sleep(100);
+                } catch (InterruptedException e) {
+                    Thread.currentThread().interrupt();
+                }
+                return incrementAndGetByDb(); // 閫掑綊閲嶈瘯
             }
-        }else{
-            Long num = Long.parseLong(approveId) + 1;
-            redisTemplate.opsForValue().set(approvalNumberPrefix + ":approveNum",num.toString(),1L, TimeUnit.HOURS);
-            return Long.parseLong(approveId);
         }
 
+        return redisTemplate.opsForValue().increment(key);
     }
 
     /**
@@ -115,12 +129,9 @@
      * 璁$畻璺濈娆℃棩鍑屾櫒鐨勭鏁�
      */
     private long calculateSecondsUntilMidnight() {
-        LocalDate tomorrow = LocalDate.now().plusDays(1);
-        LocalDate midnight = tomorrow.atStartOfDay().toLocalDate();
-        return java.time.Duration.between(
-                LocalDate.now().atTime(23, 59, 59),
-                midnight.atTime(0, 0, 0)
-        ).getSeconds() + 1;
+        LocalDateTime now = LocalDateTime.now();
+        LocalDateTime midnight = now.toLocalDate().plusDays(1).atStartOfDay();
+        return Duration.between(now, midnight).getSeconds();
     }
 
     /**
diff --git a/src/main/java/com/ruoyi/sales/pojo/SalesLedger.java b/src/main/java/com/ruoyi/sales/pojo/SalesLedger.java
index e8ca9d4..deda7c8 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;
 
     /**
-     * 鍙戣揣鐘舵�侊細1-鏈彂璐э紝2-瀹℃壒涓紝3-瀹℃壒涓嶉�氳繃锛�4-宸插彂璐�
+     * 鍙戣揣鐘舵�侊細1-鏈彂璐э紝2-瀹℃壒涓紝3-瀹℃壒涓嶉�氳繃锛�4-瀹℃壒閫氳繃锛�5-宸插彂璐�
      */
-    @ApiModelProperty("鍙戣揣鐘舵�侊細1-鏈彂璐э紝2-瀹℃壒涓紝3-瀹℃壒涓嶉�氳繃锛�4-宸插彂璐�")
+    @ApiModelProperty("鍙戣揣鐘舵�侊細1-鏈彂璐э紝2-瀹℃壒涓紝3-瀹℃壒涓嶉�氳繃锛�4-瀹℃壒閫氳繃锛�5-宸插彂璐�")
     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 65a761d..df07489 100644
--- a/src/main/java/com/ruoyi/sales/service/ShippingInfoService.java
+++ b/src/main/java/com/ruoyi/sales/service/ShippingInfoService.java
@@ -21,7 +21,6 @@
 
     boolean deductStock(ShippingInfoDto req) throws IOException;
 
-    boolean deductStockByOrder(Long salesLedgerId, ShippingInfoDto req) throws IOException;
 
     boolean delete(List<Long> ids);
 
diff --git a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
index 07aa76c..0ed7d6e 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -461,7 +461,7 @@
                         .map(SalesLedgerProductImportDto::getTaxInclusiveTotalPrice)
                         .reduce(BigDecimal.ZERO, BigDecimal::add));
                 //  鍙戣揣鐘舵��
-                salesLedger.setDeliveryStatus(4);
+                salesLedger.setDeliveryStatus(1);
                 salesLedgerMapper.insert(salesLedger);
 
                 for (SalesLedgerProductImportDto salesLedgerProductImportDto : salesLedgerProductImportDtos) {
@@ -734,7 +734,7 @@
                 salesLedger.setDeliveryStatus(1);
                 salesLedgerMapper.insert(salesLedger);
             } else {
-                if (salesLedger.getDeliveryStatus() == 4) {
+                if (salesLedger.getDeliveryStatus() == 5) {
                     throw new ServiceException("璁㈠崟宸插彂璐�,绂佹缂栬緫");
                 }
                 salesLedgerMapper.updateById(salesLedger);
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 4cade95..5394ded 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java
@@ -81,97 +81,40 @@
         if (byId == null) {
             throw new RuntimeException("鍙戣揣淇℃伅涓嶅瓨鍦�");
         }
-        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("鍏宠仈璁㈠崟涓嶅彲涓虹┖");
+        //鎵e噺搴撳瓨
+        if(!"宸插彂璐�".equals(byId.getStatus())){
+            SalesLedgerProduct salesLedgerProduct = salesLedgerProductMapper.selectById(byId.getSalesLedgerProductId());
+            if (salesLedgerProduct != null) {
+                stockUtils.substractStock(salesLedgerProduct.getProductModelId(), salesLedgerProduct.getQuantity(), StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode(), req.getId());
+            }
         }
+        byId.setExpressNumber(req.getExpressNumber());
+        byId.setExpressCompany(req.getExpressCompany());
+        byId.setStatus("宸插彂璐�");
+        byId.setShippingCarNumber(req.getShippingCarNumber());
+        byId.setShippingDate(req.getShippingDate());
+        boolean update = this.updateById(byId);
 
-        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);
+        // 鏇存柊璁㈠崟鐘舵�佷负 5-宸插彂璐� (濡傛灉鎵�鏈夊彂璐ц褰曢兘宸插彂璐�)
+        SalesLedger salesLedger = salesLedgerMapper.selectById(byId.getSalesLedgerId());
+        if (salesLedger != null && !Integer.valueOf(5).equals(salesLedger.getDeliveryStatus())) {
+            List<ShippingInfo> unsent = this.list(new LambdaQueryWrapper<ShippingInfo>()
+                    .eq(ShippingInfo::getSalesLedgerId, byId.getSalesLedgerId())
+                    .ne(ShippingInfo::getStatus, "宸插彂璐�"));
+            if (CollectionUtils.isEmpty(unsent)) {
+                salesLedger.setDeliveryStatus(5);
+                salesLedgerMapper.updateById(salesLedger);
             }
         }
 
-        //  鏇存柊璇ヨ鍗曚笅鎵�鏈夌殑鍙戣揣璁板綍鐘舵�佷负宸插彂璐�
-        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())) {
+        // 杩佺Щ鏂囦欢
+        if(CollectionUtils.isNotEmpty(req.getTempFileIds())){
             tempFileService.migrateTempFilesToFormal(req.getId(), req.getTempFileIds(), FileNameType.SHIP.getValue());
         }
-
-        return true;
+        return update ;
     }
 
+
     @Override
     public boolean delete(List<Long> ids) {
         List<ShippingInfo> shippingInfos = shippingInfoMapper.selectList(new LambdaQueryWrapper<ShippingInfo>()

--
Gitblit v1.9.3