From 83ab4c8eabb1d2f448079c03bbb2efa09d9d468a Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期四, 25 六月 2026 09:05:55 +0800
Subject: [PATCH] feat: 售后新增消息推送、数量自定义、分页查询

---
 src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java |  235 ++++++++++++++++++++++++++++++++++++++--------------------
 1 files changed, 155 insertions(+), 80 deletions(-)

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 c654b7d..020b237 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -12,6 +12,9 @@
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.ruoyi.account.service.AccountIncomeService;
+import com.ruoyi.aftersalesservice.dto.AfterSalesProductDto;
+import com.ruoyi.aftersalesservice.dto.AfterSalesServiceNewDto;
+import com.ruoyi.aftersalesservice.service.AfterSalesServiceService;
 import com.ruoyi.approve.pojo.ApproveProcess;
 import com.ruoyi.approve.service.IApproveProcessService;
 import com.ruoyi.approve.vo.ApproveProcessVO;
@@ -74,6 +77,7 @@
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.data.redis.core.script.DefaultRedisScript;
 import org.springframework.security.core.Authentication;
@@ -191,6 +195,10 @@
     ;
     @Autowired
     private SysUserMapper sysUserMapper;
+
+    @Autowired
+    @Lazy
+    private AfterSalesServiceService afterSalesServiceService;
 
     private final ICustomerRegionsService customerRegionsService;
     @Autowired
@@ -1824,6 +1832,15 @@
         if (products == null || products.isEmpty()) {
             throw new ServiceException("鍏ュ簱澶辫触,鍏ュ簱浜у搧涓嶈兘涓虹┖");
         }
