# lsfx-mock all 模式 SQL 对齐强命中实施记录

## 1. 背景

本次实施基于设计文档 [`2026-03-25-lsfx-mock-all-hit-sql-alignment-design.md`](/Users/wkc/Desktop/ccdi/ccdi/docs/design/2026-03-25-lsfx-mock-all-hit-sql-alignment-design.md)，目标是在不修改主工程打标逻辑的前提下，仅通过调整 `lsfx-mock-server` 的 `--rule-hit-mode all` 生成策略，使以下 5 条已落地真实 SQL 的规则稳定命中：

- `SPECIAL_AMOUNT_TRANSACTION`
- `MONTHLY_FIXED_INCOME`
- `SUSPICIOUS_INCOME_KEYWORD`
- `FIXED_COUNTERPARTY_TRANSFER`
- `LOW_INCOME_RELATIVE_LARGE_TRANSACTION`

## 2. 实际修改

### 2.1 规则样本对齐

修改文件：

- [statement_rule_samples.py](/Users/wkc/Desktop/ccdi/ccdi/lsfx-mock-server/services/statement_rule_samples.py)

调整内容：

- `SPECIAL_AMOUNT_TRANSACTION`
  - 将样本金额从 `88888.88` 调整为 `1314.0`
- `MONTHLY_FIXED_INCOME`
  - 将稳定收入月份从 4 个月扩展到 6 个月
- `SUSPICIOUS_INCOME_KEYWORD`
  - 将摘要改为 `劳务费发放`
  - 将交易类型改为 `劳务费入账`
- `FIXED_COUNTERPARTY_TRANSFER`
  - 将样本主体从家属证件号切换为员工本人证件号

### 2.2 低收入亲属基线补齐

修改文件：

- [phase2_baseline_service.py](/Users/wkc/Desktop/ccdi/ccdi/lsfx-mock-server/services/phase2_baseline_service.py)
- [file_service.py](/Users/wkc/Desktop/ccdi/ccdi/lsfx-mock-server/services/file_service.py)

调整内容：

- 为 `LOW_INCOME_RELATIVE_LARGE_TRANSACTION` 新增关系表基线 SQL 生成逻辑
- 基线通过 `INSERT ... ON DUPLICATE KEY UPDATE` 将目标家属 `annual_income` 收敛到 `0.00`
- 在 `all` 模式下，`FileService` 会将该规则追加到 baseline 服务执行列表
- `subset` 模式保持原有行为不变

### 2.3 all 模式噪声收敛

修改文件：

- [statement_service.py](/Users/wkc/Desktop/ccdi/ccdi/lsfx-mock-server/services/statement_service.py)

调整内容：

- 在 `all` 模式且存在真实 `FileRecord` 时，将补齐总数的噪声流水改为“低额支出型安全噪声”
- 安全噪声特征：
  - 仅生成支出流水
  - 金额范围缩窄到 `10 ~ 200`
  - 使用唯一化商户名和通用消费摘要
- 目的：
  - 避免额外收入干扰 `MONTHLY_FIXED_INCOME`
  - 避免随机稳定对手干扰 `FIXED_COUNTERPARTY_TRANSFER`

## 3. 测试补充

修改文件：

- [test_file_service.py](/Users/wkc/Desktop/ccdi/ccdi/lsfx-mock-server/tests/test_file_service.py)
- [test_statement_service.py](/Users/wkc/Desktop/ccdi/ccdi/lsfx-mock-server/tests/test_statement_service.py)
- [test_phase2_baseline_service.py](/Users/wkc/Desktop/ccdi/ccdi/lsfx-mock-server/tests/test_phase2_baseline_service.py)
- [test_full_workflow.py](/Users/wkc/Desktop/ccdi/ccdi/lsfx-mock-server/tests/integration/test_full_workflow.py)

新增验证点：

- all 模式保留目标规则，不引入占位 SQL 规则
- 特殊金额样本仅使用 `520/1314`
- 月度固定收入覆盖至少 6 个月
- 收入关键词样本直接命中 SQL 关键词集
- 固定对手转入主体为员工本人
- 低收入亲属规则会生成并执行关系表基线 SQL
- all 模式下噪声收敛为安全支出噪声
- 接口链路能返回 5 条目标规则对应的关键样本

## 4. 二次修正

### 4.1 发现的问题

在真实后端联调时，前 4 条规则已经命中，但 `MONTHLY_FIXED_INCOME` 仍未命中。

排查结论：

