From 2b463c375d600470d554dbca7d80e92110d16abf Mon Sep 17 00:00:00 2001
From: maven <2163098428@qq.com>
Date: 星期二, 03 二月 2026 10:16:53 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_New' into sqd_new

---
 src/main/resources/mapper/sales/SalesLedgerMapper.xml                                 |   24 +
 src/main/java/com/ruoyi/home/controller/HomeController.java                           |   53 +++
 src/main/java/com/ruoyi/production/dto/ProductOrderDto.java                           |    2 
 src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java |   77 ++--
 src/main/java/com/ruoyi/home/dto/UnqualifiedProductRankDto.java                       |   39 ++
 src/main/java/com/ruoyi/home/dto/QualityQualifiedAnalysisDto.java                     |   39 ++
 src/main/java/com/ruoyi/safe/service/impl/SafeTrainingServiceImpl.java                |    4 
 src/main/java/com/ruoyi/sales/pojo/SalesLedger.java                                   |    3 
 src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java                        |  546 +++++++++++++++++++++++++++++++
 src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedController.java          |    8 
 src/main/resources/mapper/production/ProductOrderMapper.xml                           |   14 
 src/main/java/com/ruoyi/home/dto/CompletedInspectionCountDto.java                     |   37 ++
 src/main/java/com/ruoyi/home/dto/NonComplianceWarningDto.java                         |   64 +++
 src/main/java/com/ruoyi/home/service/HomeService.java                                 |   17 +
 src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java                |   10 
 src/main/java/com/ruoyi/production/pojo/ProductProcessRouteItem.java                  |    3 
 src/main/java/com/ruoyi/production/pojo/ProcessRouteItem.java                         |    3 
 src/main/java/com/ruoyi/production/pojo/ProductProcess.java                           |    3 
 src/main/java/com/ruoyi/home/dto/QualityInspectionCountDto.java                       |   48 ++
 src/main/resources/mapper/safe/SafeTrainingMapper.xml                                 |    1 
 20 files changed, 937 insertions(+), 58 deletions(-)

diff --git a/src/main/java/com/ruoyi/home/controller/HomeController.java b/src/main/java/com/ruoyi/home/controller/HomeController.java
index 8d72113..7cf3f95 100644
--- a/src/main/java/com/ruoyi/home/controller/HomeController.java
+++ b/src/main/java/com/ruoyi/home/controller/HomeController.java
@@ -202,6 +202,59 @@
         return AjaxResult.success(homeService.orderCount());
     }
 
+    @GetMapping("/rawMaterialDetection")
+    @ApiOperation("鍘熸潗鏂欐娴�")
+    public AjaxResult rawMaterialDetection(@RequestParam(value = "type", defaultValue = "1") Integer type){
+        return AjaxResult.success(homeService.rawMaterialDetection(type));
+    }
+
+    @GetMapping("/processDetection")
+    @ApiOperation("杩囩▼妫�娴�")
+    public AjaxResult processDetection(@RequestParam(value = "type", defaultValue = "1") Integer type){
+        return AjaxResult.success(homeService.processDetection(type));
+    }
+
+    @GetMapping("/factoryDetection")
+    @ApiOperation("鎴愬搧鍑哄巶妫�娴�")
+    public AjaxResult factoryDetection(@RequestParam(value = "type", defaultValue = "1") Integer type){
+        return AjaxResult.success(homeService.factoryDetection(type));
+    }
+
+    @GetMapping("/qualityInspectionCount")
+    @ApiOperation("璐ㄩ噺妫�楠屾暟閲�")
+    public AjaxResult qualityInspectionCount(){
+        QualityInspectionCountDto qualityInspectionCountDto = homeService.qualityInspectionCount();
+        return AjaxResult.success(qualityInspectionCountDto);
+    }
+
+    @GetMapping("/nonComplianceWarning")
+    @ApiOperation("涓嶅悎鏍奸璀�")
+    public AjaxResult nonComplianceWarning(){
+        NonComplianceWarningDto nonComplianceWarningDto = homeService.nonComplianceWarning();
+        return AjaxResult.success(nonComplianceWarningDto);
+    }
+
+    @GetMapping("/completedInspectionCount")
+    @ApiOperation("瀹屾垚妫�楠屾暟")
+    public AjaxResult completedInspectionCount(){
+        List<CompletedInspectionCountDto> list = homeService.completedInspectionCount();
+        return AjaxResult.success(list);
+    }
+
+    @GetMapping("/unqualifiedProductRanking")
+    @ApiOperation("涓嶅悎鏍间骇鍝佹帓鍚�")
+    public AjaxResult unqualifiedProductRanking(){
+        List<UnqualifiedProductRankDto> list = homeService.unqualifiedProductRanking();
+        return AjaxResult.success(list);
+    }
+
+    @GetMapping("/unqualifiedProductProcessingAnalysis")
+    @ApiOperation("涓嶅悎鏍兼鍝佸鐞嗗垎鏋�")
+    public AjaxResult unqualifiedProductProcessingAnalysis(){
+        List<MapDto> list = homeService.unqualifiedProductProcessingAnalysis();
+        return AjaxResult.success(list);
+    }
+
     /********************************************************钀ラ攢閲囪喘绫�**************************************************/
     @GetMapping("/business")
     @Log(title = "閿�鍞�-閲囪喘-搴撳瓨鏁版嵁", businessType = BusinessType.OTHER)
