重构:合并数据库迁移为三个领域文件

This commit is contained in:
yml2213
2026-11-08 20:07:18 +08:00
parent fcf8941972
commit d76e8265f8
23 changed files with 1475 additions and 1436 deletions
@@ -3,7 +3,7 @@ type: 权威架构与实施计划
description: 订单、内部 SKU、履约路由、履约执行、商品、成本与财务的唯一权威口径及重构计划。
tags: [订单, 内部SKU, 履约, 商品, 成本, 财务, 迁移]
status: authoritative
version: 2.2
version: 2.3
updated_at: 2026-11-08
---
@@ -12,7 +12,7 @@ updated_at: 2026-11-08
> 状态:**唯一权威文档**。
> 最后校准:2026-11-08。
> 生产基线:迁移 `146`。
> 开发基线:迁移 `168`(仅本地,尚未部署生产)。
> 开发基线:迁移 `149`(仅本地,尚未部署生产)。
>
> 从本文件生效起,订单、内部 SKU、履约渠道、履约载体、标准商品、成本和财务相关实现,
> 只能以本文件为业务口径。其他旧分析只作为历史资料,不再具备设计或验收效力。
@@ -106,7 +106,7 @@ updated_at: 2026-11-08
- 计算成本。
- 决定标准商品。
`order_items` 只保存订单项与平台商品事实。迁移 `163` 后,重复的履约状态、
`order_items` 只保存订单项与平台商品事实。迁移 `148` 后,重复的履约状态、
渠道、配置关联和商品归一字段已改名为 `legacy_*` 冻结留档;
运行时不得读取或写入这些旧列。订单项履约状态统一从 `v_order_item_current` 或
`fulfillments` 读取。
@@ -332,7 +332,7 @@ finance_journal_* -- 总账凭证,可重建
2026-11-08 生产只读核对结果:
- 生产迁移 `146`,本地开发基线迁移 `168`。
- 生产迁移 `146`,本地开发基线迁移 `149`。
- 启用标准商品 `1127`:`aff:` 30、`tpl:` 903、`tpv:` 46、`man:` 148。
- `man:` 商品中只有 105 个当前主渠道为人工;41 个已走其他主渠道,2 个无主渠道。
- 人工页头部显示 `107`,商品列表显示 `148`,相差的 41 个就是跨渠道旧商品。
@@ -594,26 +594,12 @@ assigned 且 carrier_status=missing 必须进入异常队列
- 变更前备份:`backups/postgres/order_site-pre-unified-20261108.dump`,
SHA-256 `661d7751d76fcd7db80af92e97d1e84245a25c60b0ec76b8d83ca930fcbb5142`。
- 迁移 `154`:建立 `internal_skus`、`sku_channel_routes` 与兼容同步触发器。
- 迁移 `155`:建立 `v_product_current`,并归档可确认失效的旧 `man:` 商品。
- 迁移 `156`:修复 `source_kind` 默认值导致的前缀回填失效。
- 迁移 `157`:保证只有兜底配置的 SKU 不会被误升级成主渠道。
- 迁移 `158`:禁止 `man:` 来源直接冒充人工主渠道;没有 primary route 时显示“未路由”。
- 迁移 `159`:只归档无主路由、无人工配置、无启用映射的孤儿 `man:` 商品。
- 迁移 `160`:商品身份全部补齐,运行硬切到 `sku_channel_routes`,删除旧同步触发器;
`v_product_current` 不再回退 `source_kind`,`v_fulfillment_item_state` 不再读取旧表。
- 迁移 `161`:履约影子同步触发器从旧表迁移到 `sku_channel_routes`。
- 迁移 `162`:删除旧路由只读视图和旧表最后一个触发器。
- 迁移 `163`:履约状态硬切到 `fulfillments`;新增正式状态、配置关联和商品字段;
任务/工单只维护尝试历史;订单项旧状态列改名冻结;建立 `v_order_item_current`。
- 迁移 `164`:履约事件外键改为随正式履约记录级联删除。
- 迁移 `165`:履约事件只阻止 UPDATE,数据库级联删除不再被 append-only 触发器阻断。
- 迁移 `166`:无法解析内部 SKU 时,正式履约行的 `internal_sku` 统一落空字符串,
并进入 `missing_internal_sku` 异常,而不是触发非空约束。
- 迁移 `167`:建立 `v_finance_order_item_scope`,统一销售事实、重建与审计的收入、
退款、商品、渠道和业务日口径;增加销售凭证按日查询索引。
- 迁移 `168`:商品来源 `source_kind` 增加数据库约束;商品筛选、人工 SKU 清单和成本
分支统一读取 `source_kind` / `internal_sku_id`,运行期不再按 `canonical_sku` 前缀判断来源。
- 迁移 `147`:统一内部 SKU、标准商品来源与履约路由;建立 `internal_skus`、
`sku_channel_routes`、`v_product_current` 和商品来源约束,完成旧路由读取面下线。
- 迁移 `148`:履约状态、配置、载体和当前尝试硬切到 `fulfillments`;
任务/工单只维护尝试历史;订单项旧履约列冻结并统一读取 `v_order_item_current`。
- 迁移 `149`:建立 `v_finance_order_item_scope`,统一销售事实、重建与审计的收入、
退款、商品、渠道和业务日口径,并增加销售凭证按日查询索引。
- 商品列表、总览、渠道映射和商品下拉统一读取商品当前渠道。
- 运行期代码停止写入 `product_channel_capabilities`,该表仅保留到兼容期结束。
- 只读审计:`npm run audit:product-routing -- --strict`。
@@ -621,7 +607,7 @@ assigned 且 carrier_status=missing 必须进入异常队列
- 自动/卡券/接单主渠道商品的人工配置均保留为显式 `fallback`,没有被误升为人工主渠道。
- 1 个无主路由、无人工配置、无启用映射的 `man:` 商品已归档,未删除历史引用。
- 旧 `internal_sku_channels` 已冻结:运行时不再读、不再写,也不再有视图或触发器依赖。
- 空库从迁移 `001` 顺序执行到 `168` 已通过;新库不再保留任何旧履约影子同步触发器。
- 空库从迁移 `001` 顺序执行到 `149` 已通过;新库不再保留任何旧履约影子同步触发器。
- 无主路由的活动商品会进入“未路由”,不自动猜测渠道。
当前本地仍需业务处理的数据:
@@ -681,7 +667,7 @@ assigned 且 carrier_status=missing 必须进入异常队列
5. 全部业务读 SQL 切到 `v_order_item_current`,禁止直接读取订单项旧状态列。
6. 状态事件、任务尝试、工单尝试和配置变化触发器统一围绕正式履约表工作。
7. 真实 PostgreSQL 集成测试覆盖状态写入、幂等、事件留痕、当前尝试和配置关联。
8. 本地存量库与空库 `001 → 167` 均完成硬切验证。
8. 新空库 `001 → 149` 与迁移 `145` 备份升级库均完成硬切验证。
验收:
@@ -757,6 +743,8 @@ npm run audit:finance -- --strict
本地已完成:
- 数据库迁移由 `154–168` 重组为 `147–149`:内部 SKU/商品路由、履约执行、
财务派生三段各一个文件;未迁入旧 `dev` 的 `147–153`。
- 删除会直接写已改名订单项列的 `reclassify-post-cutover.ts` 和
`merge-duplicate-products.ts`。
- 删除重复的 `finance:rebuild-cutover` 入口,部署脚本统一调用
@@ -772,10 +760,10 @@ npm run audit:finance -- --strict
生产升级演练(本地临时库):
- 输入:`backups/postgres/order_site-20261106-192520.dump`,备份迁移 `145`;
恢复后执行 `146 → 168`。
恢复后执行 `146 → 149`。
- 数据规模:订单 `456777`、订单项 `456762`、商品 `1572`、正式履约 `456762`。
- 升级和迁移全部成功;恢复时唯一失败的是备份自身依赖顺序导致的函数索引,
在函数恢复后按原定义补建,随后迁移 `163` 正常删除该索引。
在函数恢复后按原定义补建,随后迁移 `148` 正常删除该索引。
- 财务重建前存在旧事实/总账差异;执行一次 `finance:rebuild-derived --execute` 后,
销售范围 `21653` 项、收入 `170241674` 分、退款 `77370` 分、成本 `104881187` 分,
事实与总账完全对平,严格审计 `critical: []`。
@@ -880,7 +868,7 @@ docs/archive/
本地阶段 0–6 已按硬切方案完成,生产仍停留在迁移 `146`。后续顺序固定为:
1. 生产执行前重新生成全量备份,并核对备份迁移号确为 `146`。
2. 在生产依次执行迁移 `147 → 168`,每阶段运行对应严格审计;
2. 在生产依次执行迁移 `147 → 149`,每阶段运行对应严格审计;
无法确定的数据进入未路由或待分类,不做猜测。
3. 执行一次 `finance:rebuild-derived` 的 dry-run,核对 A 级数据守恒后,
再按窗口执行 `--execute --confirm=REBUILD_DERIVED`。
+1 -1
View File
@@ -219,7 +219,7 @@ docker compose ps
docker compose logs -f backend
```
## 财务/成本上线后的初始化(当前开发基线 168)
## 财务/成本上线后的初始化(当前开发基线 149)
代码与迁移只负责建表;**存量订单回填、备用金账户、积分余额、商品目录、人工 SKU 不会自动创建**。
部署成功后按「回填 → 商品初始化 → 财务同步 → 验收」四步走: