From b584d2d89076149ad0e60cb67a3efcacda33b5e1 Mon Sep 17 00:00:00 2001
From: huminmin <mac@MacBook-Pro.local>
Date: 星期二, 24 三月 2026 14:05:59 +0800
Subject: [PATCH] 实际合格率低于【合格率】时,每个【生产工单】、【生产报工】台账需要标红显示。并发送消息到管理员,内容为:【xxx生产订单,xx工序合格率xx%低于标准xx%】

---
 src/main/resources/mapper/production/ProductWorkOrderMapper.xml                       |    1 
 src/main/java/com/ruoyi/production/service/impl/ProductWorkOrderServiceImpl.java      |   22 ++++++++++
 src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java |   26 ++++++++++---
 src/main/resources/mapper/production/ProductionProductMainMapper.xml                  |    3 +
 src/main/java/com/ruoyi/production/dto/ProductWorkOrderDto.java                       |    6 +++
 src/main/java/com/ruoyi/production/dto/ProductionProductMainDto.java                  |    4 ++
 6 files changed, 55 insertions(+), 7 deletions(-)

diff --git a/src/main/java/com/ruoyi/production/dto/ProductWorkOrderDto.java b/src/main/java/com/ruoyi/production/dto/ProductWorkOrderDto.java
index d9b7ec0..5d31d88 100644
--- a/src/main/java/com/ruoyi/production/dto/ProductWorkOrderDto.java
+++ b/src/main/java/com/ruoyi/production/dto/ProductWorkOrderDto.java
@@ -64,4 +64,10 @@
 
     @ApiModelProperty(value = "鐘舵�佹枃鏈�")
     private String statusText;
+
+    @ApiModelProperty(value = "宸ュ簭鍚堟牸鐜�")
+    private BigDecimal processQualifiedRate;
+
+    @ApiModelProperty(value = "瀹為檯鍚堟牸鐜�")
+    private BigDecimal actualQualifiedRate;
 }
diff --git a/src/main/java/com/ruoyi/production/dto/ProductionProductMainDto.java b/src/main/java/com/ruoyi/production/dto/ProductionProductMainDto.java
index 0c62aef..8691a21 100644
--- a/src/main/java/com/ruoyi/production/dto/ProductionProductMainDto.java
+++ b/src/main/java/com/ruoyi/production/dto/ProductionProductMainDto.java
@@ -61,6 +61,10 @@
     //宸ュ簭
     @Excel(name = "宸ュ簭")
     private String process;
+    // 宸ュ簭鍚堟牸鐜�
+    private BigDecimal processQualifiedRate;
+    // 瀹為檯鍚堟牸鐜�
+    private BigDecimal actualQualifiedRate;
     private BigDecimal workHours;
     private BigDecimal wages;
 
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductWorkOrderServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductWorkOrderServiceImpl.java
index 8c38ddf..b979cc4 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductWorkOrderServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductWorkOrderServiceImpl.java
@@ -73,6 +73,25 @@
                     record.setIsCanReport(true);
                 }
             }
+
+            // 鏌ヨ褰撳墠瀹為檯鐨勫悎鏍肩巼
+            // 鏌ヨ鍏宠仈浜у嚭琛ㄦ暟鎹�
+            List<ProductionProductMain> productionProductMains = productionProductMainMapper.selectList(Wrappers.<ProductionProductMain>lambdaQuery().eq(ProductionProductMain::getWorkOrderId, record.getId()));
+            BigDecimal totalScrapQty = BigDecimal.ZERO;
+            if (CollectionUtils.isNotEmpty(productionProductMains)) {
+                // 璁$畻鎶ュ簾鏁伴噺
+                List<Long> mainIds = productionProductMains.stream().map(ProductionProductMain::getId).collect(Collectors.toList());
+                List<ProductionProductOutput> productionProductOutputs = productionProductOutputMapper.selectList(Wrappers.<ProductionProductOutput>lambdaQuery().in(ProductionProductOutput::getProductMainId, mainIds));
+                totalScrapQty = productionProductOutputs.stream().map(ProductionProductOutput::getScrapQty).reduce(BigDecimal.ZERO, BigDecimal::add);
+            }
+            if (record.getCompleteQuantity().compareTo(BigDecimal.ZERO) > 0) {
+                record.setActualQualifiedRate((record.getCompleteQuantity().subtract(totalScrapQty))
+                        .divide(record.getCompleteQuantity(), 2, RoundingMode.HALF_UP)
+                        .multiply(new BigDecimal("100"))
+                );
+            } else {
+                record.setActualQualifiedRate((record.getCompleteQuantity().subtract(totalScrapQty)).multiply(BigDecimal.valueOf(100)));
+            }
         });
         return productWorkOrderDtoIPage;
     }
