diff --git a/docs/reports/implementation/2026-03-22-bank-tag-all-rules-validation-record.md b/docs/reports/implementation/2026-03-22-bank-tag-all-rules-validation-record.md new file mode 100644 index 00000000..f31fa25e --- /dev/null +++ b/docs/reports/implementation/2026-03-22-bank-tag-all-rules-validation-record.md @@ -0,0 +1,141 @@ +# 后端全量打标规则验证实施记录 + +## 目标 + +- 验证后端当前银行流水打标链路在真实联调环境下是否能够覆盖全部 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 未打中”。 diff --git a/docs/reports/implementation/2026-03-22-project50-bank-tag-unhit-rule-analysis.md b/docs/reports/implementation/2026-03-22-project50-bank-tag-unhit-rule-analysis.md new file mode 100644 index 00000000..30cae7db --- /dev/null +++ b/docs/reports/implementation/2026-03-22-project50-bank-tag-unhit-rule-analysis.md @@ -0,0 +1,152 @@ +# project_id=50 银行流水未命中规则逐条追因记录 + +## 目标 + +- 针对 `project_id=50` 最新一次流水打标结果,逐条追查未命中的 `12` 条规则原因。 +- 本次只做数据库与源码核验,不改动业务代码与数据。 + +## 核验范围 + +- 任务表:`ccdi_bank_tag_task` +- 结果表:`ccdi_bank_statement_tag_result` +- 规则表:`ccdi_bank_tag_rule` +- 主数据:`ccdi_base_staff`、`ccdi_staff_fmy_relation` +- 明细表:`ccdi_bank_statement` +- 源码口径:`ccdi-project/src/main/resources/mapper/ccdi/project/CcdiBankTagAnalysisMapper.xml` + +## 项目概况 + +- `project_id=50` 最新标签任务为 `id=48` +- 任务状态:`SUCCESS` +- `success_rule_count=33` +- `failed_rule_count=0` +- `hit_count=2094` +- 实际产生命中结果的规则共 `21` 条,因此仍有 `12` 条规则未命中 +- 项目流水共 `198` 条,仅涉及 `1` 名员工和 `2` 名家属: + - 员工:`499172200511062290 / 马娜` + - 家属:`320101200103037981 / 孙秀霞 / 配偶 / 年收入 152000` + - 家属:`320101198908317982 / 王德华 / 父亲 / 年收入 57000` + +## 12 条未命中规则与原因 + +### 1. `ABNORMAL_CUSTOMER_TRANSACTION` + +- 当前 Mapper SQL 仍是 `where 1 = 0` 的占位实现。 +- 直接原因不是 `project_id=50` 的样本不足,而是规则尚未落地真实 SQL。 + +### 2. `INTEREST_PAYMENT_BY_OTHERS` + +- 当前 Mapper SQL 仍是 `where 1 = 0` 的占位实现。 +- 该规则当前版本不会返回任何对象结果。 + +### 3. `MONTHLY_FIXED_INCOME` + +- 项目 `50` 员工本人近 `12` 个月满足“月流入总额 > 5000”的月份其实有 `10` 个月,并非月份数量不足。 +- 但这些月份金额波动极大: + - 常规月份多在 `7225.83 ~ 22924.28` + - `2026-03` 因多笔大额对公流入,单月达到 `113218600.98` +- 按现有 SQL,命中前提除了 `>= 6` 个月,还要求 `STDDEV(monthAmount) / AVG(monthAmount) <= 0.3`。 +- 该员工实际离散系数约为 `2.9962`,远高于阈值,最终卡在“固定收入稳定性”这一层。 + +### 4. `SPECIAL_AMOUNT_TRANSACTION` + +- 项目 `50` 中不存在金额为 `520` 或 `1314` 的员工本人特殊金额流水。 +- 现有最接近的样本是: + - `bank_statement_id=72174` + - `2026-03-14 08:00:00` + - 对手方 `兰溪特别金额结算中心` + - 摘要 `特殊金额转账` + - 支出金额 `88888.88` +- 现行 SQL 只接受 `520`、`1314` 两类固定金额,因此这条是“样本金额与真实规则枚举不一致”。 + +### 5. `FIXED_COUNTERPARTY_TRANSFER` + +- 当前阈值为季度区间 `[3000, 15000]`。 +- 样本中原本用于模拟“稳定兼职收入”的对手方 `兰溪远航信息服务有限公司`: + - `2025-Q4` 累计 `7200`,落在区间内 + - `2026-Q1` 因 `2026-01`、`2026-02`、`2026-03` 各有一笔 `7200`,季度累计变成 `21600`,超过上限 `15000` +- 因此它自己就无法满足“同一对手至少 2 个季度都落在区间内”。 +- 同时,项目 `50` 还存在多组噪声对手方也误落在区间内并跨季度重复,如: + - `小店`:`2025-Q2/Q3/Q4` + - `京东`:`2025-Q2/2026-Q1` + - `微信支付`:`2025-Q2/2026-Q1` + - `支付宝`:`2025-Q2/2025-Q4` + - `淘宝`:`2025-Q2/2026-Q1` + - `银行转账`:`2025-Q4/2026-Q1` +- 外层 SQL 还要求同一员工满足条件的固定对手数 `< 3`,而该员工实际达到 `6` 个,因此最终卡在对象收口条件。 + +### 6. `LOW_INCOME_RELATIVE_LARGE_TRANSACTION` + +- 项目 `50` 家属流水总量并不低: + - `王德华` 累计交易额 `820405.18` + - `孙秀霞` 累计交易额 `319656.22` +- 但规则要求关系人年收入为空、为 `0`,或折算月收入 `< 3000`。 +- 项目 `50` 的两个家属收入分别为: + - `王德华` 年收入 `57000`,折算月收入 `4750` + - `孙秀霞` 年收入 `152000`,折算月收入约 `12666.67` +- 因此没有任何一名家属能进入“低收入关系人”候选集,阻断点在家庭关系表收入口径,而不是流水金额不足。 + +### 7. `CROSS_BORDER_AMT` + +- 当前 Mapper SQL 仍是 `where 1 = 0` 的占位实现。 +- 该规则当前版本不会返回任何明细结果。 + +### 8. `SUSPICIOUS_INCOME_KEYWORD` + +- 项目 `50` 存在多笔“看起来像兼职/合作收入”的流入样本,例如: + - `月度稳定兼职收入` + - `年度合作收入` + - `经营往来收入` + - `项目回款收入` + - `业务合作收入` + - `咨询返现收入` +- 但现行 SQL 的关键词集合只覆盖: + - `代发、工资、分红、红利、奖金、薪酬、薪金、补贴、年终奖、年金、加班费、劳务费、劳务外包、提成、劳务派遣、绩效、酬劳、批量代付` +- 不包含 `兼职、收入、返现、回款、合作、经营、咨询` 等词。 +- 因此项目 `50` 不是没有疑似样本,而是当前关键词词表无法识别这些摘要。 + +### 9. `WITHDRAW_AMT` + +- 当前 Mapper SQL 仍是 `where 1 = 0` 的占位实现。 +- 该规则当前版本不会返回任何对象结果。 + +### 10. `INCOME_ASSET_MISMATCH` + +- 当前 Mapper SQL 仍是 `where 1 = 0` 的占位实现。 +- 该规则当前版本不会返回任何明细结果。 + +### 11. `SALARY_UNUSED` + +- 项目 `50` 共有两笔工资入账样本: + - `2026-02-10 09:00:00`,证件号 `320101198908317982`,金额 `9800` + - `2026-03-14 09:00:00`,证件号 `499172200511062290`,金额 `12000` +- 其中第一笔落在家属 `王德华` 证件号上,现行 SQL 从 `ccdi_base_staff` 内连接开始,只统计员工本人,因此这笔在连接层被排除。 +- 员工本人这笔 `2026-03-14 09:00:00` 的工资入账后,`30` 天内存在 `5` 笔非代扣支出,包含: + - `工资到账后快速转出 10800` + - `手机银行转账 12000000` + - `个人购汇 126000` + - `证券大额转托管转出 560000` + - `证券大额交易买入 880000` +- 因此这条规则一部分样本卡在员工连接,另一部分样本卡在“30 天内无非代扣支出”的 `not exists` 条件。 + +### 12. `PROXY_ACCOUNT_OPERATION` + +- 当前 Mapper SQL 仍是 `where 1 = 0` 的占位实现。 +- 该规则当前版本不会返回任何对象结果。 + +## 结论 + +- `project_id=50` 的 `12` 条未命中规则中,有 `6` 条属于当前版本仍未落地的占位 SQL: + - `ABNORMAL_CUSTOMER_TRANSACTION` + - `INTEREST_PAYMENT_BY_OTHERS` + - `CROSS_BORDER_AMT` + - `WITHDRAW_AMT` + - `INCOME_ASSET_MISMATCH` + - `PROXY_ACCOUNT_OPERATION` +- 另外 `6` 条属于真实 SQL 已执行,但项目 `50` 的样本或主数据口径不满足现行实现: + - `MONTHLY_FIXED_INCOME`:月度波动过大,离散系数超标 + - `SPECIAL_AMOUNT_TRANSACTION`:只有 `88888.88`,没有 `520/1314` + - `FIXED_COUNTERPARTY_TRANSFER`:目标样本季度累计超上限,且噪声对手方过多 + - `LOW_INCOME_RELATIVE_LARGE_TRANSACTION`:家属收入都高于低收入阈值 + - `SUSPICIOUS_INCOME_KEYWORD`:摘要词不在现行关键词集合内 + - `SALARY_UNUSED`:家属工资样本被员工连接排除,员工本人工资后 30 天内已有非代扣支出 diff --git a/docs/tests/records/2026-03-22-bank-tag-all-rules-validation-verification.md b/docs/tests/records/2026-03-22-bank-tag-all-rules-validation-verification.md new file mode 100644 index 00000000..defcaa07 --- /dev/null +++ b/docs/tests/records/2026-03-22-bank-tag-all-rules-validation-verification.md @@ -0,0 +1,189 @@ +# 后端全量打标规则验证记录 + +## 验证时间 + +- 2026-03-22 + +## 验证对象 + +- 项目:`project_id=49` +- 后端:`http://localhost:62318` +- Mock:`http://localhost:8000` +- Mock 启动参数:`main.py --rule-hit-mode all` + +## 执行命令 + +```bash +mvn -pl ccdi-project \ + -Dtest=CcdiBankTagServiceImplTest,CcdiBankTagServiceRiskCountRefreshTest,CcdiBankTagAnalysisMapperXmlTest,CcdiBankTagRuleSqlMetadataTest,CcdiModelParamSqlDefaultsTest \ + test + +curl -s http://localhost:62318/login/test \ + -H 'Content-Type: application/json' \ + -d '{"username":"admin","password":"admin123"}' + +curl -s http://localhost:62318/ccdi/file-upload/pull-bank-info \ + -H "Authorization: Bearer " \ + -H 'Content-Type: application/json' \ + -d '{"projectId":49,"idCards":["558455197203132040","523342199111246421","38056420050404632X"],"startDate":"2026-03-01","endDate":"2026-03-22"}' + +curl -s http://localhost:62318/ccdi/project/tags/rebuild \ + -H "Authorization: Bearer " \ + -H 'Content-Type: application/json' \ + -d '{"projectId":49,"modelCode":null}' +``` + +## 自动化结果 + +- Maven 回归结果:`BUILD SUCCESS` +- 用例统计:`Tests run: 29, Failures: 0, Errors: 0, Skipped: 0` +- 说明: + - 当前规则元数据、服务分发、XML 结构与风险人数刷新回归未发现失败 + - 测试日志中的异常路径日志属于断言场景,不代表回归失败 + +## 数据库核验 + +### 最新任务 + +- 查询表:`ccdi_bank_tag_task` +- 结果: + - `id=47` + - `project_id=49` + - `trigger_type=MANUAL` + - `status=SUCCESS` + - `hit_count=2340` + - `success_rule_count=33` + - `failed_rule_count=0` + +### 实际命中规则 + +- 查询表:`ccdi_bank_statement_tag_result` +- 项目 `49` 实际命中规则数:`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` + +#### A. 当前仍是占位 SQL 的规则 + +- `ABNORMAL_CUSTOMER_TRANSACTION` +- `INCOME_ASSET_MISMATCH` +- `CROSS_BORDER_AMT` +- `INTEREST_PAYMENT_BY_OTHERS` +- `WITHDRAW_AMT` +- `PROXY_ACCOUNT_OPERATION` + +结论: + +- 这 6 条当前不能判定为“可正确打标”,因为实现仍停留在占位层。 + +#### B. 已有真实 SQL,但本次 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` + +逐条追因: + +- `FREQUENT_CASH_DEPOSIT` + - 项目 `49` 的 `batch_id=45565/69755/70053` 中,分别存在 `2026-03-10` 同日 `6` 笔存现样本,金额均为 `3000000~3500000` 元,证件号为员工本人。 + - `taskId=47` 日志显示运行时阈值为 `{LARGE_CASH_DEPOSIT=5000, FREQUENT_CASH_DEPOSIT=2}`,但仍记录为“规则无命中”。 + - 当前按源码 SQL 直接复核,这批数据已经足以查出 `3` 个对象,因此这条不是“项目数据不满足”,而是 `2026-03-22 09:11` 验证时复用的旧后端进程与当前 Mapper XML 不一致,属于验证环境版本不一致造成的假阴性。 +- `LOW_INCOME_RELATIVE_LARGE_TRANSACTION` + - Mock 样本确实写入了两笔亲属转入,单个关系人累计交易额为 `120000` 元。 + - 但对应关系人的 `annual_income` 实际为 `64000~128000` 元,折算月收入均高于 `3000` 元。 + - 该规则卡在“低收入关系人”前置条件,不是金额不足,而是家庭关系表里的收入数据不满足 SQL 口径。 +- `SPECIAL_AMOUNT_TRANSACTION` + - Mock 样本金额固定为 `88888.88` 元,对手方为“兰溪特别金额结算中心”。 + - SQL 只识别 `520`、`1314` 两类特殊金额。 + - 这条未命中的直接原因是样本金额语义与真实 SQL 的金额枚举不一致。 +- `MONTHLY_FIXED_INCOME` + - Mock 只为每个对象生成了 `2025-12`、`2026-01`、`2026-02`、`2026-03` 共 `4` 个月、每月 `7200` 元的稳定转入。 + - SQL 要求近 `12` 个月内至少 `6` 个月月收入超过阈值,且波动系数不高于 `0.3`。 + - 本次样本满足金额稳定,但月数只有 `4`,被 `COUNT(DISTINCT incomeMonth) >= 6` 这一层拦截。 +- `FIXED_COUNTERPARTY_TRANSFER` + - “季度稳定兼职收入”样本都落在 `secondary` 身份,也就是家属证件号;项目 `49` 复核可见这些证件号均为 `NON_STAFF`。 + - SQL 从 `ccdi_base_staff` 开始内连接,只统计员工本人近 `12` 个月的固定对手方转入。 + - 这条未命中的直接原因是样本主体落在家属号,进入 SQL 第一层 `inner join ccdi_base_staff` 时就被过滤掉了。 +- `SUSPICIOUS_INCOME_KEYWORD` + - Mock 样本摘要为“咨询返现收入”,对手方为“灰度信息咨询有限公司”。 + - SQL 关键词仅覆盖“工资、分红、红利、奖金、劳务费、批量代付”等收入表达,不包含“返现”“咨询”。 + - 这条未命中的直接原因是摘要关键词与真实 SQL 的关键词集合不一致。 +- `WITHDRAW_CNT` + - 当前按源码 SQL 直接复核,项目 `49` 已能查出 `3` 个对象在 `2026-03-12` 单日提现次数超过阈值 `3` 次,其中计数分别为 `4`、`4`、`5`。 + - 但 `taskId=47` 日志在同一阈值 `{WITHDRAW_CNT=3}` 下仍记录为“规则无命中”。 + - 结合 `taskId=47` 发生在 `2026-03-22 09:11:57`、当前后端进程启动于 `2026-03-22 12:11:28` 这一事实,可以判定这条与 `FREQUENT_CASH_DEPOSIT` 一样,属于验证时后端运行版本未刷新导致的假阴性,而不是数据本身不满足。 +- `SALARY_UNUSED` + - `2026-02-10` 那组“工资入账 + 代扣公积金”样本全部落在家属证件号,SQL 的 `inner join ccdi_base_staff` 会直接排除。 + - 员工本人侧仅保留了 `2026-03-14` 的工资入账样本,但这些样本正是 `SALARY_QUICK_TRANSFER` 的基础数据,工资到账后 `30` 天内均已有 `2~5` 笔非代扣支出。 + - 因此这条是“双重不满足”:专用样本被员工主表连接挡掉,员工本人样本又被 `not exists` 的“30 天内无支出”条件挡掉。 + +结论: + +- 这 8 条里,`LOW_INCOME_RELATIVE_LARGE_TRANSACTION`、`SPECIAL_AMOUNT_TRANSACTION`、`MONTHLY_FIXED_INCOME`、`FIXED_COUNTERPARTY_TRANSFER`、`SUSPICIOUS_INCOME_KEYWORD`、`SALARY_UNUSED` 属于“样本/主数据口径与 SQL 条件不一致”。 +- `FREQUENT_CASH_DEPOSIT`、`WITHDRAW_CNT` 不属于数据不满足,而是 `2026-03-22` 那次验证复用了旧后端进程,导致运行时 SQL 与当前源码不一致。 + +### Mock all 模式边界 + +- Mock all 模式当前直接覆盖 26 条规则,不包含: + - `ABNORMAL_CUSTOMER_TRANSACTION` + - `INCOME_ASSET_MISMATCH` + - `CROSS_BORDER_AMT` + - `INTEREST_PAYMENT_BY_OTHERS` + - `LARGE_PURCHASE_TRANSACTION` + - `WITHDRAW_AMT` + - `PROXY_ACCOUNT_OPERATION` +- 其中 `LARGE_PURCHASE_TRANSACTION` 通过采购基线事实命中,已在本次结果中验证到 + +## 接口回查 + +- 回查接口:`GET /ccdi/project/bank-statement/detail/70334` +- 返回: + - `code=200` + - `data.hitTags` 非空 + - 命中标签包含 `LARGE_TRANSFER` + +样例摘要: + +- `bank_statement_id=70334` +- `rule_code=LARGE_TRANSFER` +- `reason_detail=大额转账支出 12000000.00 元,超过阈值 5000 元` + +## 最终结论 + +- 本次验证证明: + - 后端当前 33 条规则都已经进入执行链路,最新任务 `success_rule_count=33` + - 在项目 `49` 的真实联调链路下,只有 19 条规则产生了实际标签结果 +- 因此截至 2026-03-22,结论应为: + - 后端打标方法“不是全部规则都已验证可正确打标” + - 当前状态更准确地说是“部分规则已验证通过,部分规则未命中,另有 6 条规则仍为占位实现” + +## 环境说明 + +- 本次验证复用了已经运行中的本地后端与 Mock 服务 +- 未额外启动新的前后端进程,因此本次无新增进程需要清理