From c215f6c20445b973ff730dcdf4206426992da81d Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期一, 19 十月 2026 11:30:57 +0800
Subject: [PATCH] feat(mes): 完善质检流程功能

---
 yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcServiceImplTest.java |  110 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 104 insertions(+), 6 deletions(-)

diff --git a/yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcServiceImplTest.java b/yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcServiceImplTest.java
index 3c9e1bc..d24b047 100644
--- a/yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcServiceImplTest.java
+++ b/yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcServiceImplTest.java
@@ -2,6 +2,7 @@
 
 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.oqc.MesQcOqcDO;
+import cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo.MesQcOqcRetestReqVO;
 import cn.iocoder.yudao.module.mes.dal.mysql.qc.oqc.MesQcOqcMapper;
 import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants;
 import cn.iocoder.yudao.module.mes.enums.qc.MesQcStatusEnum;
@@ -11,6 +12,9 @@
 import cn.iocoder.yudao.module.mes.service.wm.productsales.MesWmProductSalesLineService;
 import cn.iocoder.yudao.module.mes.service.wm.productsales.MesWmProductSalesService;
 import cn.iocoder.yudao.module.mes.service.qc.indicatorresult.MesQcIndicatorResultService;
+import cn.iocoder.yudao.module.mes.service.qc.ncr.MesQcNcrService;
+import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi;
+import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi;
 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
 import jakarta.annotation.Resource;
 import org.junit.jupiter.api.Test;
@@ -28,7 +32,7 @@
 /**
  * {@link MesQcOqcServiceImpl} 鐨勫崟鍏冩祴璇曠被
  *
- * @author 鑺嬮亾婧愮爜
+ * @author 瓒呯骇绠$悊鍛�
  */
 @Import(MesQcOqcServiceImpl.class)
 public class MesQcOqcServiceImplTest extends BaseDbUnitTest {
@@ -55,6 +59,12 @@
     private AdminUserApi adminUserApi;
     @MockitoBean
     private MesQcIndicatorResultService indicatorResultService;
+    @MockitoBean
+    private MesQcNcrService ncrService;
+    @MockitoBean
+    private MdmItemApi mdmItemApi;
+    @MockitoBean
+    private CrmCustomerApi customerApi;
 
     @Test
     public void testFinishOqc_writeBack_productSales() {
@@ -66,6 +76,9 @@
             o.setSourceDocType(MesBizTypeConstants.WM_PRODUCT_SALES);
             o.setSourceLineId(sourceLineId);
             o.setCheckResult(checkResult);
+            o.setUnqualifiedQuantity(java.math.BigDecimal.ZERO);
+            o.setQualifiedQuantity(java.math.BigDecimal.TEN);
+            o.setCheckQuantity(java.math.BigDecimal.TEN);
         });
         oqcMapper.insert(oqc);
 
@@ -75,9 +88,83 @@
         // 鏂█锛氶獙璇佺姸鎬佹洿鏂颁负宸插畬鎴�
         MesQcOqcDO updatedOqc = oqcMapper.selectById(oqc.getId());
         assertEquals(MesQcStatusEnum.FINISHED.getStatus(), updatedOqc.getStatus());
-        // 鏂█锛氶獙璇佸洖鍐欓攢鍞嚭搴撳崟琛�
+        assertEquals(20, updatedOqc.getWorkflowStatus());
+        // 鍒濇瀹屾垚涓嶆斁琛岋紱閿�鍞儴鍜屽叕鍙歌川妫�鍧囧鎵瑰悗鎵嶅洖鍐欍��
+        verify(productSalesLineService, never()).updateProductSalesLineWhenOqcFinish(anyLong(), anyLong(), anyInt());
+        oqcService.salesApprove(oqc.getId(), true, "閿�鍞儴鍚屾剰");
+        oqcService.companyApprove(oqc.getId(), true, "鍏徃璐ㄦ鍚屾剰");
         verify(productSalesLineService).updateProductSalesLineWhenOqcFinish(
                 eq(sourceLineId), eq(oqc.getId()), eq(checkResult));
+    }
+
+    @Test
+    public void testFailedInitialRetestPassOnlyReleasesAfterBothApprovals() {
+        Long sourceLineId = randomLongId();
+        MesQcOqcDO oqc = randomPojo(MesQcOqcDO.class, o -> {
+            o.setStatus(MesQcStatusEnum.DRAFT.getStatus());
+            o.setSourceDocType(MesBizTypeConstants.WM_PRODUCT_SALES);
+            o.setSourceLineId(sourceLineId);
+            o.setOutQuantity(java.math.BigDecimal.valueOf(100));
+            o.setCheckQuantity(java.math.BigDecimal.TEN);
+            o.setQualifiedQuantity(java.math.BigDecimal.valueOf(9));
+            o.setUnqualifiedQuantity(java.math.BigDecimal.ONE);
+            o.setCheckResult(2);
+        });
+        oqcMapper.insert(oqc);
+        oqcService.finishOqc(oqc.getId());
+        assertEquals(10, oqcMapper.selectById(oqc.getId()).getWorkflowStatus());
+        verifyNoInteractions(ncrService);
+        verify(productSalesLineService, never()).updateProductSalesLineWhenOqcFinish(anyLong(), anyLong(), anyInt());
+
+        MesQcOqcRetestReqVO retest = new MesQcOqcRetestReqVO();
+        retest.setId(oqc.getId());
+        retest.setCheckQuantity(java.math.BigDecimal.TEN);
+        retest.setQualifiedQuantity(java.math.BigDecimal.TEN);
+        retest.setUnqualifiedQuantity(java.math.BigDecimal.ZERO);
+        retest.setCheckResult(1);
+        oqcService.retestOqc(retest);
+        assertEquals(20, oqcMapper.selectById(oqc.getId()).getWorkflowStatus());
+        oqcService.salesApprove(oqc.getId(), true, "閿�鍞儴閫氳繃");
+        assertEquals(30, oqcMapper.selectById(oqc.getId()).getWorkflowStatus());
+        verify(productSalesLineService, never()).updateProductSalesLineWhenOqcFinish(anyLong(), anyLong(), anyInt());
+        oqcService.companyApprove(oqc.getId(), true, "鍏徃璐ㄦ閫氳繃");
+        assertEquals(40, oqcMapper.selectById(oqc.getId()).getWorkflowStatus());
+        verify(productSalesLineService).updateProductSalesLineWhenOqcFinish(sourceLineId, oqc.getId(), 1);
+        verifyNoInteractions(ncrService);
+    }
+
+    @Test
+    public void testFailedRetestCreatesNcrOnlyAfterCompanyApproval() {
+        Long sourceLineId = randomLongId();
+        MesQcOqcDO oqc = randomPojo(MesQcOqcDO.class, o -> {
+            o.setStatus(MesQcStatusEnum.DRAFT.getStatus());
+            o.setSourceDocType(MesBizTypeConstants.WM_PRODUCT_SALES);
+            o.setSourceLineId(sourceLineId);
+            o.setOutQuantity(java.math.BigDecimal.valueOf(100));
+            o.setCheckQuantity(java.math.BigDecimal.TEN);
+            o.setQualifiedQuantity(java.math.BigDecimal.valueOf(9));
+            o.setUnqualifiedQuantity(java.math.BigDecimal.ONE);
+            o.setCheckResult(2);
+        });
+        oqcMapper.insert(oqc);
+        oqcService.finishOqc(oqc.getId());
+        MesQcOqcRetestReqVO retest = new MesQcOqcRetestReqVO();
+        retest.setId(oqc.getId());
+        retest.setCheckQuantity(java.math.BigDecimal.TEN);
+        retest.setQualifiedQuantity(java.math.BigDecimal.valueOf(8));
+        retest.setUnqualifiedQuantity(java.math.BigDecimal.valueOf(2));
+        retest.setCheckResult(2);
+        retest.setOpinion("澶嶆浠嶄笉鍚堟牸");
+        oqcService.retestOqc(retest);
+        assertEquals(50, oqcMapper.selectById(oqc.getId()).getWorkflowStatus());
+        verifyNoInteractions(ncrService);
+        oqcService.salesApprove(oqc.getId(), true, "閿�鍞儴纭涓嶅悎鏍�");
+        assertEquals(60, oqcMapper.selectById(oqc.getId()).getWorkflowStatus());
+        verifyNoInteractions(ncrService);
+        oqcService.companyApprove(oqc.getId(), true, "鍏徃璐ㄦ纭涓嶅悎鏍�");
+        assertEquals(70, oqcMapper.selectById(oqc.getId()).getWorkflowStatus());
+        verify(ncrService).createNcr(any());
+        verify(productSalesLineService).updateProductSalesLineWhenOqcFinish(sourceLineId, oqc.getId(), 2);
     }
 
     @Test