diff --git a/src/main/java/com/ruoyi/home/dto/CompletedInspectionCountDto.java b/src/main/java/com/ruoyi/home/dto/CompletedInspectionCountDto.java
new file mode 100644
index 0000000..68dd371
--- /dev/null
+++ b/src/main/java/com/ruoyi/home/dto/CompletedInspectionCountDto.java
@@ -0,0 +1,37 @@
+package com.ruoyi.home.dto;
+
+import java.math.BigDecimal;
+
+import lombok.Data;
+
+/**
+ * <br>
+ * 瀹屾垚妫�楠屾暟
+ * </br>
+ *
+ * @author deslrey
+ * @version 1.0
+ * @since 2026/2/2
+ */
+@Data
+public class CompletedInspectionCountDto {
+    /**
+     * 鏃ユ湡
+     */
+    private String dateStr;
+
+    /**
+     * 鍚堟牸鏁�
+     */
+    private BigDecimal qualifiedCount;
+
+    /**
+     * 涓嶅悎鏍兼暟
+     */
+    private BigDecimal unqualifiedCount;
+
+    /**
+     * 鍚堟牸鐜�
+     */
+    private BigDecimal passRate;
+}
diff --git a/src/main/java/com/ruoyi/home/dto/NonComplianceWarningDto.java b/src/main/java/com/ruoyi/home/dto/NonComplianceWarningDto.java
new file mode 100644
index 0000000..75c79b9
--- /dev/null
+++ b/src/main/java/com/ruoyi/home/dto/NonComplianceWarningDto.java
@@ -0,0 +1,64 @@
+package com.ruoyi.home.dto;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+import lombok.Data;
+
+/**
+ * <br>
+ * 涓嶅悎鏍奸璀�
+ * </br>
+ *
+ * @author deslrey
+ * @version 1.0
+ * @since 2026/2/2
+ */
+@Data
+public class NonComplianceWarningDto {
+
+    /**
+     * 鍘熸潗鏂欏崰姣�
+     */
+    private BigDecimal rawMaterialRatio;
+
+    /**
+     * 鍗婃垚鍝佸崰姣�
+     */
+    private BigDecimal semiFinishedProductRatio;
+
+    /**
+     * 鎴愬搧鍗犳瘮
+     */
+    private BigDecimal finishedProductRatio;
+
+    /**
+     * 鏁版嵁
+     */
+
+    private List<Item> children;
+
+    @Data
+    public static class Item {
+        /**
+         * 鐖剁被浜у搧鏍囬
+         */
+        private String parentProductTitle;
+
+        /**
+         * 浜у搧鏍囬
+         */
+        private String productTitle;
+
+        /**
+         * 鎻忚堪
+         */
+        private String description;
+
+        /**
+         * 鏃ユ湡
+         */
+        private String date;
+    }
+
+}
diff --git a/src/main/java/com/ruoyi/home/dto/QualityInspectionCountDto.java b/src/main/java/com/ruoyi/home/dto/QualityInspectionCountDto.java
new file mode 100644
index 0000000..74d5f81
--- /dev/null
+++ b/src/main/java/com/ruoyi/home/dto/QualityInspectionCountDto.java
@@ -0,0 +1,48 @@
+package com.ruoyi.home.dto;
+
+import java.math.BigDecimal;
+
+import lombok.Data;
+
+/**
+ * <br>
+ * 妫�楠屾暟閲�
+ * </br>
+ *
+ * @author deslrey
+ * @version 1.0
+ * @since 2026/2/2
+ */
+@Data
+public class QualityInspectionCountDto {
+
+    /**
+     * 鎬绘楠屾暟
+     */
+    private BigDecimal totalCount;
+
+    /**
+     * 鎬绘楠屾暟鍚屾瘮澧為暱
+     */
+    private BigDecimal totalCountGrowthRate;
+
+    /**
+     * 浠婃棩寰呭畬鎴愭暟
+     */
+    private BigDecimal todayPendingCount;
+
+    /**
+     * 浠婃棩寰呭畬鎴愭暟鍚屾瘮澧為暱
+     */
+    private BigDecimal todayPendingCountGrowthRate;
+
+    /**
+     * 浠婃棩宸插畬鎴愭暟
+     */
+    private BigDecimal todayCompletedCount;
+
+    /**
+     * 浠婃棩宸插畬鎴愭暟鍚屾瘮澧為暱
+     */
+    private BigDecimal todayCompletedCountGrowthRate;
+}
diff --git a/src/main/java/com/ruoyi/home/dto/QualityQualifiedAnalysisDto.java b/src/main/java/com/ruoyi/home/dto/QualityQualifiedAnalysisDto.java
new file mode 100644
index 0000000..c58887f
--- /dev/null
+++ b/src/main/java/com/ruoyi/home/dto/QualityQualifiedAnalysisDto.java
@@ -0,0 +1,39 @@
+package com.ruoyi.home.dto;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * <br>
+ * 璐ㄩ噺鎸囨爣鍚堟牸鍒嗘瀽
+ * </br>
+ *
+ * @author deslrey
+ * @version 1.0
+ * @since 2026/2/2
+ */
+
+@Data
+public class QualityQualifiedAnalysisDto {
+
+    /**
+     * 鍚堟牸鏁�
+     */
+    private int qualifiedCount;
+
+    /**
+     * 涓嶅悎鏍兼暟
+     */
+    private int unqualifiedCount;
+
+    /**
+     * 鍚堟牸姣斾緥
+     */
+    private BigDecimal qualifiedRate;
+
+    /**
+     * 涓嶅悎鏍兼瘮渚�
+     */
+    private BigDecimal unqualifiedRate;
+}
diff --git a/src/main/java/com/ruoyi/home/dto/UnqualifiedProductRankDto.java b/src/main/java/com/ruoyi/home/dto/UnqualifiedProductRankDto.java
new file mode 100644
index 0000000..cd9eec1
--- /dev/null
+++ b/src/main/java/com/ruoyi/home/dto/UnqualifiedProductRankDto.java
@@ -0,0 +1,39 @@
+package com.ruoyi.home.dto;
+
+import java.math.BigDecimal;
+
+import lombok.Data;
+
+/**
+ * <br>
+ * 涓嶅悎鏍间骇鍝佹帓鍚�
+ * </br>
+ *
+ * @author deslrey
+ * @version 1.0
+ * @since 2026/2/2
+ */
+
+@Data
+public class UnqualifiedProductRankDto {
+
+    /**
+     * 浜у搧鍚嶇О
+     */
+    private String productName;
+
+    /**
+     * 鎬诲畬鎴愭暟閲�
+     */
+    private BigDecimal totalCount;
+
+    /**
+     * 宸插畬鎴愭暟閲�
+     */
+    private BigDecimal completedCount;
+
+    /**
+     * 鍚堟牸鐜�
+     */
+    private BigDecimal passRate;
+}
diff --git a/src/main/java/com/ruoyi/home/service/HomeService.java b/src/main/java/com/ruoyi/home/service/HomeService.java
index 77bbf6b..a2e113d 100644
--- a/src/main/java/com/ruoyi/home/service/HomeService.java
+++ b/src/main/java/com/ruoyi/home/service/HomeService.java
@@ -31,6 +31,7 @@
     Long noticesCount();
 
     ProductionProgressDto productionProgress();
+
     ProductionTurnoverDto workInProcessTurnover();
 
     DeptStaffDistributionDto deptStaffDistribution();
@@ -74,4 +75,20 @@
     List<ProductionAccountingDto> productionAccountingAnalysis(Integer type);
 
     List<MapDto> orderCount();
+
+    QualityQualifiedAnalysisDto rawMaterialDetection(Integer type);
+
+    QualityQualifiedAnalysisDto processDetection(Integer type);
+
+    QualityQualifiedAnalysisDto factoryDetection(Integer type);
+
+    QualityInspectionCountDto qualityInspectionCount();
+
+    NonComplianceWarningDto nonComplianceWarning();
+
+    List<CompletedInspectionCountDto> completedInspectionCount();
+
+    List<UnqualifiedProductRankDto> unqualifiedProductRanking();
+
+    List<MapDto> unqualifiedProductProcessingAnalysis();
 }
diff --git a/src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java b/src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
index a377159..8de8a83 100644
--- a/src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
+++ b/src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java
@@ -20,6 +20,7 @@
 import com.ruoyi.collaborativeApproval.pojo.Notice;
 import com.ruoyi.common.enums.ApproveTypeEnum;
 import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.device.mapper.DeviceRepairMapper;
 import com.ruoyi.device.pojo.DeviceRepair;
 import com.ruoyi.dto.MapDto;
@@ -48,7 +49,9 @@
 import com.ruoyi.purchase.pojo.PaymentRegistration;
 import com.ruoyi.purchase.pojo.PurchaseLedger;
 import com.ruoyi.quality.mapper.QualityInspectMapper;
+import com.ruoyi.quality.mapper.QualityUnqualifiedMapper;
 import com.ruoyi.quality.pojo.QualityInspect;
