重构:统一商品渠道投影并收敛权威文档

This commit is contained in:
yml2213
2026-11-08 19:44:27 +08:00
parent 0a595acfa9
commit 1634502363
67 changed files with 2147 additions and 444 deletions
+37 -182
View File
@@ -1,200 +1,55 @@
# order_site 文档索引
# order_site 文档入口
> 最后补充:2026-11-05,新增《履约系统架构复盘与优化方案》;生产代码基线 `e8b76b3b` / 迁移 `136`,开发分支 `dev_11.5_2` 已推进到迁移 `141`(履约统一状态、追加事件与正式影子模型)。
> 数据基线:生产 dump `backups/postgres/order_site-20261022-092601.dump`(数据 2026-07-10 ~ 2026-10-22);历史全量数字仅作基线,**上线验收以 [财务上线初始化与验收-2026-10-26.md](财务上线初始化与验收-2026-10-26.md) 为准**。
> 本文是 `docs/` 的唯一入口。**整体财务流程看 [财务流程总览-2026-11-01.md](财务流程总览-2026-11-01.md)**;数据模型看 [成本中心与履约模型.md](成本中心与履约模型.md),接口看 [成本中心API契约.md](成本中心API契约.md)。
> 新增文档必须在下表登记状态;过期文档不再直接改写结论,统一移入 `docs/archive/`。
本文件只负责导航,不定义业务口径。
## 一、先记住六条口径
## 唯一权威
### 1. 来源只有三个,不是四个
[统一订单履约与财务模型-权威版](统一订单履约与财务模型-权威版.md)
| sourceKey | 包含的数据通道 | 说明 |
| --- | --- | --- |
| `kuaishou-91` | 91 回调 + 快手 send-code | **同一个来源的两条通道**:91 是订单骨架权威源,快手 send-code 是数据补全源与兜底源;共享店铺键空间与同一套匹配上下文 |
| `pdd` | 拼多多订单同步 | 两段式 `pdd_raw_orders → orders` |
| `douyin-mashida` | 抖音码速达推送 | 抖店订单、DYC 券、H5/兑换页 |
所有订单、内部 SKU、履约渠道、履约状态、商品归一、成本与财务相关开发,必须先阅读该文档。
**不要把 91 与快手 send-code 拆成两个来源、两个适配器或两条业务线。** 产品匹配层的唯一来源键是 `kuaishou-91`(`apps/backend/src/services/product-match/types.ts`),适配器是 `adapters/kuaishou-91.ts`。但订单表与成本映射里存储的 `provider` 仍是 `orders.provider = 91kaquan`;成本中心会把 `91 / open_91 / kuaishou-91` 这些别名归一为 `91kaquan`,映射键必须按落库值建。
## 项目规则
### 2. 一个订单 = 骨架 + 买家凭证 + 一个履约方式
[AGENTS.md](../AGENTS.md)
- 骨架:`orders` + `order_items`
- 买家凭证:快手电子凭证(`kuaishou_industry_vouchers`)或抖音券(`redeem_certificates`)
- 履约方式只有四种:`affiliate_dash` 自动发货、`work_orders` 接单平台、`legacy_platform` 已下线历史平台、`manual` 人工
- **电子凭证只是核销码,不参与履约方式判定**;有核销码的订单仍可能是自动发货/接单平台/人工
- 判定顺序固定:工单 → 自动发货任务 → 历史平台任务 → 其余为人工
- 人工块必须进入人工支出与成本快照,不能静默消失
包含任务读取顺序、数据安全边界、文档维护规则和提交要求。
### 3. 履约方式与成本模型必须分开
## 运维资料
- `fulfillment_channel`(+ `fulfillment_status`)回答“谁执行”;`cost_model` 回答“成本怎么算”
- 自动发货:`affiliate_purchase`
- 接单平台:`work_order_reward`
- 人工:`manual_actual`(逐单实际金额)
- 历史平台:`legacy_cost`(历史未采集则显式标记)
- 电子凭证不建成本项,也不作为成本类型
- 未确认成本时保持 `cost_missing`,不默认 0
### 4. 成本只在一个地方改
- 商品主数据:`product_catalog`
- 渠道 SKU 映射:`channel_product_mappings`
- 成本金额:只在 `cost_versions` 改,按生效日期新增版本
- 订单/工单/人工单只保存 `cost_snapshot_id`,历史成本永不回写
- 自动发货、接单平台、人工客服共用同一个成本解析器;匹配不到成本进入 `cost_missing`,不默认 0
### 5. 人工成本只有一条链路
```text
订单列表/详情「确认履约」→ 扣客服积分/备用金 → 写 cost_snapshots(manual_case)
```
| 名称 | 业务含义 | 当前状态 |
| --- | --- | --- |
| `manual_expenses` | **客服备用金支出明细**:客服从自己的备用金里充值/采购/赔偿,减少客服余额 | 已实施(迁移 100);确认履约的现金支出也写这里 |
| `cost_snapshots` | **人工成本的唯一落点**:`subject_type='manual_case'`,`subject_id=order_item_id`(资金来源写 metadata) | 已实施(迁移 104) |
**没有独立的登记单,也没有审批与报销环节。** `manual_expense_records` / `manual_expense_events` 已随迁移 `104` 归并下线(这两张表在生产 102 上从未创建)。后续做财务系统时,人工成本的钱与账都从这条链路走,不要再另造一张人工支出表。
### 6. 历史人工直接放弃,上线后必须全覆盖
- 历史人工支出找不回来,**直接放弃**:不补录、不做样本校准、不阻塞上线;
- 上线后每一笔人工单必须有处理人、实际金额、备用金支出与成本快照;
- 人工单无成本记录、人工单未扣备用金、金额与备用金流水不一致,均不允许关账。
### 7. 文档状态
| 状态 | 含义 |
| 文档 | 用途 |
| --- | --- |
| 现行 | 与当前代码一致,改动代码时必须同步更新 |
| 方案 | 尚未实施,但作为下一阶段实现依据 |
| 参考 | 外部协议、历史数据或解释性材料,不作为实现依据 |
| 历史 | 只用于追溯,不得作为实现依据;位于 `docs/archive/` |
| [部署启动与数据库重建](部署启动与数据库重建.md) | 本地与生产部署、数据库重建 |
| [数据库备份与恢复](数据库备份与恢复.md) | 备份、恢复、OSS |
| [数据库SQL约束与运维](数据库SQL约束与运维.md) | SQL 护栏与生产观测 |
## 二、财务系统当前进度
## 专项参考
| 模块 | 状态 | 事实 |
| --- | --- | --- |
| 客服备用金台账 | **已实施 P0** | 迁移 `100/101/107`;账户、流水、支出、对账;编号 `FA-<用户名>`;客服只能使用本人账户 |
| 后台用户中文显示名 | **已实施** | `admin_users.display_name`,备用金姓名触发器同步;审计、登录记录、任务处理人优先显示中文名 |
| 商品主数据 + 渠道 SKU 映射 | **已实施 P0/P1** | 2,017 个标准商品、4,897 条映射:`tpl:` 710、`man:` 1,195、`aff:` 49、`wo:` 63;订单项已按履约证据/人工内部 SKU 归一 |
| 成本中心 | **已实施 P0** | 迁移 `103`;710 个规则级版本 + 2 个全局占位版本;工单成本快照 151,939 条,其中 actual 129,430、estimated 22,509 |
| 销售事实 / 订单毛利 | **已实施 P0** | 迁移 `103`;375,447 项、收入 ¥3,143.61 万、成本 ¥572.95 万、毛利 ¥2,570.66 万;`sales_daily_facts.channel` |
| 人工成本录入(确认履约) | **已实施 P0(2026-10-26 单事务 + 防重复)** | 确认即扣积分/备用金并写 `actual` 快照;钱与成本同事务、订单项级唯一;无登记单/审批/报销 |
| 人工 SKU 配置自动匹配 | **已实施(2026-10-26)** | 保存配置立即回填 + 定时 rematch + 确认时按 SKU 兜底匹配 |
| 人工缺成本监控 | **已实施(2026-10-26)** | `manual_cost_missing`:首次人工配置之后的订单项未确认即入队,确认后自动收口 |
| 履约方式统一 | **已实施 P0** | 迁移 `103`;375,447 项全部回填:接单平台 153,148、人工 115,194、历史平台 53,901、自动发货 53,204 |
| 人工商品归一 | **已实施 P1(本次快照恢复执行)** | 人工 115,194 项已归一为 1,195 个 `man:<内部SKU>` 商品;历史人工支出仍不补录 |
| 影子总账 | **已实施 P0(2026-10-26)** | `finance_accounts/journal_entries/journal_lines/periods`;销售事实按日凭证 + 手工凭证 + 试算平衡;不接管钱包余额 |
| 成本异常归档 | **已实施** | 迁移 `108`;已处理异常超 60 天搬入 `cost_exceptions_archive`,open 行不归档;`COST_EXCEPTION_RETENTION_DAYS` 可调 |
| 平台对账 / 期间关账 | **已实施 P0** | 平台账单 JSON 导入匹配、差异明细、标记解决;关账/反关账;见 `/admin/finance/ledger` |
| 平台退款 API | **部分实施** | 快手行业(91)同意退款已接入;抖音/拼多多暂未接 API,仍手工登记 |
专项参考只解释具体平台、工具或历史问题,不能覆盖唯一权威文档。
> 分支状态(2026-10-27):`dev` 已合并 `dev1023` 与人工成本完整性修复,迁移收敛为 `103`–`105`(103 财务基础、104 财务控制/L1、105 拼单/寄卖客服);已验证 001→105 与 102→105 两条升级路径。**未推送、未部署生产**;生产口径仍以 `main` 为准。上线前按 [财务上线初始化与验收-2026-10-26.md](财务上线初始化与验收-2026-10-26.md) 初始化资金与人工 SKU。
> 财务与履约口径以 [财务与履约口径总纲-2026-10-23.md](财务与履约口径总纲-2026-10-23.md) 为准。
## 三、统一实施顺序
```text
0. 统一履约事实(渠道 + 成本模型正交) 已完成(迁移 113)
1. 商品主数据 + 渠道 SKU 映射 已完成 P0(仅自动发货/接单平台)
2. 成本中心 + 销售事实 已完成 P0
2.5 人工成本链路收敛(确认履约 → 扣积分/备用金 → 写快照) 已完成 P0(迁移 104)
3. 人工商品归一与上线后人工成本全覆盖 已完成代码;生产数据需上线后配置 SKU(历史不补录)
4. 退款冲减与异常队列 已完成手工退款 + 快手平台退款;人工缺成本已入队
5. 影子总账(销售事实 + 手工凭证) 已完成 P0(迁移 108)
6. 平台对账、期间关账 已完成 P0(手工账单导入);平台自动拉单未实施
```
**第 0 步已完成。** 迁移、回填、代码改造与验收结果见 [成本中心与履约模型](成本中心与履约模型.md) §六、§八。下一步只做第 3 步人工商品归一,不要同时改退款或总账。
## 四、当前必须拍板
| # | 问题 | 当前结论 | 影响 |
| --- | --- | --- | --- |
| 1 | 收入金额口径 | ✅ 用户实付(`orders.total_amount`) | 收入基数 |
| 2 | 收入确认时点 | ✅ 先按 `paid_at` 归属销售日;成本在快照生成后回填 | 利润表与预收账款 |
| 3 | 打手报酬 | ✅ 支出/成本,总额法 | 履约成本 |
| 4 | 退款/仲裁 | ✅ 暂不实现,只预留反向凭证 | 后续冲减 |
| 5 | 人工支出如何入账 | ✅ 逐单实际金额;从客服备用金扣款;客服只能用本人账户 | 人工成本与备用金 |
| 6 | 历史人工支出 | ✅ **不补录**,只取少量样本校准 | 上线范围 |
| 7 | 电子凭证是否作为分类 | ✅ **不作为履约/成本分类**,只是核销码状态 | 报表口径 |
| 8 | 平台服务费/支付通道费 | ⏳ 待定 | 费用科目与对账 |
| 9 | 寄卖货款成本确认时点 | ⏳ 待定 | 存货/采购成本 |
| 10 | 是否需要发票/税务、是否多币种 | ⏳ 待定 | 当前按 CNY、无税务实现 |
## 五、现行与参考文档
| 文档 | 状态 | 用途 |
| --- | --- | --- |
| [财务与履约口径总纲-2026-10-23.md](财务与履约口径总纲-2026-10-23.md) | **现行唯一口径** | 履约方式、成本模型、人工全覆盖、历史策略、实施顺序、运营日检与验收 SQL |
| [财务流程总览-2026-11-01.md](财务流程总览-2026-11-01.md) | 现行 | 断代后财务全流程:六条管道、成本快照、事实、总账、退款、异常、运维与测试 |
| [订单全流程与内部SKU架构.md](订单全流程与内部SKU架构.md) | 现行 | 平台入单、中文内部 SKU、渠道判定、四类履约载体、商品归一与财务落账的完整链路 |
| [履约系统架构复盘与优化方案-2026-11-05.md](履约系统架构复盘与优化方案-2026-11-05.md) | 方案 | 履约状态、载体、尝试、异常队列与后台信息架构的分阶段重构方案 |
| [订单服务收集与状态页设计-2026-11-03.md](订单服务收集与状态页设计-2026-11-03.md) | 现行 | 分类级资料配置、发布版本与工单快照、`/o` 客户状态页、自动发布核销和通知预留 |
| [成本中心与履约模型.md](成本中心与履约模型.md) | 现行 | 商品、成本版本、快照、异常、销售事实的数据模型;迁移 `103`–`105`;履约回填;迁移基线与本地库同步;索引与性能 |
| [成本中心API契约.md](成本中心API契约.md) | 现行 | 成本中心接口字段替换总表、枚举、模块边界(后端 5 模块 + 前端 4 个固定 Tab) |
| [人工支出与备用金.md](人工支出与备用金.md) | 现行(P0 已实施) | 确认履约流程/权限、客服备用金台账、本人账户与编号规则 |
| [财务上线初始化与验收-2026-10-26.md](财务上线初始化与验收-2026-10-26.md) | **现行上线手册** | 迁移后资金/人工 SKU 初始化、验收 SQL、日常监控 |
| [财务系统集成方案.md](财务系统集成方案.md) | 现行方案(影子总账 P0 已实施) | 复式记账、总账表、对账、关账;P1/P2 平台自动对账待接 |
| [财务系统深度分析-2026-10-27.md](财务系统深度分析-2026-10-27.md) | 参考(一次性审计,不改变现行口径) | 2026-10-27 代码/数据/权限审计、风险清单与上线前修复路线 |
| [dev合并main评估-2026-10-27.md](dev合并main评估-2026-10-27.md) | 参考(合并评估) | dev 领先 main 的改动、迁移收敛、生产规模升级实测与发布检查清单 |
| [财务代码审计复核-2026-10-27.md](财务代码审计复核-2026-10-27.md) | 参考(代码复核) | 对“旧报表重复扣减、总账 DELETE、钱包 BIGINT、死锁”等结论的逐条校正与补充 |
| [打手重复奖励核对-2026-10-27.md](打手重复奖励核对-2026-10-27.md) | 待人工核对 | 8 组疑似重复奖励、16 条流水、多计 ¥196.20;含 84886 寄卖误报说明 |
| [影子总账说明.md](影子总账说明.md) | 现行说明(P0 已实施) | 影子总账是什么、和钱包流水的区别、对账与转正标准 |
| [项目全量分析报告-2026-10-17.md](项目全量分析报告-2026-10-17.md) | 历史参考 | 2026-10-17 架构与风险;财务口径以总纲为准 |
| [接单模板匹配引擎重构设计.md](接单模板匹配引擎重构设计.md) | 现行(P0/P1 已实施) | `kuaishou-91 / pdd / douyin-mashida` 三来源匹配引擎 |
| [履约配置/多发货平台与电子凭证整体链路.md](履约配置/多发货平台与电子凭证整体链路.md) | 现行 | 进单、履约、领取、电子凭证的整体链路 |
| [affiliate-dash-发货平台/affiliate-dash对接.md](affiliate-dash-发货平台/affiliate-dash对接.md) | 现行 | affiliate-dash 自动履约接口与字段 |
| [履约配置/cloudtentacles发货平台.md](履约配置/cloudtentacles发货平台.md) | 历史参考 | 已下线通道的第三方接口样例,不代表现行实现 |
| [91卡券/6.开发设计.md](91卡券/6.开发设计.md) | 现行 | `kuaishou-91` 来源的 91 侧接入设计 |
| [抖音-码速达/00-总览.md](抖音-码速达/00-总览.md) | 现行 | 抖音码速达接入总览与增量记录 |
| [抖音-码速达/12-按SKU分类改造总设计.md](抖音-码速达/12-按SKU分类改造总设计.md) | 现行 | 抖音三层分流与载体唯一 |
| [部署启动与数据库重建.md](部署启动与数据库重建.md) | 现行 | 本地/生产启动、迁移、重建 |
| [数据库备份与恢复.md](数据库备份与恢复.md) | 现行 | 备份、恢复、OSS |
| [数据库SQL约束与运维.md](数据库SQL约束与运维.md) | 现行 | SQL 护栏与生产观测 |
### SQL 草案(未接入迁移)
草案只作设计与复盘依据;接入 `apps/backend/src/db/migrations/` 时再拆成 `NNN_slug.sql`,并先跑 `npm run check:sql`。
| 文件 | 用途 | 接入前必须处理 |
| --- | --- | --- |
| [drafts/2026-10-17-载体判定与人工块量化.sql](drafts/2026-10-17-载体判定与人工块量化.sql) | 载体分布/人工块量化查询、`carrier_type` 判定与回填 | **已过时**:`carrier_type` 已从商品/成本/快照/异常表删除;只读查询里的口径结论已吸收进总纲 §二 |
| [drafts/2026-10-17-成本中心与销售事实-DDL草案.sql](drafts/2026-10-17-成本中心与销售事实-DDL草案.sql) | `product_catalog`、`channel_product_mappings`、`cost_items/versions/snapshots/exceptions`、`sales_daily_facts` | 已落地为 `103`–`105`;草案里的 `carrier_type` 已被 `cost_model` / 渠道三列取代,仅作设计追溯 |
| [drafts/2026-10-31-112-履约渠道拆分-迁移草案.sql](drafts/2026-10-31-112-履约渠道拆分-迁移草案.sql) | 渠道/状态/来源拆列、`sku_channel_rules`、异常两级化、水位表、卡券成本项 | 已落地为 `apps/backend/src/db/migrations/112_fulfillment_channel_split.sql`;草案保留作设计追溯 |
| [drafts/2026-10-31-同步链路重构-旧函数对照.md](drafts/2026-10-31-同步链路重构-旧函数对照.md) | 16 个旧同步/回填入口 → 6 个新管道作业的对照与验收口径 | 已落地:三条管道服务 + 六个定时任务 + 后台「履约渠道」页 |
| [archive/2026-10-23/2026-10-17-人工支出登记-DDL草案.sql](archive/2026-10-23/2026-10-17-人工支出登记-DDL草案.sql) | `manual_fulfillment_cases`、`manual_expense_records`、`manual_expense_events` | **已作废**:`manual_expense_records` / `manual_expense_events` 已随迁移 `104` 归并下线,人工成本改走「人工录单 → 扣备用金 → 写快照」;文件已移入 archive |
## 六、厂商协议与外部资料
这些目录是平台方文档或抓取资料,**不作为本项目实现说明**:
| 目录 | 内容 |
| 文档或目录 | 用途 |
| --- | --- |
| `91卡券/` | 91 卡券公开接口、签名、加密示例(项目接入结论见 `91卡券/6.开发设计.md`) |
| `行业电子凭证/` | 快手电子凭证接口、售后、测试指南 |
| `发货平台-2/` | 早期发货平台协议,现行为 `affiliate_dash`;保留作历史接口对照 |
| `抖音-码速达/接口API/` | 抖音码速达出网接口 |
| `抖音-码速达/消息推送/` | 抖音码速达推送消息字段与签名 |
| [设备认证-dcauth协议](设备认证-dcauth协议.md) | 设备认证协议 |
| [affiliate-dash-发货平台](affiliate-dash-发货平台/) | affiliate-dash 对接资料 |
| [91卡券](91卡券/) | 91 卡券接口与签名资料 |
| [抖音-码速达](抖音-码速达/) | 抖音码速达接口、消息与接入资料 |
| [行业电子凭证](行业电子凭证/) | 快手行业电子凭证协议 |
| [发货平台-2](发货平台-2/) | 历史发货平台协议 |
| [履约配置](履约配置/) | 专项接入与排障参考 |
| [微博微豆-CK接口与兑换链路确认-2026-11-07](微博微豆-CK接口与兑换链路确认-2026-11-07.md) | 微博微豆接口与兑换链路 |
| [打手重复奖励核对-2026-10-27](打手重复奖励核对-2026-10-27.md) | 历史财务核对记录 |
## 七、历史文档
## 历史归档
| 位置 | 说明 |
| --- | --- |
| [archive/README.md](archive/README.md) | 2026-10-08 及更早的阶段分析、寄卖方案、性能快照、一次性迁移检查脚本;2026-10-17 复核文档 |
| [archive/2026-10-17/载体判定与成本中心落地-复核与草案.md](archive/2026-10-17/载体判定与成本中心落地-复核与草案.md) | 2026-10-17 第二轮复核与数据量化;结论已吸收进现行成本中心文档,仅作历史追溯 |
| [archive/2026-10-23/](archive/2026-10-23/) | 2026-10-23 重写前的四篇:`成本中心与三块履约模型`、`人工支出登记落地方案`、`客服备用金台账实施方案`、`财务履约改造交接总结`;结论已分别并入现行 5 篇文档 |
[archive](archive/) 中的文档均已失效,只用于追溯。
## 八、维护规则
2026-11-08 统一重构前的订单、履约、成本、财务、架构与 SQL 草案已归档到:
1. 改代码影响业务口径时,先改现行文档,再提交代码。
2. 文档头部必须写「状态 + 最后校准日期 + 代码基线」。
3. 旧分析不要在原文件上继续堆结论;新建当期报告,旧文件移入 `docs/archive/<日期>/`。
4. 行号只用于当期基线;跨版本引用优先写文件与函数名。
5. 新增来源时只加一个 `ProductMatchSourceKey` + 一个适配器;**91 + 快手 send-code 永远算一个 `kuaishou-91`**。
6. 成本金额只改 `cost_versions`,不要在多个业务表直接改价;历史订单只读 `cost_snapshots`。
7. 报表维度统一用 `canonical_product_id + shop_id + stat_date`,不要直接用原始 `sku_code` 或 `orders.total_amount`。
8. 新增 SQL 草案放 `docs/drafts/`,命名 `<日期>-<主题>.sql`;**不得**直接放进 `apps/backend/src/db/migrations/`(后端启动会自动迁移),接入时再拆编号并先跑 `npm run check:sql`。
9. 财务系统实现顺序以本索引 §三 为准;单篇文档里的分期若与本索引冲突,以本索引为准。
[archive/2026-11-08](archive/2026-11-08/)
## 维护规则
1. 业务和架构口径只修改唯一权威文档。
2. 不再新增第二份“现行架构”“现行财务口径”或“总纲”。
3. 外部平台协议可以保留,但不得覆盖项目自身模型。
4. 已被替代的内部设计文档移入 `docs/archive/<日期>/`。
5. 文档中的代码与迁移基线必须来自实际仓库和生产只读核对。
+9
View File
@@ -0,0 +1,9 @@
# 2026-11-08 历史文档归档
本目录保存 2026-11-08 统一重构前使用的订单、履约、成本、财务和架构文档。
这些文档只用于追溯当时的设计与数据来源,不再作为现行口径、开发依据或验收标准。
现行唯一权威文档:
[统一订单履约与财务模型-权威版](../../统一订单履约与财务模型-权威版.md)
+14 -4
View File
@@ -1,7 +1,8 @@
# 历史文档归档
> 这里的文档只用于追溯当时的分析过程,**不是现行实现说明**。
> 代码、数据库结构与线上行为以仓库当前 `main` 和 `docs/README.md` 中标记为「现行」的文档为准。
> 代码、数据库结构与线上行为只以
> [统一订单履约与财务模型-权威版](../统一订单履约与财务模型-权威版.md) 为准。
## 2026-10-08
@@ -18,7 +19,7 @@
| 文档 | 归档原因 |
| --- | --- |
| `2026-10-17/载体判定与成本中心落地-复核与草案.md` | 2026-10-17 第二轮复核与数据量化;现行结论已吸收进 `成本中心与三块履约模型.md` 与 `财务系统集成方案.md`,仅保留作数据与 DDL 验证追溯 |
| `2026-10-17/载体判定与成本中心落地-复核与草案.md` | 2026-10-17 第二轮复核与数据量化;仅保留作数据和 DDL 验证追溯 |
## 2026-10-23
@@ -26,9 +27,18 @@
| --- | --- |
| `2026-10-23/2026-10-23-本地库原地改造.sql` | 逐列把 `carrier_type` / `cost_type` 改成 `cost_model` / `fulfillment_mode` 的一次性脚本;迁移收敛为 `103`–`107` 后不再成立,**禁止在新环境执行**,仅作改造矩阵追溯 |
## 2026-11-08
2026-11-08 完成订单、履约、商品、成本和财务口径统一。
此前所有相关业务架构、财务方案、字段契约和 SQL 草案整体归档到:
[2026-11-08](2026-11-08/)
## 使用建议
- 需要当前架构与风险:看 `docs/项目全量分析报告-2026-10-17.md`(参考)和 `docs/README.md`(状态索引)。
- 需要财务系统设计:看 `docs/财务系统集成方案.md`;实施顺序以 `docs/README.md` §三 为准。
- 需要当前架构、数据边界和实施计划:只看
[统一订单履约与财务模型-权威版](../统一订单履约与财务模型-权威版.md)。
- 需要某个平台协议:看对应的厂商文档目录(`91卡券/`、`行业电子凭证/`、`发货平台-2/`、`抖音-码速达/接口API/`、`抖音-码速达/消息推送/`)。
- 历史文档中的代码行号、测试数量、迁移数量不要直接引用。
- 历史文档不得重新标记为“现行”,需要复活时必须并入唯一权威文档。
+1 -1
View File
@@ -266,7 +266,7 @@
### 2)接单模板匹配引擎重构(`10464fea`,P0+P1)
按 [接单模板匹配引擎重构设计.md](../接单模板匹配引擎重构设计.md) 抽出 `services/product-match/`(适配器按**来源**划分:`kuaishou-91` / `pdd` / `douyin-mashida`,其中 `kuaishou-91` 同时覆盖 91 回调与快手 send-code 两条数据通道)。生产回放 6000 条订单项:`kuaishou-91`/PDD 决策 **0 差异**,抖音 5 条全为修正。旧 `work-product-match-mappers.ts` 变为门面,签名不变。
按 [接单模板匹配引擎重构设计.md](../archive/2026-11-08/接单模板匹配引擎重构设计.md) 抽出 `services/product-match/`(适配器按**来源**划分:`kuaishou-91` / `pdd` / `douyin-mashida`,其中 `kuaishou-91` 同时覆盖 91 回调与快手 send-code 两条数据通道)。生产回放 6000 条订单项:`kuaishou-91`/PDD 决策 **0 差异**,抖音 5 条全为修正。旧 `work-product-match-mappers.js` 改为兼容门面,签名不变。
### 3)工单「发布并核销」支持抖音券(本次)
@@ -348,7 +348,7 @@
| 可观测性 | `utils/logger.ts:96/122`、`repositories/task-event-repo.ts:16`、`repositories/admin-notification-repo.ts:25`、`services/realtime/realtime-event-service.ts:92` | 日志 / 任务事件 / 后台待办 + SSE |
| 环境变量白名单(硬约束) | `config/env-documentation.test.ts:57/63`、`.env.server.example`、`.env.mac-docker.example` | 新增 env 必须登记,否则测试红 |
| 隐私红线 | `services/worker-platform/sync-worker-orders-service.ts:206-220` | 打手工单素材不含买家信息 |
| 平台接入设计范本 | `docs/91卡券/6.开发设计.md`(来源建模/配置/签名/代码落点/测试范围)、`docs/履约配置/多发货平台与电子凭证整体链路.md` | 本项目的「新平台接入」方法论 |
| 平台接入设计范本 | `docs/91卡券/6.开发设计.md`(来源建模/配置/签名/代码落点/测试范围)、`docs/archive/2026-11-08/多发货平台与电子凭证整体链路.md` | 本项目的「新平台接入」方法论 |
---
@@ -0,0 +1,760 @@
---
type: 权威架构与实施计划
description: 订单、内部 SKU、履约路由、履约执行、商品、成本与财务的唯一权威口径及重构计划。
tags: [订单, 内部SKU, 履约, 商品, 成本, 财务, 迁移]
status: authoritative
version: 1.0
updated_at: 2026-11-08
---
# 统一订单、履约与财务模型
> 状态:**唯一权威文档**。
> 最后校准:2026-11-08。
> 生产基线:迁移 `146`。
> 开发基线:迁移 `158`(仅本地,尚未部署生产)。
>
> 从本文件生效起,订单、内部 SKU、履约渠道、履约载体、标准商品、成本和财务相关实现,
> 只能以本文件为业务口径。其他旧分析只作为历史资料,不再具备设计或验收效力。
## 一、最终结论
系统按六个业务域拆分:
```text
订单接入
→ 商品身份
→ 履约路由
→ 履约执行
→ 财务核算
→ 运营治理
```
换一种更具体的表达:
```text
平台订单与原始行
→ 中文内部 SKU
→ 主渠道与兜底渠道
→ 当前履约单与执行尝试
→ 标准商品与成本事实
→ 销售事实、总账与报表
```
每一层只能回答一个问题:
| 层 | 唯一问题 | 唯一真源 |
| --- | --- | --- |
| 订单接入 | 平台实际发生了什么 | `orders` / `order_items` / 原始报文 |
| 商品身份 | 业务上这是什么商品 | `internal_skus` |
| 履约路由 | 这个商品默认由谁履约 | `sku_channel_routes` |
| 履约执行 | 当前实际执行到哪一步 | `fulfillments` / `fulfillment_attempts` |
| 财务商品 | 收入与成本归到哪个标准商品 | `product_catalog` / `channel_product_mappings` |
| 财务核算 | 应该记多少钱 | `cost_snapshots` / `sales_daily_facts` / `journal_*` |
任何页面、接口、任务和报表都必须从各自真源读取,不得根据另一层的字段反推。
## 二、不可违反的规则
1. **原始订单事实永不删除。**
`orders`、`order_items`、平台原始报文、平台售后与退款事实、真实工单执行记录、
真实钱包和资金流水、后台审计日志必须保留。
2. **标准商品不表达当前履约渠道。**
`canonical_sku` 前缀、`product_catalog.category` 和商品名称都不能反推当前渠道。
3. **人工配置不等于当前走人工。**
人工配置只表示具备人工执行或人工兜底能力。当前渠道必须来自路由结果。
4. **一个内部 SKU 最多一个主渠道。**
其他启用渠道只能是显式兜底,并记录优先级与用途。
5. **`assigned` 不等于履约完成。**
`assigned` 只允许表示路由已确定;载体是否存在由 `carrier_status` 单独表达。
6. **财务层只读上游。**
成本、事实和总账不得反向修改订单、路由、载体或商品来源。
7. **派生数据必须可重建。**
成本快照、销售事实、总账、异常队列、投影和影子履约模型都必须能够从原始订单、
输入配置和事件重算。
8. **页面与统计使用同一读模型。**
同一个数量,页签、卡片、列表和导出不得各自拼口径。
9. **历史文档不再定义现行规则。**
旧架构、旧财务方案和旧迁移说明只能放入归档目录。
10. **一次只允许一个权威写入口。**
核心状态只允许由对应领域服务修改;其他模块只能调用该服务。
## 三、领域边界
### 3.1 订单接入域
负责:
- 接收 91、快手送码、拼多多、抖音码速达的数据。
- 保存平台订单、订单项、原始报文、支付和售后事实。
- 保证来源重放幂等。
- 将平台商品字段解析为中文内部 SKU。
不负责:
- 选择履约渠道。
- 创建工单或履约任务。
- 计算成本。
- 决定标准商品。
订单项上的 `fulfillment_*`、`canonical_product_id` 等字段在过渡期保留,
但只能由对应领域服务通过兼容投影维护,不允许入单服务自行猜测。
### 3.2 商品身份域
目标真源:
```text
internal_skus
id
internal_sku_key -- NFKC、去空白、小写后的稳定键
display_name -- 运营可读名称
status -- active / disabled / merged
merged_into_id -- 合并目标
```
所有人工配置、渠道路由、订单项快照和渠道规则都必须通过 `internal_sku_id` 关联,
不再长期依赖多张表重复保存同一个中文文本。
平台字段到内部 SKU 的唯一入口:
```text
internal_sku_mappings
provider
shop_id
match_type
match_value
internal_sku_id
priority
enabled
```
匹配顺序固定:
```text
provider + shop 精确
→ provider 精确
→ shop 精确
→ 全局
```
### 3.3 履约路由域
目标真源:
```text
sku_channel_routes
id
internal_sku_id
channel
route_role -- primary / fallback
priority
enabled
carrier_config_json
source
created_by
updated_at
```
渠道枚举:
```text
affiliate_dash
work_order
third_party_voucher
manual
on_account
```
规则:
- `active + primary` 每个内部 SKU 最多一条。
- `fallback` 可以多条,按 `priority` 依次尝试。
- 主渠道失败时才能尝试兜底渠道。
- 运营指定和自动判定必须写差异化 `source`。
- 路由配置不能保存“当前订单结果”;当前结果属于履约域。
### 3.4 履约执行域
当前 `order_items.fulfillment_channel/status` 和 `v_fulfillment_item_state`
属于过渡读模型。目标模型使用:
```text
fulfillments
id
order_item_id
internal_sku_id
route_status -- unrouted / configured / locked
channel
carrier_status -- not_required / missing / creating / ready / failed / terminal
current_attempt_id
issue_code
issue_category
retryable
owner_role
created_at
updated_at
fulfillment_attempts
id
fulfillment_id
attempt_no
attempt_type -- task / work_order / manual
source_id
status
result_code
result_message
is_current
started_at
finished_at
context_json
fulfillment_issues
id
fulfillment_id
issue_code
issue_category
severity
retryable
auto_retryable
owner_role
status -- open / acknowledged / waiting / resolved
detail_json
first_seen_at
last_seen_at
resolved_at
```
状态必须正交:
```text
商业订单状态
≠ 路由状态
≠ 载体状态
≠ 当前尝试状态
≠ 异常状态
≠ 锁定原因
≠ 财务状态
```
同一订单项只能有一个当前尝试。历史尝试只追加,不覆盖。
### 3.5 商品与财务域
标准商品目标结构:
```text
product_catalog
id
canonical_sku
canonical_name
source_kind -- affiliate / work_order / voucher / manual / settlement
internal_sku_id -- 可空;关联业务内部 SKU
category -- 仅展示,不参与路由
unit_name
status
```
`canonical_sku` 前缀只用于兼容识别。运行时和统计必须读取 `source_kind`,
不能再散落 `LIKE 'man:%'` 之类的业务判断。
商品映射:
```text
channel_product_mappings
provider + shop_id + platform_sku
→ product_catalog
```
渠道规则关联的产品只用于说明该渠道执行时对应的财务商品,
不能反向决定路由。
成本与财务:
```text
cost_versions -- 成本规则与价格版本,是输入真源
cost_snapshots -- 单个订单项在某时点的成本事实,可重建
sales_daily_facts -- 收入、退款、成本汇总,可重建
finance_journal_* -- 总账凭证,可重建
```
## 四、单一真源矩阵
| 信息 | 唯一写入方 | 唯一真源 | 明确禁止 |
| --- | --- | --- | --- |
| 平台订单与订单项 | 订单接入服务 | `orders` / `order_items` | 财务或履约服务改写平台事实 |
| 平台原始报文 | 各平台适配器 | 原始表 / `raw_payload_json` | 覆盖历史报文 |
| 中文内部 SKU | 商品身份服务 | `internal_skus` | 各业务表各自发明同义 SKU |
| 平台字段到内部 SKU | 映射服务 | `internal_sku_mappings` | 按名称猜测渠道 |
| 主渠道与兜底 | 路由服务 | `sku_channel_routes` | UI 根据商品前缀筛选 |
| 当前履约状态 | 履约状态服务 | `fulfillments` | 多服务直接更新订单项 |
| 执行尝试 | 履约尝试服务 | `fulfillment_attempts` | 用最大 ID 猜当前任务 |
| 当前异常 | 履约异常服务 | `fulfillment_issues` | 自由 JSON 字符串代替问题模型 |
| 标准商品 | 商品主数据服务 | `product_catalog` | 用商品来源反推渠道 |
| 平台商品到财务商品 | 商品归一服务 | `channel_product_mappings` | 人工在多个页面重复维护 |
| 成本规则 | 成本中心 | `cost_versions` | 业务表直接改金额 |
| 成本事实 | 成本快照服务 | `cost_snapshots` | 改价覆盖历史 |
| 销售事实 | 事实服务 | `sales_daily_facts` | 报表直接从订单表现算另一套 |
| 总账 | 总账服务 | `finance_journal_*` | 业务端直接写凭证 |
| 页面投影 | 只读投影 | `v_*` / materialized view | 页面自行拼口径 |
## 五、当前系统的问题证据
2026-11-08 生产只读核对结果:
- 生产迁移 `146`,本地开发基线迁移 `158`。
- 启用标准商品 `1127`:`aff:` 30、`tpl:` 903、`tpv:` 46、`man:` 148。
- `man:` 商品中只有 105 个当前主渠道为人工;41 个已走其他主渠道,2 个无主渠道。
- 人工页头部显示 `107`,商品列表显示 `148`,相差的 41 个就是跨渠道旧商品。
- 41 个跨渠道 `man:` 商品中:卡券 33、自动发货 3、接单平台 2、统一结算 3。
- 另有 2 个 `man:` 商品无主渠道,但保留人工配置,属于人工兜底。
- 自动发货的 3 个商品中,`man:suit_shadow_gothic` 与 `man:套装-狂沙舞者`
有有效人工兜底配置,必须保持 active,但不能出现在“人工客服”页签。
- 最终可归档对象是 36 个:卡券 33、接单平台 2、无人工兜底的自动发货 1。
- 生产活动履约视图共 31744 行,其中 1226 行仍有结构化异常:
- 用户退款 532;
- 平台取消 126;
- 缺内部 SKU 29;
- 缺渠道 26;
- 人工配置缺失 19;
- 其余为载体重试、人工复核、状态不一致等。
- 当前任务重复为 0,多个活跃工单为 0,说明“当前尝试”约束已经开始生效。
这些问题证明:
1. 旧模型不是完全不可用,但多个真源同时存在。
2. 页面已经出现“总览按渠道、列表按来源”的口径分叉。
3. 历史清理功能曾经存在,但在后续重构中被移除。
4. 文档基线和生产基线不一致,旧文档仍在被当作现行依据。
## 六、数据保留与重建边界
本次重构允许清理派生数据,但必须严格分级。
### A 级:永久保留,不得删除或重写历史
- `orders`
- `order_items` 的原始平台字段
- 平台原始订单表与原始报文字段
- 平台售后、退款、支付事实
- `work_orders`、`work_order_shares`、`work_order_events`
- `fulfillment_tasks` 中真实执行与结果记录
- `worker_wallet_ledgers`、`fund_accounts` 的真实资金流水
- `admin_audit_logs`
- 财务期间、已确认退款和真实资金账户
A 级数据只能追加新事件或做字段兼容迁移,不能为了“模型整齐”重写历史事实。
### B 级:业务输入,必须迁移而不是重建
- `internal_sku_mappings`
- `internal_sku_channels` 中仍有效的路由意图
- `work_product_rules` 及模板匹配配置
- `manual_fulfillment_configs`
- `product_catalog` 中仍有效的标准商品
- `channel_product_mappings`
- `cost_versions`
- 第三方平台配置、店铺配置和账号配置
迁移时必须人工核对冲突,不得自动选最新或按出现次数猜测。
### C 级:可删除并从 A/B 级重建
- `cost_snapshots`
- `cost_exceptions`
- `sales_daily_facts`
- `finance_journal_entries` / `finance_journal_lines`
- `fulfillments` / `fulfillment_attempts` / `fulfillment_issues`
- `v_fulfillment_item_state` 及其依赖投影
- 商品统计投影、渠道统计投影、页面汇总缓存
- 管道水位与失败重试状态
重建前必须备份;重建后必须通过 A/B 级数据守恒检查。
### D 级:兼容期结束后删除
- `product_channel_capabilities`
- `manual_sku_registry` 中可由配置重建的登记行
- 订单项上的重复履约结果字段,在正式模型切换后删除
- 商品表中的历史来源前缀判断代码
- 旧路由补丁脚本和一次性迁移工具
## 七、UI 与 API 统一口径
“标准商品目录”的页签必须表示**当前路由状态**,不是商品来源:
```text
全部
自动发货
接单平台
第三方卡券
人工客服
统一结算
未路由
```
商品来源作为独立列展示:
```text
aff: / tpl: / wo: / tpv: / man:
```
列表必须显示:
```text
商品
来源
当前主渠道
兜底渠道
当前状态
成本状态
```
以下行为禁止:
- “人工客服”页签显示当前主渠道不是 `manual` 的商品。
- 用 `product_catalog.category` 决定路由或页签。
- 用 `man:` 前缀判断当前人工订单量。
- 通过商品名称或标题自动猜测渠道。
- 同一页面使用两个不同统计 SQL。
统一读模型至少提供:
```text
product_id
canonical_sku
canonical_name
source_kind
internal_sku_id
current_primary_channel
fallback_channels
manual_config_id
current_status
has_active_cost
```
## 八、存量数据处理方案
### 8.1 已被其他渠道接管的 `man:` 商品
处理原则:
1. 先确认目标主渠道已有活动商品。
2. 将仍指向旧 `man:` 的人工兜底改指目标商品。
3. 保留订单项、成本版本、成本快照和历史引用。
4. 只把旧 `man:` 商品置为 `archived`,不硬删除。
5. 如果历史成本快照必须保留旧商品维度,不改变历史快照。
预期清理范围:
- 33 个卡券重复商品;
- 2 个接单平台重复商品;
- 1 个没有有效人工兜底配置的自动发货重复商品。
以上共 36 个 `manual_normalization` 旧商品,属于可确认归档对象。
另外 2 个自动发货 `man:` 商品有有效人工兜底配置,不归档、不进入人工主渠道页签。
### 8.2 统一结算商品
3 个当前主渠道为 `on_account` 的商品不是人工商品。
处理方式:
- 保留商品和历史引用;
- 增加统一结算分类;
- 从人工页签移出;
- 由 `on_account` 路由与结算成本口径管理。
### 8.3 无主渠道但有人工配置的商品
目前有 2 个,属于合法人工兜底。
处理方式:
- 保留;
- 在商品页显示“未路由 / 人工兜底”;
- 不计入“已分配”;
- 由运营决定是否补主渠道。
### 8.4 历史清理功能
`31b6d2d6` 曾实现跨渠道 `man:` 商品归档,但 `974044a4` 在人工 SKU 重构中删除了入口,
并把筛选测试改成保留所有 `man:` 商品。
后续清理必须:
- 作为一次性数据迁移,而不是临时页面按钮;
- 有 dry-run、数量、样本和备份;
- 有真实 PostgreSQL 集成测试;
- 不依赖“运营记得点清理”。
## 九、目标迁移路线
| 阶段 | 状态 | 是否改生产数据 |
| --- | --- | --- |
| 0 口径冻结与文档收口 | 已完成 | 否 |
| 1 只读审计与领域约束 | 本地进行中 | 否 |
| 2 建立目标身份与投影 | 本地完成 | 只新增兼容结构 |
| 3 迁移路由与商品配置 | 本地进行中 | 是,需备份 |
| 4 重建履约模型 | 未开始 | 是,需断代 |
| 5 重建财务派生数据 | 未开始 | 是,需备份与对账 |
| 6 停止旧写路径并删除兼容层 | 未开始 | 是,需观察期结束 |
### 阶段 0:口径冻结与文档收口
状态:本次完成。
产出:
- 本文件成为唯一权威。
- 旧业务架构文档全部归档。
- `docs/README.md` 只保留入口。
- `AGENTS.md` 固定执行规则。
验收:
- 活跃文档中不再存在竞争性的架构结论。
- 所有 Agent 和开发者从本文件开始。
### 阶段 1:只读审计与领域约束
目标:
- 不改变生产数据,先建立全量审计。
- 核对内部 SKU、路由、商品、履约和财务的冲突。
工作:
1. 建立内部 SKU 重复与合并候选报告。
2. 建立商品来源与主渠道冲突报告。
3. 建立无主渠道、多主渠道、无载体和退款混入履约报告。
4. 建立成本快照无法重建报告。
5. 为每类冲突定义责任角色和处理动作。
验收 SQL:
```text
同一内部 SKU 主渠道数 > 1 必须为 0
启用商品无 source_kind 必须为 0
人工配置指向非 man 商品 必须为 0
当前主渠道非 manual 的 man 商品出现在人工页 必须为 0(保留则必须有显式兜底)
assigned 且 carrier_status=missing 必须进入异常队列
退款/取消出现在普通履约队列 必须为 0
同一订单项当前尝试 > 1 必须为 0
```
### 阶段 2:建立目标身份与投影
目标:
- 建立 `internal_skus`。
- 为 `product_catalog` 增加 `source_kind` 和 `internal_sku_id`。
- 建立统一商品投影 `v_product_current`。
- 建立统一履约投影 `v_fulfillment_current`。
本地已完成身份表、商品来源字段和 `v_product_current`,并已切换商品列表、
总览与渠道映射的读取口径。生产未执行。
本地产出:
- 变更前备份:`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 时显示“未路由”。
- 商品列表、总览、渠道映射和商品下拉统一读取商品当前渠道。
- 运行期代码停止写入 `product_channel_capabilities`,该表仅保留到兼容期结束。
验收:
- 旧字段与新投影差异有清单。
- 商品列表和总览读取同一投影后数量一致。
- 目前 41 个跨渠道 `man:` 商品和 2 个无主渠道商品全部能分类。
### 阶段 3:迁移路由与商品配置
目标:
- 将 `internal_sku_channels` 迁移到 `sku_channel_routes`。
- 将人工配置、卡券配置、自动发货配置和接单模板配置关联到 `internal_sku_id`。
- 清理旧商品和错误兜底。
规则:
- 一个内部 SKU 一个主渠道。
- 其余渠道全部显式 `fallback`。
- 自动创建的标准商品必须有 `source_kind`。
- 历史 `man:` 清理只归档,不删除。
验收:
- 路由迁移前后主渠道结果一致。
- 人工页数量等于当前人工渠道商品数。
- 卡券和统一结算不再出现在人工页。
### 阶段 4:重建履约模型
目标:
- 以 A 级原始订单和真实载体为输入,重建 `fulfillments`、`fulfillment_attempts`、
`fulfillment_issues`。
- 停止写入过渡字段。
工作:
1. 清空旧影子履约和派生异常。
2. 回填当前履约单。
3. 回填当前尝试与历史尝试。
4. 生成结构化 issue。
5. 对比新旧读模型。
6. 切换后台与调度读路径。
验收:
- 同一订单项只有一个当前尝试。
- 所有 `assigned` 都有明确 `carrier_status` 或开放 issue。
- 退款、取消进入售后队列。
- 页面按钮作用域与后端动作一致。
### 阶段 5:重建财务派生数据
目标:
- 保留 A 级订单、退款事实和 B 级配置。
- 删除 C 级成本和财务派生数据并从新模型重建。
重建顺序:
```text
product normalization
→ cost snapshot
→ sales facts
→ journal
→ reconciliation
```
验收:
- 收入总额守恒。
- 退款总额守恒。
- 成本快照无重复。
- 事实与总账可对平。
- 所有成本缺失有结构化异常。
### 阶段 6:停止旧写路径并删除兼容层
只有前五个阶段持续稳定后才允许:
- 删除 `product_channel_capabilities`。
- 删除 `manual_sku_registry` 的派生行。
- 删除订单项重复渠道字段。
- 删除商品前缀业务判断。
- 删除旧管道、旧同步脚本和兼容 API。
禁止一次性同时删除旧字段和旧数据。
## 十、测试与生产门禁
以下检查必须进入代码测试或每日生产审计。
### 数据模型
- 一个内部 SKU 最多一个 primary route。
- 一个 fulfillment 最多一个 current attempt。
- 一个订单项最多一个 fulfillment。
- issue code 只能来自受控枚举。
- assigned 必须有 route 和 channel。
### 商品
- 每个 active product 必须有 `source_kind`。
- `source_kind` 与渠道专用商品类型一致。
- 人工页数量必须等于当前 primary manual 商品数。
- 总览、列表、导出必须使用同一投影。
- 旧 `man:` 商品不得在没有主渠道或收口状态时继续显示为人工。
### 履约
- 用户退款、平台取消不得出现在普通补载体队列。
- 同一订单项不得同时有活跃工单和活跃自动发货任务。
- 当前尝试必须是已存在且唯一的历史尝试。
- 所有重试动作必须按 issue_code 限定作用域。
### 财务
- 成本事实不可变,只能新增、替代或冲减。
- 事实、总账、退款和订单收入必须可对平。
- 财务重建必须从 A 级数据可重复执行。
### 文档
- 任何架构变更必须更新本文件。
- 旧文档不得再标记为“现行”。
- 文档中的迁移号和代码基线必须与生产一致。
## 十一、禁止事项
1. 不删除原始订单、平台报文、真实工作单、真实资金流水和审计日志。
2. 不根据商品名称、前缀或分类猜测履约渠道。
3. 不让多个服务同时写履约核心状态。
4. 不用自由 JSON 字符串代替结构化 issue。
5. 不以“最新”“出现最多”或“看起来像”解决映射冲突。
6. 不在没有投影和差异报告时切换读写路径。
7. 不把历史清理做成依赖运营点击的临时按钮。
8. 不为兼容旧口径保留第二份“现行文档”。
9. 不在一次发布中同时完成数据清理、模型切换和旧字段删除。
10. 不把“已经跑过测试”当成生产口径正确的证明。
## 十二、执行后的文档结构
```text
AGENTS.md
常驻规则、任务路由、数据安全边界
docs/README.md
文档总入口
docs/统一订单履约与财务模型-权威版.md
唯一业务与架构权威
docs/部署启动与数据库重建.md
docs/数据库备份与恢复.md
docs/数据库SQL约束与运维.md
运维参考
docs/91卡券/
docs/发货平台-2/
docs/抖音-码速达/
docs/行业电子凭证/
docs/affiliate-dash-发货平台/
外部协议与平台参考,不得覆盖本文件
docs/archive/
历史方案、旧口径和一次性分析
```
## 十三、当前下一步
本轮只完成文档和计划,不修改业务代码、不执行生产数据清理。
后续按以下顺序启动:
1. 完成阶段 1 的只读审计脚本与冲突清单。
2. 确定 `internal_skus`、`sku_channel_routes`、`product_catalog.source_kind`
的最终字段和迁移顺序。
3. 先建立投影,不直接切换写路径。
4. 清理派生数据前先做可恢复备份。
5. 每个阶段单独验收,不合并成一次性大迁移。