Prechádzať zdrojové kódy

feat(report): 报告管理列表/详情回填采集完整度 collect_validation

Xiaogang Liao 3 dní pred
rodič
commit
5ff96f478a

+ 1 - 0
cfc-backend/src/main/java/com/etotem/cfc/dto/ReportSummaryVO.java

@@ -22,6 +22,7 @@ public class ReportSummaryVO {
   private String status;
   private String detailRoute;
   private Date createdAt;
+  private String collectValidation;
 
   public static String getReportTypeName(String reportType) {
     if (reportType == null) return "未知";

+ 52 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/ReportSummaryService.java

@@ -11,6 +11,7 @@ import com.etotem.cfc.entity.DanReportUpload;
 import com.etotem.cfc.entity.FamilyFortuneReport;
 import com.etotem.cfc.entity.FamilyMember;
 import com.etotem.cfc.entity.HealthReport;
+import com.etotem.cfc.entity.HealthReportDraft;
 import com.etotem.cfc.entity.InsurancePolicy;
 import com.etotem.cfc.entity.ReportSummary;
 import com.etotem.cfc.entity.User;
@@ -19,6 +20,7 @@ import com.etotem.cfc.mapper.DanReportUploadMapper;
 import com.etotem.cfc.mapper.FamilyFortuneReportMapper;
 import com.etotem.cfc.mapper.FamilyMemberMapper;
 import com.etotem.cfc.mapper.HealthReportMapper;
+import com.etotem.cfc.mapper.HealthReportDraftMapper;
 import com.etotem.cfc.mapper.InsurancePolicyMapper;
 import com.etotem.cfc.mapper.ReportSummaryMapper;
 import com.etotem.cfc.mapper.UserMapper;
@@ -28,8 +30,14 @@ import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
 import com.etotem.cfc.util.SortUtil;
 
 @Service
@@ -60,6 +68,9 @@ public class ReportSummaryService {
     @Resource
     private FamilyFortuneReportMapper familyFortuneReportMapper;
 
+    @Resource
+    private HealthReportDraftMapper healthReportDraftMapper;
+
     @Resource
     private JdbcTemplate jdbcTemplate;
 
@@ -303,6 +314,8 @@ public class ReportSummaryService {
         vo.setStatus(s.getStatus());
         vo.setDetailRoute(s.getDetailRoute());
         vo.setCreatedAt(s.getCreatedAt());
+        vo.setCollectValidation(loadCollectValidationBySource(
+                Collections.singletonList(s), s.getSourceTable()).get(s.getSourceId()));
         return vo;
     }
 
@@ -338,6 +351,9 @@ public class ReportSummaryService {
 
         SortUtil.applySort(wrapper);
 
+        Map<Long, String> danValidation = loadCollectValidationBySource(page.getRecords(), "dan_report_uploads");
+        Map<Long, String> healthValidation = loadCollectValidationBySource(page.getRecords(), "health_reports");
+
         Page<ReportSummaryVO> voPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
         List<ReportSummaryVO> voList = new ArrayList<>();
         for (ReportSummary rs : page.getRecords()) {
@@ -353,12 +369,48 @@ public class ReportSummaryService {
             vo.setReportDate(rs.getReportDate() != null ? rs.getReportDate().toString() : "");
             vo.setStatus(rs.getStatus());
             vo.setCreatedAt(rs.getCreatedAt());
+            if ("dan_report_uploads".equals(rs.getSourceTable())) {
+                vo.setCollectValidation(danValidation.get(rs.getSourceId()));
+            } else if ("health_reports".equals(rs.getSourceTable())) {
+                vo.setCollectValidation(healthValidation.get(rs.getSourceId()));
+            }
             voList.add(vo);
         }
         voPage.setRecords(voList);
         return voPage;
     }
 
+    /** 批量读取草稿的采集校验结果,键 = confirmed_report_id(= report_summary.source_id) */
+    private Map<Long, String> loadCollectValidationBySource(List<ReportSummary> rows, String sourceTable) {
+        Map<Long, String> map = new HashMap<>();
+        if (rows == null || rows.isEmpty()) {
+            return map;
+        }
+        Set<Long> ids = rows.stream()
+                .filter(r -> sourceTable.equals(r.getSourceTable()))
+                .map(ReportSummary::getSourceId)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toSet());
+        if (ids.isEmpty()) {
+            return map;
+        }
+        LambdaQueryWrapper<HealthReportDraft> w = new LambdaQueryWrapper<>();
+        w.in(HealthReportDraft::getConfirmedReportId, ids)
+                .isNotNull(HealthReportDraft::getCollectValidation);
+        if ("dan_report_uploads".equals(sourceTable)) {
+            w.likeRight(HealthReportDraft::getReportType, "dan");
+        } else {
+            w.and(x -> x.isNull(HealthReportDraft::getReportType)
+                    .or().notLikeRight(HealthReportDraft::getReportType, "dan"));
+        }
+        for (HealthReportDraft d : healthReportDraftMapper.selectList(w)) {
+            if (d.getConfirmedReportId() != null && d.getCollectValidation() != null) {
+                map.put(d.getConfirmedReportId(), d.getCollectValidation());
+            }
+        }
+        return map;
+    }
+
     public ReportSyncResultDTO fullSync() {
         ReportSyncResultDTO result = new ReportSyncResultDTO();
         result.setNewCount(0);

+ 67 - 0
cfc-backend/src/test/java/com/etotem/cfc/service/ReportSummaryServiceCompletenessTest.java

@@ -0,0 +1,67 @@
+package com.etotem.cfc.service;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.etotem.cfc.dto.ReportListQueryDTO;
+import com.etotem.cfc.dto.ReportSummaryVO;
+import com.etotem.cfc.entity.HealthReportDraft;
+import com.etotem.cfc.entity.ReportSummary;
+import com.etotem.cfc.mapper.HealthReportDraftMapper;
+import com.etotem.cfc.mapper.ReportSummaryMapper;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+class ReportSummaryServiceCompletenessTest {
+
+    @Mock
+    private ReportSummaryMapper reportSummaryMapper;
+
+    @Mock
+    private HealthReportDraftMapper healthReportDraftMapper;
+
+    @InjectMocks
+    private ReportSummaryService service;
+
+    @Test
+    void adminPageList_fillsCollectValidationFromDraft() {
+        ReportSummary rs = new ReportSummary();
+        rs.setId(1L);
+        rs.setReportType("dan");
+        rs.setSourceTable("dan_report_uploads");
+        rs.setSourceId(1L);
+
+        doAnswer(inv -> {
+            Page<ReportSummary> p = inv.getArgument(0);
+            p.setRecords(Collections.singletonList(rs));
+            p.setTotal(1);
+            return p;
+        }).when(reportSummaryMapper).selectPage(any(), any());
+
+        HealthReportDraft d = new HealthReportDraft();
+        d.setConfirmedReportId(1L);
+        d.setReportType("dan_a1");
+        d.setCollectValidation("{\"typeId\":\"dan_a1\",\"expected\":31,\"matched\":30,\"pass\":false,\"missing\":[\"百分位\"]}");
+        when(healthReportDraftMapper.selectList(any())).thenReturn(Collections.singletonList(d));
+
+        ReportListQueryDTO query = new ReportListQueryDTO();
+        query.setPage(1);
+        query.setSize(20);
+
+        Page<ReportSummaryVO> page = service.adminPageList(query);
+
+        List<ReportSummaryVO> records = page.getRecords();
+        assertEquals(1, records.size());
+        assertEquals(d.getCollectValidation(), records.get(0).getCollectValidation());
+    }
+}