+        
+        long pendingInspectCount = qualityInspectMapper.selectCount(Wrappers.<com.ruoyi.quality.pojo.QualityInspect>lambdaQuery()
+                .eq(com.ruoyi.quality.pojo.QualityInspect::getSalesLedgerId, ledger.getId())
+                .in(com.ruoyi.quality.pojo.QualityInspect::getSalesLedgerProductId, products)
+                .eq(com.ruoyi.quality.pojo.QualityInspect::getInspectState, 0));
+        if (pendingInspectCount > 0) {
+            throw new ServiceException("鍏ュ簱澶辫触,閫変腑鐨勪骇鍝佷腑瀛樺湪寰呭鐞嗙殑鎴愬搧妫�楠屽崟,璇峰厛瀹屾垚璐ㄦ");
+        }
+
         //  鏌ヨ閿�鍞鍗曠殑浜у搧
         List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectList(Wrappers.<SalesLedgerProduct>lambdaQuery().in(SalesLedgerProduct::getId, products));
         if (salesLedgerProducts == null || salesLedgerProducts.isEmpty()) {
@@ -1881,41 +1898,42 @@
             if (inboundQty.compareTo(BigDecimal.ZERO) <= 0) {
                 continue;
             }
-            StockInventoryDto stockInventoryDto = new StockInventoryDto();
-            stockInventoryDto.setRecordId(product.getId());
-            stockInventoryDto.setRecordType(StockInQualifiedRecordTypeEnum.SALE_STOCK_IN.getCode());
-            stockInventoryDto.setQualitity(inboundQty);
-            stockInventoryDto.setProductModelId(product.getProductModelId());
-            stockInventoryDto.setSalesLedgerId(ledger.getId());
-            stockInventoryDto.setSalesLedgerProductId(product.getId());
-            stockInventoryService.addstockInventory(stockInventoryDto);
-
-            BigDecimal newStocked = oldStocked.add(inboundQty);
-            int lineStockStatus;
-            if (newStocked.compareTo(BigDecimal.ZERO) <= 0) {
-                lineStockStatus = 0;
-            } else if (orderQty.compareTo(BigDecimal.ZERO) > 0 && newStocked.compareTo(orderQty) < 0) {
-                lineStockStatus = 1;
-            } else {
-                lineStockStatus = 2;
+            // 鏂板涓�鏉℃垚鍝佺殑璐ㄦ淇℃伅
+            com.ruoyi.quality.pojo.QualityInspect qualityInspect = new com.ruoyi.quality.pojo.QualityInspect();
+            qualityInspect.setInspectType(2); // 2: 鍑哄巶妫�楠� (鎴愬搧妫�楠�)
+            qualityInspect.setCustomer(ledger.getCustomerName());
+            qualityInspect.setSalesLedgerId(ledger.getId());
+            qualityInspect.setSalesLedgerProductId(product.getId());
+            qualityInspect.setProductId(product.getProductId());
+            qualityInspect.setProductName(product.getProductCategory());
+            qualityInspect.setModel(product.getSpecificationModel());
+            qualityInspect.setProductModelId(product.getProductModelId());
+            qualityInspect.setUnit(product.getUnit());
+            qualityInspect.setQuantity(inboundQty);
+            qualityInspect.setQualifiedQuantity(inboundQty);
+            qualityInspect.setUnqualifiedQuantity(BigDecimal.ZERO);
+            qualityInspect.setPassRate(BigDecimal.valueOf(100).setScale(2, java.math.RoundingMode.HALF_UP));
+            qualityInspect.setInspectState(0);
+            qualityInspectMapper.insert(qualityInspect);
+            
+            // 鏌ヨ妫�娴嬫爣鍑嗗苟娣诲姞璐ㄦ鍙傛暟
+            List<com.ruoyi.quality.pojo.QualityTestStandard> qualityTestStandardList = qualityTestStandardMapper.getQualityTestStandardByProductId(product.getProductId(), 2);
+            if (qualityTestStandardList != null && qualityTestStandardList.size() > 0) {
+                qualityInspect.setTestStandardId(qualityTestStandardList.get(0).getId());
+                qualityInspectMapper.updateById(qualityInspect);
+                List<com.ruoyi.quality.pojo.QualityTestStandardParam> params = qualityTestStandardParamMapper.selectList(com.baomidou.mybatisplus.core.toolkit.Wrappers.<com.ruoyi.quality.pojo.QualityTestStandardParam>lambdaQuery()
+                        .eq(com.ruoyi.quality.pojo.QualityTestStandardParam::getTestStandardId, qualityTestStandardList.get(0).getId()));
+                for (com.ruoyi.quality.pojo.QualityTestStandardParam p : params) {
+                    com.ruoyi.quality.pojo.QualityInspectParam param = new com.ruoyi.quality.pojo.QualityInspectParam();
+                    org.springframework.beans.BeanUtils.copyProperties(p, param);
+                    param.setId(null);
+                    param.setInspectId(qualityInspect.getId());
+                    qualityInspectParamMapper.insert(param);
+                }
             }
-            product.setStockedQuantity(newStocked);
-            product.setProductStockStatus(lineStockStatus);
-            product.fillRemainingQuantity();
-            salesLedgerProductMapper.updateById(product);
         }
-        //  鎸夐攢鍞鍗曚骇鍝佸叆搴撴儏鍐垫洿鏂颁富鍗曞叆搴撶姸鎬侊細1-閮ㄥ垎鍏ュ簱锛�2-宸插叆搴�
-        List<SalesLedgerProduct> ledgerAllProducts = salesLedgerProductMapper.selectList(Wrappers.<SalesLedgerProduct>lambdaQuery().eq(SalesLedgerProduct::getSalesLedgerId, ledger.getId()));
-        boolean hasStocked = CollectionUtils.isNotEmpty(ledgerAllProducts) && ledgerAllProducts.stream().anyMatch(item -> {
-            BigDecimal sq = item.getStockedQuantity();
-            return sq != null && sq.compareTo(BigDecimal.ZERO) > 0;
-        });
-        boolean allStocked = CollectionUtils.isNotEmpty(ledgerAllProducts) && ledgerAllProducts.stream().allMatch(item -> {
-            BigDecimal orderQty = item.getQuantity() == null ? BigDecimal.ZERO : item.getQuantity();
-            BigDecimal stockedQty = item.getStockedQuantity() == null ? BigDecimal.ZERO : item.getStockedQuantity();
-            return orderQty.compareTo(BigDecimal.ZERO) <= 0 || stockedQty.compareTo(orderQty) >= 0;
-        });
-        ledger.setStockStatus(allStocked ? 2 : (hasStocked ? 1 : 0));
+        // 鏇存柊涓诲崟鐘舵�佷负鏈畬鍏ㄥ叆搴擄紙寰呰川妫�瀹屾垚鍚庢洿鏂帮級
+        ledger.setStockStatus(0);
         baseMapper.updateById(ledger);
     }
 
