feat(finance): 支持代录指定客服账户,并上线影子总账/对账/关账/快手平台退款

- 人工确认履约:管理员/财务/运营可传 fundAccountId / creditOwnerAdminUserId
  指定客服备用金/积分账户;客服仍强制本人账户
- 新增迁移 112:finance_accounts / journal_entries / journal_lines /
  periods / reconciliations / reconciliation_items,种子 11 个科目
- 影子总账:销售事实按日生成收入/退款/成本凭证,支持手工凭证、试算平衡;
  不接管钱包余额;总账同步接入定时任务与退款重算
- 期间关账/反关账:关账先补凭证并校验试算平衡,closed 期间禁止新增凭证
- 平台对账:JSON 账单导入,按 provider + platform_order_id 匹配订单/退款,
  标记 matched/amount_mismatch/missing_order/missing_refund/duplicate
- 平台退款:快手行业(91)同意退款 API 接入,成功后落 source=platform;
  抖音/拼多多返回 501,保留手工退款
- 新增后台「财务 → 总账与对账」页面(总账/期间/对账三个 Tab)
- 集成测试扩展到代录、总账平衡、关账阻断、手工凭证、对账匹配

验证:backend check 844(840 pass / 4 skip);frontend check 172 + build;
迁移 112 在 scratch 库全量执行并重跑幂等;本地生产副本已升级到 112,
销售事实同步 56 条凭证,借贷合计 1,885,351,864 = 1,885,351,864。
This commit is contained in:
yml2213
2026-10-26 13:32:47 +08:00
parent f0eb8a5e05
commit 62763ddf0c
31 changed files with 2961 additions and 55 deletions
+12 -11
View File
@@ -1,6 +1,6 @@
# order_site 文档索引
> 最后校准:2026-10-26,代码基线 `dev`(合并 `dev1023` + 人工成本完整性修复,迁移到 `111`;**未推送、未部署生产**)。
> 最后校准:2026-10-26,代码基线 `dev`(合并 `dev1023` + 人工成本完整性修复,迁移到 `112`;**未推送、未部署生产**)。
> 数据基线:生产 dump `backups/postgres/order_site-20261022-092601.dump`(数据 2026-07-10 ~ 2026-10-22);本地生产副本已升级到 111,只跑了近 30 天增量。历史全量数字仅作基线,**上线验收以 [财务上线初始化与验收-2026-10-26.md](财务上线初始化与验收-2026-10-26.md) 为准**。
> 本文是 `docs/` 的唯一入口。**财务与履约口径以 [财务与履约口径总纲-2026-10-23.md](财务与履约口径总纲-2026-10-23.md) 为准**;数据模型看 [成本中心与履约模型.md](成本中心与履约模型.md),接口看 [成本中心API契约.md](成本中心API契约.md)。
> 新增文档必须在下表登记状态;过期文档不再直接改写结论,统一移入 `docs/archive/`。
@@ -86,11 +86,12 @@
| 人工缺成本监控 | **已实施(2026-10-26)** | `manual_cost_missing`:首次人工配置之后的订单项未确认即入队,确认后自动收口 |
| 履约方式统一 | **已实施 P0** | 迁移 `105`;375,447 项全部回填:接单平台 153,148、人工 115,194、历史平台 53,901、自动发货 53,204 |
| 人工商品归一 | **已实施 P1(本次快照恢复执行)** | 人工 115,194 项已归一为 1,195 个 `man:<内部SKU>` 商品;历史人工支出仍不补录 |
| 影子总账 | 未实施 | 现有财务页仍是 `UNION ALL` 业务事件拼装,不是复式总账 |
| 影子总账 | **已实施 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-26):`dev` 已合并 `dev1023` 与人工成本完整性修复,迁移到 `111`;本地生产副本已验证 101 → 111(109/110 索引在生产规模数据上实测 < 0.3s),临时库全量执行与重跑幂等通过。**未推送、未部署生产**;生产口径仍以 `main` 为准。上线前按 [财务上线初始化与验收-2026-10-26.md](财务上线初始化与验收-2026-10-26.md) 初始化资金与人工 SKU。
> 分支状态(2026-10-26):`dev` 已合并 `dev1023` 与人工成本完整性修复,迁移到 `112`;本地生产副本已验证 101 → 112(109/110 索引在生产规模数据上实测 < 0.3s),临时库全量执行与重跑幂等通过。**未推送、未部署生产**;生产口径仍以 `main` 为准。上线前按 [财务上线初始化与验收-2026-10-26.md](财务上线初始化与验收-2026-10-26.md) 初始化资金与人工 SKU。
> 财务与履约口径以 [财务与履约口径总纲-2026-10-23.md](财务与履约口径总纲-2026-10-23.md) 为准。
## 三、统一实施顺序
@@ -99,11 +100,11 @@
0. 统一履约事实(fulfillment_mode + 成本模型正交) 已完成 P0(迁移 105)
1. 商品主数据 + 渠道 SKU 映射 已完成 P0(仅自动发货/接单平台)
2. 成本中心 + 销售事实 已完成 P0
2.5 人工成本链路收敛(确认履约 → 扣积分/备用金 → 写快照) 已完成 P0(迁移 104/107)
2.5 人工成本链路收敛(确认履约 → 扣积分/备用金 → 写快照) 已完成 P0(迁移 104/107/111)
3. 人工商品归一与上线后人工成本全覆盖 已完成代码;生产数据需上线后配置 SKU(历史不补录)
4. 退款冲减与异常队列 已完成手工退款;平台退款 API 未实施;人工缺成本已入队
5. 影子总账(订单、工单、押金、提现、寄卖、售后) 未实施
6. 平台对账、报表、期间关账 未实施
4. 退款冲减与异常队列 已完成手工退款 + 快手平台退款;人工缺成本已入队
5. 影子总账(销售事实 + 手工凭证) 已完成 P0(迁移 112)
6. 平台对账、期间关账 已完成 P0(手工账单导入);平台自动拉单未实施
```
**第 0 步已完成。** 迁移、回填、代码改造与验收结果见 [成本中心与履约模型](成本中心与履约模型.md) §六、§八。下一步只做第 3 步人工商品归一,不要同时改退款或总账。
@@ -128,12 +129,12 @@
| 文档 | 状态 | 用途 |
| --- | --- | --- |
| [财务与履约口径总纲-2026-10-23.md](财务与履约口径总纲-2026-10-23.md) | **现行唯一口径** | 履约方式、成本模型、人工全覆盖、历史策略、实施顺序、运营日检与验收 SQL |
| [成本中心与履约模型.md](成本中心与履约模型.md) | 现行 | 商品、成本版本、快照、异常、销售事实的数据模型;迁移 `103`–`111`;履约回填;迁移基线与本地库同步;索引与性能 |
| [成本中心与履约模型.md](成本中心与履约模型.md) | 现行 | 商品、成本版本、快照、异常、销售事实的数据模型;迁移 `103`–`112`;履约回填;迁移基线与本地库同步;索引与性能 |
| [成本中心API契约.md](成本中心API契约.md) | 现行 | 成本中心接口字段替换总表、枚举、模块边界(后端 5 模块 + 前端 4 个固定 Tab) |
| [人工支出与备用金.md](人工支出与备用金.md) | 现行(P0 已实施) | 确认履约流程/权限、客服备用金台账、本人账户与编号规则 |
| [财务上线初始化与验收-2026-10-26.md](财务上线初始化与验收-2026-10-26.md) | **现行上线手册** | 迁移后资金/人工 SKU 初始化、验收 SQL、日常监控 |
| [财务系统集成方案.md](财务系统集成方案.md) | 现行方案(总账未实施) | 复式记账、总账表、对账、关账 |
| [影子总账说明.md](影子总账说明.md) | 现行说明(未实施) | 影子总账是什么、和钱包流水的区别、对账与转正标准 |
| [财务系统集成方案.md](财务系统集成方案.md) | 现行方案(影子总账 P0 已实施) | 复式记账、总账表、对账、关账;P1/P2 平台自动对账待接 |
| [影子总账说明.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) | 现行 | 进单、履约、领取、电子凭证的整体链路 |
+2 -2
View File
@@ -101,7 +101,7 @@
- 接口:`apps/backend/src/routes/admin/finance.ts` 的 `POST /finance/manual-fulfillment/confirm`;待办 `GET /finance/manual-fulfillment/pending`
- 组件:`apps/frontend/src/components/admin/ManualFulfillmentConfirmModal.tsx`
- 订单入口:订单列表/详情「确认履约」
- 权限:`admin / operator / support`;客服只能使用本人备用金/积分账户
- 权限:`admin / operator / support`;客服只能使用本人备用金/积分账户;管理员/财务/运营可在确认时通过 `fundAccountId` / `creditOwnerAdminUserId` 指定客服账户代录
- 配置前置:商品与成本 → 人工 SKU 配置(`manual_fulfillment_configs`)
### 3.2 资金流与成本流(同一事务)
@@ -137,7 +137,7 @@ payeeName -- 收款方(选填,默认「人工履约」)
note -- 备注(选填)
```
平台、消耗积分与固定成本都来自人工 SKU 配置,客服不选账户、不改平台。
平台、消耗积分与固定成本都来自人工 SKU 配置;客服不选账户、不改平台。管理员/财务/运营代录时额外传 `fundAccountId`(现金)或 `creditOwnerAdminUserId`(积分),未指定则回退本人账户。
### 3.5 配置与监控
@@ -1,6 +1,6 @@
# 多发货平台与电子凭证整体链路
> 状态:现行。最后校准:2026-10-23(代码基线 `dev`(合并 dev1023 后)+ 迁移 `103`–`111`;履约方式已统一落库)。
> 状态:现行。最后校准:2026-10-23(代码基线 `dev`(合并 dev1023 后)+ 迁移 `103`–`112`;履约方式已统一落库)。
> 财务与履约总口径见 [财务与履约口径总纲-2026-10-23.md](../财务与履约口径总纲-2026-10-23.md)。
> 来源口径:本系统只有三个订单来源——`kuaishou-91`、`pdd`、`douyin-mashida`。**91 回调与快手 send-code 是同一个 `kuaishou-91` 来源的两条数据通道**(91=骨架权威源,快手 send-code=补全/兜底源),不是一个来源加另一个来源。
+4 -4
View File
@@ -1,8 +1,8 @@
# 影子总账到底是什么意思
> 状态:**现行说明(未实施)**
> 最后校准:2026-10-23
> 代码基线:`dev`(合并 dev1023 后)+ 迁移 `103`–`111`(已合并到 `dev`,**未推送、未部署生产**)
> 状态:**现行说明(P0 已实施,2026-10-26)**
> 最后校准:2026-10-26
> 代码基线:`dev`(合并 dev1023 后)+ 迁移 `103`–`112`(已合并到 `dev`,**未推送、未部署生产**)
> 配套方案:[财务系统集成方案.md](财务系统集成方案.md)
> **总口径以 [财务与履约口径总纲-2026-10-23.md](财务与履约口径总纲-2026-10-23.md) 为准。**
> 前置:统一履约事实、商品主数据、渠道映射、成本中心与销售事实;实施顺序以总纲第六节为准。
@@ -10,7 +10,7 @@
>
> 边界:影子总账解决“钱怎么记、怎么对”,不负责“商品是什么、成本是多少、人工谁处理”。商品与成本见 [成本中心与履约模型.md](成本中心与履约模型.md),人工支出见 [人工支出与备用金.md](人工支出与备用金.md)。
> 当前进度:客服备用金、商品与成本中心、成本快照、销售事实、人工录单已实施;`finance_*` 表、分录、对账、转正均未实施。人工成本现在只有一条链路:人工录单 → 扣客服备用金 → 写成本快照,无登记单/审批/报销;历史人工支出找不回来、直接放弃,上线后必须全覆盖。
> 当前进度:客服备用金、商品与成本中心、成本快照、销售事实、人工确认已实施;`finance_*` 科目/凭证/期间/对账表已建,销售事实按日生成凭证、手工凭证、试算平衡、期间关账与手工账单对账已上线 P0。**尚未接管钱包余额**,平台自动拉单与正式转正未实施。人工成本现在只有一条链路:确认履约 → 扣客服积分/备用金 → 写成本快照,无登记单/审批/报销;历史人工支出找不回来、直接放弃,上线后必须全覆盖。
---
+32 -1
View File
@@ -2,7 +2,7 @@
> 状态:**现行**。后端服务与前端页面都必须严格按此实现,不得各自发挥。
> 最后校准:2026-10-25
> 代码基线:`dev`(合并 dev1023 后)+ 迁移 `103`–`111`(已合并到 `dev`,**未推送、未部署生产**)
> 代码基线:`dev`(合并 dev1023 后)+ 迁移 `103`–`112`(已合并到 `dev`,**未推送、未部署生产**)
> 详细业务口径见 [财务与履约口径总纲-2026-10-23.md](财务与履约口径总纲-2026-10-23.md);数据模型见 [成本中心与履约模型.md](成本中心与履约模型.md)。
## 一、字段替换总表
@@ -306,3 +306,34 @@ export type CostModel =
```
`CostCarrierType` 已删除。
## 八、总账 / 期间 / 对账接口(2026-10-26)
| 方法 | 路径 | 权限 | 说明 |
| --- | --- | --- | --- |
| GET | `/api/v1/admin/finance/ledger/accounts` | finance.view | 科目表 |
| GET | `/api/v1/admin/finance/ledger/trial-balance?dateFrom&dateTo` | finance.view | 试算平衡 |
| GET | `/api/v1/admin/finance/ledger/entries?dateFrom&dateTo&page&pageSize` | finance.view | 凭证列表(含分录) |
| POST | `/api/v1/admin/finance/ledger/sync` | finance.config | 按日期区间同步销售事实到总账 |
| POST | `/api/v1/admin/finance/ledger/manual-voucher` | finance.config | 手工凭证(借贷必须平衡) |
| GET | `/api/v1/admin/finance/periods` | finance.view | 会计期间列表 |
| POST | `/api/v1/admin/finance/periods/:periodKey/close` | finance.config | 关账(先补凭证) |
| POST | `/api/v1/admin/finance/periods/:periodKey/reopen` | finance.config | 反关账 |
| GET | `/api/v1/admin/finance/reconciliations` | finance.view | 对账批次 |
| POST | `/api/v1/admin/finance/reconciliations/import` | finance.config | 导入平台账单 JSON 并匹配 |
| GET | `/api/v1/admin/finance/reconciliations/:id` | finance.view | 对账明细 |
| POST | `/api/v1/admin/finance/reconciliations/:id/resolve` | finance.config | 标记差异已解决 |
| POST | `/api/v1/admin/orders/:orderId/refunds/platform` | finance.config | 平台退款(当前仅快手 91) |
确认履约接口新增代录字段:
```jsonc
{
"orderItemId": 123,
"costFen": 100,
"fundAccountId": 45, // 现金路径:管理员/财务指定客服备用金账户
"creditOwnerAdminUserId": 67 // 积分路径:管理员/财务指定客服账号
}
```
客服角色只能使用本人账户;传了也会被服务端忽略。
+4 -3
View File
@@ -2,7 +2,7 @@
> 状态:**现行**。商品主数据、成本中心、成本快照、销售事实、履约事实均已落地。
> 最后校准:2026-10-26
> 代码基线:`dev`(合并 dev1023 + 人工成本完整性修复,迁移到 `111`)
> 代码基线:`dev`(合并 dev1023 + 人工成本完整性修复,迁移到 `112`)
> 数据基线:生产 dump `order_site-20261022-092601.dump`(2026-07-10 ~ 2026-10-22);本地只跑了近 30 天增量,历史数字仅作基线。
> 上线初始化/验收见 [财务上线初始化与验收-2026-10-26.md](财务上线初始化与验收-2026-10-26.md)。
> **业务口径以 [财务与履约口径总纲-2026-10-23.md](财务与履约口径总纲-2026-10-23.md) 为准**;本文只负责数据模型、迁移与运维。
@@ -35,7 +35,7 @@ orders ──┬── order_items ──── fulfillment_mode (唯一履约
## 一、迁移基线:10 个收敛为 5 个
原 `dev` 分支上,商品、成本中心、人工履约用 10 个迁移(`103`–`112`,1,275 行)分批落地,字段反复摇摆。其中:
原 `dev` 分支上,商品、成本中心、人工履约用 10 个**历史编号**迁移(`103`–`112`,1,275 行)分批落地,字段反复摇摆。其中:
- 原 `108`(下线人工支出登记)与原 `109`(隔离历史快照主体)在「生产 102 → 当前」的唯一升级路径上是**空操作**;
- 原 `111` 是给 `104` 自身种子打的补丁(draft 占位改 active 占位);
@@ -59,6 +59,7 @@ orders ──┬── order_items ──── fulfillment_mode (唯一履约
| `109_work_order_share_participation.sql` | 拼单多次参与份额模型(与本模块无关,同批上线) |
| `110_work_order_hall_and_shop_indexes.sql` | 大厅置顶/店铺筛选索引(与本模块无关) |
| `111_manual_cost_integrity.sql` | 人工成本单事务兜底:订单项级唯一、`subject_id=order_item_id`、人工 SKU 匹配索引、`manual_cost_missing` 监控所需索引 |
| `112_finance_ledger.sql` | 财务总账(科目/凭证/期间/对账),与本模块无直接依赖,同批上线 |
**合并原则**:同一批上线的结构性 DDL 才合并;数据回填与业务口径注释跟着所属表走。`103` 保持独立(商品主数据是成本与销售事实的共同上游),`106` 保持独立(退款是独立业务线)。
@@ -267,7 +268,7 @@ resolved_at, superseded_at, created_at
- 匹配不到成本时写 `cost_missing` 异常,**不能默认 0**;
- 履约方式不存快照里,需要时 join `order_items.fulfillment_mode`;
- 人工单的快照主体是 `subject_type='manual_case'` + `subject_id=order_item_id`;资金流水 id 只写 `metadata_json`,**没有独立的登记单表**;
- 负数 `subject_id` 表示历史孤儿快照(迁移 `104` 约定),迁移 `111` 保留不动,不参与新链路;
- 负数 `subject_id` 表示历史孤儿快照(迁移 `104` 约定),迁移 `112` 保留不动,不参与新链路;
- 一个订单项最多一条有效人工快照(`uq_cost_snapshots_manual_order_item`)。
### 3.5 `cost_exceptions`
+1 -1
View File
@@ -1,6 +1,6 @@
# 接单模板匹配引擎重构设计
> 目标读者:后端 / 后台运营。状态:**P0 + P1 已实施;P2 / P3 待办**。最后校准:2026-10-23(代码基线 `dev`(合并 dev1023 后)+ 迁移 `103`–`111`;匹配业务逻辑未变)。
> 目标读者:后端 / 后台运营。状态:**P0 + P1 已实施;P2 / P3 待办**。最后校准:2026-10-23(代码基线 `dev`(合并 dev1023 后)+ 迁移 `103`–`112`;匹配业务逻辑未变)。
>
> 一句话:把「订单信息 → 接单模板(价格/拼单/要求)」的匹配,从散落的多个消费点、平台判断和"店铺必填"的绑定表里,收敛为**一个平台无关的引擎**:匹配条件完全由**订单信息**表达,**店铺只是可选条件之一**,新增来源只加一个适配器 + 一组配置。
>
@@ -1,14 +1,14 @@
# 财务/成本上线初始化与验收(2026-10-26)
> 状态:现行操作手册。适用于 `dev` 合并后的财务/成本模块上线;**历史人工成本不补录**。
> 代码基线:迁移 `103`–`111`(本手册写于人工成本完整性与配置自动匹配修复之后)。
> 代码基线:迁移 `103`–`112`(本手册写于人工成本完整性与配置自动匹配修复之后)。
> 数据基线:生产 dump `2026-10-22`(迁移 `101`)。历史人工支出找不回来,只保证**首次配置人工履约之后**的新单可记录、可监控。
---
## 〇、上线范围与边界
本次上线的是「备用金 + 人工成本 + 成本中心 + 销售事实」模块,不是复式总账:
本次上线的是「备用金 + 人工成本 + 成本中心 + 销售事实 + 影子总账 P0」模块:
| 能力 | 本次是否上线 |
| --- | --- |
@@ -16,11 +16,13 @@
| 人工 SKU 配置 + 确认履约(扣积分/备用金 + 写 actual 快照) | 是(配置需上线后设置) |
| 商品目录、渠道映射、成本版本、成本快照、销售事实 | 是 |
| 手工退款登记(冲减收入、关闭成本异常) | 是 |
| 平台退款 API、影子总账、对账中心、期间关账 | **否**(后续 P3) |
| 影子总账(科目/凭证/试算平衡)、期间关账、平台对账 | 是(迁移 `112`;对账当前为手工账单导入) |
| 平台退款 API | **部分**:快手行业(91)已接入;抖音/拼多多仍手工登记 |
明确不做:
- 历史人工支出不补录、不按均价估算;
- 历史人工单的 `cost_missing` 不进入上线后监控口径;
- 平台自动拉单、全平台退款 API、总账接管钱包余额暂不做;
- 人工成本监控从**第一次创建人工履约配置的时间**开始计算(`manual_fulfillment_configs.created_at`)。
---
@@ -209,6 +211,22 @@ SELECT
SELECT reason, status, COUNT(*) FROM cost_exceptions
WHERE created_at >= :launch_at
GROUP BY 1,2 ORDER BY 3 DESC;
-- 8. 总账借贷平衡(应为差额 0)
SELECT
COALESCE(SUM(debit_fen), 0) AS debit_fen,
COALESCE(SUM(credit_fen), 0) AS credit_fen,
COALESCE(SUM(debit_fen), 0) - COALESCE(SUM(credit_fen), 0) AS diff_fen
FROM finance_journal_lines l
JOIN finance_journal_entries e ON e.id = l.entry_id AND e.status = 'posted'
WHERE e.occurred_at >= :launch_at;
-- 9. 已关账期间不应再有新凭证
SELECT e.period_key, COUNT(*)
FROM finance_journal_entries e
JOIN finance_periods p ON p.period_key = e.period_key AND p.status = 'closed'
WHERE e.created_at >= :launch_at
GROUP BY 1;
```
---
@@ -225,10 +243,51 @@ GROUP BY 1,2 ORDER BY 3 DESC;
---
## 四、已知边界(不要对外承诺)
## 四、总账、期间关账与平台对账(迁移 112)
1. 没有复式总账、平台对账、期间关账;现有「收支明细」是业务事件拼装,不是会计账。
2. 平台退款 API 未接入,退款只支持后台手工登记(整单/指定商品,可撤销)。
入口:后台「财务 → 总账与对账」(`/admin/finance/ledger`)。
### 4.1 影子总账
- 销售事实按日同步:收入(借 1101 / 贷 4001)、退款(借 4101 / 贷 1101)、成本(借 5001 / 贷 2001);
- 财务可手工录入调整凭证(借贷科目 + 金额 + 摘要),必须借贷平衡;
- 试算平衡按日期区间展示;总账不接管 `worker_wallets` / `fund_accounts` 余额;
- 定时任务 `cost-finance-sync` 每 5 分钟同步最近窗口;也可手动「同步销售事实到总账」。
### 4.2 期间关账
- 期间按 `YYYY-MM`;关账前会先补齐该期间凭证,并校验试算平衡;
- 关账后该期间禁止新增凭证;反关账需 `finance.config` 权限并写审计;
- 关账不修改历史凭证,只是阻断新写入。
### 4.3 平台对账
- 支持粘贴 JSON 账单导入(销售/退款行),按 `provider + platform_order_id` 匹配订单/退款;
- 明细状态:`matched / amount_mismatch / missing_order / missing_refund / duplicate`;
- 差异批次可标记解决(记录备注);平台自动拉单后续复用同一匹配器。
账单行示例:
```json
[
{ "platformOrderId": "123456", "entryType": "sale", "amountFen": 990 },
{ "platformOrderId": "123456", "entryType": "refund", "amountFen": 100, "externalRef": "RF-1" }
]
```
### 4.4 平台退款 API
- 快手行业(91):`POST /api/v1/admin/orders/:orderId/refunds/platform`,传 `platformRefundId`、`orderItemId`、`amountFen`;
先调用快手「同意退款」,成功后再落 `order_refunds.source='platform'` 并冲减销售事实;
- 抖音/拼多多:暂无退款 API,返回 501,仍用「手工退款登记」;
- 平台退款必须传订单项;参数校验在调用平台之前完成,避免平台已同意、本地记账失败。
---
## 五、已知边界(不要对外承诺)
1. 总账是**影子账**:销售事实按日凭证 + 手工凭证;尚未覆盖每一笔钱包/寄卖/提现业务,也没有接管余额;「收支明细」仍是业务事件拼装。
2. 平台对账当前是**手工账单 JSON 导入**,未做平台自动拉单;平台退款 API 仅接入快手(91),抖音/拼多多仍手工登记。
3. 平台服务费/支付通道费/寄卖货款成本确认时点仍待定;相关成本项配置为空时不参与毛利。
4. 历史人工成本、历史平台成本、历史未归一商品不补齐;历史区间毛利只能作为参考。
5. 管理员/财务代录目前仍使用**本人**备用金/积分账户,不能指定客服账户。
5. 管理员/财务代录已支持指定客服备用金/积分账户;客服只能使用本人账户。
@@ -2,7 +2,7 @@
> 状态:**现行唯一口径**。本文是财务、成本、履约分类的总入口;其他文档与本文件冲突时,以本文为准。
> 最后校准:2026-10-26
> 代码基线:`dev`(合并 dev1023 + 人工成本完整性修复,迁移到 `111`)
> 代码基线:`dev`(合并 dev1023 + 人工成本完整性修复,迁移到 `112`)
> 数据基线:§二/§七 的数字来自 2026-10-22 生产 dump 的**历史快照**,只用于理解历史缺口,**不再作为上线验收依据**;
> 上线初始化与验收以 [财务上线初始化与验收-2026-10-26.md](财务上线初始化与验收-2026-10-26.md) 为准。
> 适用范围:订单接入、履约判定、商品归一、成本快照、销售事实、人工录单、备用金、后续总账与对账。
@@ -147,8 +147,8 @@
| P0 | 统一履约事实(`fulfillment_mode`)+ 成本模型正交 | **已完成(本地,未部署生产)** |
| P0.5 | 人工成本链路收敛为「人工录单 → 扣备用金 → 写快照」(下线登记/审批/报销) | **已完成(本地,未部署生产)** |
| P1 | 人工商品归一(`man:<skuId>`)+ 上线后人工成本全覆盖 | **已完成(本地,未部署生产)** |
| P2 | 退款冲减与异常闭环 | **已完成(手动登记先行,平台退款 API 待接入)** |
| P3 | 影子总账与对账 | 未实施 |
| P2 | 退款冲减与异常闭环 | **已完成(手动登记 + 快手平台退款;抖音/拼多多仍手工)** |
| P3 | 影子总账与对账 | **已完成 P0(2026-10-26)**:总账/试算平衡/期间关账/手工账单对账;平台自动拉单待接 |
P0 的具体迁移、回填、代码清单与验收 SQL 见 [成本中心与履约模型](成本中心与履约模型.md);接口契约见 [成本中心API契约](成本中心API契约.md)。
@@ -170,18 +170,18 @@ P0 的具体迁移、回填、代码清单与验收 SQL 见 [成本中心与履
| 本地 316,585 项回填 | **已实施** | `fulfillment:backfill`,四项计数与 §二 一致 |
| 成本模型与履约方式正交(去 `carrier_type`) | **已实施(本地库已改造)** | 迁移 `103`–`108`;`cost_items.cost_model` |
| 10 个迁移收敛为 5 个 | **已实施** | `103_product_catalog` ~ `107_manual_fulfillment`(后续新增 `108`–`111` 增量) |
| 人工确认原子性/防重复 | **已实施(2026-10-26)** | 单事务 + 订单项行锁 + `uq_cost_snapshots_manual_order_item`(迁移 `111`);集成测试覆盖并发/回滚 |
| 人工确认原子性/防重复 | **已实施(2026-10-26)** | 单事务 + 订单项行锁 + `uq_cost_snapshots_manual_order_item`(迁移 `112`);集成测试覆盖并发/回滚 |
| 人工 SKU 配置自动匹配 | **已实施(2026-10-26)** | 保存配置立即回填 + 定时任务 rematch + 确认时按 SKU 兜底匹配 |
| 人工缺成本监控 | **已实施(2026-10-26)** | `manual_cost_missing`,从首次人工配置时间起算,确认后自动收口 |
| 人工成本链路收敛为「人工录单 → 扣备用金 → 写快照」 | **已实施(本地库已改造)** | 迁移 `104`;登记单与审批报销已下线,口径固化在成本中心迁移 |
| 人工商品归一 `man:<skuId>` | **已实施(本地库已归一)** | `manual-product-normalization-service` + `POST /cost-center/manual-products/normalize`;1,116 个 `man:` 商品、91,606 个人工订单项归一,人工未归一 = 0 |
| 人工商品归一后的销售事实 | **已实施** | 94 天分 30 天窗口重算:26,507 行;人工 ¥1,219.20 万收入全部按 `man:` 商品归集 |
| 退款冲减、异常闭环 | **已实施(手动登记先行)** | 迁移 `106_order_refunds`;订单页「退款登记」(整单/指定商品、可撤销);销售事实按有效退款冲减;全额退完后自动关闭该订单项成本异常并写 `resolution_note` |
| 平台退款 API 接入 | **未实施** | 预留 `order_refunds.source='api'/'platform'` 与 `external_ref` |
| 影子总账、对账、关账 | **未实施** | §六 P3 |
| 平台退款 API 接入 | **部分实施** | 快手行业(91)同意退款已接入,落 `source='platform'` + `external_ref`;抖音/拼多多仍手工 |
| 影子总账、对账、关账 | **已实施 P0** | 迁移 `112`;销售事实按日凭证 + 手工凭证 + 试算平衡 + 账单导入对账 + 关账/反关账 |
> 历史平台仍有 53,901 个订单项(¥389.12 万)未归一,不属于 P1 范围;人工历史成本按既定口径不补录,因此人工毛利当前是“收入已归商品、成本仅新单有”的状态。
> 分支事实:以上实现已合并到 `dev`;迁移 `103`–`111` **未推送远端、未部署生产**。生产口径仍以 `main` 为准;上线前按 [财务上线初始化与验收-2026-10-26.md](财务上线初始化与验收-2026-10-26.md) 初始化资金与人工 SKU。
> 分支事实:以上实现已合并到 `dev`;迁移 `103`–`112` **未推送远端、未部署生产**。生产口径仍以 `main` 为准;上线前按 [财务上线初始化与验收-2026-10-26.md](财务上线初始化与验收-2026-10-26.md) 初始化资金与人工 SKU。
---
@@ -307,7 +307,7 @@ WHERE oi.fulfillment_mode = 'manual'
| [成本中心与履约模型.md](成本中心与履约模型.md) | 商品、成本版本、快照、销售事实的数据模型与迁移 | 现行 |
| [成本中心API契约.md](成本中心API契约.md) | 成本中心后端/前端接口字段与模块边界 | 现行 |
| [人工支出与备用金.md](人工支出与备用金.md) | 人工录单、客服备用金台账与权限 | 现行(P0 已实施) |
| [财务系统集成方案.md](财务系统集成方案.md) | `finance_*` 复式总账层(未实施) | 方案 |
| [财务系统集成方案.md](财务系统集成方案.md) | `finance_*` 复式总账层(P0 已实施) | 现行方案 |
| [README.md](README.md) | 文档索引、分支与进度 | 现行入口 |
维护规则:
+7 -5
View File
@@ -1,9 +1,9 @@
# 财务系统集成方案
> 状态:**现行方案(总账层未实施)**。本文只描述 `finance_*` 总账层;当前总账表尚未建立,现有财务页仍是 `UNION ALL` 业务事件拼装。
> 状态:**现行方案(影子总账 P0 已实施,2026-10-26)**。`finance_accounts / journal_entries / journal_lines / periods / reconciliations` 已建;总账不接管钱包余额;对账当前为手工账单导入,平台自动拉单待接。
> 最后校准:2026-10-26
> 代码基线:`dev`(迁移到 `111`,**未推送、未部署生产**)
> 说明:本文是后续 P3 总账/对账/关账方案,**尚未实施**;本次上线范围(备用金、人工成本、成本中心、销售事实)与初始化步骤见 [财务上线初始化与验收-2026-10-26.md](财务上线初始化与验收-2026-10-26.md)。
> 代码基线:`dev`(迁移到 `112`,**未推送、未部署生产**)
> 说明:本文是总账/对账/关账的目标架构与分期;当前已实施 P0(销售事实凭证、手工凭证、试算平衡、期间关账、手工账单对账)与快手平台退款。初始化步骤见 [财务上线初始化与验收-2026-10-26.md](财务上线初始化与验收-2026-10-26.md)。
> **履约方式、成本模型、人工全覆盖口径以 [财务与履约口径总纲-2026-10-23.md](财务与履约口径总纲-2026-10-23.md) 为准**;本文不重复分类设计。
> 目标:在**不破坏现有抢单、押金、结算、寄卖、提现链路**的前提下,增加可对账、可关账、可追溯的复式记账底座。
> 结论先说:**不要直接在 `worker_wallets` / `worker_wallet_ledgers` 上继续加字段。** 现有表是业务钱包与流水,不是会计总账;正确做法是新增复式记账底座,让现有钱包成为它的“余额投影”。
@@ -21,8 +21,10 @@
| `sales_daily_facts` / 订单级毛利 | **已实施 P0(`dev` 分支)**,迁移 `105`;94 天收入 ¥2,650.87 万、成本 ¥950.27 万 |
| 人工成本录入(确认履约 → 扣积分/备用金 → 写快照) | **已实施 P0(`dev` 分支)**,迁移 `104/107`;2026-10-24 人工履约页下线、入口收敛到订单页;**无登记单、无审批、无报销** |
| 履约方式统一 `fulfillment_mode` | **已实施 P0(`dev` 分支)**;迁移 `105`,316,585 项已回填;订单页、成本快照、销售事实统一读该字段 |
| `finance_accounts` / `finance_business_events` / `finance_journal_*` | 未实施 |
| `finance_settlements` / `finance_reconciliations` | 未实施 |
| `finance_accounts` / `finance_journal_entries` / `finance_journal_lines` | **已实施 P0(迁移 112)** |
| `finance_periods` / `finance_reconciliations` / `finance_reconciliation_items` | **已实施 P0(迁移 112)** |
| `finance_business_events` / `finance_settlements` | 未实施(当前用条目唯一键幂等) |
| 现有 `admin-finance-service.ts` | 仍是业务事件 `UNION ALL`,不是总账 |
**人工成本只有一条链路**:订单列表/详情点「确认履约」→ 扣客服积分或备用金 → 写 `cost_snapshots`(`subject_type='manual_case'`)。没有独立的人工支出登记表,也没有审批与报销环节。
+3 -2
View File
@@ -219,7 +219,7 @@ docker compose ps
docker compose logs -f backend
```
## 财务/成本上线后的初始化(迁移 102–111)
## 财务/成本上线后的初始化(迁移 102–112)
代码与迁移只负责建表;**备用金账户、积分余额、人工 SKU 配置不会自动创建**。
首次上线后按 [财务上线初始化与验收-2026-10-26.md](财务上线初始化与验收-2026-10-26.md) 执行:
@@ -227,7 +227,8 @@ docker compose logs -f backend
1. 钱包管理 → 补建客服备用金账户 → 按需拨付;
2. 商品与成本 → 积分钱包 → 给客服发放三平台积分;
3. 商品与成本 → 人工 SKU 配置 → 扫描并逐项配置(保存后自动回填订单项);
4. 用手册 §二 的验收 SQL 检查:配置覆盖、人工成本快照、`manual_cost_missing`、销售事实对平。
4. 打开「财务 → 总账与对账」,同步总账、检查试算平衡;按需关账/导入平台账单;
5. 用手册 §二 的验收 SQL 检查:配置覆盖、人工成本快照、`manual_cost_missing`、销售事实与总账对平。
> 历史人工成本不补录;人工成本监控从第一次创建人工履约配置的时间开始。
> 定时任务 `cost-finance-sync` 每 5 分钟运行,负责履约归集、人工 SKU 回填、成本快照与销售事实。