+import com.ruoyi.quality.pojo.QualityUnqualified;
 import com.ruoyi.sales.mapper.ReceiptPaymentMapper;
 import com.ruoyi.sales.mapper.SalesLedgerMapper;
 import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
@@ -94,9 +97,6 @@
     private StockInventoryMapper stockInventoryMapper;
 
     @Autowired
-    private ProcurementRecordMapper procurementRecordStorageMapper;
-
-    @Autowired
     private QualityInspectMapper qualityStatisticsMapper;
 
     @Autowired
@@ -113,27 +113,36 @@
 
     @Autowired
     private NoticeMapper noticeMapper;
+
     @Autowired
     private ProductOrderMapper productOrderMapper;
+
     @Autowired
     private ProductWorkOrderMapper productWorkOrderMapper;
-    @Autowired
-    private ProductModelMapper productModelMapper;
+
     @Autowired
     private ProductMapper productMapper;
-    @Autowired
-    private StockUtils stockUtils;
+
     @Autowired
     private StaffOnJobMapper staffOnJobMapper;
+
     @Autowired
     private CustomerMapper customerMapper;
+
     @Autowired
     private SupplierManageMapper supplierManageMapper;
+
     @Autowired
     private HomeMapper homeMapper;
 
     @Autowired
     private ProductionProductOutputMapper productionProductOutputMapper;
