docs: 记录 P0 履约事实落地结果

This commit is contained in:
yml2213
2026-10-23 13:36:25 +08:00
parent 5d1ba11523
commit b629cd27d8
10 changed files with 93 additions and 57 deletions
+8 -7
View File
@@ -1,6 +1,6 @@
# order_site 文档索引
> 最后校准:2026-10-23,代码基线 `dev @ fac34c84 + 迁移 103–113`。
> 最后校准:2026-10-23,代码基线 `dev @ 5d1ba115 + 迁移 103–114`。
> 本文是 `docs/` 的唯一入口。**财务与履约口径以 [财务与履约口径总纲-2026-10-23.md](财务与履约口径总纲-2026-10-23.md) 为准**;接手改造先读 [财务履约改造交接总结-2026-10-23.md](财务履约改造交接总结-2026-10-23.md),本文只做索引与速查。
> 新增文档必须在下表登记状态;过期文档不再直接改写结论,统一移入 `docs/archive/`。
@@ -75,28 +75,29 @@
| 后台用户中文显示名 | **已实施** | `admin_users.display_name`,备用金姓名触发器同步;审计、登录记录、任务处理人优先显示中文名 |
| 商品主数据 + 渠道 SKU 映射 | **已实施 P0(dev 分支)** | 745 个标准商品、4,426 条映射;只覆盖自动发货 38 个 + 接单平台 707 个。人工 11,349 项虽已归一但全部挂 `tpl:*` 模板商品,需在 P1 复核;人工/历史平台专用商品尚未建立 |
| 成本中心 | **已实施 P0(dev 分支)** | 迁移 `104/105/107/108/110/112`;38 个商品级版本 + 662 个规则级版本;人工走 `sys_manual_service` 实际快照 |
| 销售事实 / 订单毛利 | **已实施 P0(dev 分支)** | 迁移 `109`;94 天事实收入 ¥2,650.87 万、成本 ¥950.27 万;人工/历史平台分类口径待统一 |
| 销售事实 / 订单毛利 | **已实施 P0(dev 分支)** | 迁移 `109`;94 天事实收入 ¥2,650.87 万、成本 ¥950.27 万;四种履约方式已统一读 `fulfillment_mode` |
| 公司人工支出登记 | **已实施 P0(dev 分支)** | 迁移 `111`;登记时强制扣客服备用金并写 `fund_expense_id`;客服只能使用本人账户 |
| 履约方式统一 | **未实施** | 订单页、销售事实、成本快照仍各自推断;需要持久化 `fulfillment_mode` |
| 履约方式统一 | **已实施 P0(dev 分支)** | 迁移 `114`;316,585 项已回填;订单页、成本快照、销售事实只读 `fulfillment_mode`;人工项带核销码仍显示人工 |
| 人工商品归一 | **未实施(P1)** | 人工单按 `spec.skuId` 建 `man:<skuId>`;历史 11,349 项 `tpl:*` 商品待复核 |
| 影子总账 | 未实施 | 现有财务页仍是 `UNION ALL` 业务事件拼装,不是复式总账 |
| 退款冲减 / 平台对账 / 期间关账 | 未实施 | 仅方案 |
> 分支状态(2026-10-23):`dev` 领先 `main` 20 个提交,迁移 `103–113` 尚未合并、未部署生产;生产口径仍以 `main` 为准。
> 分支状态(2026-10-23):`dev` 领先 `main` 22 个提交,迁移 `103–114` 尚未合并、未部署生产;生产口径仍以 `main` 为准。
> 财务与履约口径以 [财务与履约口径总纲-2026-10-23.md](财务与履约口径总纲-2026-10-23.md) 为准。
## 三、统一实施顺序
```text
0. 统一履约事实(fulfillment_mode + 成本模型) 未实施,最高优先级
0. 统一履约事实(fulfillment_mode + 成本模型) 已完成 P0(迁移 114)
1. 商品主数据 + 渠道 SKU 映射 已完成 P0(仅自动发货/接单平台)
2. 成本中心 + 销售事实 已完成 P0
3. 人工商品归一与上线后人工成本全覆盖 未实施
3. 人工商品归一与上线后人工成本全覆盖 未实施(下一阶段)
4. 退款冲减与异常队列 未实施
5. 影子总账(订单、工单、押金、提现、寄卖、售后) 未实施
6. 平台对账、报表、期间关账 未实施
```
**不要跳过第 0 步直接做人工成本或总账。** 没有统一履约事实,人工、电子凭证、历史平台会继续互相串味。第 0 步的迁移、回填、代码清单和验收 SQL 已写到 [总纲 §八](财务与履约口径总纲-2026-10-23.md#八p0-开工清单统一履约事实),按那份清单逐项执行即可。
**第 0 步已完成。** 迁移、回填、代码改造与验收结果见 [总纲 §八](财务与履约口径总纲-2026-10-23.md#八p0-实施记录统一履约事实)。下一步只做第 3 步人工商品归一,不要同时改退款或总账。
## 四、当前必须拍板
@@ -2,7 +2,7 @@
> 状态:**已实施 P0(`dev` 分支,迁移 111;订单页人工录单、备用金扣款为 2026-10-22/23 增量)**
> 最后校准:2026-10-23
> 代码基线:`dev @ fac34c84 + 迁移 103–113`
> 代码基线:`dev @ 5d1ba115 + 迁移 103–114`
> **总口径以 [财务与履约口径总纲-2026-10-23.md](财务与履约口径总纲-2026-10-23.md) 为准。**
> 依据:业务口径「人工块当前不以 SLA 监管为目标,先把流程搞清楚:哪个客服处理了哪些东西、付了多少钱、什么项目、关联哪个订单」。
> 数据来源:本地生产快照克隆(数据截至 2026-10-14)。
@@ -71,7 +71,7 @@
| 数量 1 · 关联工单 1 | `totalQuantity` / `workOrderCount` | 订单项 / 工单 | 数量与载体提示 |
| ¥ 10.30 CNY | `totalAmount` / `totalAmountFen` | 订单表 | **用户实付(= 收入)**,用于算毛利 |
| 2026-10-17 22:24:21 | `paidAt` / `createdAt` | 订单表 | 支出时间不能早于支付时间 |
| 接单平台 / ⚡自动发货 / 🎫核销码 | `fulfillment_mode` + `voucher_state`(当前为 `fulfillmentType`) | 派生 | 履约方式与核销码必须分开显示;核销码不参与判定 |
| 接单平台 / ⚡自动发货 / 🎫核销码 | `fulfillmentMode` + `voucherState` | 派生 | 履约方式与核销码必须分开显示;核销码不参与判定 |
| 已支付 | `payStatus` | 订单表 | 只有已支付才允许登记支出 |
| 待准备资源 / 未开始 | `resourceStatus` / `customerStatus` | 任务/工单派生 | 提示当前进度 |
| (未在列表显示)操作人 | 后台会话 `userId` / `username` / `role` | `admin_sessions` | 默认「登记人」 |
@@ -162,7 +162,7 @@
### 4.1 订单列表(就是截图这一页)— 已落地
- 行操作已加「人工录单」按钮(与「详情」「H5」并列),只对人工单显示;点击跳转 `/admin/orders/:id?manualCost=1` 并自动打开录单弹窗。
- 行操作已加「人工录单」按钮(与「详情」「H5」并列),只在该订单存在 `manual` 项时显示(`manualItemCount > 0`);点击跳转 `/admin/orders/:id?manualCost=1` 并自动打开录单弹窗。
- 本单已登记支出合计列尚未做;后续可加,让主管扫一眼看出哪些单垫了钱。
- 筛选条件「有/无支出登记」「支出待审批」尚未做,是后续主管抽查与财务对账的入口。
@@ -2,7 +2,7 @@
> 状态:**已实施 P0**(迁移 100/101/113;代码已上线到代码库,未部署生产)。
> 最后校准:2026-10-23
> 代码基线:`dev @ fac34c84 + 迁移 103–113`
> 代码基线:`dev @ 5d1ba115 + 迁移 103–114`
> **总口径以 [财务与履约口径总纲-2026-10-23.md](财务与履约口径总纲-2026-10-23.md) 为准。**
> 背景:两位主管向客服发放备用金,客服用于充值、采购、赔偿等;目前全部走人工,无法监控每笔资金用途和每个客服余额。
> 结论:这不是报销系统,而是**客服备用金(周转金)台账**。P0 已完成“账户 + 流水 + 支出 + 对账”,不做复杂审批和总账。
@@ -19,7 +19,7 @@
| 前端 | `AdminFundPage.tsx`、`FundManagementView.tsx`、`FundSupportView.tsx`;管理端与客服端分流 |
| 权限 | `fund.view / fund.issue / fund.expense / fund.reconcile / fund.adjust / fund.export` |
| 审计 | 所有写接口接入 `createJsonHandler({ audit })` |
| 测试 | 最近全量校验(`fac34c84`):后端 760 项,757 通过 / 3 跳过;前端 `npm run check` 通过 |
| 测试 | 最近全量校验(`5d1ba115`):后端 765 项,762 通过 / 3 跳过;前端 143 项 + build 通过 |
**与本文原方案的差异:**
@@ -1,6 +1,6 @@
# 多发货平台与电子凭证整体链路
> 状态:现行。最后校准:2026-10-23(代码基线 `dev @ fac34c84 + 迁移 103–113`;业务逻辑未变,仅口径校正)。
> 状态:现行。最后校准:2026-10-23(代码基线 `dev @ 5d1ba115 + 迁移 103–114`;履约方式已统一落库)。
> 财务与履约总口径见 [财务与履约口径总纲-2026-10-23.md](../财务与履约口径总纲-2026-10-23.md)。
> 来源口径:本系统只有三个订单来源——`kuaishou-91`、`pdd`、`douyin-mashida`。**91 回调与快手 send-code 是同一个 `kuaishou-91` 来源的两条数据通道**(91=骨架权威源,快手 send-code=补全/兜底源),不是一个来源加另一个来源。
+1 -1
View File
@@ -2,7 +2,7 @@
> 状态:**现行说明(未实施)**
> 最后校准:2026-10-23
> 代码基线:`dev @ fac34c84 + 迁移 103–113`
> 代码基线:`dev @ 5d1ba115 + 迁移 103–114`
> 配套方案:[财务系统集成方案.md](财务系统集成方案.md)
> **总口径以 [财务与履约口径总纲-2026-10-23.md](财务与履约口径总纲-2026-10-23.md) 为准。**
> 前置:统一履约事实、商品主数据、渠道映射、成本中心与销售事实;实施顺序以总纲第六节为准。
+3 -3
View File
@@ -1,8 +1,8 @@
# 成本中心与履约方式模型(文件名保留)
> 状态:**现行(P0 已实施,履约方式待统一)**。商品主数据、成本中心、成本快照、销售事实、人工支出已落地;`fulfillment_mode` 持久化与人工全覆盖仍待实施。
> 状态:**现行(P0 已实施,履约方式已统一)**。商品主数据、成本中心、成本快照、销售事实、人工支出、`fulfillment_mode` 均已落地;人工商品归一与全覆盖仍待实施。
> 最后校准:2026-10-23
> 代码基线:`dev @ fac34c84 + 迁移 103–113`
> 代码基线:`dev @ 5d1ba115 + 迁移 103–114`
> 数据基线:本地生产快照克隆(数据截至 2026-10-14)
> **财务与履约口径以 [财务与履约口径总纲-2026-10-23.md](财务与履约口径总纲-2026-10-23.md) 为准**;本文只负责商品、成本、销售事实的数据模型。
> 文件名保留是为了历史链接稳定,正文不再使用“三块”作为分类依据。
@@ -601,7 +601,7 @@ flowchart LR
### P2:人工全覆盖与轻量处理记录——支出登记已完成,轻量 case 未实施
- 先统一 `fulfillment_mode`,人工只在无工单、无自动任务、无历史平台任务时出现
- `fulfillment_mode` 已统一(迁移 `114`):人工只在无工单、无自动任务、无历史平台任务时出现
- 无载体自动建轻量 case(谁在处理哪个订单项)
- **公司人工支出登记**:付款项目 / 金额 / 订单号 / 付款人 / 收款人 / 付款方式 / 凭证 / 审批
- 登记时强制从客服备用金扣款,并写 `fund_expense_id`;客服只能使用本人账户
+1 -1
View File
@@ -1,6 +1,6 @@
# 接单模板匹配引擎重构设计
> 目标读者:后端 / 后台运营。状态:**P0 + P1 已实施;P2 / P3 待办**。最后校准:2026-10-23(代码基线 `dev @ fac34c84 + 迁移 103–113`;业务逻辑未变)。
> 目标读者:后端 / 后台运营。状态:**P0 + P1 已实施;P2 / P3 待办**。最后校准:2026-10-23(代码基线 `dev @ 5d1ba115 + 迁移 103–114`;匹配业务逻辑未变)。
>
> 一句话:把「订单信息 → 接单模板(价格/拼单/要求)」的匹配,从散落的多个消费点、平台判断和"店铺必填"的绑定表里,收敛为**一个平台无关的引擎**:匹配条件完全由**订单信息**表达,**店铺只是可选条件之一**,新增来源只加一个适配器 + 一组配置。
>
+46 -24
View File
@@ -1,7 +1,7 @@
# 财务与履约口径总纲(2026-10-23)
> 状态:**现行唯一口径**。本文是财务、成本、履约分类的总入口;其他文档与本文件冲突时,以本文为准。
> 代码基线:`dev @ fac34c84 + 迁移 103–113`。历史文档中的旧基线、旧三块模型、按小时人工成本等表述全部作废。
> 代码基线:`dev @ 5d1ba115 + 迁移 103–114`。历史文档中的旧基线、旧三块模型、按小时人工成本等表述全部作废。
> 适用范围:订单接入、履约判定、商品归一、成本快照、销售事实、人工支出、备用金、后续总账与对账。
---
@@ -183,24 +183,28 @@
| 客服只能使用本人备用金账户 | **已实施** | `a7f60414` |
| 备用金账户编号 `FA-<用户名>` | **已实施** | `fac34c84` + 迁移 `113` |
| 订单页只展示平台判断 SKU | **已实施** | `c38cd8ca`、`cd9bb141` |
| `order_items.fulfillment_mode` 持久化 | **已实施** | 迁移 `114` + 统一决策服务 |
| 订单页 / 成本快照 / 销售事实统一读字段 | **已实施** | `admin-read-service`、`sales-facts-service`、`cost-snapshot-sync-service` |
| 本地 316,585 项回填 | **已实施** | `fulfillment:backfill`,四项计数与 §8.2 一致 |
| 已有成本异常载体同步 | **已实施** | 53,901 条由 `manual` 修正为 `legacy_platform` |
| 24 小时兜底归集 | **已实施** | `cost_finance_sync` 每 5 分钟先归集 |
| 财务与履约文档统一口径 | **本轮完成** | 本文件 + 交接总结 + 关联文档 |
| `order_items.fulfillment_mode` 持久化 | **未实施** | 本文 §八 |
| 人工商品归一 `man:<skuId>` | **未实施** | 本文 §八、§九 |
| 人工商品归一 `man:<skuId>` | **未实施** | P1 |
| 退款冲减、异常闭环 | **未实施** | 本文 §六 P2 |
| 影子总账、对账、关账 | **未实施** | 本文 §六 P3 |
> 分支事实:以上实现均在 `dev`,迁移 `103–113` 尚未合并/部署生产;生产仍以 `main` 为准。
> 下一阶段**只做 §八 的 P0**,不要同时改人工商品、退款或总账。
> 分支事实:以上实现均在 `dev`;迁移 `103–114` 尚未部署生产。
> 下一阶段只做 P1:人工商品归一 + 上线后人工成本全覆盖,不要同时改退款或总账。
---
## 八、P0 开工清单:统一履约事实
## 八、P0 实施记录:统一履约事实
目标:让订单页、成本快照、销售事实读同一个 `order_items.fulfillment_mode`,不再各自推断。完成后才允许做人工商品归一。
> 状态:**已实施(本地 `dev`,未部署生产)**。迁移 `114` 已执行,316,585 项已回填,四项计数与 §8.2 一致。
### 8.1 迁移 `114_order_item_fulfillment_mode.sql`
四张表的 `carrier_type` 约束目前都不接受 `legacy_platform`;只加 `order_items` 字段会在写销售事实/成本快照时直接失败。迁移必须同时放宽:
四张表的 `carrier_type` 约束原先都不接受 `legacy_platform`;只加 `order_items` 字段会在写销售事实/成本快照时直接失败。迁移 `114` 已同时放宽:
- `product_catalog.chk_product_catalog_carrier_type`
- `cost_items.chk_cost_items_carrier_type`
@@ -289,17 +293,34 @@ WHERE oi.id = d.id
| `manual` | 102,955 | ¥1,219.20 万 | 102,954 |
| **合计** | **316,585** | **¥2,650.87 万** | **157,821** |
> 以上 SQL 已在本地库用事务完整试跑并回滚:`UPDATE 316585`,四项计数与本表一致,`NULL` 为 0;耗时约 45 秒。这进一步说明回填应单独分批执行,不要放进启动迁移。
> 以上 SQL 已在本地库实际执行:定时任务先归集 20,000 项,回填脚本再处理 296,585 项,合计 316,585,`NULL = 0`;脚本耗时约 86 秒。随后同步 53,901 条 open 成本异常的 `carrier_type`(manual → legacy_platform),全表检查耗时约 5.4 秒。
### 8.3 代码改造清单
生产执行顺序:
| 文件 | 当前问题 | 必须改成 |
| --- | --- | --- |
| `apps/backend/src/services/admin/admin-order-read-helpers.ts` | `vouchers.length > 0 || provider === '91kaquan'` 判为 `voucher_only`;`provider === 'douyin_mashida'` 直接判自动发货;自动任务优先于工单 | 只读 `fulfillment_mode`;四种模式独立映射;核销码单独返回 `voucherState`;删除 provider 兜底 |
| `apps/backend/src/services/finance/sales-facts-service.ts` | `CASE` 临时推断,且没有 `legacy_platform` | 直接读 `oi.fulfillment_mode`,不得再复制判定 |
| `apps/backend/src/services/cost-center/cost-snapshot-sync-service.ts` | 又复制一套三选一判定 | 直接读 `oi.fulfillment_mode` |
| 新增 `apps/backend/src/services/fulfillment/fulfillment-mode-service.ts` | 没有统一决策入口 | 提供 `decideOrderItemFulfillmentMode()` 与 `reconcilePendingFulfillmentModes()`;工单/任务状态变化时调用,定时任务兜底 |
| `apps/frontend/src/pages/admin/AdminOrdersPage.tsx` 及类型 | 前端只有 `auto_claim / worker_dispatch / voucher_only / manual` | 增加 `legacy_platform`;核销码改为独立标签;人工按钮只认 `manual` |
```bash
# 1. 部署并等待迁移 114 完成(只做 DDL)
npm run db:migrate:status
# 2. 分批回填 + 同步已有成本异常载体
npm run fulfillment:backfill
# 3. 核对四项计数与 NULL=0,再触发财务重算
npm run finance:sync -- --from=<上线前起始日> --to=<今天> --mode=all
```
### 8.3 代码改造记录
| 文件 | 改造结果 |
| --- | --- |
| `apps/backend/src/db/migrations/114_order_item_fulfillment_mode.sql` | 新增三列 + 两个索引;放宽四张表的 `carrier_type` CHECK |
| `apps/backend/src/services/fulfillment/fulfillment-mode-service.ts` | 统一判定与批量归集;`decideOrderItemsFulfillmentModes()`、`reconcilePendingFulfillmentModes()`、`syncOpenCostExceptionCarrierTypes()` |
| `apps/backend/scripts/backfill-fulfillment-mode.ts` | 分批回填 + 同步已有成本异常载体;npm 命令 `fulfillment:backfill` |
| `apps/backend/src/services/admin/admin-order-read-helpers.ts` | 只读 `fulfillment_mode`;删除 voucher/provider 兜底;核销码单独返回 `voucherState` |
| `apps/backend/src/services/finance/sales-facts-service.ts` | 直接读 `COALESCE(oi.fulfillment_mode, 'manual')`,不再复制判定 |
| `apps/backend/src/services/cost-center/cost-snapshot-sync-service.ts` | 三处临时判定全部替换为 `fulfillment_mode` |
| `apps/backend/src/services/scheduler/cost-finance-sync-job.ts` | 每 5 分钟先归集待判定订单项,再算成本与销售事实 |
| `apps/backend/src/services/worker-platform/sync-worker-orders-service.ts` | 订单同步结束后批量落履约方式;失败不阻断下单 |
| 前端订单列表 / 详情 / 类型 / 显示工具 | 四种模式 + `mixed/pending`;核销码独立标签;人工按钮只认 `manualItemCount > 0` |
### 8.4 决策边界(写进代码注释与测试)
@@ -310,14 +331,15 @@ WHERE oi.id = d.id
5. `voucher_state` 只做展示与核销流程,不参与任何成本/履约判断。
6. 三种载体同时命中的订单项必须先告警人工复核;当前本地为 0。
### 8.5 完成标准
### 8.5 完成情况
- 迁移 `114` 可在空库与现有库各跑一次,重复执行不报错;
- 回填后 §8.2 四项数字完全一致;
- 订单页、成本快照、销售事实对同一订单项返回同一模式;
- 人工单带核销码仍显示人工;抖音无任务单仍显示人工;历史平台不再落入人工;
- 后端 `npm run check`、前端 `npm run check` 通过;
- 上线后 §九 的日检 SQL 连续 7 天为 0,才进入 P1。
- 迁移 `114` 已在本地库执行,字段、索引、四处 CHECK 均已生效;
- 回填后 §8.2 四项数字完全一致,`NULL = 0`;
- 订单页、成本快照、销售事实已统一读 `fulfillment_mode`;
- 本地联调:带已核销快手凭证的 91 人工单返回 `manual` + `voucherState=consumed`,`canClaimH5=false`;
- 销售事实重算后四种载体收入/成本与 §8.2 完全一致;
- 后端 `npm run check` 通过(765 项:762 通过 / 3 跳过);前端 `npm run check` 通过(143 项测试 + build);
- 生产仍需按 §8.2 顺序执行迁移、回填、财务重算,并连续观察 7 天日检。
---
@@ -1,9 +1,9 @@
# 财务/履约人工块修复总结(交接用)
> 状态:**交接摘要**。详细口径、迁移 SQL、代码清单与验收查询以 [财务与履约口径总纲-2026-10-23.md](财务与履约口径总纲-2026-10-23.md) 为准。
> 代码基线:`dev @ fac34c84 + 迁移 103–113`。
> 代码基线:`dev @ 5d1ba115 + 迁移 103–114`。
> 数据基线:本地生产快照克隆,数据截至 2026-10-14。
> 分支:`dev` 领先 `main` 20 个提交;迁移 `103–113` 未部署生产;本轮只做本地提交,暂不推送。
> 分支:`dev` 领先 `main` 22 个提交;迁移 `103–114` 未部署生产;本轮只做本地提交,暂不推送。
---
@@ -14,6 +14,9 @@
3. **客服只能用自己的备用金账户**:客服角色默认自动带入本人账户,传别人账户后端直接 403;管理员/财务可代录。
4. **备用金账户编号可读**:统一为 `FA-<大写用户名>`,重名追加 `-2/-3`;迁移 `113` 已回填本地历史账户。
5. **订单页只展示平台判断 SKU**:人工录单弹窗不再混入内部规格文本。
6. **履约方式统一落库**:新增 `order_items.fulfillment_mode`,订单页、成本快照、销售事实只读这一个字段。
7. **核销码与履约方式彻底拆开**:快手凭证/抖音券只作为 `voucherState` 展示,不再把 91 人工单判成 `voucher_only`。
8. **历史平台成本异常归位**:53,901 条 open 异常从 `manual` 修正为 `legacy_platform`,不再污染人工账单。
## 二、关键事实(先记住这几个数)
@@ -36,14 +39,14 @@
真实数据:91/快手人工单 100,618 项,**全部有凭证记录**(`CONSUMED` 87,310 / `DESTROYED` 13,247 / `UNUSED` 61),但它们仍然是人工单。
旧代码的根因:
旧代码的根因(已在 P0 删除):
```text
vouchers.length > 0 || provider === '91kaquan' -> voucher_only
provider === 'douyin_mashida' -> 自动发货
```
这两条兜底会把人工单从订单页隐藏。P0 必须删除,只读 `order_items.fulfillment_mode`。
这两条兜底会把人工单从订单页隐藏。现在只读 `order_items.fulfillment_mode`,核销码单独返回 `voucherState`。本地联调:带已核销快手凭证的 91 人工单返回 `manual + consumed`,不再变成 `voucher_only`。
## 四、现在不要做什么
@@ -51,19 +54,29 @@ provider === 'douyin_mashida' -> 自动发货
- 不要用均价、工时或固定单价补齐人工成本。
- 不要把 `manual_expenses` 改名或复用为 `manual_expense_records`。
- 不要用 `product_catalog.carrier_type` 反推履约方式。
- 不要在 `fulfillment_mode` 落地前做人工商品归一或总账。
- 不要在人工商品归一前重算历史总账。
- 不要把 `legacy_platform` 混回人工。
- 不要再用 `voucher_only` 或 provider 兜底判履约;P0 已统一到 `fulfillment_mode`。
## 五、下一步只做 P0:统一履约事实
## 五、下一步只做 P1:人工商品归一
完整 SQL 与代码清单见 [总纲 §八](财务与履约口径总纲-2026-10-23.md#八p0-开工清单统一履约事实)。
完整口径与验收见 [总纲 §八、§九](财务与履约口径总纲-2026-10-23.md#八p0-实施记录统一履约事实)。
1. 新增迁移 `114_order_item_fulfillment_mode.sql`:三列 + 索引 + 放宽四张表的 `carrier_type` CHECK(`product_catalog`、`cost_items`、`cost_snapshots`、`sales_daily_facts`)。
2. 单独跑回填脚本(不要塞进启动迁移),按 `work_order → affiliate_dash → legacy_platform → manual` 填 316,585 项。
3. 改三处判定:订单页、`sales-facts-service.ts`、`cost-snapshot-sync-service.ts`,全部只读 `fulfillment_mode`。
4. 新增统一决策服务:工单/任务状态变化时写模式;24 小时兜底归集未分类订单项。
5. 前端增加 `legacy_platform`,核销码改成独立标签,人工按钮只认 `manual`。
6. 跑后端/前端 `npm run check`,核对总纲 §8.2 四项数字,再连续观察 7 天日检。
P0 已完成(本地):
1. 迁移 `114`:`fulfillment_mode` / `fulfillment_decided_at` / `fulfillment_reason` + 索引;
2. 同时放宽 `product_catalog`、`cost_items`、`cost_snapshots`、`sales_daily_facts` 的 `carrier_type` CHECK;
3. 316,585 项回填完成:`work_order 118,053 / affiliate_dash 41,676 / legacy_platform 53,901 / manual 102,955`;
4. 53,901 条 open 成本异常由 `manual` 修正为 `legacy_platform`;
5. 订单页、成本快照、销售事实全部只读 `fulfillment_mode`;核销码改为独立状态;
6. 定时任务每 5 分钟兜底归集,失败不阻断下单。
P1 下一步:
1. 人工单按 `spec.skuId` 建 `man:<skuId>` 商品,PDD 用 `sku_code/sku_name` 兜底;
2. 复核 11,349 个仍挂 `tpl:*` 的人工订单项,确认是保留商品身份还是改挂 `man:*`;
3. 人工录单保持逐单实际金额,24 小时内录入;
4. 验收:人工单无成本记录 = 0(上线后区间)。
## 六、上线后运营(硬要求)
+2 -2
View File
@@ -2,7 +2,7 @@
> 状态:**现行方案(总账层未实施)**。本文只描述 `finance_*` 总账层;当前总账表尚未建立,现有财务页仍是 `UNION ALL` 业务事件拼装。
> 最后校准:2026-10-23
> 代码基线:`dev @ fac34c84 + 迁移 103–113`
> 代码基线:`dev @ 5d1ba115 + 迁移 103–114`
> **履约方式、成本模型、人工全覆盖口径以 [财务与履约口径总纲-2026-10-23.md](财务与履约口径总纲-2026-10-23.md) 为准**;本文不重复分类设计。
> 目标:在**不破坏现有抢单、押金、结算、寄卖、提现链路**的前提下,增加可对账、可关账、可追溯的复式记账底座。
> 结论先说:**不要直接在 `worker_wallets` / `worker_wallet_ledgers` 上继续加字段。** 现有表是业务钱包与流水,不是会计总账;正确做法是新增复式记账底座,让现有钱包成为它的“余额投影”。
@@ -19,7 +19,7 @@
| 商品主数据 / 渠道 SKU 映射 / 成本中心 | **已实施 P0(`dev` 分支)**,迁移 `103/104/105/106/107/108/110/112`;标准商品 745 个,只覆盖自动发货 38 + 接单平台 707 |
| `sales_daily_facts` / 订单级毛利 | **已实施 P0(`dev` 分支)**,迁移 `109`;94 天收入 ¥2,650.87 万、成本 ¥950.27 万 |
| 公司人工支出登记 `manual_expense_records` | **已实施 P0(`dev` 分支)**,迁移 `111`;登记时强制扣客服备用金并写 `fund_expense_id` |
| 履约方式统一 `fulfillment_mode` | **未实施**;订单页、成本快照、销售事实仍各自推断 |
| 履约方式统一 `fulfillment_mode` | **已实施 P0(`dev` 分支)**;迁移 `114`,316,585 项已回填;订单页、成本快照、销售事实统一读该字段 |
| `finance_accounts` / `finance_business_events` / `finance_journal_*` | 未实施 |
| `finance_settlements` / `finance_reconciliations` | 未实施 |
| 现有 `admin-finance-service.ts` | 仍是业务事件 `UNION ALL`,不是总账 |