feat(fulfillment): 统一中文内部 SKU 履约路由

This commit is contained in:
yml2213
2026-11-03 11:49:38 +08:00
parent f447b5d73a
commit 3ba808b814
49 changed files with 1643 additions and 1963 deletions
@@ -132,6 +132,32 @@ async function main() {
ORDER BY count(*) DESC, internal_sku`,
)
const internalChannels = await query<{
channel: string
source: string
total: number
}>(
`SELECT channel, source, count(*)::int AS total
FROM internal_sku_channels
WHERE enabled = TRUE
GROUP BY channel, source
ORDER BY channel, source`,
)
const canonicalChannelDuplicates = await query<{
internal_sku: string
channel: string
total: number
}>(
`SELECT canonicalize_internal_sku(internal_sku) AS internal_sku,
channel, count(*)::int AS total
FROM internal_sku_channels
WHERE enabled = TRUE
GROUP BY canonicalize_internal_sku(internal_sku), channel
HAVING count(*) > 1
ORDER BY count(*) DESC, internal_sku, channel`,
)
const assignedCarrierConflicts = await query<{
order_item_id: number
channel: string
@@ -197,7 +223,9 @@ async function main() {
rules: rules.rows,
duplicateProducts: duplicateProducts.rows[0],
capabilities: capabilities.rows,
internalChannels: internalChannels.rows,
internalChannelConflicts: internalChannelConflicts.rows,
canonicalChannelDuplicates: canonicalChannelDuplicates.rows,
assignedCarrierConflicts: assignedCarrierConflicts.rows,
byProvider: byProvider.rows,
},
@@ -1,8 +1,7 @@
/**
* 从 PDD 纯数字内部 SKU 的订单项回填中文映射(只读扫描 + 幂等写入)。
* 从平台 SKU 非中文、但商品名含中文的订单项回填中文内部 SKU 映射。
*
* 只处理 sku_name 含中文、sku_code 为纯数字的情况;
* 找不到中文名的纯数字码会列出来,等运营补映射。
* 数字码、英文码一视同仁;找不到中文名的平台码会列出来,等运营补映射。
*
* 用法:npx tsx scripts/backfill-internal-sku-mappings.ts [--apply]
*/
@@ -22,7 +21,7 @@ async function main() {
SELECT o.provider, o.shop_id, oi.sku_code, MIN(oi.sku_name) AS sku_name, count(*)::int AS total
FROM order_items oi
JOIN orders o ON o.id = oi.order_id
WHERE btrim(COALESCE(oi.manual_sku_key, '')) ~ '^[0-9]+$'
WHERE COALESCE(canonicalize_internal_sku(oi.manual_sku_key), '') !~ '[一-龥]'
AND btrim(COALESCE(oi.sku_name, '')) ~ '[一-龥]'
GROUP BY 1, 2, 3
ORDER BY 5 DESC
@@ -38,7 +37,7 @@ async function main() {
SELECT o.provider, o.shop_id, oi.sku_code, count(*)::int AS total
FROM order_items oi
JOIN orders o ON o.id = oi.order_id
WHERE btrim(COALESCE(oi.manual_sku_key, '')) ~ '^[0-9]+$'
WHERE COALESCE(canonicalize_internal_sku(oi.manual_sku_key), '') !~ '[一-龥]'
AND btrim(COALESCE(oi.sku_name, '')) !~ '[一-龥]'
GROUP BY 1, 2, 3
ORDER BY 4 DESC
@@ -118,6 +118,62 @@ async function main() {
)
).rows
checks.canonicalChannelDuplicates = (
await query<CountRow>(
`SELECT canonicalize_internal_sku(internal_sku) AS label, count(*)::int AS total
FROM internal_sku_channels
WHERE enabled = TRUE
GROUP BY canonicalize_internal_sku(internal_sku), channel
HAVING count(*) > 1
ORDER BY count(*) DESC, label`,
)
).rows
checks.incompleteCarrierConfigs = (
await query<CountRow>(
`SELECT channel AS label, count(*)::int AS total
FROM internal_sku_channels
WHERE enabled = TRUE
AND (
(
channel = 'work_order'
AND (
COALESCE(config_json->>'workRuleKey', '') = ''
OR NOT EXISTS (
SELECT 1 FROM work_product_rules rule
WHERE rule.rule_key = config_json->>'workRuleKey'
AND rule.enabled = TRUE
)
)
)
OR (
channel = 'manual'
AND NOT EXISTS (
SELECT 1 FROM manual_fulfillment_configs cfg
WHERE cfg.enabled = TRUE
AND canonicalize_internal_sku(cfg.sku_key)
= canonicalize_internal_sku(internal_sku_channels.internal_sku)
)
)
)
GROUP BY channel ORDER BY count(*) DESC`,
)
).rows
checks.pendingWithoutChineseInternalSku = (
await query<CountRow>(
`SELECT 'pending_without_chinese_internal_sku' AS label, count(*)::int AS total
FROM order_items oi
JOIN orders o ON o.id = oi.order_id
WHERE oi.fulfillment_status = 'pending'
AND ($1::boolean OR o.shop_id NOT LIKE 'sim-%')
AND COALESCE(resolve_internal_sku(
oi.manual_sku_key, oi.sku_name, oi.sku_code
), '') = ''`,
[includeDemo],
)
).rows[0]
checks.enabledLegacyRules = (
await query<CountRow>(
`SELECT match_key_type || '/' || channel AS label, count(*)::int AS total
@@ -202,6 +258,12 @@ async function main() {
failed.push('存在同时挂载多个真实履约载体的已分配订单项')
if ((checks.internalChannelConflicts as CountRow[]).length > 0)
failed.push('存在多个非兜底主渠道')
if ((checks.canonicalChannelDuplicates as CountRow[]).length > 0)
failed.push('存在规范化后重复的内部 SKU 渠道配置')
if ((checks.incompleteCarrierConfigs as CountRow[]).length > 0)
failed.push('存在缺少 workRuleKey 或人工履约配置的启用渠道')
if ((checks.pendingWithoutChineseInternalSku as CountRow).total > 0)
failed.push('存在无法归一到中文内部 SKU 的 pending 订单项')
if ((checks.enabledLegacyRules as CountRow[]).length > 0)
failed.push('仍有启用的 sku_code 兼容规则,未完全收敛到内部 SKU')
if ((checks.pendingWithoutReason as CountRow).total > 0)