- 问题不在 SQL，也不在 `7200 > 5000` 阈值
- 根因是 `all` 模式下每个 `logId` 都复制整套规则样本
- 同一员工文件内同时混入了：
  - `FIXED_COUNTERPARTY_TRANSFER` 的季度转入
  - `SUSPICIOUS_INCOME_KEYWORD` 的大额收入
  - 多条大额交易/现金存款/结汇类正向入账样本
- 这些样本都会被 `MONTHLY_FIXED_INCOME` 的 SQL 汇总到员工月收入中，导致月数和波动率口径被污染

### 4.2 修正方案

修改文件：

- [file_service.py](/Users/wkc/Desktop/ccdi/ccdi/lsfx-mock-server/services/file_service.py)
- [test_file_service.py](/Users/wkc/Desktop/ccdi/ccdi/lsfx-mock-server/tests/test_file_service.py)
- [test_statement_service.py](/Users/wkc/Desktop/ccdi/ccdi/lsfx-mock-server/tests/test_statement_service.py)

调整内容：

- 新增项目内 `all` 模式规则重平衡逻辑
- 当同一项目只有 1 个文件时，保留原始 all 模式规则计划，不额外覆盖
- 当同一项目存在 2 个及以上文件时：
  - 第 1 个文件切换为 `MONTHLY_FIXED_INCOME` 隔离档
  - 从隔离档中剔除会污染非工资月流入聚合的正向入账规则：
    - `SINGLE_LARGE_INCOME`
    - `CUMULATIVE_INCOME`
    - `ANNUAL_TURNOVER`
    - `LARGE_CASH_DEPOSIT`
    - `FREQUENT_CASH_DEPOSIT`
    - `SUSPICIOUS_INCOME_KEYWORD`
    - `FOREX_SELL_AMT`
    - `FIXED_COUNTERPARTY_TRANSFER`
  - 其余文件继续承载完整 all 模式规则计划
- 新增两条红绿测试：
  - all 模式多文件下必须出现“月固定收入隔离档”
  - 隔离档生成的员工非工资月收入必须稳定为 6 个月 `7200.0`

## 5. 验证命令

执行命令：

```bash
cd lsfx-mock-server
python3 -m pytest tests/test_file_service.py tests/test_statement_service.py tests/test_phase2_baseline_service.py tests/integration/test_full_workflow.py -v
```

验证结果：

- `51 passed`
- `0 failed`

## 6. 真实链路复验

复验环境：

- 后端：`http://localhost:62318`
- Mock：`python3 main.py --rule-hit-mode all`
- 复验项目：`project_id = 54`

复验步骤：

1. 调用 `/ccdi/project` 新建项目 `all命中复验-20260325-102625`
2. 调用 `/ccdi/file-upload/pull-bank-info` 拉取 3 个身份证号的流水
3. 等待 `ccdi_file_upload_record` 全部进入 `parsed_success`
4. 确认 `ccdi_bank_tag_task` 最新任务状态为 `SUCCESS`
5. 查询 `ccdi_bank_statement_tag_result` 核验 5 条目标规则

复验结果：

- `SPECIAL_AMOUNT_TRANSACTION`：`3` 条
- `MONTHLY_FIXED_INCOME`：`1` 条
- `SUSPICIOUS_INCOME_KEYWORD`：`2` 条
- `FIXED_COUNTERPARTY_TRANSFER`：`2` 条
- `LOW_INCOME_RELATIVE_LARGE_TRANSACTION`：`3` 条

关键命中样例：

- `MONTHLY_FIXED_INCOME`
  - `近12个月有 6 个月固定收入超过阈值，月均收入 7200.00 元`
- `SPECIAL_AMOUNT_TRANSACTION`
  - `与非配偶/子女交易出现特殊金额 1314.00 元`
- `SUSPICIOUS_INCOME_KEYWORD`
  - `摘要命中收入关键词，摘要“劳务费发放”`
- `FIXED_COUNTERPARTY_TRANSFER`
  - `固定对手“兰溪零工服务有限公司”在 4 个季度累计转入位于区间 [3000, 15000] 元`
- `LOW_INCOME_RELATIVE_LARGE_TRANSACTION`
  - `低收入关系人累计交易 ... 元，命中关系人数 1 人`

结论：

- 这 5 条目标规则在真实后端链路中均已命中
- `MONTHLY_FIXED_INCOME` 的遗漏问题已通过 all 模式多文件重平衡修复

## 7. 前端影响

本次未修改 `ruoyi-ui`。

结论：

- 接口结构未变化
- 本轮实现仅影响 Mock 样本和关联表基线
- 前端无需适配代码

## 8. 未完成项

本次范围内无新增未完成项。
