Files
ccdi/docs/plans/backend/2026-07-09-project-risk-exclusion-backend-implementation.md

6.3 KiB
Raw Blame History

项目结果总览排除可疑后端实施计划

1. 目标

后端提供“排除可疑”持久化接口,并在结果总览所有预警查询、统计、导出链路中统一过滤已排除命中。排除粒度为单条规则命中,不删除原始打标结果。

2. 涉及范围

模块:

  1. ccdi-project
  2. ruoyi-admin 装配依赖无需调整
  3. sql/migration/

重点文件:

  1. CcdiProjectOverviewController
  2. ICcdiProjectOverviewService
  3. CcdiProjectOverviewServiceImpl
  4. CcdiProjectOverviewMapper
  5. CcdiBankTagResultMapper
  6. 新增排除记录实体、DTO、Mapper

3. 数据库实施

3.1 增量脚本

新增 SQL

sql/migration/2026-07-09-create-project-risk-exclusion.sql

内容使用 CREATE TABLE IF NOT EXISTS ccdi_project_risk_exclusion,字段与 sql/ccdi_prod_init.sql 保持一致,并显式声明:

DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci

3.2 表用途

ccdi_project_risk_exclusion 保存排除记录:

  1. STATEMENT:单笔流水上的单个规则标签。
  2. OBJECT:某个对象或人员上的单个规则预警。

4. 后端对象

4.1 新增 Entity

新增:

ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/entity/CcdiProjectRiskExclusion.java

字段对应表结构,实体类使用 Lombok @Data,不继承 BaseEntity

4.2 新增 DTO

新增:

ccdi-project/src/main/java/com/ruoyi/ccdi/project/domain/dto/CcdiProjectRiskExclusionSaveDTO.java

字段:

  1. projectId
  2. staffIdCard
  3. ruleCode
  4. exclusionType
  5. bankStatementId
  6. excludeReason

校验:

  1. projectId 必填。
  2. ruleCode 必填。
  3. exclusionType 必填且只允许 STATEMENTOBJECT
  4. excludeReason 必填且最大 1000 字符。
  5. STATEMENT 要求 bankStatementId
  6. OBJECT 要求 staffIdCard

4.3 新增 Mapper

新增:

ccdi-project/src/main/java/com/ruoyi/ccdi/project/mapper/CcdiProjectRiskExclusionMapper.java
ccdi-project/src/main/resources/mapper/ccdi/project/CcdiProjectRiskExclusionMapper.xml

方法:

  1. upsertExclusion
  2. selectByProjectId
  3. selectStatementExclusions
  4. selectObjectExclusions

upsertExclusion 使用唯一键实现幂等写入;重复排除时更新 exclude_reason/update_by/update_time

5. 接口实施

CcdiProjectOverviewController 新增:

POST /ccdi/project/overview/risk-exclusions

返回:

AjaxResult.success("排除成功")

权限:

  1. @PreAuthorize("@ss.hasPermi('ccdi:project:query')")
  2. 使用 projectAccessService.assertCanRead(projectId) 校验项目访问。
  3. 使用项目状态或访问服务校验当前项目可操作;归档或只读项目返回错误。

6. Service 实施

ICcdiProjectOverviewService 增加:

void excludeRisk(CcdiProjectRiskExclusionSaveDTO dto);

CcdiProjectOverviewServiceImpl 实现流程:

  1. 校验 DTO。
  2. 校验规则是否存在于当前项目有效命中中,避免写入无效排除记录。
  3. 写入 ccdi_project_risk_exclusion
  4. 触发当前项目结果总览员工快照重算。
  5. 返回成功。

7. 查询过滤实施

7.1 统一过滤 SQL

CcdiProjectOverviewMapper.xml 中新增复用 SQL 片段:

not exists (
  select 1
  from ccdi_project_risk_exclusion ex
  where ex.project_id = tr.project_id
    and ex.rule_code = tr.rule_code
    and (
      (ex.exclusion_type = 'STATEMENT' and ex.bank_statement_id = tr.bank_statement_id)
      or
      (ex.exclusion_type = 'OBJECT' and ex.staff_id_card = resolved_staff_id_card)
    )
)

实际实现时根据不同查询上下文替换 resolved_staff_id_card

7.2 员工风险基础 SQL

修改 resolvedEmployeeRiskBaseSql

  1. 先解析 staff_id_card
  2. STATEMENTOBJECT 分别过滤。
  3. 被排除命中不进入员工风险聚合。

7.3 风险模型卡片

修改模型统计查询:

  1. warning_count 按未排除命中统计。
  2. people_count 按未排除命中涉及人员去重。

7.4 风险模型命中人员

修改命中人员查询:

  1. hitTagList 不包含已排除规则。
  2. modelNames 按剩余命中规则组装。
  3. 过滤后无有效规则的人员不返回。

7.5 人员项目分析详情

修改详情组装:

  1. BANK_STATEMENT 记录的 hitTags 排除已排除标签。
  2. 如果一条流水没有剩余 hitTags,不进入流水异常明细。
  3. OBJECT 记录排除已排除对象规则。

7.6 涉疑交易明细与导出

修改涉疑交易查询:

  1. 已排除流水标签不进入 hitTags
  2. 过滤后无有效标签的流水不作为可疑流水展示。
  3. Excel 导出和 PDF 报告复用同一过滤口径。

7.7 外部人员预警

外部人员使用证件号作为对象键:

  1. OBJECT 类型按 staff_id_card = cert_no 过滤。
  2. STATEMENT 类型按 bank_statement_id 过滤。
  3. 外部人员列表、模型卡片、详情、报告口径一致。

8. 快照重算

如果当前已有员工结果快照重算逻辑,排除成功后复用该逻辑。

若没有可复用入口,新增内部方法:

refreshOverviewEmployeeResult(Long projectId)

要求:

  1. 使用过滤排除后的有效命中重算。
  2. 删除或更新当前项目 ccdi_project_overview_employee_result
  3. 确保列表、模型统计和详情口径一致。

9. 测试计划

9.1 后端编译

mvn -pl ccdi-project -am compile -DskipTests

9.2 单接口验证

验证接口:

POST /ccdi/project/overview/risk-exclusions

场景:

  1. 缺少原因返回错误。
  2. STATEMENT 缺少 bankStatementId 返回错误。
  3. OBJECT 缺少 staffIdCard 返回错误。
  4. 重复排除幂等成功。
  5. 归档项目或只读项目不允许排除。

9.3 数据口径验证

场景:

  1. 一笔流水多个标签,排除一个后另一个仍存在。
  2. 人员多个对象型预警,排除一个后人员仍存在。
  3. 人员唯一预警被排除后,风险人员列表不再展示该人员。
  4. 模型预警次数和命中人数减少。
  5. PDF/Excel 不输出已排除预警。

10. 风险控制

  1. 排除表只影响展示和统计,不影响原始命中结果。
  2. 所有新增 SQL 使用 utf8mb4_general_ci
  3. rule_code 保持全大写。
  4. 不引入恢复接口,避免扩大范围。