9.5 KiB
9.5 KiB
兰溪流水 Mock 第二期稳定随机命中设计
1. 背景
当前仓库已经具备两条基础能力:
lsfx-mock-server已支持按logId稳定随机命中第一期规则子集,并通过 Mock 流水为主工程提供可重复联调输入。- 主工程第二期真实规则已在
docs/plans/backend/2026-03-20-bank-tag-real-rule-phase2-backend-implementation.md中明确范围,但lsfx-mock-server尚未补齐第二期命中输入与配套基线。
本次目标不是重写主工程打标逻辑,而是在保留第一期稳定随机命中方案的前提下,为第二期补齐可联调、可重复、可命中真实 SQL 的输入数据。
2. 目标
- 保留现有第一期
logId -> 稳定随机规则子集行为不变。 - 为第二期规则新增稳定随机命中计划。
- 让“拉取本行信息 / 获取流水列表 -> 入库到本地 -> 执行重打标”后,最终标签结果中可以查到抽中的第二期规则命中。
- 对依赖采购、资产等外部事实表的规则,补最小且幂等的本地数据库基线。
3. 非目标
- 不新增主工程打标补丁逻辑。
- 不把采购类、资产类规则伪造成纯银行流水规则。
- 不引入“指定特殊
logId固定命中全部第二期规则”的双轨模式。 - 不扩展第二期范围外的新规则。
4. 方案对比
4.1 方案 A:稳定随机命中 + 第二期基线编排
保留现有 FileService -> StatementService -> 缓存分页 主链路;对可由银行流水驱动的第二期规则继续通过 Mock 流水样本触发;对依赖采购、资产等外部事实表的规则,通过本地数据库最小基线补齐真实 SQL 输入。
优点:
- 与主工程真实 SQL 数据来源一致。
- 能同时覆盖“Mock 取数正确”和“真实规则可命中”。
- 保持现有第一期链路结构不变,扩展成本最低。
缺点:
- 需要同时维护流水样本和数据库基线两类输入。
4.2 方案 B:只改 Mock 流水
只扩充 lsfx-mock-server 返回的流水数据,不补采购、资产等业务表。
缺点:
- 第二期中存在真实依赖
ccdi_purchase_transaction、ccdi_asset_info的规则,最终会出现 Mock 看似有数据、真实 SQL 仍然无法命中的偏差。
4.3 方案 C:只补数据库基线
Mock 仅返回普通流水,把第二期命中主要交给数据库灌数。
缺点:
- 无法证明“兰溪本地接口获取流水列表并入库”的链路本身正确。
- 偏离本次验收口径。
5. 推荐方案
采用方案 A。
原因:
- 第二期联调必须同时证明两件事:Mock 取数入库链路没问题,真实 SQL 也确实能命中。
- 采购类和资产类规则本来就不是纯流水规则,直接补最小事实基线才符合真实业务口径。
- 继续使用“同一
logId稳定随机命中一部分规则”可以复用现有测试与排障习惯。
6. 模块边界与数据流
6.1 FileService
继续负责生成并持久化规则命中计划。
在现有字段基础上新增两组规则计划:
phase2_statement_hit_rulesphase2_baseline_hit_rules
职责边界:
- 只负责决定“这个
logId抽中了哪些第二期规则”。 - 不直接构造流水明细,也不直接写数据库业务基线。
6.2 StatementService 与 statement_rule_samples.py
继续负责把命中计划转成最小流水样本,并与噪声流水合并后返回。
职责边界:
- 只生成能通过
ccdi_bank_statement真实入库后触发的第二期样本。 - 不为采购、资产等外部事实规则伪造流水替代。
6.3 第二期基线服务
在 lsfx-mock-server/services/ 下新增一个轻量服务,负责根据 phase2_baseline_hit_rules 幂等写入本地 MySQL 最小事实数据。
职责边界:
- 只补真实 SQL 所需输入。
- 不直接写标签结果表,不参与打标逻辑计算。
6.4 主工程
主工程 CcdiFileUploadServiceImpl -> CcdiBankStatement -> CcdiBankTagServiceImpl 链路保持不变。
验收以真实链路为准:
- 拉取本行信息或通过兰溪接口获取流水。
- 流水成功入库到
ccdi_bank_statement。 - 执行项目重打标。
- 在
ccdi_bank_statement_tag_result或结果接口中看到抽中的第二期规则命中。
7. 第二期规则分层
7.1 流水样本直接驱动
以下规则以 ccdi_bank_statement 为核心输入,使用 Mock 流水样本驱动:
LOW_INCOME_RELATIVE_LARGE_TRANSACTIONMULTI_PARTY_GAMBLING_TRANSFERMONTHLY_FIXED_INCOMEFIXED_COUNTERPARTY_TRANSFERSALARY_QUICK_TRANSFERSALARY_UNUSED
要求:
- 样本必须落在同一个真实员工域或其亲属域上。
- 时间窗口、金额区间、对手方稳定性等聚合条件必须在同一对象范围内闭环。
- 互斥规则不得使用同一员工样本组。
7.2 数据库基线驱动
以下规则需要外部事实表配合:
HOUSE_REGISTRATION_MISMATCHPROPERTY_FEE_REGISTRATION_MISMATCHTAX_ASSET_REGISTRATION_MISMATCHSUPPLIER_CONCENTRATION
处理方式:
- 三条资产不匹配规则:
- Mock 生成对应交易流水。
- 基线服务在
ccdi_asset_info中补“故意缺失或不匹配”的最小资产事实。
SUPPLIER_CONCENTRATION:- 直接补
ccdi_purchase_transaction聚合命中基线。 - 不伪造银行流水替代。
- 直接补
8. 第二期样本设计
8.1 LOW_INCOME_RELATIVE_LARGE_TRANSACTION
- 选择一个真实员工及其亲属身份证范围。
- 亲属收入基线维持低收入事实。
- 生成大额累计转入或转出流水,确保超过低收入亲属的大额交易阈值。
8.2 MULTI_PARTY_GAMBLING_TRANSFER
- 同一员工对象、同一天、多名不同对手方。
- 每笔金额落在
MULTI_PARTY_AMT_MIN ~ MULTI_PARTY_AMT_MAX区间。 - 命中依赖“多人 + 多次 + 同日 + 区间金额”,不依赖敏感词。
8.3 MONTHLY_FIXED_INCOME
- 为同一员工构造连续 3 至 4 个月的固定收入转入。
- 排除工资代发主体和工资关键词。
- 每月金额稳定高于
MONTHLY_FIXED_INCOME。
8.4 FIXED_COUNTERPARTY_TRANSFER
- 为同一员工与固定对手方构造季度稳定转入。
- 每季累计金额落在
FIXED_COUNTERPARTY_TRANSFER_MIN ~ FIXED_COUNTERPARTY_TRANSFER_MAX区间。
8.5 SALARY_QUICK_TRANSFER
- 先生成可识别工资入账。
- 再在 24 小时内生成大额转出,满足比例条件。
8.6 SALARY_UNUSED
- 先生成工资入账。
- 后续 30 天不生成可计入“工资使用”的消费或转账支出。
- 与
SALARY_QUICK_TRANSFER不共用同一员工对象。
8.7 资产不匹配三条规则
HOUSE_REGISTRATION_MISMATCH:生成购房交易流水,但不提供可匹配房产登记。PROPERTY_FEE_REGISTRATION_MISMATCH:生成物业缴费流水,但不提供对应房产登记。TAX_ASSET_REGISTRATION_MISMATCH:生成大额纳税流水,但不提供与税费相符的资产登记。
8.8 SUPPLIER_CONCENTRATION
- 为同一申请人写入多笔采购记录。
- 使单一供应商采购额占比显著超过 70%。
- 使用固定业务主键和稳定供应商集合,确保可重复验证。
9. 实现落点
- Modify:
lsfx-mock-server/services/file_service.py - Modify:
lsfx-mock-server/services/statement_service.py - Modify:
lsfx-mock-server/services/statement_rule_samples.py - Add:
lsfx-mock-server/services/phase2_baseline_service.py - Add/Modify:
lsfx-mock-server/tests/test_file_service.py - Add/Modify:
lsfx-mock-server/tests/test_statement_service.py - Add/Modify:
lsfx-mock-server/tests/integration/test_full_workflow.py - Add:
sql/migration/2026-03-20-lsfx-mock-phase2-hit-baseline.sql
10. 幂等策略
- 规则命中计划继续由
logId决定,不新增第二随机源。 - 流水样本继续由
StatementService缓存,同一logId重复分页读取结果一致。 - 采购基线使用固定业务主键,按固定主键删后重建。
- 资产基线使用固定特征组合,确保可精确清理与重建。
- 所有基线写入都必须只作用于本次选中的员工域,避免污染无关人员。
11. 验证设计
11.1 Mock 单元测试
- 第二期规则池抽样稳定性。
- 第二期流水样本只装配被抽中的规则。
- 第二期数据库基线写入的幂等性。
11.2 Mock 集成测试
getJZFileOrZjrcuFile -> getBSByLogId同一logId下结果稳定。- 抽中第二期规则时,流水样本与基线写入同步成立。
11.3 主工程端到端验证
- 拉取本行信息后流水成功入库。
- 执行项目重打标后,第二期目标规则出现在结果中。
- 明细型规则可通过流水详情接口回查。
- 对象型规则可在标签结果表中看到正确
objectType/objectKey/reasonDetail。
12. 风险与边界
- 不为了联调成功去修改主工程真实 SQL。
- 不把
SUPPLIER_CONCENTRATION伪造成纯流水命中。 - 不引入兜底、补丁或兼容性双轨逻辑。
- 若第二期真实 SQL 与现有基线字段口径不一致,按验证失败暴露,不在 Mock 侧偷偷修正业务规则。
13. 结论
本方案采用“保留第一期稳定随机命中方案 + 为第二期补齐稳定随机命中计划、最小流水样本和幂等数据库基线”的最短路径实现。
这样可以同时保证:
- 兰溪本地接口能够正确返回并入库存量流水;
- 第二期新增模型所需输入事实完整;
- 主工程重打标后能够命中新增模型的真实规则结果。