Files
ccdi/docs/plans/backend/2026-03-24-special-check-extended-query-backend-implementation.md

363 lines
17 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 Extended Query Backend Implementation Plan
> **For agentic workers:** REQUIRED: Use superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 为专项核查页新增“拓展查询”后端查询能力,支持在专项核查同范围员工内查询采购、招聘、调动记录,并提供各主题列表与详情接口。
**Architecture:** 延续 `CcdiProjectSpecialCheckController + Service + Mapper` 这条专项核查专用查询链路,不复用信息采集模块现有 `/list` 接口做前端拼装。员工范围统一复用 `projectEmployeeScopeSql`,在 `ccdi-project` 内新增 3 组主题查询 DTO、列表 VO 和明细查询方法,保证项目范围口径与当前专项核查完全一致。
**Tech Stack:** Java 21, Spring Boot 3, MyBatis XML, Maven, JUnit 5
---
### Task 1: 定义拓展查询接口契约与主题 DTO/VO
**Files:**
- Modify: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/controller/CcdiProjectSpecialCheckController.java`
- Modify: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/ICcdiProjectSpecialCheckService.java`
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/CcdiProjectExtendedPurchaseQueryDTO.java`
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/CcdiProjectExtendedPurchaseDetailQueryDTO.java`
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/CcdiProjectExtendedRecruitmentQueryDTO.java`
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/CcdiProjectExtendedRecruitmentDetailQueryDTO.java`
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/CcdiProjectExtendedTransferQueryDTO.java`
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/CcdiProjectExtendedTransferDetailQueryDTO.java`
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectExtendedPurchaseListItemVO.java`
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectExtendedPurchaseListVO.java`
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectExtendedPurchaseDetailVO.java`
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectExtendedRecruitmentListItemVO.java`
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectExtendedRecruitmentListVO.java`
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectExtendedRecruitmentDetailVO.java`
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectExtendedTransferListItemVO.java`
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectExtendedTransferListVO.java`
- Create: `ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectExtendedTransferDetailVO.java`
- Test: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/controller/CcdiProjectSpecialCheckExtendedQueryContractTest.java`
- [ ] **Step 1: Write the failing test**
新增控制器契约测试,锁定以下接口路径与方法:
- `GET /ccdi/project/special-check/extended-query/purchase/list`
- `GET /ccdi/project/special-check/extended-query/purchase/detail`
- `GET /ccdi/project/special-check/extended-query/recruitment/list`
- `GET /ccdi/project/special-check/extended-query/recruitment/detail`
- `GET /ccdi/project/special-check/extended-query/transfer/list`
- `GET /ccdi/project/special-check/extended-query/transfer/detail`
同时锁定 DTO / VO 基本字段:
- 采购列表入参:`projectId``applicantName``applyDateStart``applyDateEnd``pageNum``pageSize`
- 招聘列表入参:`projectId``interviewerName``pageNum``pageSize`
- 调动列表入参:`projectId``staffName``transferDateStart``transferDateEnd``pageNum``pageSize`
- 3 个详情入参都必须带 `projectId` 和主题主键
- 3 个列表 VO 都必须包含 `rows``total`
- 列表项只保留设计文档约定的必要字段
- 详情 VO 在 `ccdi-project` 模块内独立定义,不直接依赖 `ccdi-info-collection` 模块类
- [ ] **Step 2: Run test to verify it fails**
Run:
```bash
mvn test -pl ccdi-project -Dtest=CcdiProjectSpecialCheckExtendedQueryContractTest
```
Expected:
- `FAIL`
- 原因是新增接口契约、DTO、VO 尚未落地
- [ ] **Step 3: Write minimal implementation**
补齐控制器方法、服务接口方法、DTO 与列表 VO。
实现要求:
- 控制器继续使用 `@Tag``@Operation`
- 权限沿用 `@PreAuthorize("@ss.hasPermi('ccdi:project:query')")`
- 详情接口命名直接使用业务主键,不引入额外包装对象
- 采购主题查询字段必须命名为 `applicantName`,不要用泛化的 `staffName`
- 招聘主题查询字段必须命名为 `interviewerName`,不要用泛化的 `staffName`
- 3 个列表 DTO 都显式带 `pageNum / pageSize`,默认值与若依分页口径一致
- 3 个列表返回体都显式带 `rows / total`
- `projectId` 与 3 个详情主键字段都加非空校验
- 采购、招聘、调动 3 类详情 VO 都在 `ccdi-project` 中定义,避免引入新的模块依赖
- 详情 VO 字段分别对齐现有采购、招聘、调动独立页的详情展示结构
- 返回统一使用 `AjaxResult.success(...)`
- [ ] **Step 4: Run test to verify it passes**
Run:
```bash
mvn test -pl ccdi-project -Dtest=CcdiProjectSpecialCheckExtendedQueryContractTest
```
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/CcdiProjectExtendedPurchaseQueryDTO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/CcdiProjectExtendedPurchaseDetailQueryDTO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/CcdiProjectExtendedRecruitmentQueryDTO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/CcdiProjectExtendedRecruitmentDetailQueryDTO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/CcdiProjectExtendedTransferQueryDTO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/CcdiProjectExtendedTransferDetailQueryDTO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectExtendedPurchaseListItemVO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectExtendedPurchaseListVO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectExtendedPurchaseDetailVO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectExtendedRecruitmentListItemVO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectExtendedRecruitmentListVO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectExtendedRecruitmentDetailVO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectExtendedTransferListItemVO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectExtendedTransferListVO.java ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/vo/CcdiProjectExtendedTransferDetailVO.java ccdi-project/src/test/java/com/ruoyi/ccdi/project/controller/CcdiProjectSpecialCheckExtendedQueryContractTest.java
git commit -m "定义专项核查拓展查询接口契约"
```
### Task 2: 在 Mapper 中补采购主题项目范围列表与详情查询
**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/CcdiProjectSpecialCheckExtendedPurchaseSqlTest.java`
- [ ] **Step 1: Write the failing test**
新增采购主题 SQL 测试,锁定以下口径:
- 员工范围必须复用 `projectEmployeeScopeSql`
- 列表只能返回项目范围内员工的采购记录
- 员工姓名筛选命中 `applicant_name`
- 时间范围筛选命中 `apply_date`
- 分页必须按 `pageNum / pageSize` 生效,并返回总数
- 列表字段只返回:`purchaseId``projectName``subjectName``applicantName``applyDate`
- 详情按 `projectId + purchaseId` 查询,并校验记录属于项目范围员工
- [ ] **Step 2: Run test to verify it fails**
Run:
```bash
mvn test -pl ccdi-project -Dtest=CcdiProjectSpecialCheckExtendedPurchaseSqlTest
```
Expected:
- `FAIL`
- [ ] **Step 3: Write minimal implementation**
在 Mapper 中新增采购主题列表与详情查询。
实现要求:
- 范围表先去重员工姓名,避免一名员工在项目范围内重复放大采购记录
- 列表查询使用 MyBatis Plus `Page` 或等效分页结果承载 `rows / total`
- 列表按 `apply_date desc, create_time desc, purchase_id desc` 排序
- 采购详情映射到 `CcdiProjectExtendedPurchaseDetailVO`
- `CcdiProjectExtendedPurchaseDetailVO` 字段按采购现有详情展示结构定义:基本信息、金额信息、供应商信息、日期信息、申请人信息、采购负责人信息、审计信息
- 详情查不到时交给服务层统一转业务错误
- [ ] **Step 4: Run test to verify it passes**
Run:
```bash
mvn test -pl ccdi-project -Dtest=CcdiProjectSpecialCheckExtendedPurchaseSqlTest
```
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/CcdiProjectSpecialCheckExtendedPurchaseSqlTest.java
git commit -m "补充专项核查采购拓展查询SQL"
```
### Task 3: 在 Mapper 中补招聘与调动主题项目范围查询
**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/CcdiProjectSpecialCheckExtendedRecruitmentSqlTest.java`
- Test: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/mapper/CcdiProjectSpecialCheckExtendedTransferSqlTest.java`
- [ ] **Step 1: Write the failing test**
新增招聘与调动 SQL 测试,锁定以下口径:
招聘:
- 员工范围必须复用 `projectEmployeeScopeSql`
- 员工姓名口径不使用 `candName`
- 检索字段必须是 `interviewer_name_1``interviewer_name_2`
- 同一条招聘记录若同时命中面试官 1 和面试官 2列表结果必须按 `recruit_id` 去重
- 本次不增加招聘时间筛选
- 分页必须按 `pageNum / pageSize` 生效,并返回总数
- 列表字段只返回:`recruitId``recruitName``posName``interviewerNameSummary``admitStatus`
调动:
- 员工范围必须按范围员工姓名匹配到 `ccdi_base_staff.name`
- 时间范围命中 `transfer_date`
- 分页必须按 `pageNum / pageSize` 生效,并返回总数
- 列表字段只返回:`staffName``transferType``deptNameBefore``deptNameAfter``transferDate`
- 详情按 `projectId + id` 查询,并校验记录属于项目范围员工
- [ ] **Step 2: Run test to verify it fails**
Run:
```bash
mvn test -pl ccdi-project -Dtest=CcdiProjectSpecialCheckExtendedRecruitmentSqlTest,CcdiProjectSpecialCheckExtendedTransferSqlTest
```
Expected:
- `FAIL`
- [ ] **Step 3: Write minimal implementation**
补齐招聘与调动主题 SQL。
实现要求:
- 招聘列表中生成 `interviewerNameSummary`格式统一为“面试官1 / 面试官2”单边为空时只输出存在值
- 招聘列表查询必须按 `recruit_id` 去重,避免同一条记录因双面试官命中被重复返回并放大 `total`
- 招聘详情映射到 `CcdiProjectExtendedRecruitmentDetailVO`
- `CcdiProjectExtendedRecruitmentDetailVO` 字段按招聘现有详情展示结构定义:招聘项目信息、职位信息、候选人信息、录用信息、面试官信息、审计信息
- 调动列表通过 `ccdi_staff_transfer.staff_id -> ccdi_base_staff.staff_id` 关联员工姓名
- 调动详情映射到 `CcdiProjectExtendedTransferDetailVO`
- `CcdiProjectExtendedTransferDetailVO` 字段按调动详情展示结构定义:基本信息、调动前信息、调动后信息、审计信息
- 调动排序按 `transfer_date desc, create_time desc, id desc`
- [ ] **Step 4: Run test to verify it passes**
Run:
```bash
mvn test -pl ccdi-project -Dtest=CcdiProjectSpecialCheckExtendedRecruitmentSqlTest,CcdiProjectSpecialCheckExtendedTransferSqlTest
```
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/CcdiProjectSpecialCheckExtendedRecruitmentSqlTest.java ccdi-project/src/test/java/com/ruoyi/ccdi/project/mapper/CcdiProjectSpecialCheckExtendedTransferSqlTest.java
git commit -m "补充专项核查招聘调动拓展查询SQL"
```
### Task 4: 完成服务层组装、项目校验与详情归属校验
**Files:**
- Modify: `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/CcdiProjectSpecialCheckExtendedQueryServiceImplTest.java`
- Test: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/controller/CcdiProjectSpecialCheckControllerTest.java`
- [ ] **Step 1: Write the failing test**
新增服务层与控制器测试,覆盖:
- 项目不存在时统一返回“项目不存在”
- 3 个列表接口都返回空列表而不是 `null`
- 3 个列表接口都返回正确的 `total`
- 分页参数变化时列表记录数和总数符合预期
- 3 个详情接口在记录不属于当前项目范围员工时返回明确业务错误
- 招聘列表的查询字段确实是 `interviewerName`
- 控制器都走 `AjaxResult.success(...)`
- [ ] **Step 2: Run test to verify it fails**
Run:
```bash
mvn test -pl ccdi-project -Dtest=CcdiProjectSpecialCheckExtendedQueryServiceImplTest,CcdiProjectSpecialCheckControllerTest
```
Expected:
- `FAIL`
- [ ] **Step 3: Write minimal implementation**
在服务层中:
- 复用当前 `ensureProjectExists` 校验思路
- 新增 3 个列表方法和 3 个详情方法
- 列表统一封装 `rows + total`
- 空数据场景统一封装成 `rows = List.of()``total = 0`
- 详情空数据统一抛出“当前记录不属于该项目专项核查范围”或同义明确错误
- 采购、招聘、调动 3 个详情接口错误文案保持同一风格,便于前端提示和测试断言
- 不引入缓存、异步刷新或额外结果表
在控制器中:
- 继续使用 `GET` 查询风格
- 列表与详情返回结构保持专项核查域一致
- [ ] **Step 4: Run test to verify it passes**
Run:
```bash
mvn test -pl ccdi-project -Dtest=CcdiProjectSpecialCheckExtendedQueryServiceImplTest,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/CcdiProjectSpecialCheckExtendedQueryServiceImplTest.java ccdi-project/src/test/java/com/ruoyi/ccdi/project/controller/CcdiProjectSpecialCheckControllerTest.java
git commit -m "完成专项核查拓展查询服务组装"
```
### Task 5: 运行后端回归验证并沉淀测试记录
**Files:**
- Modify: `docs/tests/records/2026-03-24-special-check-extended-query-backend-verification.md`
- Test: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/controller/CcdiProjectSpecialCheckExtendedQueryContractTest.java`
- Test: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/mapper/CcdiProjectSpecialCheckExtendedPurchaseSqlTest.java`
- Test: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/mapper/CcdiProjectSpecialCheckExtendedRecruitmentSqlTest.java`
- Test: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/mapper/CcdiProjectSpecialCheckExtendedTransferSqlTest.java`
- Test: `ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiProjectSpecialCheckExtendedQueryServiceImplTest.java`
- [ ] **Step 1: Run focused backend test suite**
Run:
```bash
mvn test -pl ccdi-project -Dtest=CcdiProjectSpecialCheckExtendedQueryContractTest,CcdiProjectSpecialCheckExtendedPurchaseSqlTest,CcdiProjectSpecialCheckExtendedRecruitmentSqlTest,CcdiProjectSpecialCheckExtendedTransferSqlTest,CcdiProjectSpecialCheckExtendedQueryServiceImplTest
```
Expected:
- 所有新增专项核查拓展查询测试 `PASS`
- 分页相关断言一并通过
- [ ] **Step 2: Run module regression**
Run:
```bash
mvn test -pl ccdi-project
```
Expected:
- `PASS`
- 若存在既有失败,需在记录中注明与本次改动是否相关
- [ ] **Step 3: Write verification record**
`docs/tests/records/2026-03-24-special-check-extended-query-backend-verification.md` 记录:
- 实际执行命令
- 结果
- 是否发现与项目范围口径相关的偏差
- 若有失败,明确是否为既有问题
- [ ] **Step 4: Commit**
```bash
git add docs/tests/records/2026-03-24-special-check-extended-query-backend-verification.md
git commit -m "补充专项核查拓展查询后端验证记录"
```