Files
ccdi/docs/plans/backend/2026-03-28-risk-detail-employee-credit-negative-backend-implementation.md

11 KiB
Raw Blame History

Risk Detail Employee Credit Negative Backend Implementation Plan

For agentic workers: REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (- [ ]) syntax for tracking.

Repo note: 本仓库 AGENTS.md 明确禁止开启 subagent执行本计划时请在当前会话使用 superpowers:executing-plans

Goal: 为结果总览“风险明细”新增项目维度的员工负面征信分页查询能力,保证页面可以按当前项目结果总览员工口径展示负面征信列表。

Architecture: 后端继续收敛到 CcdiProjectOverviewController -> ICcdiProjectOverviewService -> CcdiProjectOverviewMapper 这一条结果总览链路,不复用全局征信维护接口。查询以 ccdi_project_overview_employee_result 限定项目员工范围,再与 ccdi_credit_negative_info 关联,仅输出存在负面征信记录的员工,并按 query_date desc, person_id asc 分页返回。

Tech Stack: Java 21, Spring Boot 3, MyBatis Plus Page, MyBatis XML, Maven, JUnit 5, Mockito, Swagger/OpenAPI


Task 1: 建立结果总览员工负面征信接口契约

Files:

  • Create: ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/CcdiProjectEmployeeCreditNegativeQueryDTO.java

  • Create: ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectEmployeeCreditNegativeItemVO.java

  • Create: ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectEmployeeCreditNegativePageVO.java

  • Modify: ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/ICcdiProjectOverviewService.java

  • Modify: ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/CcdiProjectOverviewController.java

  • Test: ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/CcdiProjectOverviewServiceStructureTest.java

  • Test: ccdi-project/src/test/java/com/ruoyi/ccdi/project/controller/CcdiProjectOverviewControllerContractTest.java

  • Test: ccdi-project/src/test/java/com/ruoyi/ccdi/project/controller/CcdiProjectOverviewControllerTest.java

  • Step 1: 先写失败测试,锁定新 DTO、VO、Service 方法和 Controller 路由

assertNotNull(clazz.getMethod(
    "getEmployeeCreditNegative",
    Class.forName("com.ruoyi.ccdi.project.domain.dto.CcdiProjectEmployeeCreditNegativeQueryDTO")
));
assertEquals("/employee-credit-negative", getMapping.value()[0]);
assertEquals(List.of("projectId", "pageNum", "pageSize"), fieldNames);
  • Step 2: 运行结构测试和控制器契约测试,确认当前仓库尚未暴露该能力

Run:

mvn -pl ccdi-project -Dtest=CcdiProjectOverviewServiceStructureTest,CcdiProjectOverviewControllerContractTest,CcdiProjectOverviewControllerTest test

Expected:

  • CcdiProjectOverviewServiceStructureTestNoSuchMethodException

  • CcdiProjectOverviewControllerContractTest 提示缺少 /employee-credit-negative

  • CcdiProjectOverviewControllerTest 还没有对应控制器方法

  • Step 3: 写最小 DTO / VO / Controller / Service 签名

public class CcdiProjectEmployeeCreditNegativeQueryDTO {
    private Long projectId;
    private Integer pageNum;
    private Integer pageSize;
}
@GetMapping("/employee-credit-negative")
public AjaxResult getEmployeeCreditNegative(CcdiProjectEmployeeCreditNegativeQueryDTO queryDTO) {
    return AjaxResult.success(overviewService.getEmployeeCreditNegative(queryDTO));
}
  • Step 4: 回跑接口契约测试,确保新接口已被正确暴露

Run:

mvn -pl ccdi-project -Dtest=CcdiProjectOverviewServiceStructureTest,CcdiProjectOverviewControllerContractTest,CcdiProjectOverviewControllerTest test

Expected: PASS

  • Step 5: 提交本任务
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/CcdiProjectEmployeeCreditNegativeQueryDTO.java \
  ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectEmployeeCreditNegativeItemVO.java \
  ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectEmployeeCreditNegativePageVO.java \
  ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/ICcdiProjectOverviewService.java \
  ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/CcdiProjectOverviewController.java \
  ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/CcdiProjectOverviewServiceStructureTest.java \
  ccdi-project/src/test/java/com/ruoyi/ccdi/project/controller/CcdiProjectOverviewControllerContractTest.java \
  ccdi-project/src/test/java/com/ruoyi/ccdi/project/controller/CcdiProjectOverviewControllerTest.java
git commit -m "新增结果总览员工负面征信接口契约"

Task 2: 落地项目员工负面征信 SQL 查询与分页服务

Files:

  • Modify: ccdi-project/src/main/java/com/ruoyi/ccdi/project/mapper/CcdiProjectOverviewMapper.java

  • Modify: ccdi-project/src/main/resources/mapper/ccdi/project/CcdiProjectOverviewMapper.xml

  • Modify: ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectOverviewServiceImpl.java

  • Test: ccdi-project/src/test/java/com/ruoyi/ccdi/project/mapper/CcdiProjectOverviewMapperSqlTest.java

  • Create: ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectOverviewServiceEmployeeCreditNegativeTest.java

  • Step 1: 先写 SQL 结构测试和服务测试,锁定项目范围、负面字段与排序规则