@@ -2484,13 +2502,23 @@
                 if (CollectionUtils.isEmpty(rowList)) {
                     return;
                 }
-                if (StringUtils.hasText(rowList.get(0).getCustomerName()) && rowList.get(0).getCustomerName().startsWith("琛ョ墖")) {
-                    return;
-                }
                 rowList.sort(Comparator.comparing(r -> buildCategoryProductName(r) + "||" + buildSpecificationModel(r)));
-                SalesLedger ledger = salesLedgerMapper.selectOne(new LambdaQueryWrapper<SalesLedger>().eq(SalesLedger::getSalesContractNo, orderNo).last("LIMIT 1"));
+                SalesLedger ledger = salesLedgerMapper.selectOne(new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<SalesLedger>().eq(SalesLedger::getSalesContractNo, orderNo).last("LIMIT 1"));
                 if (ledger == null) {
 //                throw new ServiceException("瀵煎叆澶辫触,璁㈠崟缂栧彿[" + orderNo + "]涓嶅瓨鍦�,鏃犳硶琛ュ綍宸插彂璐ф暟鎹�");
+                    return;
+                }
+                
+                boolean skipInboundAndShipping = false;
+                if (org.springframework.util.StringUtils.hasText(ledger.getCustomerName()) && ledger.getCustomerName().startsWith("琛ョ墖")) {
+                    if (ledger.getEntryDate() != null) {
+                        java.time.LocalDate entryDate = com.ruoyi.common.utils.DateUtils.toLocalDate(ledger.getEntryDate());
+                        if (entryDate.plusDays(7).isAfter(java.time.LocalDate.now())) {
+                            skipInboundAndShipping = true;
+                        }
+                    }
+                }
+                if (skipInboundAndShipping) {
                     return;
                 }
                 List<SalesLedgerProduct> dbProducts = salesLedgerProductMapper.selectList(new LambdaQueryWrapper<SalesLedgerProduct>().eq(SalesLedgerProduct::getSalesLedgerId, ledger.getId()).eq(SalesLedgerProduct::getType, SaleEnum.SALE.getCode()));
@@ -2813,7 +2841,10 @@
 
                     ledger.setContractAmount(BigDecimal.ZERO);
                     salesLedgerMapper.insert(ledger);
-                    bindImportProcessRoute(ledger.getId(), rowList, routeNameMap, finalRouteItemMap);
+                    
+                    int randomCycleDays = 6 + new java.util.Random().nextInt(3); // 6, 7, 8
+                    Date reportDate = rowList.get(0).getReportDate();
+                    bindImportProcessRoute(ledger.getId(), rowList, routeNameMap, finalRouteItemMap, reportDate, randomCycleDays);
                     int reviewCount = 0;
 
                     BigDecimal contractAmount = BigDecimal.ZERO;
@@ -2876,7 +2907,17 @@
                         // salesLedgerProductServiceImpl.addProductionData(product);
                         contractAmount = contractAmount.add(lineAmount);
 
