From 61f1de60e6f58dd8e19f01c56f2e56e40885d65b Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期二, 23 六月 2026 17:39:58 +0800
Subject: [PATCH] 点击发货-》发货审核-》出厂质检-》出库审核-》出库通过

---
 src/main/java/com/ruoyi/approve/service/impl/ApprovalInstanceServiceImpl.java |  209 ++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 194 insertions(+), 15 deletions(-)

diff --git a/src/main/java/com/ruoyi/approve/service/impl/ApprovalInstanceServiceImpl.java b/src/main/java/com/ruoyi/approve/service/impl/ApprovalInstanceServiceImpl.java
index 251ff05..317ecfb 100644
--- a/src/main/java/com/ruoyi/approve/service/impl/ApprovalInstanceServiceImpl.java
+++ b/src/main/java/com/ruoyi/approve/service/impl/ApprovalInstanceServiceImpl.java
@@ -25,6 +25,7 @@
 import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeDept;
 import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeUser;
 import com.ruoyi.common.enums.*;
+import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.OrderUtils;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.framework.security.LoginUser;
@@ -39,12 +40,15 @@
 import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
 import com.ruoyi.purchase.pojo.PurchaseLedger;
 import com.ruoyi.quality.utils.QualityInspectHelper;
+import com.ruoyi.sales.mapper.SalesLedgerMapper;
 import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
 import com.ruoyi.sales.mapper.SalesQuotationMapper;
 import com.ruoyi.sales.mapper.ShippingInfoMapper;
+import com.ruoyi.sales.mapper.ShippingProductDetailMapper;
 import com.ruoyi.sales.pojo.SalesLedgerProduct;
 import com.ruoyi.sales.pojo.SalesQuotation;
 import com.ruoyi.sales.pojo.ShippingInfo;
+import com.ruoyi.sales.pojo.ShippingProductDetail;
 import com.ruoyi.staff.mapper.HolidayApplicationMapper;
 import com.ruoyi.staff.pojo.HolidayApplication;
 import lombok.RequiredArgsConstructor;
@@ -93,9 +97,13 @@
     private final EnterpriseNewsMapper enterpriseNewsMapper;
     private final EnterpriseNewsScopeDeptMapper enterpriseNewsScopeDeptMapper;
     private final ApprovalTemplateNodeApproverMapper approvalTemplateNodeApproverMapper;
+    private final ShippingProductDetailMapper shippingProductDetailMapper;
+    private final SalesLedgerMapper salesLedgerMapper;
 
     @Override
     public R listPage(Page<ApprovalInstanceVo> page, ApprovalInstanceDto approvalInstanceDto) {
+        // 娉ㄥ叆褰撳墠鐢ㄦ埛ID锛岀敤浜庤繃婊ゅ彧鏌ョ湅鐢宠浜哄拰瀹℃牳浜烘槸鑷繁鐨勬暟鎹�
+        approvalInstanceDto.setCurrentUserId(SecurityUtils.getUserId());
         IPage<ApprovalInstanceVo> approvalInstanceVoIPage = approvalInstanceMapper.listPage(page, approvalInstanceDto);
 
         List<ApprovalInstanceVo> records = approvalInstanceVoIPage.getRecords();
@@ -104,6 +112,30 @@
         }
         records.forEach(vo -> {
             vo.setBusinessName(TypeEnums.getLabelByValue(vo.getBusinessType()));
+
+            // 鏍规嵁涓氬姟绫诲瀷鏌ヨ瀵瑰簲鐨勫崟鍙�
+            if (vo.getBusinessType() != null && vo.getBusinessId() != null) {
+                if (TypeEnums.PURCHASE_APPROVAL.getCode().equals(vo.getBusinessType())) {
+                    // 閲囪喘瀹℃壒 - 鏌ヨ閲囪喘鍗曞彿
+                    PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectById(vo.getBusinessId());
+                    System.out.println("涓氬姟绫诲瀷锛�" + purchaseLedger.getPurchaseContractNumber());
+                    if (purchaseLedger != null) {
+                        vo.setPurchaseContractNumber(purchaseLedger.getPurchaseContractNumber());
+                    }
+                } else if (TypeEnums.QUOTATION_APPROVAL.getCode().equals(vo.getBusinessType())) {
+                    // 鎶ヤ环瀹℃壒 - 鏌ヨ鎶ヤ环鍗曞彿
+                    SalesQuotation salesQuotation = salesQuotationMapper.selectById(vo.getBusinessId());
+                    if (salesQuotation != null) {
+                        vo.setQuotationNo(salesQuotation.getQuotationNo());
+                    }
+                } else if (TypeEnums.SHIPPING_APPROVAL.getCode().equals(vo.getBusinessType())) {
+                    // 鍙戣揣瀹℃壒 - 鏌ヨ鍙戣揣鍗曞彿
+                    ShippingInfo shippingInfo = shippingInfoMapper.selectById(vo.getBusinessId());
+                    if (shippingInfo != null) {
+                        vo.setShippingNo(shippingInfo.getShippingNo());
+                    }
+                }
+            }
         });
         Long currentUserId = SecurityUtils.getUserId();
 