+
+    @Autowired
+    private QualityInspectMapper qualityInspectMapper;
+
+    @Autowired
+    private QualityUnqualifiedMapper qualityUnqualifiedMapper;
 
     @Override
     public HomeBusinessDto business() {
@@ -1812,7 +1821,8 @@
 
         String endStr = endDate.plusDays(1).atStartOfDay().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
 
-        List<Map<String, Object>> wagesList = salesLedgerProductionAccountingMapper.selectDailyWagesStats(startStr, endStr);
+        List<Map<String, Object>> wagesList = salesLedgerProductionAccountingMapper.selectDailyWagesStats(startStr,
+                endStr);
 
         if (CollectionUtils.isEmpty(wagesList)) {
             return new ArrayList<>();
@@ -1882,4 +1892,522 @@
         return dto;
     }
 
-}
+
+    @Override
+    public QualityQualifiedAnalysisDto rawMaterialDetection(Integer type) {
+        return commonDetection(type, 0);
+    }
+
+    @Override
+    public QualityQualifiedAnalysisDto processDetection(Integer type) {
+        return commonDetection(type, 1);
+    }
+
+    @Override
+    public QualityQualifiedAnalysisDto factoryDetection(Integer type) {
+        return commonDetection(type, 2);
+    }
+
+    private QualityQualifiedAnalysisDto commonDetection(Integer type, Integer inspectType) {
+
+        LocalDate[] range = calcDateRange(type);
+        LocalDate startDate = range[0];
+        LocalDate endDate = range[1];
+
+        String startStr = startDate.atStartOfDay()
+                .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+        String endStr = endDate.atTime(LocalTime.MAX)
+                .format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+
+        List<QualityInspect> list = qualityInspectMapper.selectList(
+                new LambdaQueryWrapper<QualityInspect>()
+                        .eq(QualityInspect::getInspectType, inspectType)
+                        .eq(QualityInspect::getInspectState, 1)
+                        .ge(QualityInspect::getCheckTime, startStr)
+                        .le(QualityInspect::getCheckTime, endStr));
+
+        return buildQualifiedAnalysis(list);
+    }
+
+    private LocalDate[] calcDateRange(Integer type) {
+        LocalDate today = LocalDate.now();
+        LocalDate startDate;
+        LocalDate endDate;
+
+        switch (type) {
+            case 1: // 鍛�
+                startDate = today.with(DayOfWeek.MONDAY);
+                endDate = today.with(DayOfWeek.SUNDAY);
+                break;
+            case 2: // 鏈�
+                startDate = today.with(TemporalAdjusters.firstDayOfMonth());
+                endDate = today.with(TemporalAdjusters.lastDayOfMonth());
+                break;
+            case 3: // 瀛e害
+                int currentMonth = today.getMonthValue();
+                int startMonth = ((currentMonth - 1) / 3) * 3 + 1;
+                startDate = LocalDate.of(today.getYear(), startMonth, 1);
+                endDate = LocalDate.of(today.getYear(), startMonth + 2, 1)
+                        .with(TemporalAdjusters.lastDayOfMonth());
+                break;
+            default:
+                startDate = today.with(DayOfWeek.MONDAY);
+                endDate = today.with(DayOfWeek.SUNDAY);
+        }
+
+        return new LocalDate[]{startDate, endDate};
+    }
+
+    private QualityQualifiedAnalysisDto buildQualifiedAnalysis(List<QualityInspect> list) {
+        List<QualityQualifiedAnalysisDto> result = new ArrayList<>();
+        QualityQualifiedAnalysisDto dto = new QualityQualifiedAnalysisDto();
+
+        if (CollectionUtils.isEmpty(list)) {
+            dto.setQualifiedCount(0);
+            dto.setUnqualifiedCount(0);
+            dto.setQualifiedRate(BigDecimal.ZERO.setScale(2));
+            dto.setUnqualifiedRate(BigDecimal.ZERO.setScale(2));
+            return dto;
+        }
+
+        BigDecimal qualifiedCount = BigDecimal.ZERO;
+        BigDecimal unqualifiedCount = BigDecimal.ZERO;
+
+        for (QualityInspect item : list) {
+            if ("鍚堟牸".equals(item.getCheckResult())) {
+                qualifiedCount = qualifiedCount.add(item.getQuantity());
+            } else {
+                unqualifiedCount = unqualifiedCount.add(item.getQuantity());
+            }
+        }
+
+        BigDecimal totalCount = qualifiedCount.add(unqualifiedCount);
+
+        dto.setQualifiedCount(qualifiedCount.intValue());
+        dto.setUnqualifiedCount(unqualifiedCount.intValue());
+
+        if (totalCount.compareTo(BigDecimal.ZERO) == 0) {
+            dto.setQualifiedRate(BigDecimal.ZERO.setScale(2));
+            dto.setUnqualifiedRate(BigDecimal.ZERO.setScale(2));
+            return dto;
+        }
+
+        BigDecimal hundred = BigDecimal.valueOf(100);
+
+        dto.setQualifiedRate(qualifiedCount.divide(totalCount, 4, RoundingMode.HALF_UP)
+                .multiply(hundred)
+                .setScale(2, RoundingMode.HALF_UP));
+
+        dto.setUnqualifiedRate(unqualifiedCount.divide(totalCount, 4, RoundingMode.HALF_UP)
+                .multiply(hundred)
+                .setScale(2, RoundingMode.HALF_UP));
+
+        return dto;
+    }
+
+    @Override
+    public QualityInspectionCountDto qualityInspectionCount() {
+        // 鑾峰彇浠婂ぉ鐨勫紑濮嬪拰缁撴潫鏃ユ湡,鍖呭惈鏃跺垎绉�
+        LocalDateTime todayStart = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0);
+        LocalDateTime todayEnd = LocalDateTime.now().withHour(23).withMinute(59).withSecond(59).withNano(0);
+        // 鑾峰彇鍓嶄竴澶╃殑寮�濮嬪拰缁撴潫鏃ユ湡,鍖呭惈鏃跺垎绉�
+        LocalDateTime prevStart = todayStart.minusDays(1);
+        LocalDateTime prevEnd = todayEnd.minusDays(1);
+        // 鏌ヨ鍑烘埅姝粖鏃ョ殑鎬绘楠屾暟
+        List<QualityInspect> todayList = qualityInspectMapper.selectList(new LambdaQueryWrapper<QualityInspect>()
+                // .eq(QualityInspect::getInspectState, 1)
+                .le(QualityInspect::getCheckTime, todayEnd));
+        // 鏌ヨ鍑烘埅姝㈠墠涓�澶╃殑鎬绘楠屾暟
+        List<QualityInspect> prevList = qualityInspectMapper.selectList(new LambdaQueryWrapper<QualityInspect>()
+                // .eq(QualityInspect::getInspectState, 1)
+                .le(QualityInspect::getCheckTime, prevEnd));
+        // 璁$畻浠婃棩鐨勬�绘楠屾暟
+        BigDecimal todayCount = todayList.stream()
+                .map(QualityInspect::getQuantity)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+        // 璁$畻鍓嶄竴澶╃殑鎬绘楠屾暟
+        BigDecimal prevCount = prevList.stream()
+                .map(QualityInspect::getQuantity)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+        // 璁$畻浠婃棩鐩稿鏄ㄥぉ鐨勪竴涓�绘瘮澧為暱
+        BigDecimal growthRate = calcGrowthRate(todayCount, prevCount);
+
+        // 璁$畻浠婂ぉ鐨勫緟瀹屾垚鏁伴噺
+        List<QualityInspect> todayPendingList = qualityInspectMapper.selectList(new LambdaQueryWrapper<QualityInspect>()
+                .eq(QualityInspect::getInspectState, 0)
+                .ge(QualityInspect::getCheckTime, todayStart)
+                .le(QualityInspect::getCheckTime, todayEnd));
+
+        // 璁$畻鍓嶄竴澶╃殑寰呭畬鎴愭暟閲�
+        List<QualityInspect> prevPendingList = qualityInspectMapper.selectList(new LambdaQueryWrapper<QualityInspect>()
+                .eq(QualityInspect::getInspectState, 0)
+                .ge(QualityInspect::getCheckTime, prevStart)
+                .le(QualityInspect::getCheckTime, prevEnd));
+        // 璁$畻浠婂ぉ鐨勫緟瀹屾垚鏁伴噺
+        BigDecimal todayPendingCount = todayPendingList.stream()
+                .map(QualityInspect::getQuantity)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+        // 璁$畻鍓嶄竴澶╃殑寰呭畬鎴愭暟閲�
+        BigDecimal prevPendingCount = prevPendingList.stream()
+                .map(QualityInspect::getQuantity)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+        // 璁$畻浠婂ぉ鐨勫緟瀹屾垚鏁伴噺鐩稿鏄ㄥぉ鐨勪竴涓悓姣斿闀�
+        BigDecimal todayPendingCountGrowthRate = calcGrowthRate(todayPendingCount, prevPendingCount);
+        // 璁$畻浠婂ぉ鐨勫凡瀹屾垚鏁伴噺
+        List<QualityInspect> todayCompletedList = qualityInspectMapper
+                .selectList(new LambdaQueryWrapper<QualityInspect>()
+                        .eq(QualityInspect::getInspectState, 1)
+                        .ge(QualityInspect::getCheckTime, todayStart)
+                        .le(QualityInspect::getCheckTime, todayEnd));
+        // 璁$畻鍓嶄竴澶╃殑宸插畬鎴愭暟閲�
+        List<QualityInspect> prevCompletedList = qualityInspectMapper
+                .selectList(new LambdaQueryWrapper<QualityInspect>()
+                        .eq(QualityInspect::getInspectState, 1)
+                        .ge(QualityInspect::getCheckTime, prevStart)
+                        .le(QualityInspect::getCheckTime, prevEnd));
+        // 璁$畻浠婂ぉ鐨勫凡瀹屾垚鏁伴噺
+        BigDecimal todayCompletedCount = todayCompletedList.stream()
+                .map(QualityInspect::getQuantity)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+        // 璁$畻鍓嶄竴澶╃殑宸插畬鎴愭暟閲�
+        BigDecimal prevCompletedCount = prevCompletedList.stream()
+                .map(QualityInspect::getQuantity)
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+        // 璁$畻浠婂ぉ鐨勫凡瀹屾垚鏁伴噺鐩稿鏄ㄥぉ鐨勪竴涓悓姣斿闀�
+        BigDecimal todayCompletedCountGrowthRate = calcGrowthRate(todayCompletedCount, prevCompletedCount);
+        QualityInspectionCountDto dto = new QualityInspectionCountDto();
+        dto.setTotalCount(todayCount);
+        dto.setTotalCountGrowthRate(growthRate);
+        dto.setTodayPendingCount(todayPendingCount);
+        dto.setTodayPendingCountGrowthRate(todayPendingCountGrowthRate);
+        dto.setTodayCompletedCount(todayCompletedCount);
+        dto.setTodayCompletedCountGrowthRate(todayCompletedCountGrowthRate);
+        return dto;
+    }
+
+    private BigDecimal calcGrowthRate(BigDecimal today, BigDecimal prev) {
+        if (prev == null || prev.compareTo(BigDecimal.ZERO) == 0) {
+            return BigDecimal.ZERO.setScale(2);
+        }
+        return today.subtract(prev)
+                .divide(prev, 4, RoundingMode.HALF_UP)
+                .multiply(BigDecimal.valueOf(100))
+                .setScale(2, RoundingMode.HALF_UP);
+    }
+
+    @Override
+    public NonComplianceWarningDto nonComplianceWarning() {
+
+        // 杩戜竷澶╂椂闂村尯闂�
+        LocalDateTime[] range = lastSevenDaysRange();
+        LocalDateTime startTime = range[0];
+        LocalDateTime endTime = range[1];
+
+        // 鏌ヨ杩戜竷澶╁凡澶勭悊涓嶅悎鏍兼暟鎹�
+        List<QualityUnqualified> list = qualityUnqualifiedMapper.selectList(
+                new LambdaQueryWrapper<QualityUnqualified>()
+                        .eq(QualityUnqualified::getInspectState, 1)
+                        .ge(QualityUnqualified::getCheckTime, startTime)
+                        .le(QualityUnqualified::getCheckTime, endTime));
+
+        NonComplianceWarningDto dto = new NonComplianceWarningDto();
+
+        if (CollectionUtils.isEmpty(list)) {
+            dto.setRawMaterialRatio(BigDecimal.ZERO);
+            dto.setSemiFinishedProductRatio(BigDecimal.ZERO);
+            dto.setFinishedProductRatio(BigDecimal.ZERO);
+            dto.setChildren(new ArrayList<>());
+            return dto;
+        }
+
+        // 鏌ヨ鎵�鏈変骇鍝�
+        List<Product> products = productMapper.selectList(null);
+
+        Map<Long, Product> productMap = products.stream()
+                .collect(Collectors.toMap(Product::getId, p -> p));
+
+        BigDecimal rawMaterialCount = BigDecimal.ZERO;
+        BigDecimal semiFinishedCount = BigDecimal.ZERO;
+        BigDecimal finishedCount = BigDecimal.ZERO;
+
+        List<NonComplianceWarningDto.Item> children = new ArrayList<>();
+
+        for (QualityUnqualified item : list) {
+
+            BigDecimal quantity = item.getQuantity();
+            Long productId = item.getProductId();
+
+            Product product = productMap.get(productId);
+            if (product == null) {
+                continue;
+            }
+
+            // 鎵惧埌浜у搧澶х被
+            Product parent = product.getParentId() == null
+                    ? product
+                    : productMap.get(product.getParentId());
+
+            if (parent == null) {
+                continue;
+            }
+
+            switch (parent.getProductName()) {
+                case "鍘熸潗鏂�":
+                    rawMaterialCount = rawMaterialCount.add(quantity);
+                    break;
+                case "鍗婃垚鍝�":
+                    semiFinishedCount = semiFinishedCount.add(quantity);
+                    break;
+                case "鎴愬搧":
+                    finishedCount = finishedCount.add(quantity);
+                    break;
+                default:
+                    break;
+            }
+
+            // 缁勮鏄庣粏
+            NonComplianceWarningDto.Item child = new NonComplianceWarningDto.Item();
+            // child.setProductTitle(item.getProductName());
+            child.setParentProductTitle(parent.getProductName());
+            child.setProductTitle(item.getProductName());
+            child.setDescription(item.getDefectivePhenomena());
+            child.setDate(formatDate(item.getCheckTime()));
+            children.add(child);
+        }
+
+        BigDecimal total = rawMaterialCount
+                .add(semiFinishedCount)
+                .add(finishedCount);
+
+        dto.setRawMaterialRatio(calcRate(rawMaterialCount, total));
+        dto.setSemiFinishedProductRatio(calcRate(semiFinishedCount, total));
+        dto.setFinishedProductRatio(calcRate(finishedCount, total));
+        dto.setChildren(children);
+
+        return dto;
+    }
+
+    private BigDecimal calcRate(BigDecimal part, BigDecimal total) {
+        if (total == null || total.compareTo(BigDecimal.ZERO) == 0) {
+            return BigDecimal.ZERO.setScale(2);
+        }
+        return part.divide(total, 4, RoundingMode.HALF_UP)
+                .multiply(BigDecimal.valueOf(100))
+                .setScale(2, RoundingMode.HALF_UP);
+    }
+
+    public static String formatDate(Date date) {
+        if (date == null) {
+            return null;
+        }
+        return date.toInstant()
+                .atZone(ZoneId.systemDefault())
+                .toLocalDate()
+                .format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
+    }
+
+    /**
+     * 鑾峰彇杩戜竷澶╃殑鏃堕棿鍖洪棿锛堝寘鍚粖澶╋級
+     */
+    public static LocalDateTime[] lastSevenDaysRange() {
+        LocalDate today = LocalDate.now();
+
+        LocalDateTime startTime = today.minusDays(6).atStartOfDay();
+        LocalDateTime endTime = today.atTime(23, 59, 59);
+
+        return new LocalDateTime[]{startTime, endTime};
+    }
+
+    @Override
+    public List<CompletedInspectionCountDto> completedInspectionCount() {
+        // 杩戜竷澶╂椂闂村尯闂�
+        LocalDateTime[] range = lastSevenDaysRange();
+        LocalDateTime startTime = range[0];
+        LocalDateTime endTime = range[1];
+
+        // 鏌ヨ杩戜竷澶╁凡瀹屾垚鐨勬楠屾暟鎹�
+        List<QualityInspect> list = qualityInspectMapper.selectList(new LambdaQueryWrapper<QualityInspect>()
+                .eq(QualityInspect::getInspectState, 1)
+                .ge(QualityInspect::getCheckTime, startTime)
+                .le(QualityInspect::getCheckTime, endTime));
+
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd");
+
+        Map<String, CompletedInspectionCountDto> resultMap = new LinkedHashMap<>();
+
+        for (int i = 6; i >= 0; i--) {
+            LocalDate date = LocalDate.now().minusDays(i);
+            String dateStr = date.format(formatter);
+
+            CompletedInspectionCountDto dto = new CompletedInspectionCountDto();
+            dto.setDateStr(dateStr);
+            dto.setQualifiedCount(BigDecimal.ZERO);
+            dto.setUnqualifiedCount(BigDecimal.ZERO);
+            dto.setPassRate(BigDecimal.ZERO);
+
+            resultMap.put(dateStr, dto);
+        }
+
+        // 绱姞鍚堟牸 / 涓嶅悎鏍兼暟閲�
+        for (QualityInspect item : list) {
+
+            String dateStr = item.getCheckTime()
+                    .toInstant()
+                    .atZone(ZoneId.systemDefault())
+                    .toLocalDate()
+                    .format(formatter);
+
+            CompletedInspectionCountDto dto = resultMap.get(dateStr);
+            if (dto == null) {
+                continue;
+            }
+
+            BigDecimal quantity = item.getQuantity();
+
+            if ("鍚堟牸".equals(item.getCheckResult())) {
+                dto.setQualifiedCount(dto.getQualifiedCount().add(quantity));
+            } else {
+                dto.setUnqualifiedCount(dto.getUnqualifiedCount().add(quantity));
+            }
+        }
+
+        // 璁$畻鍚堟牸鐜�
+        for (CompletedInspectionCountDto dto : resultMap.values()) {
+            BigDecimal total = dto.getQualifiedCount().add(dto.getUnqualifiedCount());
+            dto.setPassRate(calcRate(dto.getQualifiedCount(), total));
+        }
+
+        return new ArrayList<>(resultMap.values());
+    }
+
+    @Override
+    public List<UnqualifiedProductRankDto> unqualifiedProductRanking() {
+
+        List<QualityInspect> list = qualityInspectMapper.selectList(new LambdaQueryWrapper<QualityInspect>()
+                .eq(QualityInspect::getInspectState, 1));
+
+        if (CollectionUtils.isEmpty(list)) {
+            return new ArrayList<>();
+        }
+
+        Map<Long, String> productNameMap = productMapper.selectList(null)
+                .stream()
+                .collect(Collectors.toMap(Product::getId, Product::getProductName));
+
+        Map<Long, List<QualityInspect>> groupMap = list.stream()
+                .collect(Collectors.groupingBy(QualityInspect::getProductId));
+
+        List<UnqualifiedProductRankDto> resultList = new ArrayList<>();
+
+        for (Map.Entry<Long, List<QualityInspect>> entry : groupMap.entrySet()) {
+
+            Long productId = entry.getKey();
+            List<QualityInspect> items = entry.getValue();
+
+            BigDecimal totalCount = BigDecimal.ZERO;
+            BigDecimal qualifiedCount = BigDecimal.ZERO;
+            BigDecimal unqualifiedCount = BigDecimal.ZERO;
+
+            for (QualityInspect item : items) {
+                BigDecimal qty = item.getQuantity();
+                totalCount = totalCount.add(qty);
+
+                if ("鍚堟牸".equals(item.getCheckResult())) {
+                    qualifiedCount = qualifiedCount.add(qty);
+                } else {
+                    unqualifiedCount = unqualifiedCount.add(qty);
+                }
+            }
+
+            if (totalCount.compareTo(BigDecimal.ZERO) == 0) {
+                continue;
+            }
+
+            BigDecimal passRate = qualifiedCount
+                    .divide(totalCount, 4, RoundingMode.HALF_UP)
+                    .multiply(new BigDecimal("100"))
+                    .setScale(2, RoundingMode.HALF_UP);
+
+            UnqualifiedProductRankDto dto = new UnqualifiedProductRankDto();
+            dto.setProductName(productNameMap.get(productId));
+            dto.setTotalCount(totalCount);
+            dto.setCompletedCount(qualifiedCount);
+            dto.setPassRate(passRate);
+
+            resultList.add(dto);
+        }
+
+        resultList.sort(Comparator.comparing(UnqualifiedProductRankDto::getPassRate));
+
+        return resultList.stream().limit(5).collect(Collectors.toList());
+    }
+
+    @Override
+    public List<MapDto> unqualifiedProductProcessingAnalysis() {
+
+        List<QualityUnqualified> list = qualityUnqualifiedMapper.selectList(null);
+        if (CollectionUtils.isEmpty(list)) {
+            return new ArrayList<>();
+        }
+
+        //  缁熻姣忕澶勭悊缁撴灉鐨勬暟閲�
+        Map<String, BigDecimal> countMap = new HashMap<>();
+        for (QualityUnqualified item : list) {
+            if (StringUtils.isEmpty(item.getDealResult()) || item.getQuantity() == null) {
+                continue;
+            }
+            countMap.merge(item.getDealResult(), item.getQuantity(), BigDecimal::add);
+        }
+
+        if (countMap.isEmpty()) {
+            return new ArrayList<>();
+        }
+
+        //  璁$畻鎬绘暟
+        BigDecimal totalCount = countMap.values()
+                .stream()
+                .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+        if (totalCount.compareTo(BigDecimal.ZERO) == 0) {
+            return new ArrayList<>();
+        }
+
+        //  鎸夋暟閲忓�掑簭鎺掑簭
+        List<Map.Entry<String, BigDecimal>> sortedList = countMap.entrySet()
+                .stream()
+                .sorted((a, b) -> b.getValue().compareTo(a.getValue()))
+                .collect(Collectors.toList());
+
+        List<MapDto> result = new ArrayList<>();
+
+        int limit = Math.min(3, sortedList.size());
+        BigDecimal otherCount = BigDecimal.ZERO;
+
+        for (int i = 0; i < sortedList.size(); i++) {
+            Map.Entry<String, BigDecimal> entry = sortedList.get(i);
+
+            if (i < limit) {
+                MapDto dto = new MapDto();
+                dto.setName(entry.getKey());
+                dto.setValue(entry.getValue().setScale(2, RoundingMode.HALF_UP).toPlainString());
+                dto.setRate(calcRate(entry.getValue(), totalCount).toString());
+                result.add(dto);
+            } else {
+                otherCount = otherCount.add(entry.getValue());
+            }
+        }
+
+        if (otherCount.compareTo(BigDecimal.ZERO) > 0) {
+            MapDto otherDto = new MapDto();
+            otherDto.setName("鍏朵粬");
+            otherDto.setValue(otherCount.setScale(2, RoundingMode.HALF_UP).toPlainString());
+            otherDto.setRate(calcRate(otherCount, totalCount).toString());
+            result.add(otherDto);
+        }
+
+        return result;
+    }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/production/dto/ProductOrderDto.java b/src/main/java/com/ruoyi/production/dto/ProductOrderDto.java
index 299cfd7..84539b0 100644
--- a/src/main/java/com/ruoyi/production/dto/ProductOrderDto.java
+++ b/src/main/java/com/ruoyi/production/dto/ProductOrderDto.java
@@ -54,4 +54,6 @@
     @JsonFormat(pattern = "yyyy-MM-dd")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private LocalDate deliveryDate;