@@ -154,10 +173,11 @@
                     scrapQty = productionProductOutputs.stream().map(ProductionProductOutput::getScrapQty).reduce(BigDecimal.ZERO, BigDecimal::add);
                 }
                 if (productWorkOrderDto.getCompleteQuantity().compareTo(BigDecimal.ZERO) > 0) {
-                    productWorkOrderDto.setScrapRate(scrapQty.divide(productWorkOrderDto.getCompleteQuantity(), 2, RoundingMode.HALF_UP));
+                    productWorkOrderDto.setScrapRate(scrapQty.divide(productWorkOrderDto.getCompleteQuantity(), 4, RoundingMode.HALF_UP));
                 } else {
                     productWorkOrderDto.setScrapRate(scrapQty.multiply(BigDecimal.valueOf(100)));
                 }
+                productWorkOrderDto.setScrapQty(scrapQty);
                 productWorkOrderDto.setCompleteQty(productWorkOrderDto.getCompleteQuantity().subtract(scrapQty));
             });
         }
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 9f4fe5a..7a0a9c6 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
@@ -24,6 +24,7 @@
 import com.ruoyi.production.service.ProductionProductMainService;
 import com.ruoyi.project.system.domain.SysUser;
 import com.ruoyi.project.system.mapper.SysUserMapper;
+import com.ruoyi.project.system.service.ISysNoticeService;
 import com.ruoyi.quality.mapper.*;
 import com.ruoyi.quality.pojo.*;
 import com.ruoyi.quality.service.IQualityInspectService;
@@ -33,13 +34,11 @@
 import com.ruoyi.production.mapper.ProductionProductMainMapper;
 
 import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.stream.Collectors;
 
 @Service
@@ -85,6 +84,7 @@
 
     private StockUtils stockUtils;
 