@@ -139,7 +171,7 @@
     @Override
     @Transactional(rollbackFor = Exception.class)
     public Boolean add(ApprovalInstanceDto approvalInstanceDto) {
-        String instanceNo = OrderUtils.countTodayByCreateTime(approvalInstanceMapper, "SP", "instance_no");
+        String instanceNo = OrderUtils.countTodayByCreateTime(approvalInstanceMapper, "SP", "instance_no", approvalInstanceDto.getCreateTime() != null ? approvalInstanceDto.getCreateTime() : LocalDateTime.now());
         approvalInstanceDto.setInstanceNo(instanceNo);
         approvalInstanceDto.setStatus("PENDING");
         approvalInstanceDto.setCurrentLevel(1);
@@ -158,6 +190,16 @@
     public Boolean update(ApprovalInstanceDto approvalInstanceDto) {
         if (approvalInstanceDto == null || approvalInstanceDto.getId() == null) {
             return false;
+        }
+        // 鍒ゆ柇鏄惁鏈夋鍦ㄨ繘琛岀殑瀹℃壒浠诲姟锛屾湁鍒欎笉鍏佽淇敼
+        long pendingTaskCount = approvalTaskService.count(
+                Wrappers.<ApprovalTask>lambdaQuery()
+                        .eq(ApprovalTask::getInstanceId, approvalInstanceDto.getId())
+                        .eq(ApprovalTask::getTaskStatus, "PENDING")
+                        .eq(ApprovalTask::getDeleted, 0)
+        );
+        if (pendingTaskCount > 0) {
+            throw new ServiceException("璇ュ鎵瑰崟鏈夋鍦ㄨ繘琛岀殑瀹℃壒浠诲姟锛屼笉鍏佽淇敼");
         }
         boolean updated = this.updateById(approvalInstanceDto);
         if (!updated) {
@@ -220,6 +262,12 @@
             return R.fail("瀹℃壒瀹炰緥涓嶅瓨鍦�");
         }
 
+        // 濡傛灉鍓嶇浼犻�掍簡浠撳簱淇℃伅锛屾洿鏂板鎵瑰疄渚嬬殑浠撳簱瀛楁
+        if (StringUtils.hasText(approvalInstanceDto.getWarehouse())) {
+            instance.setWarehouse(approvalInstanceDto.getWarehouse());
+            this.updateById(instance);
+        }
+
         ApprovalInstanceNode currentNode = approveProcessConfigNodeUtils.getCurrentNode(instance.getId());
         if (currentNode == null) {
             return R.fail("褰撳墠娌℃湁寰呭鐞嗙殑瀹℃壒鑺傜偣");
@@ -257,6 +305,87 @@
         }
 
         return approveAndMoveNext(instance, currentNode, approvalInstanceDto, now);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public R autoApprove(Long instanceId) {
+        if (instanceId == null) {
+            return R.fail("瀹℃壒瀹炰緥 ID 涓嶈兘涓虹┖");
+        }
+
+        ApprovalInstance instance = getPendingApprovalInstance(instanceId);
+        if (instance == null) {
+            return R.fail("瀹℃壒瀹炰緥涓嶅瓨鍦�");
+        }
+        if ("REJECTED".equals(instance.getStatus())) {
+            return R.fail("瀹℃壒宸查┏鍥烇紝鏃犳硶鑷姩閫氳繃");
+        }
+        if ("APPROVED".equals(instance.getStatus())) {
+            return R.ok("瀹℃壒宸插畬鎴�");
+        }
+
+        ApprovalInstanceDto autoApproveDto = new ApprovalInstanceDto();
+        autoApproveDto.setId(instanceId);
+        autoApproveDto.setApproveComment("绯荤粺鑷姩瀹℃壒");
+
+        int loopCount = 0;
+        while (loopCount++ < 20) {
+            ApprovalInstance currentInstance = getPendingApprovalInstance(instanceId);
+            if (currentInstance == null) {
+                return R.fail("瀹℃壒瀹炰緥涓嶅瓨鍦�");
+            }
+            if ("APPROVED".equals(currentInstance.getStatus())) {
+                return R.ok("瀹℃壒宸插畬鎴�");
+            }
+            if ("REJECTED".equals(currentInstance.getStatus())) {
+                return R.fail("瀹℃壒宸查┏鍥烇紝鏃犳硶鑷姩閫氳繃");
+            }
+
+            ApprovalInstanceNode currentNode = approveProcessConfigNodeUtils.getCurrentNode(currentInstance.getId());
+            if (currentNode == null) {
+                currentInstance.setStatus("APPROVED");
+                currentInstance.setFinishTime(LocalDateTime.now());
+                this.updateById(currentInstance);
+                handleBusinessAfterApprovalFinished(currentInstance);
+                return R.ok("瀹℃壒宸插畬鎴�");
+            }
+
+            List<ApprovalTask> pendingTasks = approvalTaskService.list(
+                    Wrappers.<ApprovalTask>lambdaQuery()
+                            .eq(ApprovalTask::getInstanceId, currentInstance.getId())
+                            .eq(ApprovalTask::getNodeId, currentNode.getId())
+                            .eq(ApprovalTask::getTaskStatus, "PENDING")
+                            .eq(ApprovalTask::getDeleted, 0)
+            );
+
+            LocalDateTime now = LocalDateTime.now();
+            for (ApprovalTask currentTask : pendingTasks) {
+                if (!updateCurrentTask(autoApproveDto, "APPROVED", currentTask, now)) {
+                    return R.fail("褰撳墠浠诲姟宸茶澶勭悊锛岃鍒锋柊鍚庨噸璇�");
+                }
+                saveApprovalRecord(
+                        currentInstance.getId(),
+                        currentNode.getId(),
+                        currentTask.getId(),
+                        0L,
+                        "绯荤粺鑷姩瀹℃壒",
+                        "APPROVED",
+                        autoApproveDto.getApproveComment()
+                );
+            }
+
+            if (!approveProcessConfigNodeUtils.canProceedToNextLevel(currentInstance.getId(), currentNode.getApproveType())) {
+                return R.ok("瀹℃壒鎴愬姛锛岀瓑寰呭叾浠栧鎵逛汉澶勭悊");
+            }
+
+            R moveResult = moveToNextLevel(currentInstance, currentNode, autoApproveDto, now, false);
+            if (!R.isSuccess(moveResult)) {
+                return moveResult;
+            }
+        }
+
+        return R.fail("鑷姩瀹℃壒寰幆娆℃暟瓒呴檺");
     }
 
     private String normalizeApproveAction(String approveAction) {
@@ -325,6 +454,14 @@
                                  ApprovalInstanceNode currentNode,
                                  ApprovalInstanceDto approvalInstanceDto,
                                  LocalDateTime now) {
+        return moveToNextLevel(instance, currentNode, approvalInstanceDto, now, true);
+    }
+
+    private R moveToNextLevel(ApprovalInstance instance,
+                              ApprovalInstanceNode currentNode,
+                              ApprovalInstanceDto approvalInstanceDto,
+                              LocalDateTime now,
+                              boolean notifyNextNode) {
         if (!updateCurrentNodeStatus(currentNode.getId(), "APPROVED", now)) {
             return R.ok("褰撳墠鑺傜偣宸插鐞嗗畬鎴�");
         }
@@ -348,14 +485,16 @@
             instance.setCurrentLevel(nextLevel);
             instance.setStatus("PENDING");
             this.updateById(instance);
-            List<ApprovalTask> nextTasks = approvalTaskService.list(
-                    Wrappers.<ApprovalTask>lambdaQuery()
-                            .eq(ApprovalTask::getInstanceId, instance.getId())
-                            .eq(ApprovalTask::getNodeId, nextInstanceNode.getId())
-                            .eq(ApprovalTask::getTaskStatus, "PENDING")
-                            .eq(ApprovalTask::getDeleted, 0)
-            );
-            sendApproveNotice(instance, nextTasks);
+            if (notifyNextNode) {
+                List<ApprovalTask> nextTasks = approvalTaskService.list(
+                        Wrappers.<ApprovalTask>lambdaQuery()
+                                .eq(ApprovalTask::getInstanceId, instance.getId())
+                                .eq(ApprovalTask::getNodeId, nextInstanceNode.getId())
+                                .eq(ApprovalTask::getTaskStatus, "PENDING")
+                                .eq(ApprovalTask::getDeleted, 0)
+                );
+                sendApproveNotice(instance, nextTasks);
+            }
             return R.ok("瀹℃壒鎴愬姛锛屽凡娴佽浆鍒颁笅涓�鑺傜偣");
         }
 
@@ -379,7 +518,9 @@
         instance.setStatus("PENDING");
         this.updateById(instance);
         approveProcessConfigNodeUtils.createCurrentNodeAndTasks(instance, false);
-        sendApproveNotice(instance, approveProcessConfigNodeUtils.getCurrentPendingTasks(approvalInstanceDto.getId()));
+        if (notifyNextNode) {
+            sendApproveNotice(instance, approveProcessConfigNodeUtils.getCurrentPendingTasks(approvalInstanceDto.getId()));
+        }
         return R.ok("瀹℃壒鎴愬姛锛屽凡娴佽浆鍒颁笅涓�鑺傜偣");
     }
 
@@ -496,7 +637,7 @@
     private void handlePurchaseApprovalFinished(ApprovalInstance instance, String status) {
         PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectOne(
                 new LambdaQueryWrapper<PurchaseLedger>()
-                        .eq(PurchaseLedger::getPurchaseContractNumber, instance.getTitle())
+                        .eq(PurchaseLedger::getId, instance.getBusinessId())
                         .last("limit 1")
         );
         if (purchaseLedger == null) {
@@ -519,7 +660,9 @@
                             salesLedgerProduct.getQuantity(),
                             StockInQualifiedRecordTypeEnum.PURCHASE_STOCK_IN.getCode(),
                             purchaseLedger.getId(),
-                            purchaseLedger.getPurchaseContractNumber() + "-" + salesLedgerProduct.getId()
+                            purchaseLedger.getPurchaseContractNumber() + "-" + salesLedgerProduct.getId(),
+                            null,
+                            instance.getWarehouse()
                     );
                 }
             }
@@ -534,7 +677,7 @@
     private void handleSalesQuotationApprovalFinished(ApprovalInstance instance, String status) {
         SalesQuotation salesQuote = salesQuotationMapper.selectOne(
                 new LambdaQueryWrapper<SalesQuotation>()
-                        .eq(SalesQuotation::getQuotationNo, instance.getTitle())
+                        .eq(SalesQuotation::getId, instance.getBusinessId())
                         .last("limit 1")
         );
         if (salesQuote == null) {
@@ -554,8 +697,7 @@
     private void handleShippingApprovalFinished(ApprovalInstance instance, String status) {
         ShippingInfo shippingInfo = shippingInfoMapper.selectOne(
                 new LambdaQueryWrapper<ShippingInfo>()
-                        .eq(ShippingInfo::getShippingNo, instance.getTitle())
-                        .orderByDesc(ShippingInfo::getCreateTime)
+                        .eq(ShippingInfo::getId, instance.getBusinessId())
                         .last("limit 1")
         );
         if (shippingInfo == null) {
@@ -566,6 +708,9 @@
             shippingInfo.setStatus(ShippingStatusEnum.APPROVED.getCode());
             shippingInfo.setShippingDate(new Date());
             stockUtils.shipmentStatus(StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode(), shippingInfo.getId());
+
+            // 鍙戣揣瀹℃壒閫氳繃鍚庯紝鑷姩鐢熸垚鍑哄巶妫�楠屽崟
+            createFactoryInspectForShipping(shippingInfo);
         } else if ("REJECTED".equals(status)) {
             stockUtils.deleteStockOutRecord(shippingInfo.getId(), StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode());
             shippingInfo.setStatus(ShippingStatusEnum.REJECTED.getCode());
@@ -575,6 +720,40 @@
         shippingInfoMapper.updateById(shippingInfo);
     }
 
+    /**
+     * 鍙戣揣瀹℃壒閫氳繃鍚庯紝鑷姩鐢熸垚鍑哄巶妫�楠屽崟
+     */
+    private void createFactoryInspectForShipping(ShippingInfo shippingInfo) {
+        // 鏌ヨ鍙戣揣浜у搧鏄庣粏
+        List<ShippingProductDetail> detailList = shippingProductDetailMapper.selectList(
+                new LambdaQueryWrapper<ShippingProductDetail>()
+                        .eq(ShippingProductDetail::getShippingInfoId, shippingInfo.getId())
+        );
+
+        if (detailList == null || detailList.isEmpty()) {
+            return;
+        }
+
+        // 鑾峰彇瀹㈡埛鍚嶇О
+        String customerName = null;
+        if (shippingInfo.getSalesLedgerId() != null) {
+            com.ruoyi.sales.pojo.SalesLedger salesLedger = salesLedgerMapper.selectById(shippingInfo.getSalesLedgerId());
+            if (salesLedger != null) {
+                customerName = salesLedger.getCustomerName();
+            }
+        }
+
+        // 涓烘瘡涓彂璐т骇鍝佸垱寤哄嚭鍘傛楠屽崟
+        for (ShippingProductDetail detail : detailList) {
+            qualityInspectHelper.addFactoryInspect(
+                    shippingInfo,
+                    detail,
+                    customerName,
+                    shippingInfo.getSalesLedgerId()
+            );
+        }
+    }
+
     private List<ApprovalTask> createNodeAndTasks(ApprovalInstance instance, ApprovalTemplateNode templateNode) {
         List<ApprovalTemplateNodeApprover> approvers = approvalTemplateNodeApproverMapper.selectList(
                 new LambdaQueryWrapper<ApprovalTemplateNodeApprover>()

--
Gitblit v1.9.3