# 后端全量打标规则验证实施记录

## 目标

- 验证后端当前银行流水打标链路在真实联调环境下是否能够覆盖全部 33 条规则。
- 不改动业务代码，只输出当前实现状态与验证结论。

## 本次执行范围

- 复用当前本地已运行的后端服务 `http://localhost:62318`
- 复用当前本地已运行的 Mock 服务 `http://localhost:8000`
- 使用 `project_id=49` 执行“拉取本行信息 -> 手动重打标 -> 数据库结果核验 -> 详情接口回查”
- 补充规则清单、占位 SQL、Mock all 模式覆盖范围与实际命中结果的交叉核验

## 实施内容

### 1. 自动化与实现现状核对

- 执行 `mvn -pl ccdi-project -Dtest=CcdiBankTagServiceImplTest,CcdiBankTagServiceRiskCountRefreshTest,CcdiBankTagAnalysisMapperXmlTest,CcdiBankTagRuleSqlMetadataTest,CcdiModelParamSqlDefaultsTest test`
- 结果为 `BUILD SUCCESS`
- 结论：当前 33 条规则的服务分发、XML 结构、元数据校验与风险人数刷新回归均通过

### 2. 规则可验证范围核对

- 规则总数：33
- `CcdiBankTagServiceImpl` 中分发 `case` 数量：33
- 当前仍为占位 SQL 的规则共 6 条：
  - `ABNORMAL_CUSTOMER_TRANSACTION`
  - `INCOME_ASSET_MISMATCH`
  - `CROSS_BORDER_AMT`
  - `INTEREST_PAYMENT_BY_OTHERS`
  - `WITHDRAW_AMT`
  - `PROXY_ACCOUNT_OPERATION`
- Mock 服务 `--rule-hit-mode all` 当前可直接提供的“全部兼容规则命中”覆盖 26 条规则，不包含以下 7 条：
  - `ABNORMAL_CUSTOMER_TRANSACTION`
  - `INCOME_ASSET_MISMATCH`
  - `CROSS_BORDER_AMT`
  - `INTEREST_PAYMENT_BY_OTHERS`
  - `LARGE_PURCHASE_TRANSACTION`
  - `WITHDRAW_AMT`
  - `PROXY_ACCOUNT_OPERATION`
- 其中 `LARGE_PURCHASE_TRANSACTION` 依赖采购基线表，不依赖 Mock 银行流水样本

### 3. 真实链路验证

- 登录接口返回 `code=200`
- 对项目 `49` 调用 `/ccdi/file-upload/pull-bank-info`，返回“拉取任务已提交”
- 对项目 `49` 调用 `/ccdi/project/tags/rebuild`，返回“标签重算任务已提交”
- 最新手动任务：
  - `id=47`
  - `status=SUCCESS`
  - `hit_count=2340`
  - `success_rule_count=33`
  - `failed_rule_count=0`

### 4. 结果核验

- 项目 `49` 当前在标签结果表 `ccdi_bank_statement_tag_result` 中实际命中的规则共 19 条：
  - `HOUSE_OR_CAR_EXPENSE`
  - `TAX_EXPENSE`
  - `SINGLE_LARGE_INCOME`
  - `CUMULATIVE_INCOME`
  - `ANNUAL_TURNOVER`
  - `LARGE_CASH_DEPOSIT`
  - `LARGE_TRANSFER`
  - `MULTI_PARTY_GAMBLING_TRANSFER`
  - `GAMBLING_SENSITIVE_KEYWORD`
  - `HOUSE_REGISTRATION_MISMATCH`
  - `PROPERTY_FEE_REGISTRATION_MISMATCH`
  - `TAX_ASSET_REGISTRATION_MISMATCH`
  - `FOREX_BUY_AMT`
  - `FOREX_SELL_AMT`
  - `LARGE_PURCHASE_TRANSACTION`
  - `SUPPLIER_CONCENTRATION`
  - `STOCK_TFR_LARGE`
  - `SALARY_QUICK_TRANSFER`
  - `LARGE_STOCK_TRADING`
- 未命中的 14 条规则中：
  - 6 条属于占位 SQL，当前无法证明“可正确打标”
  - 8 条虽然已有真实 SQL，但本次项目 `49` 在 all 模式联调数据下未产生命中：
    - `FREQUENT_CASH_DEPOSIT`
    - `LOW_INCOME_RELATIVE_LARGE_TRANSACTION`
    - `SPECIAL_AMOUNT_TRANSACTION`
    - `MONTHLY_FIXED_INCOME`
    - `FIXED_COUNTERPARTY_TRANSFER`
    - `SUSPICIOUS_INCOME_KEYWORD`
    - `WITHDRAW_CNT`
    - `SALARY_UNUSED`

### 5. 8 条真实 SQL 未命中规则的具体原因

