fix(finance): 收敛内部 SKU 履约路由与载体状态
统一内部 SKU 与渠道主/兜底解析,禁止并列主渠道。 运营指定渠道改为先创建真实载体,失败保持明确 pending。 历史缺载体、多载体冲突和自动发货兜底统一由管道修复。 迁移人工配置与旧 sku_code 规则,补充严格预检和集成测试。
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
# 履约与财务分流统一方案
|
||||
|
||||
日期:2026-11-02
|
||||
状态:设计稿,待实施
|
||||
状态:已落地(2026-11-02);代码基线:迁移 121 + backend/frontend 当前 HEAD
|
||||
目标:以内部中文 SKU 为唯一主键,统一「下单路由 → 履约载体 → 财务渠道 → 成本」链路。
|
||||
|
||||
## 1. 现状结论
|
||||
@@ -220,9 +220,19 @@ pending 只保留:
|
||||
- 后端/前端测试、构建、SQL 护栏通过;
|
||||
- 生产迁移/部署验证。
|
||||
|
||||
## 8. 待确认
|
||||
## 8. 最终落地口径(2026-11-02)
|
||||
|
||||
1. PDD 纯数字内部 SKU 的中文映射由谁维护(商品名/规格/运营表)?
|
||||
2. 双渠道商品(自动发货 + 人工)的兜底触发条件:任务失败、超时、还是人工手动切换?
|
||||
3. 接单平台是否所有内部 SKU 都必须自动建工单,还是保留“运营指定”模式?
|
||||
4. 同名 man/tpl 商品是否合并,还是保留多载体配置、只统一 internal_sku_channels?
|
||||
1. **内部 SKU 只有一个解析函数**:`resolve_internal_sku(manual_sku_key, sku_name, sku_code)`;入口 TS 侧使用同一顺序,不再由各脚本自行拼 SQL。
|
||||
2. **渠道配置只有一个运行时入口**:`internal_sku_channels`。一个内部 SKU 最多一个主渠道,其余渠道必须 `is_fallback = true`;数据库唯一索引阻止并列主渠道。
|
||||
3. **载体先行**:自动发货/接单先创建 `fulfillment_tasks` / `work_orders`,成功后才写 `fulfillment_status = assigned`。创建失败保持 `pending / no_carrier`。
|
||||
4. **兜底触发**:主渠道为自动发货/接单且载体无法创建时,按 priority 尝试显式 fallback;人工配置、卡券为无需外部载体的安全渠道。已分配后自动任务失败仍由 `affiliate_fallback` 接管。
|
||||
5. **财务只镜像事实**:已有唯一真实载体优先;否则读取统一渠道计划;旧 `sku_channel_rules` 仅保留兼容回退,新增/修改会同步到统一渠道表。
|
||||
6. **人工配置即时入表**:保存/停用人工 SKU 配置会同步 `internal_sku_channels`,历史配置由迁移 120 回填。
|
||||
7. **旧规则自动迁移**:可确定的 `sku_code` 自动发货/卡券规则在迁移中转为内部 SKU 渠道并停用旧规则;无法唯一解析的规则由严格预检阻断。
|
||||
8. **同名 man/tpl 不强制合并**:保留不同载体能力,但同一内部 SKU 只能配置一个主渠道,其余显式兜底。
|
||||
|
||||
### 数据与回填约定
|
||||
|
||||
- PDD 纯数字码优先由 `internal_sku_mappings` 维护;未命中时使用中文 `sku_name`,仍无中文则保留原码并进入待分类。
|
||||
- 所有历史人工配置进入 `manual` 兜底能力;存在自动/接单/卡券能力时,人工 priority 固定不低于 90。
|
||||
- `npm run products:merge-duplicates`、`cleanup-legacy-sku-code-rules`、`reclassify-post-cutover` 保持 dry-run 默认;执行前后都运行严格预检。
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# 生产部署核对清单(履约与财务分流统一)
|
||||
|
||||
日期:2026-11-02
|
||||
适用:生产当前在迁移 115,本次新增 116–119 + backend/frontend。
|
||||
适用:生产当前在迁移 115,本次新增 116–121 + backend/frontend。
|
||||
|
||||
## 1. 部署前
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
117_internal_sku_mappings
|
||||
118_internal_sku_channels
|
||||
119_fulfillment_pending_reason
|
||||
120_fulfillment_routing_invariants
|
||||
121_internal_sku_single_primary
|
||||
```
|
||||
|
||||
重点检查:
|
||||
@@ -32,10 +34,12 @@
|
||||
- 118:按商品能力/规则回填 `internal_sku_channels`;
|
||||
- SQL 已做聚合,避免同名商品同渠道 `ON CONFLICT` 二次更新报错;
|
||||
- 119:只加列和索引,风险低。
|
||||
- 120:建立统一内部 SKU SQL 函数、回填人工配置、迁移可确定的旧 sku_code 规则。
|
||||
- 121:建立唯一主渠道索引;若仍有并列主渠道会主动阻断迁移。
|
||||
|
||||
## 3. 部署顺序
|
||||
|
||||
1. 执行迁移 116–119;
|
||||
1. 执行迁移 116–121;
|
||||
2. 部署 backend;
|
||||
3. 部署 frontend;
|
||||
4. 启动/恢复定时任务。
|
||||
@@ -56,6 +60,7 @@ GROUP BY 1;
|
||||
- `no_internal_sku`
|
||||
- `no_channel_capability`
|
||||
- `no_carrier`
|
||||
- `routing_conflict`(如仍有配置冲突,必须处理)
|
||||
|
||||
### 11月改名卡
|
||||
|
||||
@@ -110,6 +115,25 @@ WHERE enabled
|
||||
GROUP BY 1;
|
||||
```
|
||||
|
||||
### 严格预检
|
||||
|
||||
```bash
|
||||
# 本地演示数据默认排除 sim-*;生产应直接执行
|
||||
npx tsx scripts/preflight-fulfillment-routing.ts --strict
|
||||
|
||||
# 如确实要把演示数据也纳入检查
|
||||
npx tsx scripts/preflight-fulfillment-routing.ts --strict --include-demo
|
||||
```
|
||||
|
||||
严格预检必须为 0 失败,重点包括:
|
||||
|
||||
- 有内部 SKU 但无渠道能力的 pending;
|
||||
- pending 未写入明确原因(说明管道尚未跑完);
|
||||
- 已分配自动发货/接单但没有真实载体;
|
||||
- 已分配订单同时存在多个真实履约载体;
|
||||
- 多个主渠道;
|
||||
- 仍启用的 `sku_code` 兼容规则。
|
||||
|
||||
## 5. 数据清理(确认后执行)
|
||||
|
||||
```bash
|
||||
@@ -136,6 +160,6 @@ npx tsx scripts/reclassify-post-cutover.ts --apply
|
||||
|
||||
- 代码:回退到部署前镜像/commit;
|
||||
- 数据库:
|
||||
- 116–119 均为新增表/列/数据,不删旧表,可保留;
|
||||
- 116–121 均为新增表/列/函数/数据,不删旧表,可保留;
|
||||
- 若必须回滚,恢复到部署前备份;
|
||||
- 迁移 118/119 不改旧字段语义,回滚代码后旧逻辑仍可运行。
|
||||
- 迁移 118–121 不改旧字段语义,回滚代码后旧逻辑仍可运行;121 的唯一主渠道索引会阻止旧代码写入并列主渠道。
|
||||
|
||||
Reference in New Issue
Block a user