refactor(finance)!: 事实维度与接口字段统一改名 channel
- migration 114 将 sales_daily_facts.fulfillment_mode 重命名为 channel - DTO/查询参数/前端类型从 fulfillmentMode 统一为 channel - 成本中心类型 FulfillmentMode 更名为 FulfillmentChannel,并补齐卡券/待分类/归档取值 - 销售事实响应分组改为 byChannel
This commit is contained in:
@@ -69,7 +69,7 @@ type ConfirmContextRow = {
|
||||
revenue_fen: string
|
||||
basis_at: string
|
||||
canonical_product_id: number | null
|
||||
fulfillment_mode: string
|
||||
channel: string
|
||||
config_id: number | null
|
||||
platform_key: string
|
||||
credit_quantity: string
|
||||
@@ -225,7 +225,7 @@ export async function confirmManualFulfillment(payload: JsonObject, session: Adm
|
||||
COALESCE(oi.revenue_amount_fen, 0)::bigint AS revenue_fen,
|
||||
COALESCE(o.paid_at, o.created_at) AS basis_at,
|
||||
oi.canonical_product_id,
|
||||
COALESCE(oi.fulfillment_channel, CASE WHEN oi.fulfillment_status = 'archived' THEN 'archived' ELSE 'pending' END) AS fulfillment_mode,
|
||||
COALESCE(oi.fulfillment_channel, CASE WHEN oi.fulfillment_status = 'archived' THEN 'archived' ELSE 'pending' END) AS channel,
|
||||
oi.fulfillment_config_id AS config_id,
|
||||
COALESCE(cfg.platform_key, '') AS platform_key,
|
||||
COALESCE(cfg.credit_quantity, 0)::bigint AS credit_quantity,
|
||||
@@ -256,7 +256,7 @@ export async function confirmManualFulfillment(payload: JsonObject, session: Adm
|
||||
errorCode: 'manual_fulfillment_order_item_not_found',
|
||||
})
|
||||
}
|
||||
if (row.fulfillment_mode !== 'manual') {
|
||||
if (row.channel !== 'manual') {
|
||||
throw createHttpError('该订单项不是人工履约', {
|
||||
statusCode: 409,
|
||||
errorCode: 'manual_fulfillment_not_manual',
|
||||
|
||||
@@ -544,7 +544,7 @@ async function createManualItem(
|
||||
const orderId = Number(order.rows[0]?.id)
|
||||
const item = await query(
|
||||
`INSERT INTO order_items (
|
||||
order_id, sku_code, sku_name, fulfillment_mode, spec_json,
|
||||
order_id, sku_code, sku_name, channel, spec_json,
|
||||
revenue_amount_fen, revenue_basis, created_at, updated_at
|
||||
) VALUES ($1, $2, $3, 'manual', $4::jsonb, 5000, 'order_total', NOW(), NOW())
|
||||
RETURNING id`,
|
||||
|
||||
@@ -10,7 +10,7 @@ import { nowIso } from '../../utils/time.js'
|
||||
* 2. 归档订单(archived)不进事实;
|
||||
* 3. 成本来自 `cost_snapshots`,缺失就记 0 并计数,不把 0 当真实成本。
|
||||
*
|
||||
* 事实表暂时沿用 `fulfillment_mode` 列承载渠道值(113 再改列名)。
|
||||
* 事实表暂时沿用 `channel` 列承载渠道值(113 再改列名)。
|
||||
*/
|
||||
|
||||
export type ChannelFactsResult = {
|
||||
@@ -107,7 +107,7 @@ export async function rebuildChannelSalesDailyFacts(input: {
|
||||
) c ON c.order_item_id = s.order_item_id
|
||||
)
|
||||
INSERT INTO sales_daily_facts (
|
||||
stat_date, provider, shop_id, canonical_product_id, fulfillment_mode,
|
||||
stat_date, provider, shop_id, canonical_product_id, channel,
|
||||
order_count, item_count, quantity,
|
||||
gross_revenue_fen, refund_amount_fen, net_revenue_fen,
|
||||
cost_amount_fen, cost_missing_count, cost_stage,
|
||||
|
||||
@@ -18,7 +18,7 @@ type SalesFactRow = {
|
||||
canonical_product_id: number | null
|
||||
canonical_sku: string | null
|
||||
canonical_name: string | null
|
||||
fulfillment_mode: string
|
||||
channel: string
|
||||
order_count: number
|
||||
item_count: number
|
||||
quantity: string | number
|
||||
@@ -99,7 +99,7 @@ export async function getSalesProfitOverview(input: SalesFactsInput = {}) {
|
||||
[range.fromDate, range.toDate],
|
||||
),
|
||||
query<{
|
||||
fulfillment_mode: string
|
||||
channel: string
|
||||
item_count: number
|
||||
gross_revenue_fen: number
|
||||
cost_amount_fen: number
|
||||
@@ -108,7 +108,7 @@ export async function getSalesProfitOverview(input: SalesFactsInput = {}) {
|
||||
}>(
|
||||
`
|
||||
SELECT
|
||||
fulfillment_mode,
|
||||
channel,
|
||||
SUM(item_count)::int AS item_count,
|
||||
SUM(gross_revenue_fen)::bigint AS gross_revenue_fen,
|
||||
SUM(cost_amount_fen)::bigint AS cost_amount_fen,
|
||||
@@ -116,7 +116,7 @@ export async function getSalesProfitOverview(input: SalesFactsInput = {}) {
|
||||
SUM(gross_profit_fen)::bigint AS gross_profit_fen
|
||||
FROM sales_daily_facts
|
||||
WHERE stat_date BETWEEN $1::date AND $2::date
|
||||
GROUP BY fulfillment_mode
|
||||
GROUP BY channel
|
||||
ORDER BY gross_revenue_fen DESC
|
||||
`,
|
||||
[range.fromDate, range.toDate],
|
||||
@@ -210,8 +210,8 @@ export async function getSalesProfitOverview(input: SalesFactsInput = {}) {
|
||||
costMissingCount: Number(row.cost_missing_count || 0),
|
||||
grossProfitFen: Number(row.gross_profit_fen || 0),
|
||||
})),
|
||||
byFulfillmentMode: carrierResult.rows.map((row) => ({
|
||||
fulfillmentMode: row.fulfillment_mode,
|
||||
byChannel: carrierResult.rows.map((row) => ({
|
||||
channel: row.channel,
|
||||
itemCount: Number(row.item_count || 0),
|
||||
grossRevenueFen: Number(row.gross_revenue_fen || 0),
|
||||
costAmountFen: Number(row.cost_amount_fen || 0),
|
||||
@@ -239,9 +239,7 @@ export async function listSalesDailyFacts(input: Record<string, unknown> = {}) {
|
||||
normalizePositiveInteger(input.pageSize ?? input.page_size, 20, '每页数量'),
|
||||
)
|
||||
const provider = String(input.provider || '').trim()
|
||||
const fulfillmentMode = String(
|
||||
input.fulfillmentMode || input.fulfillment_mode || input.carrierType || '',
|
||||
).trim()
|
||||
const channel = String(input.channel || input.channel || input.carrierType || '').trim()
|
||||
const canonicalProductId = Number(input.canonicalProductId || input.canonical_product_id || 0)
|
||||
|
||||
const conditions = ['f.stat_date BETWEEN $1::date AND $2::date']
|
||||
@@ -250,9 +248,9 @@ export async function listSalesDailyFacts(input: Record<string, unknown> = {}) {
|
||||
params.push(provider)
|
||||
conditions.push(`f.provider = $${params.length}`)
|
||||
}
|
||||
if (fulfillmentMode) {
|
||||
params.push(fulfillmentMode)
|
||||
conditions.push(`f.fulfillment_mode = $${params.length}`)
|
||||
if (channel) {
|
||||
params.push(channel)
|
||||
conditions.push(`f.channel = $${params.length}`)
|
||||
}
|
||||
if (Number.isInteger(canonicalProductId) && canonicalProductId > 0) {
|
||||
params.push(canonicalProductId)
|
||||
@@ -301,7 +299,7 @@ function mapSalesFact(row: SalesFactRow) {
|
||||
canonicalProductId: row.canonical_product_id ? Number(row.canonical_product_id) : null,
|
||||
canonicalSku: row.canonical_sku || '',
|
||||
canonicalName: row.canonical_name || '未归一',
|
||||
fulfillmentMode: row.fulfillment_mode,
|
||||
channel: row.channel,
|
||||
orderCount: Number(row.order_count || 0),
|
||||
itemCount: Number(row.item_count || 0),
|
||||
quantity: Number(row.quantity || 0),
|
||||
|
||||
Reference in New Issue
Block a user