B-43: 双边流水归并与规范事件层——迁移5、匹配引擎、个人过账映射与事件API
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
# 005 规范转账事件与双边归并技术决策
|
||||
|
||||
对应 Issue:B-43/B-83/B-114(`docs/issues/006-p1-canonical-transfer-matching.md`)。
|
||||
|
||||
## 分层模型
|
||||
|
||||
- 银行源行是不可变观察;匹配层从不修改 `source_rows`。
|
||||
- 新增“不可变决定日志 + 可重建当前投影”的规范事件层:
|
||||
- `transfer_match_decisions` 等证据表只增不改(UPDATE/DELETE 被触发器拒绝)。
|
||||
- `current_transfer_decisions` 与 `transfer_observation_claims` 是可更新、可重建的
|
||||
当前投影,`source_row_id` 主键保证一条观察不可能同时属于两个当前事件。
|
||||
- B-44 余额计算只读 `eligible_intercompany_events` 视图,只含
|
||||
`active + current + classification='intercompany'`;单边内部、待审、同公司调拨、
|
||||
外部事件全部排除。
|
||||
|
||||
## 已确认业务口径(B-114)
|
||||
|
||||
1. 单边流水即使双方公司都能由批准账号唯一确认,也先进入未决金额,不进入 B-44
|
||||
已确认往来余额;只有完成双边归并(`intercompany` + `paired`)或管理员按证据确认
|
||||
(`intercompany` + locked 单边)后才可计算。
|
||||
2. 跨日事件经济日期取付款方 outgoing 银行入账时间,与导入顺序无关。
|
||||
3. 自动窗口 v1:非空参考号相同且账号镜像 <= 3 自然日(M1);无参考号精确账号镜像
|
||||
<= 1 自然日(M2);别名/个人映射镜像 <= 1 自然日且参考号或摘要相等(M3)。
|
||||
超窗或同层多候选全部进入人工审核,禁止按行号、导入顺序或名字破平局。
|
||||
4. 个人过账映射绑定具体账号、生效区间、允许方向和代表公司,必须管理员批准;
|
||||
姓名只作辅助证据,不能单独定案。
|
||||
|
||||
## 参与方解析
|
||||
|
||||
- 本方:源行 `own_account` 精确命中生效期内已批准账户(`own_exact`);缺失时才用
|
||||
上传时持久化的批准上传账户(`upload_account`),且必须与批次公司一致。冲突进入
|
||||
审核,不以 `company_id` 或户名反推。
|
||||
- 对方:严格按账号层解析——精确账号 -> 已审核账号别名 -> 已批准且在窗口内、方向
|
||||
允许的个人过账映射;每层唯一最佳结果才继续。户名/户名别名只用于一致性/冲突证据,
|
||||
冲突降级到审核。
|
||||
- 方向:`expense > 0 且 income = 0` 为 outgoing;`income > 0 且 expense = 0` 为
|
||||
incoming;双正/双零/负数/缺币种进入 `unresolved`。金额用 `Decimal` 精确相等,
|
||||
不设手续费容差。
|
||||
|
||||
## 匹配与状态机
|
||||
|
||||
- 候选硬门槛:双方工作表 confirmed、方向相反、金额与币种相等、公司端点互为反向。
|
||||
- M1/M2/M3 唯一候选自动 paired;R1(端点可确认但镜像/参考号证据不足)与 R2(同层
|
||||
多候选)进入 `needs_review`;待审行不能被其他自动匹配抢占。
|
||||
- 状态:`unresolved -> internal_single -> matched`、`needs_review -> matched |
|
||||
same_company_transfer | external`;单边确认两端同公司立即为同公司调拨。
|
||||
- 幂等:rule_version + 当前观察集合 + 证据未变时零写入;locked 人工决定自动重跑
|
||||
跳过;纠错只能通过 `reverse`(`mode='reversal'` 新记录)+ 原因,之后允许重跑。
|
||||
|
||||
## 事务、并发与回滚
|
||||
|
||||
- “确认工作表 + 为新增确认行建立/更新事件 + audit”在同一个服务事务,任一失败整体
|
||||
回滚,不存在 confirmed 但未匹配的半成品。
|
||||
- 独立重跑使用 `BEGIN IMMEDIATE`,按 `source_row_id` 升序写,SQLite 30 秒 busy
|
||||
timeout 保留;投影可从只增日志重建(`rebuild_current_projection`)。
|
||||
- migration down 只用于测试/上线前回退;生产产生决定后默认保留 migration 5 与审计
|
||||
数据,不执行破坏性 down。
|
||||
|
||||
## Decimal
|
||||
|
||||
金额全程以规范十进制字符串存储和比较,任何路径都不转 `float`;`100.0` 与 `100.00`
|
||||
视为相等,`100.00` 与 `100.01` 不匹配。
|
||||
Reference in New Issue
Block a user