refactor(cost-center): 收敛人工 SKU 自动创建流程

This commit is contained in:
yml2213
2026-11-06 16:37:29 +08:00
parent eef4cc1673
commit 974044a4c6
17 changed files with 601 additions and 731 deletions
@@ -1,3 +1,5 @@
import type { PoolClient } from 'pg'
import { query, withTransaction } from '../../db/client.js'
import type { FulfillmentChannel } from './channel-types.js'
import { canonicalizeInternalSku, compareFulfillmentChannel } from './internal-sku-resolver.js'
@@ -127,7 +129,7 @@ export function planInternalSkuChannels(input: InternalSkuChannelRow[]): Interna
}
}
export async function upsertInternalSkuChannel(input: {
type InternalSkuChannelUpsertInput = {
internalSku: string
channel: FulfillmentChannel
priority?: number
@@ -139,25 +141,29 @@ export async function upsertInternalSkuChannel(input: {
note?: string | undefined
adminUserId?: number | null | undefined
replacePriority?: boolean
}): Promise<number> {
}
async function upsertInternalSkuChannelWithExecutor(
client: Pick<PoolClient, 'query'>,
input: InternalSkuChannelUpsertInput,
): Promise<number> {
const internalSku = canonicalizeInternalSku(input.internalSku)
if (!internalSku) return 0
return withTransaction(async (client) => {
if (input.enabled !== false && input.isFallback !== true) {
await client.query(
`UPDATE internal_sku_channels
SET is_fallback = TRUE,
priority = GREATEST(priority, 90),
updated_at = NOW()
WHERE canonicalize_internal_sku(internal_sku) = $1
AND channel <> $2
AND enabled = TRUE
AND is_fallback = FALSE`,
[internalSku, input.channel],
)
}
const result = await client.query<{ id: number }>(
`
if (input.enabled !== false && input.isFallback !== true) {
await client.query(
`UPDATE internal_sku_channels
SET is_fallback = TRUE,
priority = GREATEST(priority, 90),
updated_at = NOW()
WHERE canonicalize_internal_sku(internal_sku) = $1
AND channel <> $2
AND enabled = TRUE
AND is_fallback = FALSE`,
[internalSku, input.channel],
)
}
const result = await client.query<{ id: number }>(
`
INSERT INTO internal_sku_channels (
internal_sku, channel, priority, is_fallback, enabled,
canonical_product_id, config_json, source, note, created_by_admin_user_id,
@@ -177,23 +183,35 @@ export async function upsertInternalSkuChannel(input: {
created_by_admin_user_id = COALESCE(EXCLUDED.created_by_admin_user_id, internal_sku_channels.created_by_admin_user_id),
updated_at = NOW()
RETURNING id
`,
[
internalSku,
input.channel,
Number.isFinite(Number(input.priority)) ? Number(input.priority) : 100,
input.isFallback === true,
input.enabled !== false,
input.canonicalProductId ?? null,
JSON.stringify(input.configJson || {}),
String(input.source || 'auto').trim() || 'auto',
String(input.note || '').slice(0, 300),
input.adminUserId ?? null,
input.replacePriority === true,
],
)
return Number(result.rows[0]?.id || 0)
})
`,
[
internalSku,
input.channel,
Number.isFinite(Number(input.priority)) ? Number(input.priority) : 100,
input.isFallback === true,
input.enabled !== false,
input.canonicalProductId ?? null,
JSON.stringify(input.configJson || {}),
String(input.source || 'auto').trim() || 'auto',
String(input.note || '').slice(0, 300),
input.adminUserId ?? null,
input.replacePriority === true,
],
)
return Number(result.rows[0]?.id || 0)
}
export async function upsertInternalSkuChannelWithClient(
client: PoolClient,
input: InternalSkuChannelUpsertInput,
): Promise<number> {
return upsertInternalSkuChannelWithExecutor(client, input)
}
export async function upsertInternalSkuChannel(
input: InternalSkuChannelUpsertInput,
): Promise<number> {
return withTransaction((client) => upsertInternalSkuChannelWithExecutor(client, input))
}
/**