+                        boolean skipInboundAndShipping = false;
                         if (customer.getCustomerName() != null && customer.getCustomerName().startsWith("琛ョ墖")) {
+                            if (ledger.getEntryDate() != null) {
+                                java.time.LocalDate entryDate = com.ruoyi.common.utils.DateUtils.toLocalDate(ledger.getEntryDate());
+                                if (entryDate.plusDays(7).isAfter(java.time.LocalDate.now())) {
+                                    skipInboundAndShipping = true;
+                                }
+                            }
+                        }
+
+                        if (customer.getCustomerName() != null && customer.getCustomerName().startsWith("琛ョ墖") && !skipInboundAndShipping) {
                             Long inspectId = createNotShippingQualityInspect(ledger, product, row, qty);
                             stockUtils.addStock(
                                     ledger.getId(),
@@ -2895,7 +2936,7 @@
                                     product.getId()
                             );
 
-                            StockInRecord inRecord = stockInRecordMapper.selectOne(new LambdaQueryWrapper<StockInRecord>()
+                            StockInRecord inRecord = stockInRecordMapper.selectOne(new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<StockInRecord>()
                                     .eq(StockInRecord::getSalesLedgerProductId, product.getId())
                                     .orderByDesc(StockInRecord::getId).last("LIMIT 1"));
                             if (inRecord != null) {
@@ -2908,14 +2949,14 @@
                                 }
                                 inRecord.setInboundBatches(batch);
                                 if (row.getReportDate() != null) {
-                                    LocalDateTime reportDateTime = LocalDateTime.ofInstant(row.getReportDate().toInstant(), ZoneId.systemDefault());
+                                    java.time.LocalDateTime reportDateTime = java.time.LocalDateTime.ofInstant(row.getReportDate().toInstant(), java.time.ZoneId.systemDefault());
                                     inRecord.setCreateTime(reportDateTime);
                                     inRecord.setUpdateTime(reportDateTime);
                                 }
                                 stockInRecordMapper.updateById(inRecord);
                             }
 
-                            StockOutRecord outRecord = stockOutRecordMapper.selectOne(new LambdaQueryWrapper<StockOutRecord>()
+                            StockOutRecord outRecord = stockOutRecordMapper.selectOne(new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<StockOutRecord>()
                                     .eq(StockOutRecord::getSalesLedgerProductId, product.getId())
                                     .orderByDesc(StockOutRecord::getId).last("LIMIT 1"));
                             if (outRecord != null) {
@@ -3050,6 +3091,31 @@
                         } catch (Exception e) {
                             log.error("鑷姩鐢熸垚鍙戣揣瀹℃壒鐢宠澶辫触", e);
                         }
+
+                        try {
+                            AfterSalesServiceNewDto afterSalesDto = new AfterSalesServiceNewDto();
+                            afterSalesDto.setSalesLedgerId(ledger.getId());
+                            afterSalesDto.setCustomerName(customer.getCustomerName());
+                            afterSalesDto.setCheckUserId(creatorUser.getUserId());
+                            afterSalesDto.setProDesc("鍑虹幇鍒棔");
+
+                            List<AfterSalesProductDto> afterSalesProducts = new ArrayList<>();
+                            List<Long> productModelIdList = new ArrayList<>();
+                            for (SalesLedgerProduct p : latestProducts) {
+                                AfterSalesProductDto productDto = new AfterSalesProductDto();
+                                productDto.setId(p.getId());
+                                productDto.setAfterSalesQuantity(defaultDecimal(p.getQuantity()));
+                                afterSalesProducts.add(productDto);
+                                if (p.getProductModelId() != null) {
+                                    productModelIdList.add(p.getProductModelId());
+                                }
+                            }
+                            afterSalesDto.setAfterSalesProductList(afterSalesProducts);
+                            afterSalesDto.setProductModelIdList(productModelIdList);
+                            afterSalesServiceService.addAfterSalesServiceDto(afterSalesDto);
+                        } catch (Exception e) {
+                            log.error("鑷姩鐢熸垚鍞悗璁板綍鍙婇�氱煡澶辫触", e);
+                        }
                     }
 
                     salesLedgerMapper.updateById(ledger);
@@ -3093,7 +3159,7 @@
         return result;
     }
 