@@ -86,6 +173,9 @@
         MesQcOqcDO oqc = randomPojo(MesQcOqcDO.class, o -> {
             o.setStatus(MesQcStatusEnum.DRAFT.getStatus());
             o.setCheckResult(1);
+            o.setUnqualifiedQuantity(java.math.BigDecimal.ZERO);
+            o.setQualifiedQuantity(java.math.BigDecimal.TEN);
+            o.setCheckQuantity(java.math.BigDecimal.TEN);
             o.setSourceDocType(null);
             o.setSourceLineId(null);
         });
@@ -108,13 +198,17 @@
         MesQcOqcDO oqc = randomPojo(MesQcOqcDO.class, o -> {
             o.setStatus(MesQcStatusEnum.DRAFT.getStatus());
             o.setCheckResult(1);
+            o.setUnqualifiedQuantity(java.math.BigDecimal.ZERO);
+            o.setQualifiedQuantity(java.math.BigDecimal.TEN);
+            o.setCheckQuantity(java.math.BigDecimal.TEN);
             o.setSourceDocType(MesBizTypeConstants.WM_PRODUCT_SALES);
             o.setSourceLineId(null); // 鑴忔暟鎹�
         });
         oqcMapper.insert(oqc);
 
-        // 璋冪敤锛屽苟鏂█寮傚父
-        assertThrows(IllegalArgumentException.class, () -> oqcService.finishOqc(oqc.getId()));
+        oqcService.finishOqc(oqc.getId());
+        oqcService.salesApprove(oqc.getId(), true, "閿�鍞儴鍚屾剰");
+        assertThrows(IllegalArgumentException.class, () -> oqcService.companyApprove(oqc.getId(), true, "鍏徃璐ㄦ鍚屾剰"));
     }
 
     @Test
@@ -123,13 +217,17 @@
         MesQcOqcDO oqc = randomPojo(MesQcOqcDO.class, o -> {
             o.setStatus(MesQcStatusEnum.DRAFT.getStatus());
             o.setCheckResult(1);
+            o.setUnqualifiedQuantity(java.math.BigDecimal.ZERO);
+            o.setQualifiedQuantity(java.math.BigDecimal.TEN);
+            o.setCheckQuantity(java.math.BigDecimal.TEN);
             o.setSourceDocType(99999); // 鏃犳硶璇嗗埆鐨勭被鍨�
             o.setSourceLineId(randomLongId());
         });
         oqcMapper.insert(oqc);
 
-        // 璋冪敤锛屽苟鏂█寮傚父
-        assertThrows(IllegalArgumentException.class, () -> oqcService.finishOqc(oqc.getId()));
+        oqcService.finishOqc(oqc.getId());
+        oqcService.salesApprove(oqc.getId(), true, "閿�鍞儴鍚屾剰");
+        assertThrows(IllegalArgumentException.class, () -> oqcService.companyApprove(oqc.getId(), true, "鍏徃璐ㄦ鍚屾剰"));
     }
 
     @Test

--
Gitblit v1.9.3