refactor(cost-center): 收敛人工 SKU 自动创建流程
This commit is contained in:
+126
-86
@@ -7,16 +7,16 @@
|
||||
|
||||
## 一、字段替换总表
|
||||
|
||||
| 旧字段 | 新字段 | 出现位置 |
|
||||
| --- | --- | --- |
|
||||
| `cost_items.carrier_type` | `cost_items.cost_model` | DB / 成本项接口 |
|
||||
| `cost_items.cost_type` | (并入 `cost_model`) | DB / 成本项接口 |
|
||||
| `cost_snapshots.carrier_type` | (删除) | DB |
|
||||
| `cost_exceptions.carrier_type` | (删除) | DB |
|
||||
| `product_catalog.carrier_type` | (删除,改由 `canonical_sku` 前缀推导) | DB / 商品接口 |
|
||||
| `sales_daily_facts.carrier_type` | `sales_daily_facts.channel` | DB / 销售事实接口 |
|
||||
| `work_product_rules.legacy_cost_source` | (删除) | DB |
|
||||
| `manual_expense_records` / `manual_expense_events` | (删除,人工成本只走确认履约) | DB |
|
||||
| 旧字段 | 新字段 | 出现位置 |
|
||||
| -------------------------------------------------- | --------------------------------------- | ----------------- |
|
||||
| `cost_items.carrier_type` | `cost_items.cost_model` | DB / 成本项接口 |
|
||||
| `cost_items.cost_type` | (并入 `cost_model`) | DB / 成本项接口 |
|
||||
| `cost_snapshots.carrier_type` | (删除) | DB |
|
||||
| `cost_exceptions.carrier_type` | (删除) | DB |
|
||||
| `product_catalog.carrier_type` | (删除,改由 `canonical_sku` 前缀推导) | DB / 商品接口 |
|
||||
| `sales_daily_facts.carrier_type` | `sales_daily_facts.channel` | DB / 销售事实接口 |
|
||||
| `work_product_rules.legacy_cost_source` | (删除) | DB |
|
||||
| `manual_expense_records` / `manual_expense_events` | (删除,人工成本只走确认履约) | DB |
|
||||
|
||||
## 二、枚举映射
|
||||
|
||||
@@ -24,16 +24,16 @@
|
||||
|
||||
成本模型与履约方式正交:专属模型只对对应履约方式生效,通用模型对所有履约方式生效。
|
||||
|
||||
| 新值 | 含义 | 取代旧的 |
|
||||
| --- | --- | --- |
|
||||
| `affiliate_purchase` | 自动发货上游采购成本 | `cost_type=auto_purchase` |
|
||||
| `work_order_reward` | 接单平台打手报酬 | `cost_type=work_order_reward` |
|
||||
| `third_party_voucher_cost` | 第三方卡券采购成本 | 新增 |
|
||||
| `manual_actual` | 人工客服实际支出 | `cost_type=manual_service` |
|
||||
| `platform_fee` | 平台服务费 | `cost_type=platform_fee` |
|
||||
| `payment_fee` | 支付通道费 | `cost_type=payment_fee` |
|
||||
| `after_sales_loss` | 售后损失 | `cost_type=after_sales_loss` |
|
||||
| `other` | 其他 | `cost_type=shipping_other` / `cost_type=other` |
|
||||
| 新值 | 含义 | 取代旧的 |
|
||||
| -------------------------- | -------------------- | ---------------------------------------------- |
|
||||
| `affiliate_purchase` | 自动发货上游采购成本 | `cost_type=auto_purchase` |
|
||||
| `work_order_reward` | 接单平台打手报酬 | `cost_type=work_order_reward` |
|
||||
| `third_party_voucher_cost` | 第三方卡券采购成本 | 新增 |
|
||||
| `manual_actual` | 人工客服实际支出 | `cost_type=manual_service` |
|
||||
| `platform_fee` | 平台服务费 | `cost_type=platform_fee` |
|
||||
| `payment_fee` | 支付通道费 | `cost_type=payment_fee` |
|
||||
| `after_sales_loss` | 售后损失 | `cost_type=after_sales_loss` |
|
||||
| `other` | 其他 | `cost_type=shipping_other` / `cost_type=other` |
|
||||
|
||||
### 2.2 `pricing_mode`(精简为 3 个)
|
||||
|
||||
@@ -67,7 +67,7 @@ DELETE /api/v1/admin/cost-center/cost-items/:id
|
||||
"unitName": "件",
|
||||
"currency": "CNY",
|
||||
"status": "active | archived",
|
||||
"note": ""
|
||||
"note": "",
|
||||
}
|
||||
```
|
||||
|
||||
@@ -88,7 +88,7 @@ DELETE /api/v1/admin/cost-center/cost-items/:id
|
||||
"note": "",
|
||||
"snapshotCount": 0,
|
||||
"createdAt": "...",
|
||||
"updatedAt": "..."
|
||||
"updatedAt": "...",
|
||||
}
|
||||
```
|
||||
|
||||
@@ -96,13 +96,13 @@ DELETE /api/v1/admin/cost-center/cost-items/:id
|
||||
|
||||
商品**不再返回 `carrierType`**。前端若要按来源分组,用 `canonicalSku` 前缀:
|
||||
|
||||
| 前缀 | 来源 | 建议展示名 |
|
||||
| --- | --- | --- |
|
||||
| `aff:` | 自动发货 | 自动发货 |
|
||||
| `tpl:` | 接单模板 | 接单平台 |
|
||||
| `wo:` | 工单证据 | 接单平台 |
|
||||
| `man:` | 人工 | 人工 |
|
||||
| 其他 | 未分类 | 未分类 |
|
||||
| 前缀 | 来源 | 建议展示名 |
|
||||
| ------ | -------- | ---------- |
|
||||
| `aff:` | 自动发货 | 自动发货 |
|
||||
| `tpl:` | 接单模板 | 接单平台 |
|
||||
| `wo:` | 工单证据 | 接单平台 |
|
||||
| `man:` | 人工 | 人工 |
|
||||
| 其他 | 未分类 | 未分类 |
|
||||
|
||||
`GET /api/v1/admin/cost-center/products` 的 `carrierType` 查询参数**保留**,
|
||||
但语义改为「按 `canonical_sku` 前缀筛选」,取值 `affiliate_dash | work_order | manual`。
|
||||
@@ -118,11 +118,11 @@ AND (
|
||||
|
||||
### 4.1 渠道映射诊断与未归一队列
|
||||
|
||||
| 接口 | 说明 |
|
||||
| --- | --- |
|
||||
| `GET /api/v1/admin/cost-center/mappings/diagnostics` | 标准商品数 / 映射数 / 有映射商品数 / 未归一订单项 / 未归一 SKU 组;按 `channel` 拆分聚合 |
|
||||
| `GET /api/v1/admin/cost-center/mappings/unmapped` | 未归一队列,按「来源 + 店铺 + 平台 SKU + 履约方式」聚合,支持 `keyword` / `provider` / `channel` 与分页 |
|
||||
| `POST /api/v1/admin/cost-center/mappings/backfill` | 回填订单项映射;返回 `resolvedExceptionCount`(已归一的 `product_mapping_missing` 异常自动收口) |
|
||||
| 接口 | 说明 |
|
||||
| ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
|
||||
| `GET /api/v1/admin/cost-center/mappings/diagnostics` | 标准商品数 / 映射数 / 有映射商品数 / 未归一订单项 / 未归一 SKU 组;按 `channel` 拆分聚合 |
|
||||
| `GET /api/v1/admin/cost-center/mappings/unmapped` | 未归一队列,按「来源 + 店铺 + 平台 SKU + 履约方式」聚合,支持 `keyword` / `provider` / `channel` 与分页 |
|
||||
| `POST /api/v1/admin/cost-center/mappings/backfill` | 回填订单项映射;返回 `resolvedExceptionCount`(已归一的 `product_mapping_missing` 异常自动收口) |
|
||||
|
||||
### 4.2 人工商品归一(已删除)
|
||||
|
||||
@@ -150,6 +150,30 @@ AND (
|
||||
商品 `canonical_sku = man:<内部SKU>`,`canonical_name` 优先取 `manual_sku_registry.display_name`,否则取订单里最常见的 `sku_name`。
|
||||
每日 `cost_finance_sync` 任务会对最近 N 天执行同一归一(不重复收口异常)。
|
||||
|
||||
### 4.3 人工 SKU 配置(现行)
|
||||
|
||||
人工标准商品不允许通过通用 `POST /api/v1/admin/cost-center/products` 手工创建。
|
||||
统一入口为:
|
||||
|
||||
```text
|
||||
POST /api/v1/admin/cost-center/manual-configs
|
||||
```
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"skuKey": "破片手榴弹-兔兔白日梦",
|
||||
"channels": [
|
||||
{ "platformKey": "nanhang", "creditQuantity": 10 },
|
||||
{ "platformKey": "fund_cash", "creditQuantity": 3.5 },
|
||||
],
|
||||
"note": "长期人工商品",
|
||||
}
|
||||
```
|
||||
|
||||
保存时后端自动创建或复用 `man:<skuKey>` 标准商品,再写人工配置和
|
||||
`internal_sku_channels` 人工规则。待分类队列的“去补配置”会携带
|
||||
`scope=manual&tab=cost&manualSku=<内部SKU>` 直接打开对应配置。
|
||||
|
||||
## 五、成本版本接口
|
||||
|
||||
路径不变,字段不变:
|
||||
@@ -163,20 +187,34 @@ AND (
|
||||
"costModel": "affiliate_purchase",
|
||||
"pricingMode": "per_item",
|
||||
"scopeType": "product | rule | shop | provider | global",
|
||||
"provider": "", "shopId": "",
|
||||
"canonicalProductId": 3, "canonicalSku": "aff:SKU-1", "canonicalName": "...",
|
||||
"workProductRuleId": null, "workProductRuleName": "", "workProductRuleKey": "",
|
||||
"ruleRewardAmountFen": 0, "ruleUnitPriceFen": 0,
|
||||
"revenueItemCount": 0, "revenueFen": 0, "revenueAvgFen": 0,
|
||||
"rewardAvgFen": 0, "rewardFen": 0, "amountKind": "unit_price | fixed",
|
||||
"provider": "",
|
||||
"shopId": "",
|
||||
"canonicalProductId": 3,
|
||||
"canonicalSku": "aff:SKU-1",
|
||||
"canonicalName": "...",
|
||||
"workProductRuleId": null,
|
||||
"workProductRuleName": "",
|
||||
"workProductRuleKey": "",
|
||||
"ruleRewardAmountFen": 0,
|
||||
"ruleUnitPriceFen": 0,
|
||||
"revenueItemCount": 0,
|
||||
"revenueFen": 0,
|
||||
"revenueAvgFen": 0,
|
||||
"rewardAvgFen": 0,
|
||||
"rewardFen": 0,
|
||||
"amountKind": "unit_price | fixed",
|
||||
"isSystemPlaceholder": false,
|
||||
"amountFen": 1000, "rateBps": 0,
|
||||
"effectiveFrom": "...", "effectiveTo": null,
|
||||
"amountFen": 1000,
|
||||
"rateBps": 0,
|
||||
"effectiveFrom": "...",
|
||||
"effectiveTo": null,
|
||||
"source": "manual | upstream_sync | import",
|
||||
"status": "draft | active | retired",
|
||||
"changeReason": "",
|
||||
"createdByAdminUserId": null, "approvedByAdminUserId": null,
|
||||
"createdAt": "...", "updatedAt": "..."
|
||||
"createdByAdminUserId": null,
|
||||
"approvedByAdminUserId": null,
|
||||
"createdAt": "...",
|
||||
"updatedAt": "...",
|
||||
}
|
||||
```
|
||||
|
||||
@@ -213,7 +251,9 @@ AND (
|
||||
"reason": "cost_missing",
|
||||
"status": "open",
|
||||
"detail": {},
|
||||
"createdAt": "...", "resolvedAt": null, "resolvedByAdminUserId": null
|
||||
"createdAt": "...",
|
||||
"resolvedAt": null,
|
||||
"resolvedByAdminUserId": null,
|
||||
}
|
||||
```
|
||||
|
||||
@@ -233,7 +273,7 @@ AND (
|
||||
"grossRevenueFen": 1219202470,
|
||||
"costAmountFen": 32000,
|
||||
"costMissingCount": 102954,
|
||||
"grossProfitFen": -1219200470
|
||||
"grossProfitFen": -1219200470,
|
||||
}
|
||||
```
|
||||
|
||||
@@ -255,13 +295,13 @@ AND (
|
||||
"affiliate_dash": 38,
|
||||
"work_order": 707,
|
||||
"manual": 0,
|
||||
"uncategorized": 0
|
||||
"uncategorized": 0,
|
||||
},
|
||||
"costModelCounts": {
|
||||
"affiliate_purchase": 1,
|
||||
"work_order_reward": 1,
|
||||
"manual_actual": 1
|
||||
}
|
||||
"manual_actual": 1,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
@@ -272,13 +312,13 @@ AND (
|
||||
|
||||
原 `apps/backend/src/services/admin/admin-cost-center-service.ts`(4,248 行)已拆为:
|
||||
|
||||
| 新文件 | 行数 | 负责的导出 |
|
||||
| --- | ---: | --- |
|
||||
| `services/cost-center/cost-center-shared.ts` | ~800 | 类型、常量、归一化函数、`mapXxx` 映射函数、provider 归一、`costModelScopeSql` |
|
||||
| `services/cost-center/cost-center-overview-service.ts` | ~150 | 总览统计与选项 |
|
||||
| `services/cost-center/product-catalog-service.ts` | ~1,000 | 商品与渠道映射的 CRUD、回填、选项 |
|
||||
| `services/cost-center/template-bootstrap-service.ts` | ~1,380 | 接单模板引导、自动发货商品同步、工单证据回填、模板成本版本同步、`buildTemplateMappingPlan` |
|
||||
| `services/cost-center/cost-definition-service.ts` | ~1,240 | 成本项 / 成本版本 / 成本异常 / 成本预览 / 成本快照写入 |
|
||||
| 新文件 | 行数 | 负责的导出 |
|
||||
| ------------------------------------------------------ | -----: | ------------------------------------------------------------------------------------------ |
|
||||
| `services/cost-center/cost-center-shared.ts` | ~800 | 类型、常量、归一化函数、`mapXxx` 映射函数、provider 归一、`costModelScopeSql` |
|
||||
| `services/cost-center/cost-center-overview-service.ts` | ~150 | 总览统计与选项 |
|
||||
| `services/cost-center/product-catalog-service.ts` | ~1,000 | 商品与渠道映射的 CRUD、回填、选项 |
|
||||
| `services/cost-center/template-bootstrap-service.ts` | ~1,380 | 接单模板引导、自动发货商品同步、工单证据回填、模板成本版本同步、`buildTemplateMappingPlan` |
|
||||
| `services/cost-center/cost-definition-service.ts` | ~1,240 | 成本项 / 成本版本 / 成本异常 / 成本预览 / 成本快照写入 |
|
||||
|
||||
原文件**已删除**,路由 `apps/backend/src/routes/admin/cost-center.ts` 从新模块导入。
|
||||
`routes/admin/worker-platform/config.ts` 的模板成本同步也从新模块导入。
|
||||
@@ -287,19 +327,19 @@ AND (
|
||||
|
||||
原 `apps/frontend/src/pages/admin/AdminCostCenterPage.tsx`(2,887 行)已拆为:
|
||||
|
||||
| 新文件 | 内容 |
|
||||
| --- | --- |
|
||||
| `pages/admin/cost-center/CostCenterShell.tsx` | 页面骨架、顶部来源切换(全部/自动发货/接单平台/人工)、Tab 定义 |
|
||||
| `pages/admin/cost-center/shared.ts` | 常量、类型、标签函数 |
|
||||
| `pages/admin/cost-center/CostCenterContext.ts` | 页面上下文(`useCostCenter`) |
|
||||
| `pages/admin/cost-center/ProductCatalogPanel.tsx` | 标准商品 Tab |
|
||||
| `pages/admin/cost-center/ChannelMappingPanel.tsx` | 渠道映射 Tab |
|
||||
| `pages/admin/cost-center/CostConfigPanel.tsx` | 成本配置 Tab(按来源切换下面三个) |
|
||||
| `pages/admin/cost-center/AffiliateSkuPanel.tsx` | 自动发货采购价(成本配置内) |
|
||||
| `pages/admin/cost-center/CostItemPanel.tsx` | 成本项 Tab |
|
||||
| `pages/admin/cost-center/CostVersionPanel.tsx` | 成本版本 Tab |
|
||||
| `pages/admin/cost-center/CostExceptionPanel.tsx` | 成本异常 Tab |
|
||||
| `pages/admin/cost-center/CostPreviewPanel.tsx` | 成本预览 Tab |
|
||||
| 新文件 | 内容 |
|
||||
| ------------------------------------------------- | --------------------------------------------------------------- |
|
||||
| `pages/admin/cost-center/CostCenterShell.tsx` | 页面骨架、顶部来源切换(全部/自动发货/接单平台/人工)、Tab 定义 |
|
||||
| `pages/admin/cost-center/shared.ts` | 常量、类型、标签函数 |
|
||||
| `pages/admin/cost-center/CostCenterContext.ts` | 页面上下文(`useCostCenter`) |
|
||||
| `pages/admin/cost-center/ProductCatalogPanel.tsx` | 标准商品 Tab |
|
||||
| `pages/admin/cost-center/ChannelMappingPanel.tsx` | 渠道映射 Tab |
|
||||
| `pages/admin/cost-center/CostConfigPanel.tsx` | 成本配置 Tab(按来源切换下面三个) |
|
||||
| `pages/admin/cost-center/AffiliateSkuPanel.tsx` | 自动发货采购价(成本配置内) |
|
||||
| `pages/admin/cost-center/CostItemPanel.tsx` | 成本项 Tab |
|
||||
| `pages/admin/cost-center/CostVersionPanel.tsx` | 成本版本 Tab |
|
||||
| `pages/admin/cost-center/CostExceptionPanel.tsx` | 成本异常 Tab |
|
||||
| `pages/admin/cost-center/CostPreviewPanel.tsx` | 成本预览 Tab |
|
||||
|
||||
`AdminCostCenterPage.tsx` 只保留 `export default` 转发到 `CostCenterShell`(18 行)。
|
||||
|
||||
@@ -322,21 +362,21 @@ export type CostModel =
|
||||
|
||||
## 八、总账 / 期间 / 对账接口(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/kuaishou-industry/orders/:orderId/refunds/approve-and-record` | finance.config | 平台退款(当前仅快手 91) |
|
||||
| 方法 | 路径 | 权限 | 说明 |
|
||||
| ---- | ---------------------------------------------------------------------------- | -------------- | ---------------------------- |
|
||||
| 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/kuaishou-industry/orders/:orderId/refunds/approve-and-record` | finance.config | 平台退款(当前仅快手 91) |
|
||||
|
||||
确认履约接口新增代录字段:
|
||||
|
||||
@@ -344,8 +384,8 @@ export type CostModel =
|
||||
{
|
||||
"orderItemId": 123,
|
||||
"costFen": 100,
|
||||
"fundAccountId": 45, // 现金路径:管理员/财务指定客服备用金账户
|
||||
"creditOwnerAdminUserId": 67 // 积分路径:管理员/财务指定客服账号
|
||||
"fundAccountId": 45, // 现金路径:管理员/财务指定客服备用金账户
|
||||
"creditOwnerAdminUserId": 67, // 积分路径:管理员/财务指定客服账号
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
+105
-101
@@ -38,11 +38,11 @@ orders ──┬── order_items ──── fulfillment_channel + fulfillmen
|
||||
|
||||
2026-10-27 最终收敛为 3 个领域迁移(合计约 2,177 行):
|
||||
|
||||
| 迁移 | 内容 | 行数 |
|
||||
| --- | --- | ---: |
|
||||
| `103_finance_foundation.sql` | 商品目录、渠道映射、成本项/版本/快照/异常、订单项收入与履约方式、销售事实、退款单 | 861 |
|
||||
| `104_finance_controls.sql` | 人工 SKU/配置、备用金/积分、影子总账、对账/关账、财务控制、L1 钱包硬化 | 1,119 |
|
||||
| `105_work_order_consignment.sql` | 拼单多次参与、大厅/店铺索引、撤份额注释、寄卖对接客服 | 197 |
|
||||
| 迁移 | 内容 | 行数 |
|
||||
| -------------------------------- | --------------------------------------------------------------------------------- | ----: |
|
||||
| `103_finance_foundation.sql` | 商品目录、渠道映射、成本项/版本/快照/异常、订单项收入与履约方式、销售事实、退款单 | 861 |
|
||||
| `104_finance_controls.sql` | 人工 SKU/配置、备用金/积分、影子总账、对账/关账、财务控制、L1 钱包硬化 | 1,119 |
|
||||
| `105_work_order_consignment.sql` | 拼单多次参与、大厅/店铺索引、撤份额注释、寄卖对接客服 | 197 |
|
||||
|
||||
原来 103–114 的 12 个补丁文件已删除;生产当前在 102,只需执行 103–105。
|
||||
|
||||
@@ -52,42 +52,44 @@ orders ──┬── order_items ──── fulfillment_channel + fulfillmen
|
||||
|
||||
### 1.1 字段替换对照
|
||||
|
||||
| 旧字段 | 新字段 | 出现位置 |
|
||||
| --- | --- | --- |
|
||||
| `cost_items.carrier_type` | `cost_items.cost_model` | DB / 成本项接口 |
|
||||
| `cost_items.cost_type` | (并入 `cost_model`) | DB / 成本项接口 |
|
||||
| `cost_snapshots.carrier_type` | (删除) | DB |
|
||||
| `cost_exceptions.carrier_type` | (删除) | DB |
|
||||
| `product_catalog.carrier_type` | (删除,改由 `canonical_sku` 前缀推导) | DB / 商品接口 |
|
||||
| `sales_daily_facts.carrier_type` | `sales_daily_facts.channel` | DB / 销售事实接口 |
|
||||
| `work_product_rules.legacy_cost_source` | (删除) | DB |
|
||||
| `cost_versions.cost_item_carrier_type` | `cost_versions.cost_item_cost_model` | 成本版本接口 |
|
||||
| `pricing_mode: per_hour / fixed_daily` | (删除,只剩三种) | 成本项接口 |
|
||||
| `manual_expense_records` / `manual_expense_events` | (删除,人工成本只走确认履约) | DB |
|
||||
| 旧字段 | 新字段 | 出现位置 |
|
||||
| -------------------------------------------------- | --------------------------------------- | ----------------- |
|
||||
| `cost_items.carrier_type` | `cost_items.cost_model` | DB / 成本项接口 |
|
||||
| `cost_items.cost_type` | (并入 `cost_model`) | DB / 成本项接口 |
|
||||
| `cost_snapshots.carrier_type` | (删除) | DB |
|
||||
| `cost_exceptions.carrier_type` | (删除) | DB |
|
||||
| `product_catalog.carrier_type` | (删除,改由 `canonical_sku` 前缀推导) | DB / 商品接口 |
|
||||
| `sales_daily_facts.carrier_type` | `sales_daily_facts.channel` | DB / 销售事实接口 |
|
||||
| `work_product_rules.legacy_cost_source` | (删除) | DB |
|
||||
| `cost_versions.cost_item_carrier_type` | `cost_versions.cost_item_cost_model` | 成本版本接口 |
|
||||
| `pricing_mode: per_hour / fixed_daily` | (删除,只剩三种) | 成本项接口 |
|
||||
| `manual_expense_records` / `manual_expense_events` | (删除,人工成本只走确认履约) | DB |
|
||||
|
||||
### 1.2 成本模型映射
|
||||
|
||||
| 旧 `cost_type` | 新 `cost_model` |
|
||||
| --- | --- |
|
||||
| `auto_purchase` | `affiliate_purchase` |
|
||||
| `work_order_reward` | `work_order_reward` |
|
||||
| `manual_service` | `manual_actual` |
|
||||
| `platform_fee` | `platform_fee` |
|
||||
| `payment_fee` | `payment_fee` |
|
||||
| `after_sales_loss` | `after_sales_loss` |
|
||||
| `shipping_other` / `other` | `other` |
|
||||
| 旧 `cost_type` | 新 `cost_model` |
|
||||
| -------------------------- | -------------------- |
|
||||
| `auto_purchase` | `affiliate_purchase` |
|
||||
| `work_order_reward` | `work_order_reward` |
|
||||
| `manual_service` | `manual_actual` |
|
||||
| `platform_fee` | `platform_fee` |
|
||||
| `payment_fee` | `payment_fee` |
|
||||
| `after_sales_loss` | `after_sales_loss` |
|
||||
| `shipping_other` / `other` | `other` |
|
||||
|
||||
### 1.3 商品来源前缀
|
||||
|
||||
| 前缀 | 来源 | 对应履约方式(仅参考,不作推导依据) |
|
||||
| --- | --- | --- |
|
||||
| `aff:` | 自动发货 | `affiliate_dash` |
|
||||
| `tpl:` | 接单模板 | `work_order` |
|
||||
| `wo:` | 历史工单证据 | `work_order` |
|
||||
| `man:` | 人工 | `manual` |
|
||||
| 其他 | 未分类 | 不得推断 |
|
||||
| 前缀 | 来源 | 对应履约方式(仅参考,不作推导依据) |
|
||||
| ------ | ------------ | ------------------------------------ |
|
||||
| `aff:` | 自动发货 | `affiliate_dash` |
|
||||
| `tpl:` | 接单模板 | `work_order` |
|
||||
| `wo:` | 历史工单证据 | `work_order` |
|
||||
| `man:` | 人工 | `manual` |
|
||||
| 其他 | 未分类 | 不得推断 |
|
||||
|
||||
本地现状:`aff:` 38 个、`tpl:` 662 个、`wo:` 45 个,`man:` 0 个(P1 待建)。
|
||||
人工标准商品 `man:<内部 SKU>` 不在商品目录手工创建。运营在「成本配置 → 人工 SKU 配置」
|
||||
新增或保存配置时,系统在同一业务流程内创建或复用标准商品,并同步人工渠道规则。
|
||||
商品目录中的 `man:` 商品因此是人工配置的派生结果。
|
||||
|
||||
---
|
||||
|
||||
@@ -188,15 +190,15 @@ normalized_sku_series -- 剥离数量并归一同义字后的名称系列
|
||||
|
||||
### 3.1 成本模型与适用履约方式
|
||||
|
||||
| `cost_model` | 适用履约方式 | 计价方式 | 成本来源 |
|
||||
| --- | --- | --- | --- |
|
||||
| `affiliate_purchase` | `affiliate_dash` | `per_item` | 上游 SKU 固定成本版本 |
|
||||
| `work_order_reward` | `work_order` | `per_order` | 模板规则级版本 / 工单实际报酬 |
|
||||
| `manual_actual` | `manual` | `per_order` | 订单页逐单录入的实际支出 |
|
||||
| `platform_fee` | 全部 | `per_order` / `percent_of_revenue` | 未配置 |
|
||||
| `payment_fee` | 全部 | `per_order` / `percent_of_revenue` | 未配置 |
|
||||
| `after_sales_loss` | 全部 | `per_order` | 未配置 |
|
||||
| `other` | 全部 | `per_order` | 未配置 |
|
||||
| `cost_model` | 适用履约方式 | 计价方式 | 成本来源 |
|
||||
| -------------------- | ---------------- | ---------------------------------- | ----------------------------- |
|
||||
| `affiliate_purchase` | `affiliate_dash` | `per_item` | 上游 SKU 固定成本版本 |
|
||||
| `work_order_reward` | `work_order` | `per_order` | 模板规则级版本 / 工单实际报酬 |
|
||||
| `manual_actual` | `manual` | `per_order` | 订单页逐单录入的实际支出 |
|
||||
| `platform_fee` | 全部 | `per_order` / `percent_of_revenue` | 未配置 |
|
||||
| `payment_fee` | 全部 | `per_order` / `percent_of_revenue` | 未配置 |
|
||||
| `after_sales_loss` | 全部 | `per_order` | 未配置 |
|
||||
| `other` | 全部 | `per_order` | 未配置 |
|
||||
|
||||
后端判定见 `cost-center-shared.ts` 的 `costModelScopeSql()`;通用模型对所有履约方式生效,专属模型只对对应履约方式生效。
|
||||
|
||||
@@ -228,11 +230,11 @@ cost_versions
|
||||
|
||||
### 3.3 系统内置成本项
|
||||
|
||||
| 编码 | 成本模型 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `sys_work_order_reward` | `work_order_reward` | 每个可启用的接单模板各一条规则级版本;全局 0 元版本只作"按工单实际结算"的占位 |
|
||||
| `sys_affiliate_purchase` | `affiliate_purchase` | 上游 SKU 固定成本版本,38 个商品级 |
|
||||
| `sys_manual_service` | `manual_actual` | 订单页确认履约写入 `actual` 快照;版本为 0 元占位 |
|
||||
| 编码 | 成本模型 | 说明 |
|
||||
| ------------------------ | -------------------- | ----------------------------------------------------------------------------- |
|
||||
| `sys_work_order_reward` | `work_order_reward` | 每个可启用的接单模板各一条规则级版本;全局 0 元版本只作"按工单实际结算"的占位 |
|
||||
| `sys_affiliate_purchase` | `affiliate_purchase` | 上游 SKU 固定成本版本,38 个商品级 |
|
||||
| `sys_manual_service` | `manual_actual` | 订单页确认履约写入 `actual` 快照;版本为 0 元占位 |
|
||||
|
||||
工单报酬的三种快照:
|
||||
|
||||
@@ -286,12 +288,12 @@ created_at, resolved_at, resolved_by
|
||||
|
||||
`order_items.revenue_amount_fen` / `revenue_basis` 在迁移 `103` 里固化:
|
||||
|
||||
| `revenue_basis` | 含义 |
|
||||
| --- | --- |
|
||||
| `order_total` | 一单一品,订单实付全部归该订单项 |
|
||||
| `equal_split` | 多订单项按等额拆分,余数给最后一项 |
|
||||
| `platform_item` | 有平台明细时替换 |
|
||||
| `manual` / `unknown` | 未定 |
|
||||
| `revenue_basis` | 含义 |
|
||||
| -------------------- | ---------------------------------- |
|
||||
| `order_total` | 一单一品,订单实付全部归该订单项 |
|
||||
| `equal_split` | 多订单项按等额拆分,余数给最后一项 |
|
||||
| `platform_item` | 有平台明细时替换 |
|
||||
| `manual` / `unknown` | 未定 |
|
||||
|
||||
本地全量 316,585 项都是 `order_total`(当前一单一品),但模型按"订单项"设计,不把"一单一品"写死。
|
||||
|
||||
@@ -328,12 +330,12 @@ computed_at
|
||||
|
||||
### 5.2 本地重算结果(2026-10-23)
|
||||
|
||||
| 履约方式 | 事实行 | 订单项 | 收入 | 成本 | 缺失成本 |
|
||||
| --- | ---: | ---: | ---: | ---: | ---: |
|
||||
| `work_order` | 9,585 | 118,053 | ¥533.57 万 | ¥452.83 万 | 966 |
|
||||
| `affiliate_dash` | 3,163 | 41,676 | ¥508.97 万 | ¥497.41 万 | 0 |
|
||||
| `manual` | 1,849 | 102,955 | ¥1,219.20 万 | ¥0.32 万 | 102,954 |
|
||||
| `legacy_platform` | 201 | 53,901 | ¥389.12 万 | ¥0 | 53,901 |
|
||||
| 履约方式 | 事实行 | 订单项 | 收入 | 成本 | 缺失成本 |
|
||||
| ----------------- | -----: | ------: | -----------: | ---------: | -------: |
|
||||
| `work_order` | 9,585 | 118,053 | ¥533.57 万 | ¥452.83 万 | 966 |
|
||||
| `affiliate_dash` | 3,163 | 41,676 | ¥508.97 万 | ¥497.41 万 | 0 |
|
||||
| `manual` | 1,849 | 102,955 | ¥1,219.20 万 | ¥0.32 万 | 102,954 |
|
||||
| `legacy_platform` | 201 | 53,901 | ¥389.12 万 | ¥0 | 53,901 |
|
||||
|
||||
---
|
||||
|
||||
@@ -396,7 +398,9 @@ fulfillment_decided_at / fulfillment_reason
|
||||
4. **商品来源和平台 SKU 都不能反推渠道**:判定只认统一 SKU 配置与真实载体。
|
||||
5. `voucher_state` 只做展示与核销流程,不参与任何成本/履约判断。
|
||||
6. 多渠道证据同时命中必须先告警人工复核,不能静默取其一。
|
||||
7. **旧人工来源清理只归档**:同名内部 SKU 已有其他非兜底主渠道时,旧 `man:` 商品从当前目录归档;历史订单、成本版本、成本快照和事实数据保持不动,人工兜底改指当前主商品。
|
||||
7. **人工商品只从人工 SKU 配置创建**:普通“新建标准商品”不再接受 `man:`;
|
||||
人工 SKU 配置保存时自动创建或复用 `man:<内部 SKU>`。历史商品清理入口已下线,
|
||||
避免运营通过商品目录维护人工履约事实。
|
||||
|
||||
---
|
||||
|
||||
@@ -404,21 +408,21 @@ fulfillment_decided_at / fulfillment_reason
|
||||
|
||||
财务链路已改成六条独立管道,由定时任务驱动,不再有手工同步脚本:
|
||||
|
||||
| 管道 | 作用 | 默认间隔 |
|
||||
| --- | --- | --- |
|
||||
| `channel_assign` | 规则/证据判定履约渠道 | 60s |
|
||||
| `carrier_dispatch` | 挂载人工配置、发现缺失载体 | 60s |
|
||||
| `product_normalize` | 模板/人工配置/前缀直达归一 | 300s |
|
||||
| `cost_snapshot` | 按渠道解析成本版本写快照 | 300s |
|
||||
| `sales_facts` | 按渠道重算销售事实(含未分类桶) | 600s |
|
||||
| `ledger_post` | 事实过账到总账 | 600s |
|
||||
| 管道 | 作用 | 默认间隔 |
|
||||
| ------------------- | -------------------------------- | -------- |
|
||||
| `channel_assign` | 规则/证据判定履约渠道 | 60s |
|
||||
| `carrier_dispatch` | 挂载人工配置、发现缺失载体 | 60s |
|
||||
| `product_normalize` | 模板/人工配置/前缀直达归一 | 300s |
|
||||
| `cost_snapshot` | 按渠道解析成本版本写快照 | 300s |
|
||||
| `sales_facts` | 按渠道重算销售事实(含未分类桶) | 600s |
|
||||
| `ledger_post` | 事实过账到总账 | 600s |
|
||||
|
||||
运维命令只剩断代与重建:
|
||||
|
||||
| 命令 | 作用 |
|
||||
| --- | --- |
|
||||
| 命令 | 作用 |
|
||||
| -------------------------------------------------------------- | ----------------------------- |
|
||||
| `npm run finance:cutover-v2 -- --execute --confirm=2026-10-31` | 断代:归档历史 + 清空派生数据 |
|
||||
| `npm run finance:rebuild-cutover -- --date-from=2026-10-31` | 断代后重跑管道并生成期初分录 |
|
||||
| `npm run finance:rebuild-cutover -- --date-from=2026-10-31` | 断代后重跑管道并生成期初分录 |
|
||||
|
||||
后台「履约渠道 → 管道状态」可查看每条管道的水位、上次成功时间与错误;
|
||||
「立即执行」只用于排障补跑,日常无需干预。
|
||||
@@ -427,11 +431,11 @@ fulfillment_decided_at / fulfillment_reason
|
||||
|
||||
生产数据库当前在 **102**。dev 已把原 103–114 收敛为 3 个领域迁移:
|
||||
|
||||
| 迁移 | 内容 |
|
||||
| --- | --- |
|
||||
| `103_finance_foundation.sql` | 商品目录、成本中心、成本项/版本/快照、销售事实、退款单 |
|
||||
| `104_finance_controls.sql` | 人工履约、备用金/积分、影子总账、对账/关账、财务控制、L1 钱包硬化 |
|
||||
| `105_work_order_consignment.sql` | 拼单多次参与、大厅/店铺索引、撤份额注释、寄卖对接客服 |
|
||||
| 迁移 | 内容 |
|
||||
| -------------------------------- | ----------------------------------------------------------------- |
|
||||
| `103_finance_foundation.sql` | 商品目录、成本中心、成本项/版本/快照、销售事实、退款单 |
|
||||
| `104_finance_controls.sql` | 人工履约、备用金/积分、影子总账、对账/关账、财务控制、L1 钱包硬化 |
|
||||
| `105_work_order_consignment.sql` | 拼单多次参与、大厅/店铺索引、撤份额注释、寄卖对接客服 |
|
||||
|
||||
- 生产升级:**102 → 103 → 104 → 105**,只执行 3 个迁移文件。
|
||||
- 全新库:`001 → 105` 一次跑完。
|
||||
@@ -461,35 +465,35 @@ npm run revenue:backfill -- --batch-size=2000 --max-batches=100
|
||||
|
||||
## 九、索引与性能
|
||||
|
||||
| 索引 | 用途 |
|
||||
| --- | --- |
|
||||
| `idx_order_items_fulfillment_channel (fulfillment_channel, order_id)` | 按渠道筛订单项 |
|
||||
| `idx_order_items_fulfillment_id (fulfillment_status, id)` | 管道按状态扫增量 |
|
||||
| `idx_order_items_canonical_product` | 按标准商品查订单项 |
|
||||
| `idx_order_items_normalized_sku_lookup` | 按归一名称/系列匹配映射 |
|
||||
| `idx_channel_product_mappings_match_lookup` | 映射查找 |
|
||||
| `uq_channel_product_mappings_match_key` | 映射唯一键 |
|
||||
| `idx_cost_versions_lookup / product / rule` | 成本版本解析 |
|
||||
| `uq_cost_snapshots_active_subject_item` | 每个主体 + 成本项只允许一条有效快照 |
|
||||
| `idx_cost_exceptions_status_created` | 异常队列列表 |
|
||||
| `idx_sales_daily_facts_date / shop / product / mode` | 销售事实各维度 |
|
||||
| `idx_work_orders_rule_cover` | 成本版本页按接单规则聚合 |
|
||||
| `idx_order_items_revenue_cover` | 收入聚合 |
|
||||
| `idx_work_categories_name` | 商品目录按分类名 lateral join |
|
||||
| `idx_cost_exceptions_archivable` | 归档任务扫描「已处理且超期」的异常(部分索引,`status <> 'open'`) |
|
||||
| 索引 | 用途 |
|
||||
| --------------------------------------------------------------------- | ------------------------------------------------------------------ |
|
||||
| `idx_order_items_fulfillment_channel (fulfillment_channel, order_id)` | 按渠道筛订单项 |
|
||||
| `idx_order_items_fulfillment_id (fulfillment_status, id)` | 管道按状态扫增量 |
|
||||
| `idx_order_items_canonical_product` | 按标准商品查订单项 |
|
||||
| `idx_order_items_normalized_sku_lookup` | 按归一名称/系列匹配映射 |
|
||||
| `idx_channel_product_mappings_match_lookup` | 映射查找 |
|
||||
| `uq_channel_product_mappings_match_key` | 映射唯一键 |
|
||||
| `idx_cost_versions_lookup / product / rule` | 成本版本解析 |
|
||||
| `uq_cost_snapshots_active_subject_item` | 每个主体 + 成本项只允许一条有效快照 |
|
||||
| `idx_cost_exceptions_status_created` | 异常队列列表 |
|
||||
| `idx_sales_daily_facts_date / shop / product / mode` | 销售事实各维度 |
|
||||
| `idx_work_orders_rule_cover` | 成本版本页按接单规则聚合 |
|
||||
| `idx_order_items_revenue_cover` | 收入聚合 |
|
||||
| `idx_work_categories_name` | 商品目录按分类名 lateral join |
|
||||
| `idx_cost_exceptions_archivable` | 归档任务扫描「已处理且超期」的异常(部分索引,`status <> 'open'`) |
|
||||
|
||||
### 9.1 成本异常归档(60 天)
|
||||
|
||||
`cost_exceptions` 只增不减:本地快照 260,253 行(resolved 151,939 / open 108,314)。已处理的行只是审计痕迹,继续留在热表会拖慢按状态+时间的分页,并让唯一索引持续膨胀。
|
||||
|
||||
| 项 | 规则 |
|
||||
| --- | --- |
|
||||
| 归档对象 | `status <> 'open'` 且 `COALESCE(resolved_at, created_at)` 超过保留期 |
|
||||
| open 行 | **永不归档**——它是待办队列,超期也要留在页面上 |
|
||||
| 保留期 | `COST_EXCEPTION_RETENTION_DAYS`,默认 **60** 天 |
|
||||
| 落点 | `cost_exceptions_archive`(保留原 id 与时间字段,加 `archived_at`) |
|
||||
| 执行 | `data-retention` 每日任务;每批 1000 行,`DELETE ... RETURNING` + `INSERT` 同语句,单批原子 |
|
||||
| 手动 | `npm run cost-exceptions:archive -- --dry-run` / `-- --days=90` |
|
||||
| 项 | 规则 |
|
||||
| ---------- | ---------------------------------------------------------------------------------------------- |
|
||||
| 归档对象 | `status <> 'open'` 且 `COALESCE(resolved_at, created_at)` 超过保留期 |
|
||||
| open 行 | **永不归档**——它是待办队列,超期也要留在页面上 |
|
||||
| 保留期 | `COST_EXCEPTION_RETENTION_DAYS`,默认 **60** 天 |
|
||||
| 落点 | `cost_exceptions_archive`(保留原 id 与时间字段,加 `archived_at`) |
|
||||
| 执行 | `data-retention` 每日任务;每批 1000 行,`DELETE ... RETURNING` + `INSERT` 同语句,单批原子 |
|
||||
| 手动 | `npm run cost-exceptions:archive -- --dry-run` / `-- --days=90` |
|
||||
| 一次性清理 | `npm run cost-exceptions:archive -- --days=0`(不按时间过滤,归档全部已处理行;open 仍不归档) |
|
||||
|
||||
归档不删除审计痕迹,但热表查询与页面上不会再出现这些历史行;需要追溯时查归档表。
|
||||
|
||||
Reference in New Issue
Block a user