Files
ccdi/docs/design/2026-03-20-bank-tag-real-rule-two-phase-design.md

360 lines
10 KiB
Markdown
Raw Normal View History

# 银行流水模型真实规则两阶段落地设计文档
**模块**: 银行流水打标
**日期**: 2026-03-20
## 一、背景
当前项目已经具备银行流水打标基础链路:
- 规则元数据表 `ccdi_bank_tag_rule`
- 结果表 `ccdi_bank_statement_tag_result`
- 任务表 `ccdi_bank_tag_task`
- 规则执行入口 `CcdiBankTagServiceImpl`
- SQL 承载文件 `CcdiBankTagAnalysisMapper.xml`
- 参数解析器 `BankTagRuleConfigResolver`
其中“大额交易”模型下的首批规则已经具备真实 SQL其余不少规则虽然已经补齐了
- `rule_code`
- `model_code`
- Service 分发入口
- Mapper 方法签名
- XML `select`
但当前 XML 仍是 `where 1 = 0` 的占位 SQL尚未产生真实命中结果。
根据 [assets/模型信息.xlsx](/Users/wkc/Desktop/ccdi/ccdi/assets/模型信息.xlsx) 当前整理结果,现有未真实实现、且在本环境中已判定可直接执行 SQL 的银行流水模型共 19 条。本次需求是将这 19 条规则从“占位规则”替换为“真实规则”。
## 二、目标
本次设计目标如下:
1. 将 19 条未真实实现的银行流水模型接入现有真实打标链路。
2. 保持现有规则式架构不变,不新增平行模块或兼容性补丁链路。
3. 将真实命中逻辑统一收敛到 `CcdiBankTagAnalysisMapper.xml`
4. 补齐规则执行所需的参数映射、初始化 SQL 与验证测试。
5. 为控制改动规模,将 19 条规则拆成两期实施,并分别产出前后端实施计划。
## 三、范围
### 3.1 本次范围
- `CcdiBankTagAnalysisMapper.xml` 中 19 条占位规则替换为真实 SQL
- `CcdiBankTagServiceImpl` 中对应规则的真实执行分发校准
- `BankTagRuleConfigResolver` 中新增规则参数映射补齐
- `sql/` 下与本次规则相关的初始化脚本或增量脚本调整
- 单元测试、结构测试与回归测试补齐
- 新增 1 份设计文档、2 份后端实施计划、2 份前端实施计划
### 3.2 不在本次范围
- 不新增前端页面字段、交互或展示组件
- 不引入动态规则引擎、脚本注册中心或 DSL
- 不新增数据库表结构
- 不处理 `xlsx` 中当前环境不可直接执行的规则
- 不改造“大额交易”已真实落地的 8 条规则逻辑
## 四、现状分析
### 4.1 当前实现结构
当前银行流水打标流程为:
1. `CcdiBankTagServiceImpl.rebuildProject(...)` 加载启用规则。
2.`rule_code` 分发到 `executeStatementRule / executeObjectRule`
3. 通过 `CcdiBankTagAnalysisMapper` 调用 XML 中的具体 SQL。
4. 将命中结果组装为 `CcdiBankTagResult` 后批量入库。
5. 刷新项目风险人数,供结果总览等后续页面使用。
### 4.2 当前核心问题
19 条目标规则目前已具备“入口”,但不具备“真实命中能力”:
- `ccdi_bank_tag_rule` 中已有规则元数据
- `CcdiBankTagServiceImpl` 中已有大部分分发分支
- `CcdiBankTagAnalysisMapper.java` 中已有对应方法
- `CcdiBankTagAnalysisMapper.xml` 中对应 `<select>` 仍为占位 SQL
因此当前的主要缺口不是“补骨架”,而是“把占位 SQL 换成真实规则 SQL并补齐参数映射与测试”。
### 4.3 当前环境可直接落地的 19 条规则
#### 第一期
- `GAMBLING_SENSITIVE_KEYWORD`
- `SPECIAL_AMOUNT_TRANSACTION`
- `SUSPICIOUS_INCOME_KEYWORD`
- `SINGLE_PURCHASE_AMOUNT`
- `SINGLE_SETTLEMENT_AMOUNT`
- `LARGE_PURCHASE_TRANSACTION`
- `STOCK_TFR_LARGE`
- `LARGE_STOCK_TRADING`
- `WITHDRAW_CNT`
#### 第二期
- `LOW_INCOME_RELATIVE_LARGE_TRANSACTION`
- `MULTI_PARTY_GAMBLING_TRANSFER`
- `MONTHLY_FIXED_INCOME`
- `FIXED_COUNTERPARTY_TRANSFER`
- `HOUSE_REGISTRATION_MISMATCH`
- `PROPERTY_FEE_REGISTRATION_MISMATCH`
- `TAX_ASSET_REGISTRATION_MISMATCH`
- `SUPPLIER_CONCENTRATION`
- `SALARY_QUICK_TRANSFER`
- `SALARY_UNUSED`
## 五、方案对比
### 5.1 方案一:一次性直接替换 19 条占位 SQL
优点:
- 最短路径
- 架构最稳定
- 规则口径统一落地后可立即进入现有结果链路
缺点:
- 单次改动面较大
- SQL、参数、测试回归压力集中
### 5.2 方案二:按模型组拆成多轮交付
优点:
- 单次改动更小
缺点:
- 一部分规则真实、一部分规则仍占位,阶段内口径不完整
- 和本次“一次性纳入两批规划”的目标不一致
### 5.3 方案三:改造成更通用的动态规则架构
优点:
- 长期可维护性表面上更统一
缺点:
- 明显超出本次需求
- 会把风险扩大到 Service、Mapper、配置、测试结构整体重构
### 5.4 结论
采用方案一,但执行层面拆成两期实施:
- 总体架构保持不变
- 设计一次性定稿
- 实施按“先易后难”拆成两期
## 六、总体设计
### 6.1 架构原则
本次遵循以下原则:
1. 不引入新模块
2. 不新增兼容性双轨逻辑
3. 不在 Java Service 层补业务口径判断
4. 所有真实命中逻辑统一落在 `CcdiBankTagAnalysisMapper.xml`
5. 参数解析仍通过 `BankTagRuleConfigResolver`
### 6.2 数据流
真实规则执行链路保持为:
1. `CcdiBankTagServiceImpl.rebuildProject(...)` 发起重算。
2. `ruleMapper.selectEnabledRules(modelCode)` 获取启用规则。
3. `BankTagRuleConfigResolver.resolve(projectId, rule)` 解析项目有效参数。
4. `executeStatementRule / executeObjectRule` 依据 `rule_code` 分发。
5. `CcdiBankTagAnalysisMapper.xml` 执行真实 SQL返回 `STATEMENT``OBJECT` 命中结果。
6. Service 将命中结果组装为 `CcdiBankTagResult` 并批量入库。
7. 调用 `projectOverviewService.refreshProjectRiskCounts(projectId, operator)` 刷新项目风险人数。
### 6.3 规则落地边界
#### 流水明细型规则
输出:
- `bankStatementId`
- `groupId`
- `logId`
- `reasonDetail`
代表规则包括:
- `GAMBLING_SENSITIVE_KEYWORD`
- `SPECIAL_AMOUNT_TRANSACTION`
- `SUSPICIOUS_INCOME_KEYWORD`
- `HOUSE_REGISTRATION_MISMATCH`
- `PROPERTY_FEE_REGISTRATION_MISMATCH`
- `TAX_ASSET_REGISTRATION_MISMATCH`
- `LARGE_PURCHASE_TRANSACTION`
- `STOCK_TFR_LARGE`
- `LARGE_STOCK_TRADING`
- 外汇购汇/结汇规则
#### 对象型规则
输出:
- `objectType`
- `objectKey`
- `reasonDetail`
对象维度统一使用员工主键口径:
- `objectType = STAFF_ID_CARD`
- `objectKey = 员工身份证号`
代表规则包括:
- `LOW_INCOME_RELATIVE_LARGE_TRANSACTION`
- `MULTI_PARTY_GAMBLING_TRANSFER`
- `MONTHLY_FIXED_INCOME`
- `FIXED_COUNTERPARTY_TRANSFER`
- `SUPPLIER_CONCENTRATION`
- `WITHDRAW_CNT`
- `SALARY_QUICK_TRANSFER`
- `SALARY_UNUSED`
### 6.4 参数策略
参数只通过现有 `ccdi_model_param` 获取,不新增第二参数源。
本次需要补齐的规则参数映射包括:
- `MULTI_PARTY_GAMBLING_TRANSFER` -> `MULTI_PARTY_AMT_MIN``MULTI_PARTY_AMT_MAX`
- `FIXED_COUNTERPARTY_TRANSFER` -> `FIXED_COUNTERPARTY_TRANSFER_MIN``FIXED_COUNTERPARTY_TRANSFER_MAX`
- `SINGLE_PURCHASE_AMOUNT` 对应购汇类单值阈值
- `SINGLE_SETTLEMENT_AMOUNT` 对应结汇类单值阈值
- `WITHDRAW_CNT` 对应提现频次阈值
- `STOCK_TFR_LARGE``LARGE_STOCK_TRADING` 等单值阈值按现有参数脚本统一校准
对本身不依赖阈值的规则,不强行补充虚假参数。
### 6.5 错误处理策略
本次不增加补丁式兜底逻辑:
- 真实 SQL 报错:整次打标任务按现有逻辑失败
- 规则无命中:任务正常成功,命中数为 0
- 参数缺失:按现有解析结果暴露问题,并通过脚本与测试补齐
## 七、两期拆分设计
### 7.1 第一期设计目标
优先替换依赖简单、回归范围可控的规则,形成第一批真实命中能力。
第一期规则:
- `GAMBLING_SENSITIVE_KEYWORD`
- `SPECIAL_AMOUNT_TRANSACTION`
- `SUSPICIOUS_INCOME_KEYWORD`
- `SINGLE_PURCHASE_AMOUNT`
- `SINGLE_SETTLEMENT_AMOUNT`
- `LARGE_PURCHASE_TRANSACTION`
- `STOCK_TFR_LARGE`
- `LARGE_STOCK_TRADING`
- `WITHDRAW_CNT`
第一期特点:
- 单表筛选为主
- 依赖关系较少
- 参数映射简单
- 适合先完成真实 SQL 替换和基础回归
### 7.2 第二期设计目标
完成跨表比对、对象聚合和窗口口径更复杂的规则。
第二期规则:
- `LOW_INCOME_RELATIVE_LARGE_TRANSACTION`
- `MULTI_PARTY_GAMBLING_TRANSFER`
- `MONTHLY_FIXED_INCOME`
- `FIXED_COUNTERPARTY_TRANSFER`
- `HOUSE_REGISTRATION_MISMATCH`
- `PROPERTY_FEE_REGISTRATION_MISMATCH`
- `TAX_ASSET_REGISTRATION_MISMATCH`
- `SUPPLIER_CONCENTRATION`
- `SALARY_QUICK_TRANSFER`
- `SALARY_UNUSED`
第二期特点:
- 跨表比对较多
- 聚合口径更复杂
- 对交易时间、关系人口径、资产登记口径更敏感
## 八、测试设计
### 8.1 XML 结构测试
`CcdiBankTagAnalysisMapperXmlTest` 中补充:
- 目标规则不再使用 `where 1 = 0`
- 新增真实 SQL 仍满足 XML 结构合法
- `STATEMENT` 规则仍返回完整命中字段
- `OBJECT` 规则仍返回完整命中字段
### 8.2 参数解析测试
`BankTagRuleConfigResolverTest` 中补充:
- 新增规则参数映射断言
- 双阈值规则参数完整性断言
- 无参数规则仍返回空参数集
### 8.3 Service 分发测试
`CcdiBankTagServiceImplTest` 中补充:
- 每条新增规则都能命中正确 Mapper 方法
- 不再落入默认空分支
- 真实规则空命中时任务仍可成功结束
### 8.4 受影响链路回归
至少覆盖:
- `CcdiBankTagAnalysisMapperXmlTest`
- `BankTagRuleConfigResolverTest`
- `CcdiBankTagServiceImplTest`
- 受影响的项目风险人数回写与结果总览后端测试
## 九、文档产物
按仓库规范,本次输出以下文档:
1. 本设计文档:
- `docs/design/2026-03-20-bank-tag-real-rule-two-phase-design.md`
2. 第一期后端实施计划:
- `docs/plans/backend/2026-03-20-bank-tag-real-rule-phase1-backend-implementation.md`
3. 第一期前端实施计划:
- `docs/plans/frontend/2026-03-20-bank-tag-real-rule-phase1-frontend-implementation.md`
4. 第二期后端实施计划:
- `docs/plans/backend/2026-03-20-bank-tag-real-rule-phase2-backend-implementation.md`
5. 第二期前端实施计划:
- `docs/plans/frontend/2026-03-20-bank-tag-real-rule-phase2-frontend-implementation.md`
其中前端实施计划用于明确边界:
- 本期无前端代码改造
- 前端仅做依赖说明和联调预期记录
## 十、结论
本方案采用“现有架构内真实替换占位 SQL”的最短路径设计并将 19 条目标规则拆成两期实施:
- 第一期先处理依赖少、风险低的 9 条规则
- 第二期再处理聚合与跨表逻辑更重的 10 条规则
这样既满足“一次性完成完整设计”的要求,又能在实施阶段有效控制改动规模和回归风险,不会偏离当前项目既有技术路线。