+
+    private Boolean isFh;
 }
diff --git a/src/main/java/com/ruoyi/production/pojo/ProcessRouteItem.java b/src/main/java/com/ruoyi/production/pojo/ProcessRouteItem.java
index f2ebd44..973b29e 100644
--- a/src/main/java/com/ruoyi/production/pojo/ProcessRouteItem.java
+++ b/src/main/java/com/ruoyi/production/pojo/ProcessRouteItem.java
@@ -38,4 +38,7 @@
     private Integer dragSort;
 
 
+    @ApiModelProperty(value ="鏄惁璐ㄦ")
+    private Boolean isQuality;
+
 }
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductProcess.java b/src/main/java/com/ruoyi/production/pojo/ProductProcess.java
index d25f9cf..5903783 100644
--- a/src/main/java/com/ruoyi/production/pojo/ProductProcess.java
+++ b/src/main/java/com/ruoyi/production/pojo/ProductProcess.java
@@ -71,4 +71,7 @@
     private Long tenantId;
 
 
+    private Boolean isQuality;
+
+
 }
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductProcessRouteItem.java b/src/main/java/com/ruoyi/production/pojo/ProductProcessRouteItem.java
index 4b6762c..d84a7ce 100644
--- a/src/main/java/com/ruoyi/production/pojo/ProductProcessRouteItem.java
+++ b/src/main/java/com/ruoyi/production/pojo/ProductProcessRouteItem.java
@@ -38,4 +38,7 @@
     @ApiModelProperty(value ="鎷栧姩鎺掑簭")
     private Integer dragSort;
 
