feat(cost-center): 第三方卡券渠道完整接入成本模型
- 商品来源筛选补 tpv: 前缀,卡券商品列表不再为空 - 成本模型新增 third_party_voucher_cost,覆盖预览/成本项/概览作用域 - 前后端成本模型枚举与下拉同步
This commit is contained in:
@@ -28,6 +28,7 @@ export type TemplateMappingMatchType =
|
||||
export type CostModel =
|
||||
| 'affiliate_purchase'
|
||||
| 'work_order_reward'
|
||||
| 'third_party_voucher_cost'
|
||||
| 'manual_actual'
|
||||
| 'platform_fee'
|
||||
| 'payment_fee'
|
||||
@@ -37,6 +38,7 @@ export type CostModel =
|
||||
export const COST_MODELS = new Set<string>([
|
||||
'affiliate_purchase',
|
||||
'work_order_reward',
|
||||
'third_party_voucher_cost',
|
||||
'manual_actual',
|
||||
'platform_fee',
|
||||
'payment_fee',
|
||||
@@ -48,6 +50,7 @@ export const COST_MODELS = new Set<string>([
|
||||
export const COST_MODEL_CODE_BASE: Record<string, string> = {
|
||||
affiliate_purchase: 'affiliate_purchase',
|
||||
work_order_reward: 'work_order_reward',
|
||||
third_party_voucher_cost: 'third_party_voucher_cost',
|
||||
manual_actual: 'manual_actual',
|
||||
platform_fee: 'platform_fee',
|
||||
payment_fee: 'payment_fee',
|
||||
|
||||
@@ -38,6 +38,7 @@ export function productSourceFilterSql(paramIndex: number, column = 'p.canonical
|
||||
return `(
|
||||
($${paramIndex} = 'affiliate_dash' AND ${column} LIKE 'aff:%')
|
||||
OR ($${paramIndex} = 'work_order' AND (${column} LIKE 'tpl:%' OR ${column} LIKE 'wo:%'))
|
||||
OR ($${paramIndex} = 'third_party_voucher' AND ${column} LIKE 'tpv:%')
|
||||
OR ($${paramIndex} = 'manual' AND ${column} LIKE 'man:%')
|
||||
)`
|
||||
}
|
||||
@@ -52,6 +53,7 @@ export function costModelAppliesTo(costModel: string, fulfillmentMode: string) {
|
||||
if ((GENERIC_COST_MODELS as readonly string[]).includes(costModel)) return true
|
||||
if (costModel === 'affiliate_purchase') return fulfillmentMode === 'affiliate_dash'
|
||||
if (costModel === 'work_order_reward') return fulfillmentMode === 'work_order'
|
||||
if (costModel === 'third_party_voucher_cost') return fulfillmentMode === 'third_party_voucher'
|
||||
if (costModel === 'manual_actual') return fulfillmentMode === 'manual'
|
||||
return false
|
||||
}
|
||||
@@ -67,6 +69,8 @@ export function costModelScopeSql(fulfillmentModeExpression: string): string {
|
||||
AND ${fulfillmentModeExpression} = 'affiliate_dash')
|
||||
OR (ci.cost_model = 'work_order_reward'
|
||||
AND ${fulfillmentModeExpression} = 'work_order')
|
||||
OR (ci.cost_model = 'third_party_voucher_cost'
|
||||
AND ${fulfillmentModeExpression} = 'third_party_voucher')
|
||||
OR (ci.cost_model = 'manual_actual'
|
||||
AND ${fulfillmentModeExpression} = 'manual')
|
||||
)`
|
||||
|
||||
@@ -41,6 +41,7 @@ export async function getAdminCostCenterOverview(params: { scope?: string } = {}
|
||||
$1::text IS NULL
|
||||
OR ($1 = 'affiliate_dash' AND p.canonical_sku LIKE 'aff:%')
|
||||
OR ($1 = 'work_order' AND (p.canonical_sku LIKE 'tpl:%' OR p.canonical_sku LIKE 'wo:%'))
|
||||
OR ($1 = 'third_party_voucher' AND p.canonical_sku LIKE 'tpv:%')
|
||||
OR ($1 = 'manual' AND p.canonical_sku LIKE 'man:%')
|
||||
)
|
||||
),
|
||||
@@ -48,6 +49,7 @@ export async function getAdminCostCenterOverview(params: { scope?: string } = {}
|
||||
SELECT CASE $1
|
||||
WHEN 'affiliate_dash' THEN 'affiliate_purchase'
|
||||
WHEN 'work_order' THEN 'work_order_reward'
|
||||
WHEN 'third_party_voucher' THEN 'third_party_voucher_cost'
|
||||
WHEN 'manual' THEN 'manual_actual'
|
||||
END AS cost_model
|
||||
)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import test from 'node:test'
|
||||
|
||||
import { costModelAppliesTo } from './cost-center-mappers.js'
|
||||
import {
|
||||
normalizeMappingMatchType,
|
||||
normalizeProviderKey,
|
||||
@@ -8,6 +9,7 @@ import {
|
||||
} from './cost-center-shared.js'
|
||||
import { calculateCostTotal, validateCostVersionScope } from './cost-resolution-service.js'
|
||||
import { resolveMappingProductId } from './product-catalog-service.js'
|
||||
import { productSourceFilterSql } from './cost-center-mappers.js'
|
||||
import {
|
||||
buildTemplateMappingPlan,
|
||||
buildTemplateProductSku,
|
||||
@@ -289,3 +291,10 @@ test('接单模板改价 SQL 的参数必须显式指定 bigint', async () => {
|
||||
),
|
||||
)
|
||||
})
|
||||
|
||||
test('成本模型与商品来源必须覆盖第三方卡券渠道', () => {
|
||||
assert.equal(costModelAppliesTo('third_party_voucher_cost', 'third_party_voucher'), true)
|
||||
assert.equal(costModelAppliesTo('third_party_voucher_cost', 'manual'), false)
|
||||
assert.ok(productSourceFilterSql(1).includes("'third_party_voucher'"))
|
||||
assert.ok(productSourceFilterSql(1).includes("'tpv:%'"))
|
||||
})
|
||||
|
||||
@@ -78,6 +78,7 @@ export type CostVersionFormValues = {
|
||||
export const COST_MODEL_OPTIONS = [
|
||||
{ value: 'affiliate_purchase', label: '上游采购成本' },
|
||||
{ value: 'work_order_reward', label: '接单平台打手报酬' },
|
||||
{ value: 'third_party_voucher_cost', label: '第三方卡券采购成本' },
|
||||
{ value: 'manual_actual', label: '人工客服实际支出' },
|
||||
{ value: 'platform_fee', label: '平台服务费' },
|
||||
{ value: 'payment_fee', label: '支付通道费' },
|
||||
|
||||
@@ -18,6 +18,7 @@ export type ProductSource = 'affiliate_dash' | 'work_order' | 'third_party_vouch
|
||||
export type CostModel =
|
||||
| 'affiliate_purchase'
|
||||
| 'work_order_reward'
|
||||
| 'third_party_voucher_cost'
|
||||
| 'manual_actual'
|
||||
| 'platform_fee'
|
||||
| 'payment_fee'
|
||||
|
||||
Reference in New Issue
Block a user