assertTrue(employeeCreditSql.contains("from ccdi_project_overview_employee_result"), employeeCreditSql);
assertTrue(employeeCreditSql.contains("inner join ccdi_credit_negative_info"), employeeCreditSql);
assertTrue(employeeCreditSql.contains("result.project_id = #{query.projectId}"), employeeCreditSql);
assertTrue(employeeCreditSql.contains("order by neg.query_date desc, neg.person_id asc"), employeeCreditSql);
assertFalse(employeeCreditSql.contains("ccdi_debts_info"), employeeCreditSql);
verify(overviewMapper).selectEmployeeCreditNegativePage(
    any(Page.class),
    argThat(query -> query.getProjectId().equals(40L))
);
  • Step 2: 运行测试,确认当前查询链路还不存在

Run:

mvn -pl ccdi-project -Dtest=CcdiProjectOverviewMapperSqlTest,CcdiProjectOverviewServiceEmployeeCreditNegativeTest test

Expected:

  • SQL 测试提示缺少 selectEmployeeCreditNegativePage

  • Service 测试编译失败或断言失败,提示未新增 mapper / service 能力

  • Step 3: 写最小 SQL 与服务实现

<select id="selectEmployeeCreditNegativePage"
        resultType="com.ruoyi.ccdi.project.domain.vo.CcdiProjectEmployeeCreditNegativeItemVO">
    select
        coalesce(neg.person_name, result.staff_name) as personName,
        neg.person_id as personId,
        neg.query_date as queryDate,
        ifnull(neg.civil_cnt, 0) as civilCnt,
        ifnull(neg.civil_lmt, 0) as civilLmt,
        ifnull(neg.enforce_cnt, 0) as enforceCnt,
        ifnull(neg.enforce_lmt, 0) as enforceLmt,
        ifnull(neg.adm_cnt, 0) as admCnt,
        ifnull(neg.adm_lmt, 0) as admLmt
    from ccdi_project_overview_employee_result result
    inner join ccdi_credit_negative_info neg
        on neg.person_id = result.staff_id_card
    where result.project_id = #{query.projectId}
    order by neg.query_date desc, neg.person_id asc
</select>
Page<CcdiProjectEmployeeCreditNegativeItemVO> page = new Page<>(
    defaultPageNum(queryDTO.getPageNum()),
    defaultPageSize(queryDTO.getPageSize())
);
Page<CcdiProjectEmployeeCreditNegativeItemVO> resultPage =
    overviewMapper.selectEmployeeCreditNegativePage(page, queryDTO);
  • Step 4: 回跑 SQL 与服务测试,验证只返回项目内有负面征信的员工

Run:

mvn -pl ccdi-project -Dtest=CcdiProjectOverviewMapperSqlTest,CcdiProjectOverviewServiceEmployeeCreditNegativeTest test

Expected:

  • SQL 测试确认不关联 ccdi_debts_info

  • Service 测试确认分页结果包含 rowstotal

  • 项目不存在时继续抛 ServiceException("项目不存在")

  • Step 5: 提交本任务

git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/mapper/CcdiProjectOverviewMapper.java \
  ccdi-project/src/main/resources/mapper/ccdi/project/CcdiProjectOverviewMapper.xml \
  ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectOverviewServiceImpl.java \
  ccdi-project/src/test/java/com/ruoyi/ccdi/project/mapper/CcdiProjectOverviewMapperSqlTest.java \
  ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectOverviewServiceEmployeeCreditNegativeTest.java
git commit -m "实现结果总览员工负面征信分页查询"

Task 3: 补齐控制器返回与回归验证

Files:

  • Modify: ccdi-project/src/test/java/com/ruoyi/ccdi/project/controller/CcdiProjectOverviewControllerTest.java

  • Modify: ccdi-project/src/test/java/com/ruoyi/ccdi/project/controller/CcdiProjectOverviewControllerContractTest.java

  • Modify: ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/CcdiProjectOverviewServiceStructureTest.java

  • Reference: docs/superpowers/specs/2026-03-28-risk-detail-employee-credit-negative-design.md

  • Step 1: 在控制器测试里锁定返回字段和权限沿用

CcdiProjectEmployeeCreditNegativePageVO pageVO = new CcdiProjectEmployeeCreditNegativePageVO();
pageVO.setRows(List.of(item));
pageVO.setTotal(1L);
when(overviewService.getEmployeeCreditNegative(queryDTO)).thenReturn(pageVO);

AjaxResult result = controller.getEmployeeCreditNegative(queryDTO);
assertEquals(pageVO, result.get("data"));
  • Step 2: 回跑控制器相关测试,确认没有破坏既有结果总览契约

Run:

mvn -pl ccdi-project -Dtest=CcdiProjectOverviewControllerTest,CcdiProjectOverviewControllerContractTest,CcdiProjectOverviewServiceStructureTest test

Expected: PASS

  • Step 3: 做一次后端最小回归

Run:

mvn -pl ccdi-project -Dtest=CcdiProjectOverviewMapperSqlTest,CcdiProjectOverviewServiceEmployeeCreditNegativeTest,CcdiProjectOverviewControllerTest test

Expected:

  • 新增员工负面征信链路测试全部通过

  • 结果总览既有涉疑交易和项目分析控制器测试不回归

  • Step 4: 记录实施边界

将以下结论补到提交说明或实施记录中:

  • 本次只新增项目维度负面征信列表

  • 未改动全局征信维护接口

  • 未接入负债明细

  • Step 5: 提交本任务

git add ccdi-project/src/test/java/com/ruoyi/ccdi/project/controller/CcdiProjectOverviewControllerTest.java \
  ccdi-project/src/test/java/com/ruoyi/ccdi/project/controller/CcdiProjectOverviewControllerContractTest.java \
  ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/CcdiProjectOverviewServiceStructureTest.java
git commit -m "补充结果总览员工负面征信后端回归测试"