- `FREQUENT_CASH_DEPOSIT`
  - 项目 `49` 的 `batch_id=45565/69755/70053` 中存在 `2026-03-10` 同日 `6` 笔存现样本，金额均高于运行阈值。
  - `taskId=47` 日志显示运行参数为 `{LARGE_CASH_DEPOSIT=5000, FREQUENT_CASH_DEPOSIT=2}`，但规则仍记为无命中。
  - 当前按源码 SQL 直接复核，这批数据已经足以命中 `3` 个对象；结合当前后端进程启动时间为 `2026-03-22 12:11:28`、晚于 `taskId=47` 的 `2026-03-22 09:11:57`，可判定这是验证时旧运行进程未刷新 Mapper XML 导致的假阴性。
- `LOW_INCOME_RELATIVE_LARGE_TRANSACTION`
  - Mock 样本给关系人打入两笔资金，累计 `120000` 元，金额条件已满足。
  - 但项目 `49` 中这些关系人的 `annual_income` 实际为 `64000~128000` 元，折算月收入均高于 `3000` 元。
  - 实际阻断点是家庭关系表收入口径，不是流水金额不足。
- `SPECIAL_AMOUNT_TRANSACTION`
  - Mock 样本金额为 `88888.88` 元。
  - SQL 仅接受 `520`、`1314` 两类特殊金额。
  - 这条未命中是样本金额与真实规则枚举不一致。
- `MONTHLY_FIXED_INCOME`
  - Mock 每个对象只生成了 `4` 个月稳定收入（`2025-12` 到 `2026-03`，每月 `7200` 元）。
  - SQL 要求近 `12` 个月至少 `6` 个月达到阈值。
  - 样本满足“固定金额”，但不满足“月份数量”条件。
- `FIXED_COUNTERPARTY_TRANSFER`
  - “季度稳定兼职收入”样本全部写在家属证件号上，项目 `49` 复核时这些证件号均未进入员工主表。
  - SQL 从 `ccdi_base_staff` 内连接开始，只统计员工本人。
  - 因此这条在第一层员工连接就被过滤掉。
- `SUSPICIOUS_INCOME_KEYWORD`
  - Mock 摘要为“咨询返现收入”。
  - SQL 关键词集合仅覆盖“工资、分红、红利、奖金、劳务费、批量代付”等收入词，不包含“返现”“咨询”。
  - 直接阻断点是摘要关键词不匹配。
- `WITHDRAW_CNT`
  - 当前按源码 SQL 直接复核，项目 `49` 已能查出 `3` 个对象在 `2026-03-12` 单日提现 `4/4/5` 次，均超过阈值 `3`。
  - 但 `taskId=47` 日志在同一阈值下仍记为无命中。
  - 这条与 `FREQUENT_CASH_DEPOSIT` 一样，不是数据不满足，而是 `2026-03-22 09:11` 那次验证使用了旧后端运行进程，导致运行时 SQL 与当前源码不一致。
- `SALARY_UNUSED`
  - `2026-02-10` 的“工资入账 + 代扣公积金”专用样本全部落在家属证件号，被 `ccdi_base_staff` 内连接排除。
  - 员工本人侧仅剩 `2026-03-14` 的工资入账样本，而这些样本在 `30` 天内都已有 `2~5` 笔非代扣支出。
  - 因此该规则一部分样本卡在员工连接，另一部分样本卡在“30 天无支出”的 `not exists` 条件。

### 6. 接口回查

- 使用 `bank_statement_id=70334` 调用详情接口 `/ccdi/project/bank-statement/detail/70334`
- 返回 `code=200`
- `data.hitTags` 中成功回查到 `LARGE_TRANSFER`

## 产物

- [`2026-03-22-bank-tag-all-rules-validation-record.md`](/Users/wkc/Desktop/ccdi/ccdi/docs/reports/implementation/2026-03-22-bank-tag-all-rules-validation-record.md)
- [`2026-03-22-bank-tag-all-rules-validation-verification.md`](/Users/wkc/Desktop/ccdi/ccdi/docs/tests/records/2026-03-22-bank-tag-all-rules-validation-verification.md)

## 结论

- 当前后端可以证明“33 条规则都已接入执行链路”，但不能证明“33 条规则现在都能正确打上标签”。
- 截至 2026-03-22，本次真实联调链路只验证到 19 条规则产生实际标签结果。
- 其余 14 条里有 6 条仍是占位 SQL，另外 8 条里有 6 条属于样本/主数据口径不满足，`FREQUENT_CASH_DEPOSIT`、`WITHDRAW_CNT` 则属于验证时运行进程版本不一致导致的假阴性。
- 因此当前结论应判定为“全量规则未全部验证通过”，且 `2026-03-22` 这次验证记录不能继续把 `FREQUENT_CASH_DEPOSIT`、`WITHDRAW_CNT` 简单归类为“真实 SQL 未打中”。