+    private ISysNoticeService sysNoticeService;
 
     @Override
     public IPage<ProductionProductMainDto> listPageProductionProductMainDto(Page page, ProductionProductMainDto productionProductMainDto) {
@@ -187,8 +187,24 @@
         productionProductOutput.setScrapQty(dto.getScrapQty() != null ? dto.getScrapQty() : BigDecimal.ZERO);
         productionProductOutput.setOtherData(dto.getOtherData() != null ? dto.getOtherData() : "");
         productionProductOutputMapper.insert(productionProductOutput);
+
+        ProductWorkOrder productWorkOrder = productWorkOrderMapper.selectById(dto.getWorkOrderId());
+        ProductOrder productOrder = productOrderMapper.selectById(productWorkOrder.getProductOrderId());
+
         //鍚堟牸鏁伴噺=鎶ュ伐鏁伴噺-鎶ュ簾鏁伴噺
         BigDecimal productQty = productionProductOutput.getQuantity().subtract(productionProductOutput.getScrapQty());
+        // 鍚堟牸鐜�=鍚堟牸鏁伴噺/鎶ュ伐鏁伴噺
+        BigDecimal productQtyRate = productQty.divide(productionProductOutput.getQuantity(), 2, RoundingMode.HALF_UP)
+                .multiply(new BigDecimal("100"));
+        // 璇ュ伐搴忕殑鍚堟牸鐜� < 鍚堟牸鐜�
+        if (productQtyRate.compareTo(productProcess.getQualifiedRate()) < 0) {
+            // 鍙戦�侀�氱煡缁欑鐞嗗憳
+            sysNoticeService.simpleNoticeByUser("鎶ュ伐鎻愮ず",
+                    String.format("%s鐢熶骇璁㈠崟锛�%s宸ュ簭鍚堟牸鐜�%.2f%%浣庝簬鏍囧噯%.2f%%", productOrder.getNpsNo(), productProcess.getName(), productQtyRate, productProcess.getQualifiedRate()),
+                    Arrays.asList(Long.valueOf(1L)),
+                    "/productionManagement/productionReporting");
+        }
+
         List<ProductProcessRouteItem> productProcessRouteItems = productProcessRouteItemMapper.selectList(Wrappers.<ProductProcessRouteItem>lambdaQuery().eq(ProductProcessRouteItem::getProductRouteId, productProcessRouteItem.getProductRouteId()));
         //鍙湁鍚堟牸鏁伴噺>0鎵嶈兘澧炲姞鐩稿簲鏁版嵁
         if (productQty.compareTo(BigDecimal.ZERO) > 0) {
@@ -242,7 +258,6 @@
                 }
             }
             /*鏇存柊宸ュ崟鍜岀敓浜ц鍗�*/
-            ProductWorkOrder productWorkOrder = productWorkOrderMapper.selectById(dto.getWorkOrderId());
             productWorkOrder.setCompleteQuantity(productWorkOrder.getCompleteQuantity().add(productQty));
             if (ObjectUtils.isNull(productWorkOrder.getActualStartTime())) {
                 productWorkOrder.setActualStartTime(LocalDate.now());//瀹為檯寮�濮嬫椂闂�
@@ -252,7 +267,6 @@
             }
             productWorkOrderMapper.updateById(productWorkOrder);
             //鐢熶骇璁㈠崟
-            ProductOrder productOrder = productOrderMapper.selectById(productWorkOrder.getProductOrderId());
             if (ObjectUtils.isNull(productOrder.getStartTime())) {
                 productOrder.setStartTime(LocalDateTime.now());//寮�濮嬫椂闂�
             }
diff --git a/src/main/resources/mapper/production/ProductWorkOrderMapper.xml b/src/main/resources/mapper/production/ProductWorkOrderMapper.xml
index 8398221..f3784fd 100644
--- a/src/main/resources/mapper/production/ProductWorkOrderMapper.xml
+++ b/src/main/resources/mapper/production/ProductWorkOrderMapper.xml
@@ -23,6 +23,7 @@
         pwo.*,
         pp.id as processId,
         pp.NAME as processName,
+        pp.qualified_rate as processQualifiedRate,
         pm.model,
         pm.unit,
         p.product_name AS productName,
diff --git a/src/main/resources/mapper/production/ProductionProductMainMapper.xml b/src/main/resources/mapper/production/ProductionProductMainMapper.xml
index 875c2a1..36b0204 100644
--- a/src/main/resources/mapper/production/ProductionProductMainMapper.xml
+++ b/src/main/resources/mapper/production/ProductionProductMainMapper.xml
@@ -19,9 +19,12 @@
         u.nick_name as nickName,
         p.product_name as productName,
         pp.name as process,
+        pp.qualified_rate as processQualifiedRate,
         pm.model as productModelName,
         ppo.quantity,
         ppo.scrap_qty,
+        (ppo.quantity - ppo.scrap_qty) as qualifiedQty,
+        case when ppo.quantity > 0 then round((ppo.quantity - ppo.scrap_qty) / ppo.quantity * 100, 2) else 0 end as actualQualifiedRate,
         ppo.other_data,
         pm.unit,
         sl.sales_contract_no salesContractNo

--
Gitblit v1.9.3