+    @ApiModelProperty(value ="鏄惁璐ㄦ")
+    private Boolean isQuality;
+
 }
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
index 76a5757..8ac0c7e 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
@@ -163,41 +163,46 @@
         //鍙湁鍚堟牸鏁伴噺>0鎵嶈兘澧炲姞鐩稿簲鏁版嵁
         if (productQty.compareTo(BigDecimal.ZERO) > 0) {
             /*鏂板璐ㄦ*/
-            //瀵瑰簲鐨勮繃绋嬫鎴栬�呭嚭鍘傛
             List<ProductProcessRouteItem> productProcessRouteItems = productProcessRouteItemMapper.selectList(Wrappers.<ProductProcessRouteItem>lambdaQuery().eq(ProductProcessRouteItem::getProductRouteId, productProcessRouteItem.getProductRouteId()));
-            int inspectType = 1;
-            String process = productProcess.getName();//宸ュ簭
-            if (productProcessRouteItem.getDragSort() == productProcessRouteItems.size()) {
-                //鏈�鍚庝竴閬撳伐搴忕敓鎴愬嚭鍘傛
-                inspectType = 2;
-                process = null;
-            }
-            Product product = productMapper.selectById(productModel.getProductId());
-            QualityInspect qualityInspect = new QualityInspect();
-            qualityInspect.setProductId(product.getId());
-            qualityInspect.setProductName(product.getProductName());
-            qualityInspect.setModel(productModel.getModel());
-            qualityInspect.setUnit(productModel.getUnit());
-            qualityInspect.setQuantity(productQty);
-            qualityInspect.setProcess(process);
-            qualityInspect.setInspectState(0);
-            qualityInspect.setInspectType(inspectType);
-            qualityInspect.setProductMainId(productionProductMain.getId());
-            qualityInspect.setProductModelId(productModel.getId());
-            qualityInspectMapper.insert(qualityInspect);
-            List<QualityTestStandard> qualityTestStandard = qualityTestStandardMapper.getQualityTestStandardByProductId(product.getId(), inspectType, process);
-            if (qualityTestStandard.size() > 0) {
-                qualityInspect.setTestStandardId(qualityTestStandard.get(0).getId());
-                qualityInspectMapper.updateById(qualityInspect);
-                qualityTestStandardParamMapper.selectList(Wrappers.<QualityTestStandardParam>lambdaQuery()
-                                .eq(QualityTestStandardParam::getTestStandardId, qualityTestStandard.get(0).getId()))//榛樿鑾峰彇鏈�鏂扮殑
-                        .forEach(qualityTestStandardParam -> {
-                            QualityInspectParam param = new QualityInspectParam();
-                            BeanUtils.copyProperties(qualityTestStandardParam, param);
-                            param.setId(null);
-                            param.setInspectId(qualityInspect.getId());
-                            qualityInspectParamMapper.insert(param);
-                        });
+            if (productProcessRouteItem.getIsQuality()) {
+                //瀵瑰簲鐨勮繃绋嬫鎴栬�呭嚭鍘傛
+                int inspectType = 1;
+                String process = productProcess.getName();//宸ュ簭
+                if (productProcessRouteItem.getDragSort() == productProcessRouteItems.size()) {
+                    //鏈�鍚庝竴閬撳伐搴忕敓鎴愬嚭鍘傛
+                    inspectType = 2;
+                    process = null;
+                }
+                Product product = productMapper.selectById(productModel.getProductId());
+                QualityInspect qualityInspect = new QualityInspect();
+                qualityInspect.setProductId(product.getId());
+                qualityInspect.setProductName(product.getProductName());
+                qualityInspect.setModel(productModel.getModel());
+                qualityInspect.setUnit(productModel.getUnit());
+                qualityInspect.setQuantity(productQty);
+                qualityInspect.setProcess(process);
+                qualityInspect.setInspectState(0);
+                qualityInspect.setInspectType(inspectType);
+                qualityInspect.setProductMainId(productionProductMain.getId());
+                qualityInspect.setProductModelId(productModel.getId());
+                qualityInspectMapper.insert(qualityInspect);
+                List<QualityTestStandard> qualityTestStandard = qualityTestStandardMapper.getQualityTestStandardByProductId(product.getId(), inspectType, process);
+                if (qualityTestStandard.size() > 0) {
+                    qualityInspect.setTestStandardId(qualityTestStandard.get(0).getId());
+                    qualityInspectMapper.updateById(qualityInspect);
+                    qualityTestStandardParamMapper.selectList(Wrappers.<QualityTestStandardParam>lambdaQuery()
+                                    .eq(QualityTestStandardParam::getTestStandardId, qualityTestStandard.get(0).getId()))//榛樿鑾峰彇鏈�鏂扮殑
+                            .forEach(qualityTestStandardParam -> {
+                                QualityInspectParam param = new QualityInspectParam();
+                                BeanUtils.copyProperties(qualityTestStandardParam, param);
+                                param.setId(null);
+                                param.setInspectId(qualityInspect.getId());
+                                qualityInspectParamMapper.insert(param);
+                            });
+                }
+            }else {
+                //鐩存帴鍏ュ簱
+                stockUtils.addStock(productProcessRouteItem.getProductModelId(), productionProductOutput.getQuantity(), StockQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode(), productionProductMain.getId());
             }
             /*鏇存柊宸ュ崟鍜岀敓浜ц鍗�*/
             ProductWorkOrder productWorkOrder = productWorkOrderMapper.selectById(dto.getWorkOrderId());
@@ -240,7 +245,7 @@
         }
         //濡傛灉鎶ュ簾鏁伴噺>0,闇�瑕佽繘鍏ユ姤搴熺殑搴撳瓨
         if (ObjectUtils.isNotEmpty(dto.getScrapQty())) {
-            if (BigDecimal.ZERO.compareTo(dto.getScrapQty()) > 0) {
+            if (dto.getScrapQty().compareTo(BigDecimal.ZERO) > 0) {
                 stockUtils.addUnStock(productModel.getId(), dto.getScrapQty(), StockUnQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode(), productionProductMain.getId());
             }
         }
@@ -289,6 +294,8 @@
                 .eq(ProductionProductInput::getProductMainId, productionProductMain.getId()));
         //鍒犻櫎鎶ュ簾鐨勫叆搴撹褰�
         stockUtils.deleteStockInRecord(productionProductMain.getId(), StockUnQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode());
+        //鍒犻櫎涓嶉渶瑕佽川妫�鐨勫悎鏍煎叆搴�
+        stockUtils.deleteStockInRecord(productionProductMain.getId(), StockQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode());
         //鍒犻櫎鎶曞叆瀵瑰簲鐨勫嚭搴撹褰�
         stockUtils.deleteStockOutRecord(productionProductMain.getId(), StockQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode());
         // 鍒犻櫎涓昏〃
diff --git a/src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedController.java b/src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedController.java
index b015150..041d75c 100644
--- a/src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedController.java
+++ b/src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedController.java
@@ -40,9 +40,11 @@
      */
     @DeleteMapping("/del")
     public AjaxResult delQualityUnqualified(@RequestBody List<Integer> ids) {
-        if(CollectionUtils.isEmpty(ids)){
-            return AjaxResult.error("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
-        }
+       qualityUnqualifiedService.listByIds(ids).stream().forEach(qualityUnqualified -> {
+           if (qualityUnqualified.getInspectState()==1){
+               throw new RuntimeException("璇ヤ笉鍚堟牸鏁版嵁宸茬粡澶勭悊鏃犳硶鍒犻櫎!");
+           }
+       });
         return AjaxResult.success(qualityUnqualifiedService.removeBatchByIds(ids));
     }
 
diff --git a/src/main/java/com/ruoyi/safe/service/impl/SafeTrainingServiceImpl.java b/src/main/java/com/ruoyi/safe/service/impl/SafeTrainingServiceImpl.java
index fbf234b..05f1ae7 100644
--- a/src/main/java/com/ruoyi/safe/service/impl/SafeTrainingServiceImpl.java
+++ b/src/main/java/com/ruoyi/safe/service/impl/SafeTrainingServiceImpl.java
@@ -67,7 +67,7 @@
     @Override
     public int addOrUpdate(SafeTraining safeTraining) {
         if (ObjectUtils.isNull(safeTraining.getId())) {
-            String datePrefix = LocalDate.now().format(DateTimeFormatter.ofPattern("yyMMdd"));
+            String datePrefix ="KC-"+ LocalDate.now().format(DateTimeFormatter.ofPattern("yyMMdd"));
             // 鏌ヨ浠婃棩宸插瓨鍦ㄧ殑鏈�澶ц绋嬬紪鍙�
             QueryWrapper<SafeTraining> queryWrapper = new QueryWrapper<>();
             queryWrapper.likeRight("course_code", datePrefix)
@@ -87,7 +87,7 @@
                 }
             }
             // 鐢熸垚瀹屾暣鐨勮绋嬬紪鍙�
-            String no = "KC-" + String.format("%s%03d", datePrefix, sequenceNumber);
+            String no = String.format("%s%03d", datePrefix, sequenceNumber);
             safeTraining.setCourseCode(no);
         }
         //鏍规嵁鏃堕棿鍒ゆ柇鍩硅鐘舵��
diff --git a/src/main/java/com/ruoyi/sales/pojo/SalesLedger.java b/src/main/java/com/ruoyi/sales/pojo/SalesLedger.java
index 30097b4..695a17c 100644
--- a/src/main/java/com/ruoyi/sales/pojo/SalesLedger.java
+++ b/src/main/java/com/ruoyi/sales/pojo/SalesLedger.java
@@ -139,5 +139,8 @@
     @TableField(exist = false)
     @ApiModelProperty(value = "浜よ揣澶╂暟宸�")
     private Integer deliveryDaysDiff;
+
+    @TableField(exist = false)
+    private Boolean isFh;
 }
 
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 f62f179..ffa35f1 100644
--- a/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
+++ b/src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -173,6 +173,14 @@
             product.setTempNoInvoiceNum(product.getNoInvoiceNum());
             product.setRegister(SecurityUtils.getLoginUser().getUser().getNickName());
             product.setRegisterDate(LocalDateTime.now());
