原 9 篇 3,647 行,履约分类口径在总纲、模型文档、交接总结里重复三遍, 且仍留着"三块履约""按小时人工成本"等已作废表述。本次收敛为 5 篇 1,778 行: - 财务与履约口径总纲-2026-10-23.md(300 行):唯一口径来源 七条硬口径、三个正交维度、真实履约构成、成本模型规则、人工全覆盖、 实施顺序、进度、验收 SQL、防回归清单 - 成本中心与履约模型.md(471 行):数据模型、迁移 103–107、履约回填、 销售事实、本地库原地改造、索引与性能 - 成本中心API契约.md(270 行):字段替换总表、枚举、前后端模块边界 - 人工支出与备用金.md(218 行):人工支出登记字段/状态机/权限 + 客服备用金台账 - 财务系统集成方案.md:复式总账层(未实施) 旧的 4 篇(成本中心与三块履约模型、人工支出登记落地方案、 客服备用金台账实施方案、财务履约改造交接总结)移入 docs/archive/2026-10-23/ 并加归档提示。 履约分类判定 SQL 只在总纲保留一份,其它文档改为链接。
14 KiB
载体判定与成本中心落地:复核与草案(2026-10-17 第二轮)
状态:历史(2026-10-17 第二轮复核,已归档);基线:
main @ ccd5ed2a;代码未改动。 说明:本文的现行结论已吸收进 成本中心与三块履约模型.md 与 财务系统集成方案.md;本文件只用于追溯 2026-10-17 的数据量化与 DDL 验证过程,不再作为实现依据。 数据来源:本地只读克隆(生产快照,orders316,597 行,数据截至 2026-10-14 14:52),全程只读 SELECT,未连生产、未写入任何业务库。 金额单位:分(orders.total_amount/work_orders.reward_amount/source_order_amount_fen均为分)。 上游文档:成本中心与三块履约模型.md、项目全量分析报告-2026-10-17.md。
本轮任务是把上一轮「只分析」的结论复核到底、量化到数、落成可执行草案。三件事:① 提交并推送待提交文档;② 收敛本机生产备份暴露面;③ 用只读 SQL 量化载体分布与人工块,并产出载体判定 + 成本中心两份 SQL 草案。
一、本轮执行结果
| # | 事项 | 结果 |
|---|---|---|
| 1 | 提交并推送文档 | ccd5ed2a docs: 补充三块执行载体与通用成本中心方案,已推送 6850bc64..ccd5ed2a main -> main;pre-push 两端全量 check 通过 |
| 2 | 备份目录加固 | backups/ 与子目录 chmod 700,两份 dump chmod 600;删除残留临时 dump(见 §六) |
| 3 | 数据量化 | 只读克隆上完成 8 组聚合(见 §二、§三) |
| 4 | SQL 草案 | 载体判定 + 成本中心/销售事实两份,已在沙箱库零错误应用验证(见 §五) |
二、独立复核:上一轮结论逐条对照
| 上一轮结论 | 本轮复核方式 | 结果 |
|---|---|---|
| 后端 740 测试(737 pass / 3 skipped) | 本地实跑 npm test |
✅ tests 740 / pass 737 / fail 0 / skipped 3 |
| 前端 143 测试全绿 | 本地实跑 | ✅ 143 pass / 0 fail |
typecheck 通过 |
实跑 tsc --noEmit |
✅ 通过 |
| 99 个迁移 / 53 张表 | 数文件 + 数 CREATE TABLE + 查库 |
✅ 99 迁移、53 条 CREATE TABLE;本地库 55 张 = 53 业务表 + schema_migrations + pg_stat_statements×2 |
| 后端非测试源码 371 文件 | find 实测 |
✅ 371(另有测试 109) |
| 无 CI、实际单分支 | 查 .github / .gitlab-ci.yml;git log main..dev |
✅ 均不存在;main..dev 为 0 |
| 巨文件行数(3686/2015/1499/1478) | wc -l |
✅ 完全一致 |
风险项抽查(读源码确认,非复述):发单金额后端只校验 > 0(admin-work-order-management-service.ts:228)✅;寄卖审核 payload.workerId 覆盖归属(consignment-admin-service.ts:606)✅;抢单先锁钱包、指派先锁工单(work-order-grab-repo.ts:25 vs :156)✅ 锁序反转成立;自动工单押金硬编码 0(sync-worker-orders-service.ts:245)✅;Webhook 先落库去重后处理(douyin-mashida/notify-service.ts:95 → :112)✅;/collect/upload 不校验订单存在、/redeem 仅凭订单号、/files/object 无鉴权、CLAIM_TOKEN_TTL_HOURS=0 ✅;Caddy 无 CSP/HSTS ✅。
三、载体分布(近 30 天,只读克隆实测)
判定口径:已支付订单项为单位,「人工块」= 既无 fulfillment_tasks 也无 work_orders。
| 来源 | 已支付项 | 自动发货 affiliate_dash |
接单工单 | 人工块 | 双载体冲突 | 人工块金额 | 人工占比 |
|---|---|---|---|---|---|---|---|
kuaishou-91 |
112,520 | 30,900 | 42,907 | 38,451 | 0 | ¥4,853,281 | 34.2% |
pdd |
3,714 | 0 | 1,648 | 2,066 | 0 | ¥361,364 | 55.6% |
douyin-mashida |
4 | 2 | 0 | 2 | 0 | ¥63 | 50.0% |
| 合计 | 116,238 | 30,902 | 44,555 | 40,519 | 0 | ¥5,214,708 | 34.9% |
补充说明(都已核对):
- 91 的
112,520减去上述三类后还差 262 项,经查是历史执行器kuaishou_ct_assisted(=KUAISHOU_CLOUD,已下线,活到 2026-09-15)的存量任务。这是载体建模必须单列legacy的原因,否则这 262 项会被错算成人工。 - 双载体冲突 = 0 条,说明文档「一个订单项只有一个执行载体」的不变式在当前数据上成立。
- 人工块
order_status全部paid、pay_status全部paid、claim_status全部active—— 零完成信号,与上一轮结论一致。
人工块的形状(监管收益判断)
| 来源 | 涉及店铺 | 单均 | p50 | p90 | ≥¥100 | ≥¥500 |
|---|---|---|---|---|---|---|
| 91 | 8 | ¥126.22 | ¥53 | ¥288 | 13,229 | 2,708 |
| PDD | 4 | ¥174.91 | ¥141 | ¥306 | 1,353 | 150 |
Top 店铺(人工块):向日葵游戏服务店 14,903 项 / ¥183.9 万;西瓜游戏交易店 7,768 项 / ¥118.0 万;小鱼儿游戏服务店 8,190 项 / ¥97.4 万;佳佳游戏交易店 7,460 项 / ¥84.5 万;PDD 向日葵网络游戏专营店 1,885 项 / ¥32.8 万。
结论:人工块店铺高度集中(91 只有 8 个店铺),意味着「先上线人工 case 队列」的监管收益集中在少数店铺上,容易先抓重点、快速看到效果。
月度趋势(确认不是历史遗留)
| 月份 | 已支付项 | 人工块 |
|---|---|---|
| 2026-08 | 142,969 | 46,337 |
| 2026-09 | 103,010 | 39,148 |
| 2026-10(截至 14 日) | 55,647 | 17,469 |
人工成本区间(单均人工成本 X 元的月度量级)
| X | ¥3 | ¥5 | ¥8 | ¥15 |
|---|---|---|---|---|
| 月人工成本 | ¥121,557 | ¥202,595 | ¥324,152 | ¥607,785 |
这是「人工履约投入」的量级估算,不含商品/货源成本(那部分属于 cost_versions)。
四、两个口径硬问题(比上一轮描述更严重)
1. 数量:quantity 不可用,低估约 7.3 倍
| 指标 | 实测值(全量已支付 316,585 项) |
|---|---|
quantity = 1 |
316,578(99.998%) |
quantity > 1 |
7 |
名称里带「N个」但 quantity = 1 |
104,710 |
sum(quantity) |
316,593 |
| 按 SKU 名称解析的数量合计 | 2,316,222 |
用 quantity 统计「卖了多少件」会低估约 7.3 倍。必须在订单项固化 normalized_quantity(草案已加列)。
2. SKU 多码一名:比上一轮更严重
| 商品名 | 不同 sku_code 数 |
项数 |
|---|---|---|
| 苏尔南钻石100颗 | 47 | 3,319 |
| 99999 | 44 | 540 |
| 指挥官密钥1个 | 42 | 26,748 |
| 指挥官密钥5个 | 41 | 3,608 |
| 指挥官密钥10个 | 37 | 3,059 |
| 苏尔南钻石50颗 | 35 | 379 |
(上一轮报的是近 30 天窗口的 27/35/10;本轮是全量已支付口径,两者不矛盾,但都指向同一个结论:不做 channel_product_mappings 就无法统计销量。)
五、对上一轮结论的 4 处修正
| # | 上一轮说法 | 本轮修正 |
|---|---|---|
| 1 | C5「订单项无金额字段」是当下风险 | 是潜在缺口:实测每笔已支付订单恰好 1 个订单项(316,585 单 = 316,585 项),订单级金额暂时等价;但 schema 允许多项,应在做销售事实前补齐 |
| 2 | 三载体互斥(设计不变式) | 数据上已验证:近 30 天双载体 = 0 条 |
| 3 | 自动发货执行器只剩 affiliate_dash |
还有 262 项历史 kuaishou_ct_assisted 任务(已下线,2026-09-15 停);载体建模需单列 legacy,且这类任务仍在领取页给出「已下线」提示 |
| 4 | 手动履约 manual_dispatch 任务极少 |
补充:affiliate_dash 侧仍在途 552 项(link_generated 300 + waiting_binding 252),属运营待跟进而非人工块 |
六、两份 SQL 草案
放在 docs/drafts/,未接入 apps/backend/src/db/migrations(接入时再拆分编号并先跑 npm run check:sql,避免本地栈重启时自动迁移)。
| 文件 | 内容 |
|---|---|
| 载体判定与人工块量化.sql | §1 八组只读量化查询(含实测值注释);§2 判定规则与优先级(含 legacy 与冲突处理);§3 加列 + 回填 + 索引 + 回滚;§4 守恒校验与异常队列查询;§5 人工成本区间 |
| 成本中心与销售事实-DDL草案.sql | product_catalog、channel_product_mappings、cost_items、cost_versions、cost_snapshots、cost_exceptions、sales_daily_facts;订单项口径补齐(normalized_quantity/revenue_amount_fen/revenue_basis/refunded_at);work_product_rules.cost_item_id 过渡列;§5 对平校验;§6 已确认口径与剩余待确认 |
| 人工支出登记-DDL草案.sql | manual_fulfillment_cases(轻量处理记录)+ manual_expense_records(付款项目/金额/订单号/付款人/收款人/凭证/审批)+ manual_expense_events 审计;§3 校验查询;§4 与影子总账的分录约定 |
验证方式:在本地副本上 pg_dump --schema-only 建了一个一次性沙箱库(55 张表),按依赖顺序(载体判定 → 成本中心 → 人工支出登记)用 psql -v ON_ERROR_STOP=1 应用三份草案 —— 零错误:生成 10 张新表(共 65 张)、order_items 由 9 列增至 19 列、27 个 CHECK 约束、169 个索引;校验查询与回填语句均可执行。验证后沙箱库已 DROP。
关键设计约束(三份草案共同遵循):
- 改价只发生在
cost_versions,历史成本靠cost_snapshots固化,永不回写; - 匹配不到成本不默认 0,写入
cost_exceptions,报表必须暴露open数量; carrier_type/carrier_status是派生列,事实来源仍是任务/工单存在性,必须有重算作业与守恒校验;- 报表维度统一
canonical_product_id + shop_id + stat_date,禁止直接用sku_code或orders.total_amount。
七、本机卫生记录(第 2 项执行细节)
| 项 | 处理前 | 处理后 |
|---|---|---|
backups/、backups/postgres/、backups/douyin-platform-clear-20261014/ |
755 |
700 |
order_site_latest.dump(559 MB)、order_site_remote.dump(105 MB) |
644 |
600 |
.order_site_readonly.dump.nKbeRp8kUA(137,330,688 B) |
600,残留 |
已删除,backups/ 由 765 MB 降至 634 MB |
删除前已确认:① 解析后绝对路径为 …/order_site/backups/postgres/.order_site_readonly.dump.nKbeRp8kUA;② 是完整可读的 PostgreSQL 自定义 dump(pg_restore --list 795 条目 / 53 个 TABLE DATA),sha256 1a666af11ae9df2058bc2a5afa2196baefb9c125daf0cdecf18dfd20c59cc075;③ 全仓库无任何脚本引用该文件或其余两份 dump 名;④ 无进程占用;⑤ 与同分钟产出的 order_site_latest.dump 属同一批快照,且本地克隆数据(截至 10-14)比这两份 10-10 快照更新。
遗留建议:本机仍存两份全量生产 dump(含买家信息与平台凭据)。建议确认磁盘已加密;若后续以本地克隆为唯一分析基线,可只保留一份最新 dump。
分析基线建议:本地 docker 栈(order_site-postgres-1)已含 10-14 生产快照(orders 316,597),后续所有 SQL 迭代直接打本地克隆即可,无需再连生产。
八、业务口径确认(2026-10-17)
业务已就四个阻塞问题给出结论;其中两条已用克隆数据独立核验。
| # | 问题 | 结论 | 数据核验 |
|---|---|---|---|
| 1 | 91 的 total_amount 是收入还是成本上限? |
收入:它就是用户付款金额,与快手发码配合 | ✅ 91 已支付 312,569 笔,其中 235,271 笔含快手 kuaishouSendCode.paymentFen;235,268 笔与 total_amount 完全一致(100.00%),仅 3 笔差 ¥1.80 / ¥1.85 / ¥2.00(2026-09-05 / 09-18 / 10-04) |
| 2 | 打手报酬是成本还是代收代付? | 支出/成本:工单结算 → 打手可提现 → 提现打款,属我方真实支出 → 总额法 | — |
| 3 | 人工块的目标? | 先把流程搞清楚:谁处理了哪些、付了多少钱。现状「很多地方需要人工付款,但不知道付款项目、金额、订单号」→ 新增人工支出登记草案;SLA/监管指标延后 | — |
| 4 | 退款/仲裁? | 暂未接入,先预留:字段 + reversal_of_id + 事件类型,本轮不实现逻辑 |
— |
影响:
- 收入口径统一为
revenue_amount_fen = orders.total_amount(revenue_basis = 'user_payment'),草案中原本枚举的三家字段名已简化; - 成本侧确认「打手报酬 = 支出」,
cost_items.cost_type = 'work_order_reward'计入履约成本,不做净额; - 人工块方案重心从「case + SLA」改为「人工支出登记(付款项目 / 金额 / 订单号 / 付款人 / 收款人 / 凭证 / 审批)」;
- 退款相关列与冲正关系保留为预留,不写逻辑。
九、下一步
- 业务仍待拍板 1 个关键口径:收入确认时点(付款 / 发货 / 验收 / 售后期结束)—— 它决定利润表与预收账款;金额口径已定。
- 工程可先做两件不改业务代码的事:
- 建
channel_product_mappings初始映射,把 47 个sku_code归到 1 个标准商品; - 用现有
resolveSkuNameQuantity解析并回填normalized_quantity。
- 建
- 紧接着做人工支出登记(业务当前最痛):
manual_fulfillment_cases+manual_expense_records,先解决「谁付的、什么项目、多少钱、哪个订单」。 - 之后按「商品主数据 → 成本中心影子期 → 人工支出 → 影子总账 → 对账转正」推进。