feat(fulfillment): 统一中文内部 SKU 履约路由
This commit is contained in:
@@ -68,11 +68,9 @@ skuNick → outSkuSn → sku_code → sku_name
|
||||
|
||||
### 3.1 自动发货
|
||||
|
||||
1. `resolveOrderItemForFulfillment`
|
||||
- 91:affiliate-dash SKU 映射 + `fulfillmentRouting`(商品名/内部 SKU)。
|
||||
- 抖音:`sku_order_list[].code` 即内部 SKU,查常量/后台映射表。
|
||||
- PDD:没有 affiliate 入口。
|
||||
2. 命中后写 `item_snapshot_json.fulfillmentRoute.selectedExecutorKey=affiliate_dash` 和 `snapshot.affiliateDash.sku`。
|
||||
1. 所有平台先统一归一到规范化中文内部 SKU;平台 SKU 只作为入口映射字段。
|
||||
2. `internal_sku_channels` 指定 `affiliate_dash` 后,才解析该内部 SKU 的 affiliate 载体 SKU。
|
||||
3. 命中后写 `item_snapshot_json.fulfillmentRoute.selectedExecutorKey=affiliate_dash` 和 `snapshot.affiliateDash.sku`。
|
||||
3. `syncDeliveryTasksForOrder` 只为 `isConfigured` 的订单项建 `fulfillment_tasks`。
|
||||
4. 工单层跳过 `classification.channel=affiliate_dash` 的订单项,保证载体唯一。
|
||||
|
||||
@@ -152,8 +150,14 @@ internal_sku_channels (
|
||||
- 接单平台 priority 10;
|
||||
- 卡券 priority 10。
|
||||
|
||||
待分类队列按内部 SKU 全局聚合:同一中文 SKU 即使来自不同平台或店铺,也只展示一行;
|
||||
运营指定渠道后写入同一份全局配置,并回填该内部 SKU 的全部待分类订单项。
|
||||
|
||||
下单入口、财务、成本中心都读这一份配置。
|
||||
|
||||
规范化规则固定为 NFKC → 去全部空白 → 小写。没有中文内部 SKU 的订单项保持 pending,
|
||||
不再回退到平台 SKU 或英文码。
|
||||
|
||||
### 5.3 载体保证
|
||||
|
||||
选定渠道后必须保证载体:
|
||||
@@ -205,15 +209,17 @@ pending 只保留:
|
||||
|
||||
### 阶段 4:清理与重判
|
||||
|
||||
1. 清理旧 `sku_code` affiliate/voucher 规则;
|
||||
2. 按内部 SKU 生成全局规则;
|
||||
3. 重判断代后 assigned/pending;
|
||||
4. 本地三平台模拟 → 生产迁移/部署。
|
||||
1. 下线旧「平台配置 → 履约配置」入口,旧路由不再参与运行时决策;
|
||||
2. 清理旧 `sku_code` affiliate/voucher 规则;
|
||||
3. 按中文内部 SKU 生成全局规则;
|
||||
4. 重判断代后 assigned/pending;
|
||||
5. 本地三平台模拟 → 生产迁移/部署。
|
||||
|
||||
## 7. 验收
|
||||
|
||||
- 三平台订单:下单 → 内部 SKU → 渠道 → 载体 → 成本 → 销售事实全链路可追踪;
|
||||
- 同名不同平台码不再拆 pending;
|
||||
- 同一内部 SKU 跨平台/跨店铺只展示一条待分类、一条渠道配置和一个问题聚合;
|
||||
- 财务渠道与真实载体一致;
|
||||
- pending 仅三类语义;
|
||||
- 审计脚本 0 空内部 SKU、0 纯数字(映射后)、0 载体/渠道矛盾;
|
||||
|
||||
+6
-5
@@ -370,14 +370,15 @@ fulfillment_locked -- 人工指定后为 true,自动判定跳过
|
||||
fulfillment_decided_at / fulfillment_reason
|
||||
```
|
||||
|
||||
判定顺序固定:**规则命中 → 载体证据(工单/自动发货任务)→ 无证据则 pending**。
|
||||
判定顺序固定:**真实载体证据 → `internal_sku_channels` 统一配置 → 无证据则 pending**。
|
||||
渠道选择只认规范化中文内部 SKU;平台 SKU 仅用于入口映射,不能参与路由。
|
||||
渠道值不再有 `legacy_platform`:断代归档后统一是 `archived`。
|
||||
|
||||
决策服务在 `services/fulfillment/channel-assign-service.ts`:
|
||||
|
||||
- `resolveChannelDecision()` —— 纯函数,规则与证据的优先级;
|
||||
- `resolveChannelDecision()` —— 纯函数,真实载体与统一 SKU 配置的优先级;
|
||||
- `assignPendingOrderItemChannels()` —— 按水位游标批量判定;
|
||||
- `assignChannelBySku()` —— 运营按 SKU 指定,写 `operator` 规则并锁定。
|
||||
- `assignChannelByInternalSku()` —— 运营按中文内部 SKU 全局指定并锁定。
|
||||
|
||||
### 6.2 断代与归档
|
||||
|
||||
@@ -390,9 +391,9 @@ fulfillment_decided_at / fulfillment_reason
|
||||
### 6.3 决策边界(写进代码注释与测试)
|
||||
|
||||
1. 新订单项默认 `pending`;由 `channel_assign` 管道在分钟级判定,不要求下单瞬间有渠道。
|
||||
2. 规则优先级:运营指定(10)> 自动发货(60)> 人工配置(70)> 默认;冲突会记 `routing_conflict` 异常。
|
||||
2. 渠道能力只来自 `internal_sku_channels`;同一内部 SKU 只能有一个主渠道,冲突记 `routing_conflict` 异常。
|
||||
3. 被运营指定的订单项 `fulfillment_locked=true`,自动判定与回填都不得覆盖。
|
||||
4. **商品来源不能反推渠道**:`man:` 商品也可能由自动发货履约,判定只认规则与证据。
|
||||
4. **商品来源和平台 SKU 都不能反推渠道**:判定只认统一 SKU 配置与真实载体。
|
||||
5. `voucher_state` 只做展示与核销流程,不参与任何成本/履约判断。
|
||||
6. 多渠道证据同时命中必须先告警人工复核,不能静默取其一。
|
||||
7. **旧人工来源清理只归档**:同名内部 SKU 已有其他非兜底主渠道时,旧 `man:` 商品从当前目录归档;历史订单、成本版本、成本快照和事实数据保持不动,人工兜底改指当前主商品。
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# 生产部署核对清单(履约与财务分流统一)
|
||||
|
||||
日期:2026-11-02
|
||||
适用:生产已应用 116–123(main 合并的履约路由 120–123 已先行上线),本次新增 124–125(工单付款金额审计与价格历史)+ backend/frontend。
|
||||
适用:生产已应用 116–125(其中 120–125 已随 main 先行上线),本次新增 126(统一中文内部 SKU)+ backend/frontend。
|
||||
|
||||
## 1. 部署前
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
123_work_product_rule_pricing_mode
|
||||
124_work_order_user_payment_amount_audit
|
||||
125_work_order_payment_amount_history
|
||||
126_internal_sku_canonical_routing
|
||||
```
|
||||
|
||||
> 序号说明:生产在合并 main 后已按 120–123 应用了履约路由四支迁移,因此这四支编号固定不变;
|
||||
@@ -48,11 +49,12 @@
|
||||
- 123:接单模板增加计价方式并回填历史模板,金额字段继续只由商品与成本中心投影。
|
||||
- 124:`work_orders` 增加付款金额旧价、修改时间、修改人三列(`ADD COLUMN IF NOT EXISTS`),幂等且不动存量数据。
|
||||
- 125:新建 `work_order_payment_amount_history` 并回填已有 `payment_amount_updated` 事件,写入按工单级联删除。
|
||||
- SQL 护栏默认只保护到生产已发布的迁移 119;部署 120 后应把 `PUBLISHED_MIGRATION_MAX_VERSION` 提升为 120。
|
||||
- 126:统一中文内部 SKU 规范化函数,平台 SKU 不再作为渠道兜底;补充统一配置查询索引。
|
||||
- 生产已发布到 125;部署 126 后应把 `PUBLISHED_MIGRATION_MAX_VERSION` 提升为 126。
|
||||
|
||||
## 3. 部署顺序
|
||||
|
||||
1. 执行迁移 116–125;
|
||||
1. 执行迁移 116–126;
|
||||
2. 部署 backend;
|
||||
3. 部署 frontend;
|
||||
4. 启动/恢复定时任务。
|
||||
@@ -145,6 +147,10 @@ npx tsx scripts/preflight-fulfillment-routing.ts --strict --include-demo
|
||||
- 已分配自动发货/接单但没有真实载体;
|
||||
- 已分配订单同时存在多个真实履约载体;
|
||||
- 多个主渠道;
|
||||
- 规范化后重复的内部 SKU 渠道配置;
|
||||
- `work_order` 缺 `workRuleKey` 或规则不存在;
|
||||
- 人工渠道缺启用的人工履约配置;
|
||||
- pending 订单项无法解析出中文内部 SKU;
|
||||
- 仍启用的 `sku_code` 兼容规则。
|
||||
|
||||
## 5. 数据清理(确认后执行)
|
||||
@@ -173,6 +179,6 @@ npx tsx scripts/reclassify-post-cutover.ts --apply
|
||||
|
||||
- 代码:回退到部署前镜像/commit;
|
||||
- 数据库:
|
||||
- 116–125 均为新增表/列/函数/投影数据,不删旧表,可保留;
|
||||
- 116–126 均为新增表/列/函数/触发器/投影数据,不删旧表,可保留;
|
||||
- 若必须回滚,恢复到部署前备份;
|
||||
- 迁移 118–121 不改旧字段语义,回滚代码后旧逻辑仍可运行;121 的唯一主渠道索引会阻止旧代码写入并列主渠道。
|
||||
|
||||
@@ -35,8 +35,9 @@
|
||||
|
||||
## 三、渠道判定
|
||||
|
||||
- 规则 `sku_channel_rules`:运营指定(10)> 自动发货(60)> 人工配置(70);
|
||||
- 无规则时看证据:工单 → `work_order`,自动发货任务 → `affiliate_dash`;
|
||||
- 唯一配置源是 `internal_sku_channels`,按规范化中文内部 SKU 全局生效;
|
||||
- 平台 SKU 只用于订单入口映射到中文内部 SKU,不参与渠道选择;
|
||||
- 真实载体证据:工单 → `work_order`,自动发货任务 → `affiliate_dash`;
|
||||
- 仍无证据 → `pending`,进「待分类」;
|
||||
- 运营指定后 `fulfillment_locked=true`,自动判定不再覆盖;
|
||||
- 多渠道证据冲突 → `routing_conflict` 异常,不静默取其一。
|
||||
|
||||
Reference in New Issue
Block a user