+            // 鍙戣揣淇℃伅
+            ShippingInfo shippingInfo = shippingInfoMapper.selectOne(new LambdaQueryWrapper<ShippingInfo>()
+                    .eq(ShippingInfo::getSalesLedgerProductId, product.getId())
+                    .orderByDesc(ShippingInfo::getCreateTime)
+                    .last("limit 1"));
+            if(shippingInfo != null){
+                product.setShippingStatus(shippingInfo.getStatus());
+            }
         }
 
         // 3.鏌ヨ涓婁紶鏂囦欢
@@ -542,7 +550,7 @@
         }
         // 鍒犻櫎鍙戣揣鍙拌处璁板綍
         List<ShippingInfo> shippingInfos = shippingInfoMapper.selectList(new LambdaQueryWrapper<ShippingInfo>()
-                .eq(ShippingInfo::getSalesLedgerId, idList));
+                .in(ShippingInfo::getSalesLedgerId, idList));
         if(CollectionUtils.isNotEmpty(shippingInfos)){
             shippingInfoServiceImpl.delete(shippingInfos.stream().map(ShippingInfo::getId).collect(Collectors.toList()));
         }
diff --git a/src/main/resources/mapper/production/ProductOrderMapper.xml b/src/main/resources/mapper/production/ProductOrderMapper.xml
index 227e707..4837e64 100644
--- a/src/main/resources/mapper/production/ProductOrderMapper.xml
+++ b/src/main/resources/mapper/production/ProductOrderMapper.xml
@@ -23,9 +23,21 @@
         pb.bom_no,
         ROUND(po.complete_quantity / po.quantity * 100, 2) AS completionStatus,
         DATEDIFF(sl.delivery_date, CURDATE()) AS delivery_days_diff,
