Files
ccdi/docs/plans/backend/2026-03-24-special-check-family-asset-liability-backend-implementation.md

310 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Special Check Family Asset Liability 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.
**Goal:** 为专项排查页新增“员工家庭资产负债专项核查”后端查询能力,支持项目内员工列表出数与单个员工家庭收入、资产、负债明细展开。
**Architecture:** 采用专项核查专用查询链路,不复用结果总览员工结果表。新增 `CcdiProjectSpecialCheckController + Service + Mapper`,按项目内已入库流水命中的员工范围聚合本人与配偶的收入、资产、征信本金余额,并拆成列表接口与详情接口两条只读查询。
**Tech Stack:** Java 21, Spring Boot 3, MyBatis XML, Maven, JUnit 5
---
### Task 1: 定义专项核查接口契约、DTO 与 VO
**Files:**
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/CcdiProjectSpecialCheckController.java`
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/ICcdiProjectSpecialCheckService.java`
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/CcdiProjectFamilyAssetLiabilityListQueryDTO.java`
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/CcdiProjectFamilyAssetLiabilityDetailQueryDTO.java`
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectFamilyAssetLiabilityListItemVO.java`
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectFamilyAssetLiabilityListVO.java`
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectFamilyIncomeDetailVO.java`
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectFamilyAssetItemVO.java`
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectFamilyAssetDetailVO.java`
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectFamilyDebtItemVO.java`
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectFamilyDebtDetailVO.java`
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectFamilyAssetLiabilityDetailVO.java`
- Test: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/controller/CcdiProjectSpecialCheckControllerContractTest.java`
- [ ] **Step 1: Write the failing test**
为控制器契约补静态/反射测试,锁定以下路径和方法:
- `GET /ccdi/project/special-check/family-asset-liability/list`
- `GET /ccdi/project/special-check/family-asset-liability/detail`
并锁定 DTO / VO 基本字段:
- 列表入参:`projectId`
- 详情入参:`projectId``staffIdCard`
- 列表项:`staffIdCard``staffCode``staffName``deptName``totalIncome``totalAsset``totalDebt``comparisonAmount``riskLevelCode``riskLevelName`
- 详情:`incomeDetail``assetDetail``debtDetail``summary`
- [ ] **Step 2: Run test to verify it fails**
Run:
```bash
mvn test -pl ccdi-project -Dtest=CcdiProjectSpecialCheckControllerContractTest
```
Expected:
- `FAIL`
- 原因是控制器、DTO、VO 尚未创建
- [ ] **Step 3: Write minimal implementation**
补齐控制器、服务接口、DTO 与 VO。
控制器要求:
- 继续使用 `@Tag``@Operation`
- 权限沿用 `@PreAuthorize("@ss.hasPermi('ccdi:project:query')")`
- 返回统一使用 `AjaxResult.success(...)`
DTO 要求:
- 使用独立 DTO不直接裸接 `Long`
- `projectId``staffIdCard` 做基础非空约束
- [ ] **Step 4: Run test to verify it passes**
Run:
```bash
mvn test -pl ccdi-project -Dtest=CcdiProjectSpecialCheckControllerContractTest
```
Expected:
- `PASS`
- [ ] **Step 5: Commit**
```bash
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/CcdiProjectSpecialCheckController.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/ICcdiProjectSpecialCheckService.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/CcdiProjectFamilyAssetLiabilityListQueryDTO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/CcdiProjectFamilyAssetLiabilityDetailQueryDTO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectFamilyAssetLiabilityListItemVO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectFamilyAssetLiabilityListVO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectFamilyIncomeDetailVO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectFamilyAssetItemVO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectFamilyAssetDetailVO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectFamilyDebtItemVO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectFamilyDebtDetailVO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectFamilyAssetLiabilityDetailVO.java ccdi-project/src/test/java/com/ruoyi/ccdi/project/controller/CcdiProjectSpecialCheckControllerContractTest.java
git commit -m "定义专项核查家庭资产负债接口契约"
```
### Task 2: 实现项目员工范围与列表聚合 SQL
**Files:**
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/mapper/CcdiProjectSpecialCheckMapper.java`
- Create: `ccdi-project/src/main/resources/mapper/ccdi/project/CcdiProjectSpecialCheckMapper.xml`
- Test: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/mapper/CcdiProjectSpecialCheckMapperListSqlTest.java`
- [ ] **Step 1: Write the failing test**
新增 Mapper XML 测试,锁定以下核心 SQL 口径:
- 项目员工范围沿用“项目内已入库流水命中且能匹配员工主数据”的口径
- 配偶通过 `relation_type = '配偶'` 识别
- 收入使用 `annual_income`
- 资产使用 `current_value`
- 负债使用 `principal_balance`
- 风险等级边界为 `<= 1.5``> 1.5 and <= 3``> 3`
- [ ] **Step 2: Run test to verify it fails**
Run:
```bash
mvn test -pl ccdi-project -Dtest=CcdiProjectSpecialCheckMapperListSqlTest
```
Expected:
- `FAIL`
- [ ] **Step 3: Write minimal implementation**
`CcdiProjectSpecialCheckMapper.xml` 中实现列表查询。
实现要求:
- 先抽取项目员工基础集合,避免明细聚合时丢失“无资产/无负债/无配偶”的员工
- 家庭总年收入 = 本人年收入 + 配偶年收入,均需 `COALESCE(..., 0)`
- 家庭总资产需限定持有人为“员工本人 + 配偶”
- 家庭总负债需限定归属人为“员工本人 + 配偶”
- 输出 `comparisonAmount = totalIncome + totalDebt`
- 风险等级同时输出 `riskLevelCode``riskLevelName`
- 排序建议先按风险等级倒序,再按 `comparisonAmount desc`,最后按 `staff_name asc`
- [ ] **Step 4: Run test to verify it passes**
Run:
```bash
mvn test -pl ccdi-project -Dtest=CcdiProjectSpecialCheckMapperListSqlTest
```
Expected:
- `PASS`
- [ ] **Step 5: Commit**
```bash
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/mapper/CcdiProjectSpecialCheckMapper.java ccdi-project/src/main/resources/mapper/ccdi/project/CcdiProjectSpecialCheckMapper.xml ccdi-project/src/test/java/com/ruoyi/ccdi/project/mapper/CcdiProjectSpecialCheckMapperListSqlTest.java
git commit -m "补充专项核查家庭资产负债列表查询"
```
### Task 3: 实现详情聚合 SQL 与明细结构
**Files:**
- Modify: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/mapper/CcdiProjectSpecialCheckMapper.java`
- Modify: `ccdi-project/src/main/resources/mapper/ccdi/project/CcdiProjectSpecialCheckMapper.xml`
- Test: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/mapper/CcdiProjectSpecialCheckMapperDetailSqlTest.java`
- [ ] **Step 1: Write the failing test**
新增详情查询 XML 测试,锁定以下内容:
- 详情必须返回收入、资产、负债三组结构
- 资产明细包含:资产名称、大类、小类、持有人、当前估值、估值日期
- 负债明细包含:负债名称、大类、小类、债权人类型、归属人、本金余额、查询日期
- 本人与配偶小计必须拆开
- [ ] **Step 2: Run test to verify it fails**
Run:
```bash
mvn test -pl ccdi-project -Dtest=CcdiProjectSpecialCheckMapperDetailSqlTest
```
Expected:
- `FAIL`
- [ ] **Step 3: Write minimal implementation**
在 Mapper 中新增详情查询与结果映射。
实现要求:
- 详情接口按 `projectId + staffIdCard` 查询
- 先校验该员工属于当前项目员工范围,再返回详情
- 资产、负债列表都要显式带出“归属人”名称或证件号映射
- 详情返回值中保留 `summary`,避免前端展开区自行重复计算
- 对空列表返回空数组,不返回 `null`
- [ ] **Step 4: Run test to verify it passes**
Run:
```bash
mvn test -pl ccdi-project -Dtest=CcdiProjectSpecialCheckMapperDetailSqlTest
```
Expected:
- `PASS`
- [ ] **Step 5: Commit**
```bash
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/mapper/CcdiProjectSpecialCheckMapper.java ccdi-project/src/main/resources/mapper/ccdi/project/CcdiProjectSpecialCheckMapper.xml ccdi-project/src/test/java/com/ruoyi/ccdi/project/mapper/CcdiProjectSpecialCheckMapperDetailSqlTest.java
git commit -m "补充专项核查家庭资产负债详情查询"
```
### Task 4: 完成服务组装与控制器返回
**Files:**
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectSpecialCheckServiceImpl.java`
- Test: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectSpecialCheckServiceImplTest.java`
- Test: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/controller/CcdiProjectSpecialCheckControllerTest.java`
- [ ] **Step 1: Write the failing test**
补服务层与控制器测试,覆盖:
- 项目不存在时返回统一异常
- 列表接口返回空列表而不是 `null`
- 详情接口在员工不属于当前项目时返回明确错误
- 详情 `summary` 中金额与列表同口径
- [ ] **Step 2: Run test to verify it fails**
Run:
```bash
mvn test -pl ccdi-project -Dtest=CcdiProjectSpecialCheckServiceImplTest,CcdiProjectSpecialCheckControllerTest
```
Expected:
- `FAIL`
- [ ] **Step 3: Write minimal implementation**
在服务层:
- 校验项目存在性
- 调用 Mapper 查询列表与详情
- 空数据场景统一封装为空列表或空明细结构
- 不在服务层新增与本次需求无关的缓存、异步、预计算逻辑
在控制器层:
- 直接接收 DTO
- 维持 GET 查询模式
- 返回 `AjaxResult.success(...)`
- [ ] **Step 4: Run test to verify it passes**
Run:
```bash
mvn test -pl ccdi-project -Dtest=CcdiProjectSpecialCheckServiceImplTest,CcdiProjectSpecialCheckControllerTest
```
Expected:
- `PASS`
- [ ] **Step 5: Commit**
```bash
git add ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectSpecialCheckServiceImpl.java ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectSpecialCheckServiceImplTest.java ccdi-project/src/test/java/com/ruoyi/ccdi/project/controller/CcdiProjectSpecialCheckControllerTest.java
git commit -m "完成专项核查家庭资产负债服务组装"
```
### Task 5: 写实施记录与验证记录
**Files:**
- Create: `docs/reports/implementation/2026-03-24-special-check-family-asset-liability-backend-record.md`
- Create: `docs/tests/records/2026-03-24-special-check-family-asset-liability-backend-verification.md`
- [ ] **Step 1: Write implementation record**
`docs/reports/implementation/2026-03-24-special-check-family-asset-liability-backend-record.md` 中记录:
- 本次新增的接口、Mapper、DTO、VO、测试文件
- 项目员工范围口径
- 收入、资产、负债、风险等级的计算口径
- 未扩展到其他家庭成员的范围说明
- [ ] **Step 2: Run targeted verification and record output**
Run:
```bash
mvn test -pl ccdi-project -Dtest=CcdiProjectSpecialCheckControllerContractTest,CcdiProjectSpecialCheckMapperListSqlTest,CcdiProjectSpecialCheckMapperDetailSqlTest,CcdiProjectSpecialCheckServiceImplTest,CcdiProjectSpecialCheckControllerTest
```
Expected:
- `PASS`
将实际执行命令、结果和结论记录到 `docs/tests/records/2026-03-24-special-check-family-asset-liability-backend-verification.md`
- [ ] **Step 3: Commit**
```bash
git add docs/reports/implementation/2026-03-24-special-check-family-asset-liability-backend-record.md docs/tests/records/2026-03-24-special-check-family-asset-liability-backend-verification.md
git commit -m "补充专项核查家庭资产负债后端记录"
```