-    private void bindImportProcessRoute(Long salesLedgerId, List<SalesNotShippingImportDto> rowList, Map<String, ProcessRoute> routeNameMap, Map<Long, List<ProcessRouteItem>> routeItemMap) {
+    private void bindImportProcessRoute(Long salesLedgerId, List<SalesNotShippingImportDto> rowList, Map<String, ProcessRoute> routeNameMap, Map<Long, List<ProcessRouteItem>> routeItemMap, Date reportDate, int randomCycleDays) {
         String flowKey = rowList.stream().map(SalesNotShippingImportDto::getProcessFlow).filter(StringUtils::hasText).map(this::normalizeRouteFlowKey).filter(StringUtils::hasText).findFirst().orElse("");
         if (!StringUtils.hasText(flowKey)) {
             throw new ServiceException("瀵煎叆澶辫触,璁㈠崟宸ヨ壓娴佺▼涓嶈兘涓虹┖");
@@ -3120,6 +3186,48 @@
             bindList.add(bind);
         }
         salesLedgerProcessRouteService.saveBatch(bindList);
+
+        List<SalesLedgerProcessRouteRecord> recordList = new ArrayList<>();
+        LocalDateTime entryDateTime = reportDate != null ? LocalDateTime.ofInstant(reportDate.toInstant(), ZoneId.systemDefault()) : LocalDateTime.now();
+        int totalItems = routeItems.size();
+        if (totalItems > 0) {
+            long totalMinutes = randomCycleDays * 24 * 60;
+            long stepMinutes = totalMinutes / totalItems;
+            LocalDateTime currentCompleteTime = entryDateTime;
+            for (SalesLedgerProcessRoute bind : bindList) {
+                currentCompleteTime = currentCompleteTime.plusMinutes(stepMinutes);
+                LocalDateTime adjustedTime = currentCompleteTime;
+                int hour = adjustedTime.getHour();
+                if (hour < 10) {
+                    adjustedTime = adjustedTime.withHour(10).withMinute(10);
+                } else if (hour >= 12 && hour < 14) {
+                    adjustedTime = adjustedTime.withHour(14).withMinute(10);
+                } else if (hour > 18 || (hour == 18 && adjustedTime.getMinute() > 30)) {
+                    adjustedTime = adjustedTime.plusDays(1).withHour(10).withMinute(10);
+                }
+                if (!recordList.isEmpty()) {
+                    LocalDateTime prevTime = recordList.get(recordList.size() - 1).getCompletedTime();
+                    if (!adjustedTime.isAfter(prevTime)) {
+                        adjustedTime = prevTime.plusMinutes(15);
+                        int newHour = adjustedTime.getHour();
+                        if (newHour == 12 || newHour == 13) {
+                            adjustedTime = adjustedTime.withHour(14).withMinute(0);
+                        } else if (newHour > 18 || (newHour == 18 && adjustedTime.getMinute() > 30)) {
+                            adjustedTime = adjustedTime.plusDays(1).withHour(10).withMinute(0);
+                        }
+                    }
+                }
+                currentCompleteTime = adjustedTime;
+                SalesLedgerProcessRouteRecord record = new SalesLedgerProcessRouteRecord();
+                record.setSalesLedgerId(salesLedgerId);
+                record.setSalesLedgerProcessRouteId(bind.getId());
+                record.setIsCompleted(1);
+                record.setCompletedTime(currentCompleteTime);
+                record.setCreateTime(currentCompleteTime);
+                recordList.add(record);
+            }
+            salesLedgerProcessRouteRecordService.saveBatch(recordList);
+        }
     }
 
     private ProcessRoute createImportProcessRoute(String flowKey, Map<String, ProcessRoute> routeNameMap, Map<Long, List<ProcessRouteItem>> routeItemMap) {
@@ -3461,7 +3569,7 @@
 
         QualityTestStandard selectedStandard = null;
         if (dbProduct.getProductId() != null) {
-            List<QualityTestStandard> standards = qualityTestStandardMapper.getQualityTestStandardByProductId(dbProduct.getProductId(), 2, null);
+            List<QualityTestStandard> standards = qualityTestStandardMapper.getQualityTestStandardByProductId(dbProduct.getProductId(), 2);
             if (CollectionUtils.isNotEmpty(standards)) {
                 selectedStandard = standards.get(0);
                 qualityInspect.setTestStandardId(selectedStandard.getId());
@@ -3523,7 +3631,7 @@
 
         QualityTestStandard selectedStandard = null;
         if (dbProduct.getProductId() != null) {
-            List<QualityTestStandard> standards = qualityTestStandardMapper.getQualityTestStandardByProductId(dbProduct.getProductId(), 2, null);
+            List<QualityTestStandard> standards = qualityTestStandardMapper.getQualityTestStandardByProductId(dbProduct.getProductId(), 2);
             if (CollectionUtils.isNotEmpty(standards)) {
                 selectedStandard = standards.get(0);
                 qualityInspect.setTestStandardId(selectedStandard.getId());
@@ -3928,43 +4036,10 @@
             // 5. 鍙栨秷瀹℃壒娴佺▼
             cancelApproveProcesses(id, originalLedger.getSalesContractNo());
 
-            // 6. 閲嶆柊鐢熸垚锛氬垱寤烘柊鍙拌处鍓湰
+            // 6. 閲嶆柊鐢熸垚锛氭澶勪笉鐩存帴鍦ㄥ悗绔叆搴擄紝鑰屾槸杩斿洖鍘熷崟鎹甀D缁欏墠绔�
+            // 鍓嶇鎷垮埌ID鍚庝細鑾峰彇鍘熷崟鎹鎯呭苟璺宠浆鍒版柊澧為〉闈紙甯﹀叆棰勫~鏁版嵁锛夛紝鐢辩敤鎴峰湪椤甸潰涓婄紪杈戝悗缁熶竴鏂板锛屼互閬垮厤鏁版嵁閲嶅鐢熸垚
             if (dto.getCounterReviewType() == 2) {
-                SalesLedger newLedger = new SalesLedger();
-                BeanUtils.copyProperties(originalLedger, newLedger);
-                newLedger.setId(null);
-                newLedger.setSalesContractNo(generateSalesContractNo());
-                newLedger.setDeliveryStatus(1);
-                newLedger.setStockStatus(0);
-                newLedger.setReviewStatus(0);
-                newLedger.setCounterReviewTime(null);
-                newLedger.setCounterReviewPerson(null);
-                newLedger.setCounterReviewPersonId(null);
-                newLedger.setCounterReviewType(null);
-                newLedger.setCounterReviewDesc(null);
-                salesLedgerMapper.insert(newLedger);
-
-                // 澶嶅埗浜у搧鍒版柊鍙拌处
-                List<SalesLedgerProduct> originalProducts = salesLedgerProductMapper.selectList(
-                        Wrappers.<SalesLedgerProduct>lambdaQuery()
-                                .eq(SalesLedgerProduct::getSalesLedgerId, id)
-                );
-                for (SalesLedgerProduct originalProduct : originalProducts) {
-                    SalesLedgerProduct newProduct = new SalesLedgerProduct();
-                    BeanUtils.copyProperties(originalProduct, newProduct);
-                    newProduct.setId(null);
-                    newProduct.setSalesLedgerId(newLedger.getId());
-                    newProduct.setStockedQuantity(BigDecimal.ZERO);
-                    newProduct.setShippedQuantity(BigDecimal.ZERO);
-                    newProduct.setUnqualifiedStockedQuantity(BigDecimal.ZERO);
-                    newProduct.setUnqualifiedShippedQuantity(BigDecimal.ZERO);
-                    newProduct.setReturnQuality(BigDecimal.ZERO);
-                    newProduct.setAvailableQuality(newProduct.getQuantity().subtract(newProduct.getReturnQuality()));
-                    newProduct.setProductStockStatus(0);
-                    newProduct.fillRemainingQuantity();
-                    salesLedgerProductMapper.insert(newProduct);
-                }
-                newLedgerIds.add(newLedger.getId());
+                newLedgerIds.add(id);
             }
         }
         return newLedgerIds;

--
Gitblit v1.9.3