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
@@ -0,0 +1,134 @@
-- 126_internal_sku_canonical_routing.sql
--
-- 履约渠道的唯一标准键是规范化后的中文内部 SKU。
-- 平台 SKU 只能用于入口映射,不能再成为渠道判定或兜底键。
CREATE OR REPLACE FUNCTION canonicalize_internal_sku(p_value TEXT)
RETURNS TEXT
LANGUAGE SQL
IMMUTABLE
PARALLEL SAFE
AS $$
SELECT NULLIF(
LOWER(
REGEXP_REPLACE(
BTRIM(NORMALIZE(COALESCE(p_value, ''), NFKC)),
'\s+',
'',
'g'
)
),
''
)
$$;
COMMENT ON FUNCTION canonicalize_internal_sku(TEXT) IS
'内部 SKU 唯一规范化:NFKC、去全部空白、转小写';
CREATE OR REPLACE FUNCTION resolve_internal_sku(
p_manual_sku_key TEXT,
p_sku_name TEXT,
p_sku_code TEXT
) RETURNS TEXT
LANGUAGE SQL
IMMUTABLE
PARALLEL SAFE
AS $$
SELECT COALESCE(
CASE
WHEN canonicalize_internal_sku(p_manual_sku_key) ~ '[一-龥]'
THEN canonicalize_internal_sku(p_manual_sku_key)
END,
CASE
WHEN canonicalize_internal_sku(p_sku_name) ~ '[一-龥]'
THEN canonicalize_internal_sku(p_sku_name)
END
)
$$;
COMMENT ON FUNCTION resolve_internal_sku(TEXT, TEXT, TEXT) IS
'订单项唯一内部 SKU 解析:只接受规范化后的中文 SKU,平台 SKU 不参与兜底';
COMMENT ON COLUMN order_items.manual_sku_key IS
'原始内部 SKU 匹配键(skuNick -> outSkuSn -> sku_code -> sku_name);渠道判定统一使用 resolve_internal_sku() 的中文规范值';
CREATE OR REPLACE FUNCTION normalize_internal_sku_channel_key()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
BEGIN
NEW.internal_sku := canonicalize_internal_sku(NEW.internal_sku);
RETURN NEW;
END;
$$;
CREATE OR REPLACE FUNCTION normalize_manual_fulfillment_config_key()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
BEGIN
NEW.sku_key := canonicalize_internal_sku(NEW.sku_key);
RETURN NEW;
END;
$$;
CREATE OR REPLACE FUNCTION normalize_manual_sku_registry_key()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
BEGIN
NEW.sku_key := canonicalize_internal_sku(NEW.sku_key);
RETURN NEW;
END;
$$;
CREATE OR REPLACE FUNCTION normalize_internal_sku_mapping_keys()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
BEGIN
NEW.match_value := canonicalize_internal_sku(NEW.match_value);
NEW.internal_sku := canonicalize_internal_sku(NEW.internal_sku);
RETURN NEW;
END;
$$;
DROP TRIGGER IF EXISTS trg_normalize_internal_sku_channel_key ON internal_sku_channels;
CREATE TRIGGER trg_normalize_internal_sku_channel_key
BEFORE INSERT OR UPDATE OF internal_sku ON internal_sku_channels
FOR EACH ROW EXECUTE FUNCTION normalize_internal_sku_channel_key();
DROP TRIGGER IF EXISTS trg_normalize_manual_fulfillment_config_key ON manual_fulfillment_configs;
CREATE TRIGGER trg_normalize_manual_fulfillment_config_key
BEFORE INSERT OR UPDATE OF sku_key ON manual_fulfillment_configs
FOR EACH ROW EXECUTE FUNCTION normalize_manual_fulfillment_config_key();
DROP TRIGGER IF EXISTS trg_normalize_manual_sku_registry_key ON manual_sku_registry;
CREATE TRIGGER trg_normalize_manual_sku_registry_key
BEFORE INSERT OR UPDATE OF sku_key ON manual_sku_registry
FOR EACH ROW EXECUTE FUNCTION normalize_manual_sku_registry_key();
DROP TRIGGER IF EXISTS trg_normalize_internal_sku_mapping_keys ON internal_sku_mappings;
CREATE TRIGGER trg_normalize_internal_sku_mapping_keys
BEFORE INSERT OR UPDATE OF match_value, internal_sku ON internal_sku_mappings
FOR EACH ROW EXECUTE FUNCTION normalize_internal_sku_mapping_keys();
CREATE INDEX IF NOT EXISTS idx_internal_sku_channels_canonical
ON internal_sku_channels (canonicalize_internal_sku(internal_sku), priority, channel)
WHERE enabled = TRUE;
CREATE INDEX IF NOT EXISTS idx_manual_fulfillment_configs_canonical_sku
ON manual_fulfillment_configs (canonicalize_internal_sku(sku_key))
WHERE enabled = TRUE;
CREATE INDEX IF NOT EXISTS idx_internal_sku_mappings_canonical_match
ON internal_sku_mappings (match_type, canonicalize_internal_sku(match_value))
WHERE enabled = TRUE;
CREATE INDEX IF NOT EXISTS idx_product_catalog_canonical_name
ON product_catalog (canonicalize_internal_sku(canonical_name))
WHERE status = 'active';
CREATE INDEX IF NOT EXISTS idx_order_items_pending_internal_sku
ON order_items (resolve_internal_sku(manual_sku_key, sku_name, sku_code))
WHERE fulfillment_status = 'pending';