diff --git a/README.md b/README.md index 2965fda7..a1a5b014 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,8 @@ docker compose -f docker-compose.dev.yml exec -T frontend npm run build docker compose -f docker-compose.dev.yml exec -T backend npm run db:migrate ``` +当前数据库脚本只保留新库初始化结构,不维护历史测试库的升级兼容;切换到这版前请重建开发库或重置 Docker volume。 + ## 环境变量 本地开发从根目录 `.env` 读取,模板为: diff --git a/apps/backend/README.md b/apps/backend/README.md index 606d98ac..76179c76 100644 --- a/apps/backend/README.md +++ b/apps/backend/README.md @@ -68,7 +68,7 @@ npm test - `src/services/fulfillment`:快手 Cloud 履约编排 - `src/services/admin`:后台读写、权限、配置管理 - `src/repositories`:数据库访问 -- `src/db/migrations`:数据库迁移 +- `src/db/migrations`:新库初始化脚本 ## Docker 开发 diff --git a/apps/backend/src/db/migrations/001_fulfillment_rebuild.sql b/apps/backend/src/db/migrations/001_init.sql similarity index 84% rename from apps/backend/src/db/migrations/001_fulfillment_rebuild.sql rename to apps/backend/src/db/migrations/001_init.sql index 9c7a0006..c3389371 100644 --- a/apps/backend/src/db/migrations/001_fulfillment_rebuild.sql +++ b/apps/backend/src/db/migrations/001_init.sql @@ -68,6 +68,37 @@ CREATE TABLE IF NOT EXISTS sku_fulfillment_bindings ( CREATE INDEX IF NOT EXISTS idx_sku_fulfillment_bindings_lookup ON sku_fulfillment_bindings(sku_code, provider, platform, shop_id, enabled, priority); +CREATE TABLE IF NOT EXISTS product_match_rules ( + id BIGSERIAL PRIMARY KEY, + provider TEXT NOT NULL DEFAULT '', + platform TEXT NOT NULL DEFAULT '', + shop_id TEXT NOT NULL DEFAULT '', + external_item_id TEXT NOT NULL DEFAULT '', + external_sku_code TEXT NOT NULL DEFAULT '', + external_sku_name TEXT NOT NULL DEFAULT '', + external_sku_name_normalized TEXT NOT NULL DEFAULT '', + resolved_sku_code TEXT NOT NULL, + enabled BOOLEAN NOT NULL DEFAULT TRUE, + priority INTEGER NOT NULL DEFAULT 100, + config_json JSONB NOT NULL DEFAULT '{}'::jsonb, + created_at TIMESTAMPTZ NOT NULL, + updated_at TIMESTAMPTZ NOT NULL +); + +CREATE UNIQUE INDEX IF NOT EXISTS idx_product_match_rules_unique + ON product_match_rules( + provider, + platform, + shop_id, + external_item_id, + external_sku_code, + external_sku_name_normalized, + resolved_sku_code + ); + +CREATE INDEX IF NOT EXISTS idx_product_match_rules_lookup + ON product_match_rules(provider, platform, shop_id, enabled, priority, id); + CREATE TABLE IF NOT EXISTS orders ( id BIGSERIAL PRIMARY KEY, provider TEXT NOT NULL, @@ -114,6 +145,7 @@ CREATE TABLE IF NOT EXISTS inventory_items ( source_type TEXT NOT NULL DEFAULT 'static_import', status TEXT NOT NULL DEFAULT 'available', invalid_reason TEXT NOT NULL DEFAULT '', + inventory_group_code TEXT NOT NULL DEFAULT '', metadata_json JSONB NOT NULL DEFAULT '{}'::jsonb, consumed_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL, @@ -124,6 +156,20 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_inventory_items_unique_payload ON inventory_items(sku_code, credential_type, md5(payload_json::text)); CREATE INDEX IF NOT EXISTS idx_inventory_items_pool ON inventory_items(sku_code, credential_type, status, id); +CREATE INDEX IF NOT EXISTS idx_inventory_items_group_lookup + ON inventory_items(sku_code, credential_type, inventory_group_code, status, id); + +CREATE TABLE IF NOT EXISTS admin_user_inventory_group_bindings ( + id BIGSERIAL PRIMARY KEY, + admin_user_id BIGINT NOT NULL REFERENCES admin_users(id) ON DELETE CASCADE, + inventory_group_code TEXT NOT NULL, + created_at TIMESTAMPTZ NOT NULL, + updated_at TIMESTAMPTZ NOT NULL, + UNIQUE(admin_user_id, inventory_group_code) +); + +CREATE INDEX IF NOT EXISTS idx_admin_user_inventory_group_bindings_user_id + ON admin_user_inventory_group_bindings(admin_user_id, inventory_group_code); CREATE TABLE IF NOT EXISTS fulfillment_tasks ( id BIGSERIAL PRIMARY KEY, diff --git a/apps/backend/src/db/migrations/002_product_match_rules.sql b/apps/backend/src/db/migrations/002_product_match_rules.sql deleted file mode 100644 index b500c726..00000000 --- a/apps/backend/src/db/migrations/002_product_match_rules.sql +++ /dev/null @@ -1,30 +0,0 @@ -CREATE TABLE IF NOT EXISTS product_match_rules ( - id BIGSERIAL PRIMARY KEY, - provider TEXT NOT NULL DEFAULT '', - platform TEXT NOT NULL DEFAULT '', - shop_id TEXT NOT NULL DEFAULT '', - external_item_id TEXT NOT NULL DEFAULT '', - external_sku_code TEXT NOT NULL DEFAULT '', - external_sku_name TEXT NOT NULL DEFAULT '', - external_sku_name_normalized TEXT NOT NULL DEFAULT '', - resolved_sku_code TEXT NOT NULL, - enabled BOOLEAN NOT NULL DEFAULT TRUE, - priority INTEGER NOT NULL DEFAULT 100, - config_json JSONB NOT NULL DEFAULT '{}'::jsonb, - created_at TIMESTAMPTZ NOT NULL, - updated_at TIMESTAMPTZ NOT NULL -); - -CREATE UNIQUE INDEX IF NOT EXISTS idx_product_match_rules_unique - ON product_match_rules( - provider, - platform, - shop_id, - external_item_id, - external_sku_code, - external_sku_name_normalized, - resolved_sku_code - ); - -CREATE INDEX IF NOT EXISTS idx_product_match_rules_lookup - ON product_match_rules(provider, platform, shop_id, enabled, priority, id); diff --git a/apps/backend/src/db/migrations/004_inventory_group_bindings.sql b/apps/backend/src/db/migrations/004_inventory_group_bindings.sql deleted file mode 100644 index 6a3a7a27..00000000 --- a/apps/backend/src/db/migrations/004_inventory_group_bindings.sql +++ /dev/null @@ -1,17 +0,0 @@ -ALTER TABLE inventory_items - ADD COLUMN IF NOT EXISTS inventory_group_code TEXT NOT NULL DEFAULT ''; - -CREATE INDEX IF NOT EXISTS idx_inventory_items_group_lookup - ON inventory_items(sku_code, credential_type, inventory_group_code, status, id); - -CREATE TABLE IF NOT EXISTS admin_user_inventory_group_bindings ( - id BIGSERIAL PRIMARY KEY, - admin_user_id BIGINT NOT NULL REFERENCES admin_users(id) ON DELETE CASCADE, - inventory_group_code TEXT NOT NULL, - created_at TIMESTAMPTZ NOT NULL, - updated_at TIMESTAMPTZ NOT NULL, - UNIQUE(admin_user_id, inventory_group_code) -); - -CREATE INDEX IF NOT EXISTS idx_admin_user_inventory_group_bindings_user_id - ON admin_user_inventory_group_bindings(admin_user_id, inventory_group_code); diff --git a/apps/backend/src/db/migrations/005_drop_message_deliveries.sql b/apps/backend/src/db/migrations/005_drop_message_deliveries.sql deleted file mode 100644 index 1a53bdae..00000000 --- a/apps/backend/src/db/migrations/005_drop_message_deliveries.sql +++ /dev/null @@ -1 +0,0 @@ -DROP TABLE IF EXISTS message_deliveries; diff --git a/apps/backend/src/db/migrations/006_rename_task_runtime_contexts.sql b/apps/backend/src/db/migrations/006_rename_task_runtime_contexts.sql deleted file mode 100644 index 77290219..00000000 --- a/apps/backend/src/db/migrations/006_rename_task_runtime_contexts.sql +++ /dev/null @@ -1,7 +0,0 @@ -DO $$ -BEGIN - IF to_regclass('public.tencent_browser_contexts') IS NOT NULL - AND to_regclass('public.task_runtime_contexts') IS NULL THEN - ALTER TABLE tencent_browser_contexts RENAME TO task_runtime_contexts; - END IF; -END $$; diff --git a/apps/backend/src/db/migrations/007_drop_legacy_tencent_profiles.sql b/apps/backend/src/db/migrations/007_drop_legacy_tencent_profiles.sql deleted file mode 100644 index cdefd4d7..00000000 --- a/apps/backend/src/db/migrations/007_drop_legacy_tencent_profiles.sql +++ /dev/null @@ -1,7 +0,0 @@ -DELETE FROM fulfillment_profiles -WHERE profile_key IN ('tencent_claim_redeem', 'tencent_claim_assisted') - AND NOT EXISTS ( - SELECT 1 - FROM fulfillment_tasks - WHERE fulfillment_tasks.profile_id = fulfillment_profiles.id - ); diff --git a/apps/backend/src/db/migrations/008_rename_claim_code_credential.sql b/apps/backend/src/db/migrations/008_rename_claim_code_credential.sql deleted file mode 100644 index 6df5993d..00000000 --- a/apps/backend/src/db/migrations/008_rename_claim_code_credential.sql +++ /dev/null @@ -1,16 +0,0 @@ -UPDATE inventory_items -SET credential_type = 'claim_code' -WHERE credential_type = 'tencent_code'; - -UPDATE fulfillment_profile_requirements -SET credential_type = 'claim_code' -WHERE credential_type = 'tencent_code'; - -UPDATE fulfillment_tasks -SET context_json = jsonb_set( - context_json, - '{primaryRequirement,credentialType}', - '"claim_code"'::jsonb, - false -) -WHERE context_json #>> '{primaryRequirement,credentialType}' = 'tencent_code'; diff --git a/apps/backend/src/db/migrations/009_rename_runtime_session_id.sql b/apps/backend/src/db/migrations/009_rename_runtime_session_id.sql deleted file mode 100644 index bbf88316..00000000 --- a/apps/backend/src/db/migrations/009_rename_runtime_session_id.sql +++ /dev/null @@ -1,20 +0,0 @@ -DO $$ -BEGIN - IF to_regclass('public.task_runtime_contexts') IS NOT NULL - AND EXISTS ( - SELECT 1 - FROM information_schema.columns - WHERE table_schema = 'public' - AND table_name = 'task_runtime_contexts' - AND column_name = 'browser_session_id' - ) - AND NOT EXISTS ( - SELECT 1 - FROM information_schema.columns - WHERE table_schema = 'public' - AND table_name = 'task_runtime_contexts' - AND column_name = 'runtime_session_id' - ) THEN - ALTER TABLE task_runtime_contexts RENAME COLUMN browser_session_id TO runtime_session_id; - END IF; -END $$;