From 23317ed94a5e2d9b19c16627a70f9c7b69c908a2 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期四, 29 十月 2026 16:36:54 +0800
Subject: [PATCH] feat: 发货支持无库存批号(未启用仓储模块的租户)

---
 src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java |   53 ++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 46 insertions(+), 7 deletions(-)

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 e9b04eb..17909ec 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java
@@ -85,7 +85,7 @@
                 throw new RuntimeException("鍙戣揣淇℃伅涓嶅瓨鍦�");
             }
             for (ShippingProductDetail shippingProductDetail : shippingProductDetails) {
-                stockUtils.substractStock(shippingProductDetail.getProductModelId(), shippingProductDetail.getQuantity(), StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode(), req.getId(), shippingProductDetail.getBatchNo());
+                deductOrRecordStock(shippingProductDetail, req.getId());
             }
         }
         byId.setExpressNumber(req.getExpressNumber());
@@ -143,14 +143,29 @@
     @Override
     public boolean add(ShippingInfoDto req) {
         this.save(req);
-        req.getBatchNoDetailList().forEach(item -> item.setShippingInfoId(req.getId()));
-        shippingProductDetailMapper.insert(req.getBatchNoDetailList());
-        for (ShippingProductDetail shippingProductDetail : req.getBatchNoDetailList()) {
-            stockUtils.substractStock(shippingProductDetail.getProductModelId(), shippingProductDetail.getQuantity(), StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode(), req.getId(), shippingProductDetail.getBatchNo());
+        List<ShippingProductDetail> detailList = req.getBatchNoDetailList();
+        if (CollectionUtils.isNotEmpty(detailList)) {
+            detailList.forEach(item -> item.setShippingInfoId(req.getId()));
+            shippingProductDetailMapper.insert(detailList);
+            for (ShippingProductDetail shippingProductDetail : detailList) {
+                deductOrRecordStock(shippingProductDetail, req.getId());
+            }
         }
         // 淇濆瓨鏂囦欢
         fileUtil.saveStorageAttachment(ApplicationTypeEnum.IMAGE, RecordTypeEnum.SHIPPING_INFO, req.getId(), req.getStorageBlobDTOs());
         return true;
+    }
+
+    /**
+     * 鏈夊簱瀛樻壒鍙风殑鍙戣揣鎵e噺搴撳瓨锛涙病鏈夊簱瀛樻壒鍙凤紙鏈惎鐢ㄤ粨鍌ㄦā鍧楋級鐨勫彂璐у彧鐧昏鍑哄簱娴佹按銆�
+     */
+    private void deductOrRecordStock(ShippingProductDetail detail, Long shippingInfoId) {
+        String recordType = StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode();
+        if (detail.getStockInventoryId() == null) {
+            stockUtils.recordStockOutWithoutInventory(detail.getProductModelId(), detail.getQuantity(), recordType, shippingInfoId, detail.getBatchNo());
+        } else {
+            stockUtils.substractStock(detail.getProductModelId(), detail.getQuantity(), recordType, shippingInfoId, detail.getBatchNo());
+        }
     }
 
     @Override
@@ -172,6 +187,17 @@
     @Override
     public boolean addReq(ShippingInfoDto req) {
 
+        // 鏍¢獙璇ヤ骇鍝佹槸鍚﹀凡鏈夊緟瀹℃牳/瀹℃牳涓殑鍙戣揣璁板綍锛岄槻姝㈤噸澶嶆彁浜�
+        Long salesLedgerProductId = req.getSalesLedgerProductId();
+        if (salesLedgerProductId != null) {
+            long pendingCount = this.count(new LambdaQueryWrapper<ShippingInfo>()
+                    .eq(ShippingInfo::getSalesLedgerProductId, salesLedgerProductId)
+                    .in(ShippingInfo::getStatus, "寰呭鏍�", "瀹℃牳涓�"));
+            if (pendingCount > 0) {
+                throw new RuntimeException("璇ヤ骇鍝佸凡鏈夊緟瀹℃牳鐨勫彂璐ц褰曪紝璇峰嬁閲嶅鎻愪氦");
+            }
+        }
+
         LoginUser loginUser = SecurityUtils.getLoginUser();
         String sh = OrderUtils.countTodayByCreateTime(shippingInfoMapper, "SH","shipping_no",req.getCreateTime());
         // 鍏堜繚瀛樺彂璐у崟锛屽啀鍙戣捣瀹℃壒锛涙棤瀹℃牳浜鸿嚜鍔ㄩ�氳繃鏃堕渶瑕佹寜鍙戣揣缂栧彿鍥炲啓鍙戣揣鐘舵�併��
@@ -179,9 +205,19 @@
         req.setStatus("寰呭鏍�");
         boolean save = this.add(req);
         // 鍙戣揣瀹℃壒
+        ApprovalTemplate approvalTemplate = approvalTemplateMapper.selectOne(
+                new LambdaQueryWrapper<ApprovalTemplate>()
+                        .eq(ApprovalTemplate::getBusinessType, 7L)
+                        .eq(ApprovalTemplate::getDeleted, 0)
+                        .orderByDesc(ApprovalTemplate::getId)
+                        .last("LIMIT 1")
+        );
+        if (approvalTemplate == null) {
+            throw new RuntimeException("璇峰厛閰嶇疆鍙戣揣瀹℃壒妯℃澘");
+        }
         ApprovalInstanceDto approvalInstance = new ApprovalInstanceDto();
-        approvalInstance.setTemplateId(approvalTemplateMapper.selectOne(new LambdaQueryWrapper<ApprovalTemplate>().eq(ApprovalTemplate::getBusinessType,7L).orderByDesc(ApprovalTemplate::getId).last("LIMIT 1")).getId());
-        approvalInstance.setTemplateName(approvalTemplateMapper.selectOne(new LambdaQueryWrapper<ApprovalTemplate>().eq(ApprovalTemplate::getBusinessType,7L).orderByDesc(ApprovalTemplate::getId).last("LIMIT 1")).getTemplateName());
+        approvalInstance.setTemplateId(approvalTemplate.getId());
+        approvalInstance.setTemplateName(approvalTemplate.getTemplateName());
         approvalInstance.setBusinessId(req.getId());
         approvalInstance.setBusinessType(7L);
         approvalInstance.setCurrentLevel(1);
@@ -190,6 +226,9 @@
         approvalInstance.setApplicantName(loginUser.getNickName());
         approvalInstance.setApplyTime(LocalDateTime.now());
         approvalInstanceService.add(approvalInstance);
+        // 鍒涘缓瀹℃壒瀹炰緥鍚庯紝鏇存柊鍙戣揣鐘舵�佷负"瀹℃牳涓�"锛屼娇鍓嶇姝g‘鏄剧ず瀹℃壒鐘舵��
+        req.setStatus("瀹℃牳涓�");
+        this.updateById(req);
         return true;
     }
 }

--
Gitblit v1.9.3