-        sl.delivery_date
+        sl.delivery_date,
+        CASE
+        WHEN shipping_status_counts.total_count = 0 THEN false
+        WHEN shipping_status_counts.unshipped_count = 0 THEN true
+        ELSE false
+        END AS is_fh
         from product_order po
         left join sales_ledger sl on po.sales_ledger_id = sl.id
+        LEFT JOIN (
+        SELECT sales_ledger_id,
+        COUNT(*) as total_count,
+        SUM(CASE WHEN status != '宸插彂璐�' THEN 1 ELSE 0 END) as unshipped_count
+        FROM shipping_info
+        GROUP BY sales_ledger_id
+        ) shipping_status_counts ON sl.id = shipping_status_counts.sales_ledger_id
         left join sales_ledger_product slp on po.sale_ledger_product_id = slp.id
         left join product_process_route ppr on po.id = ppr.product_order_id
         left join product_bom pb on pb.id = ppr.bom_id
diff --git a/src/main/resources/mapper/safe/SafeTrainingMapper.xml b/src/main/resources/mapper/safe/SafeTrainingMapper.xml
index dac3417..b45878c 100644
--- a/src/main/resources/mapper/safe/SafeTrainingMapper.xml
+++ b/src/main/resources/mapper/safe/SafeTrainingMapper.xml
@@ -38,6 +38,7 @@
         left join safe_training_details std on std.safe_training_id = st.id
         left join sys_user su on st.assessment_user_id = su.user_id
         where  st.state = #{c.state}
+        GROUP BY st.id
         <if test="c.placeTraining != null and c.placeTraining != ''">
             and st.place_training like concat('%', #{c.placeTraining}, '%')
         </if>
diff --git a/src/main/resources/mapper/sales/SalesLedgerMapper.xml b/src/main/resources/mapper/sales/SalesLedgerMapper.xml
index 215f0a7..c5d7aed 100644
--- a/src/main/resources/mapper/sales/SalesLedgerMapper.xml
+++ b/src/main/resources/mapper/sales/SalesLedgerMapper.xml
@@ -43,8 +43,7 @@
     </select>
 
     <select id="selectSalesLedgerListPage" resultType="com.ruoyi.sales.pojo.SalesLedger">
-        SELECT
-        T1.id,
+        SELECT T1.id,
         T1.sales_contract_no,
         T1.customer_contract_no,
         T1.project_name,
@@ -57,15 +56,26 @@
         T1.attachment_materials,
         T1.tenant_id,
         T1.contract_amount,
-        T1.contract_amount as noInvoiceAmountTotal,
+        T1.contract_amount                    as noInvoiceAmountTotal,
         T1.execution_date,
-        T2.nick_name AS entry_person_name,
+        T2.nick_name                          AS entry_person_name,
         T1.payment_method,
         T1.delivery_date,
-        DATEDIFF(T1.delivery_date, CURDATE()) AS delivery_days_diff
-        FROM
-        sales_ledger T1
+        DATEDIFF(T1.delivery_date, CURDATE()) AS delivery_days_diff,
+        CASE
+        WHEN shipping_status_counts.total_count = 0 THEN false
+        WHEN shipping_status_counts.unshipped_count = 0 THEN true
+        ELSE false
+        END AS is_fh
+        FROM sales_ledger T1
         LEFT JOIN sys_user T2 ON T1.entry_person = T2.user_id
+        LEFT JOIN (
+        SELECT sales_ledger_id,
+        COUNT(*) as total_count,
+        SUM(CASE WHEN status != '宸插彂璐�' THEN 1 ELSE 0 END) as unshipped_count
+        FROM shipping_info
+        GROUP BY sales_ledger_id
+        ) shipping_status_counts ON T1.id = shipping_status_counts.sales_ledger_id
         <where>
             <if test="salesLedgerDto.customerName != null and salesLedgerDto.customerName != '' ">
                 AND  T1.customer_name LIKE CONCAT('%',#{salesLedgerDto.customerName},'%')

--
Gitblit v1.9.3