From 60fb8a4d7fdaa5f79ec726a4279e38fdcfdef8ac Mon Sep 17 00:00:00 2001 From: liangxu Date: Fri, 17 Apr 2026 07:53:56 +0800 Subject: [PATCH] feat(kol): add migration for KOL core tables --- .../20260417100000_create_kol_tables.down.sql | 8 + .../20260417100000_create_kol_tables.up.sql | 150 ++++++++++++++++++ 2 files changed, 158 insertions(+) create mode 100644 server/migrations/20260417100000_create_kol_tables.down.sql create mode 100644 server/migrations/20260417100000_create_kol_tables.up.sql diff --git a/server/migrations/20260417100000_create_kol_tables.down.sql b/server/migrations/20260417100000_create_kol_tables.down.sql new file mode 100644 index 0000000..57c5a10 --- /dev/null +++ b/server/migrations/20260417100000_create_kol_tables.down.sql @@ -0,0 +1,8 @@ +DROP TABLE IF EXISTS kol_assist_tasks; +DROP TABLE IF EXISTS kol_usage_logs; +DROP TABLE IF EXISTS kol_subscription_prompts; +DROP TABLE IF EXISTS kol_subscriptions; +DROP TABLE IF EXISTS kol_prompt_revisions; +DROP TABLE IF EXISTS kol_prompts; +DROP TABLE IF EXISTS kol_packages; +DROP TABLE IF EXISTS kol_profiles; diff --git a/server/migrations/20260417100000_create_kol_tables.up.sql b/server/migrations/20260417100000_create_kol_tables.up.sql new file mode 100644 index 0000000..b837125 --- /dev/null +++ b/server/migrations/20260417100000_create_kol_tables.up.sql @@ -0,0 +1,150 @@ +CREATE TABLE kol_profiles ( + id BIGSERIAL PRIMARY KEY, + tenant_id BIGINT NOT NULL REFERENCES tenants(id), + user_id BIGINT NOT NULL REFERENCES users(id), + display_name VARCHAR(100) NOT NULL, + bio TEXT, + avatar_url TEXT, + market_enabled BOOLEAN NOT NULL DEFAULT FALSE, + status VARCHAR(20) NOT NULL DEFAULT 'active', + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + deleted_at TIMESTAMPTZ +); +CREATE UNIQUE INDEX uk_kol_profile_user_active + ON kol_profiles(user_id) WHERE deleted_at IS NULL; +CREATE INDEX idx_kol_profile_tenant + ON kol_profiles(tenant_id) WHERE deleted_at IS NULL; + +CREATE TABLE kol_packages ( + id BIGSERIAL PRIMARY KEY, + tenant_id BIGINT NOT NULL REFERENCES tenants(id), + kol_profile_id BIGINT NOT NULL REFERENCES kol_profiles(id), + name VARCHAR(200) NOT NULL, + description TEXT, + cover_url TEXT, + industry VARCHAR(100), + tags JSONB NOT NULL DEFAULT '[]', + price_note VARCHAR(200), + status VARCHAR(20) NOT NULL DEFAULT 'draft', + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + deleted_at TIMESTAMPTZ +); +CREATE INDEX idx_kol_package_profile + ON kol_packages(kol_profile_id, created_at DESC) WHERE deleted_at IS NULL; +CREATE INDEX idx_kol_package_status + ON kol_packages(status, created_at DESC) WHERE deleted_at IS NULL; + +CREATE TABLE kol_prompts ( + id BIGSERIAL PRIMARY KEY, + tenant_id BIGINT NOT NULL REFERENCES tenants(id), + package_id BIGINT NOT NULL REFERENCES kol_packages(id), + name VARCHAR(200) NOT NULL, + platform_hint VARCHAR(100), + status VARCHAR(20) NOT NULL DEFAULT 'draft', + sort_order INT NOT NULL DEFAULT 0, + published_revision_no INT, + draft_revision_no INT, + created_by BIGINT NOT NULL REFERENCES users(id), + updated_by BIGINT NOT NULL REFERENCES users(id), + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + deleted_at TIMESTAMPTZ +); +CREATE INDEX idx_kol_prompt_package + ON kol_prompts(package_id, sort_order, created_at) WHERE deleted_at IS NULL; +CREATE INDEX idx_kol_prompt_tenant_status + ON kol_prompts(tenant_id, status, created_at DESC) WHERE deleted_at IS NULL; + +CREATE TABLE kol_prompt_revisions ( + id BIGSERIAL PRIMARY KEY, + tenant_id BIGINT NOT NULL REFERENCES tenants(id), + prompt_id BIGINT NOT NULL REFERENCES kol_prompts(id), + revision_no INT NOT NULL, + prompt_asset_key TEXT NOT NULL, + schema_json JSONB NOT NULL DEFAULT '{}', + card_config_json JSONB NOT NULL DEFAULT '{}', + created_by BIGINT NOT NULL REFERENCES users(id), + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + UNIQUE (prompt_id, revision_no) +); +CREATE INDEX idx_kol_prompt_revision_prompt + ON kol_prompt_revisions(prompt_id, revision_no DESC); + +CREATE TABLE kol_subscriptions ( + id BIGSERIAL PRIMARY KEY, + tenant_id BIGINT NOT NULL REFERENCES tenants(id), + package_id BIGINT NOT NULL REFERENCES kol_packages(id), + status VARCHAR(20) NOT NULL DEFAULT 'pending', + approved_by BIGINT REFERENCES users(id), + start_at TIMESTAMPTZ, + end_at TIMESTAMPTZ, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); +CREATE UNIQUE INDEX uk_kol_subscription_active + ON kol_subscriptions(tenant_id, package_id) + WHERE status IN ('pending', 'active'); +CREATE INDEX idx_kol_subscription_package + ON kol_subscriptions(package_id, status, created_at DESC); + +CREATE TABLE kol_subscription_prompts ( + id BIGSERIAL PRIMARY KEY, + tenant_id BIGINT NOT NULL REFERENCES tenants(id), + subscription_id BIGINT NOT NULL REFERENCES kol_subscriptions(id), + package_id BIGINT NOT NULL REFERENCES kol_packages(id), + prompt_id BIGINT NOT NULL REFERENCES kol_prompts(id), + status VARCHAR(20) NOT NULL DEFAULT 'active', + granted_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + revoked_at TIMESTAMPTZ, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); +CREATE UNIQUE INDEX uk_kol_subscription_prompt + ON kol_subscription_prompts(subscription_id, prompt_id); +CREATE INDEX idx_kol_subscription_prompt_tenant + ON kol_subscription_prompts(tenant_id, status, created_at DESC); + +CREATE TABLE kol_usage_logs ( + id BIGSERIAL PRIMARY KEY, + tenant_id BIGINT NOT NULL REFERENCES tenants(id), + subscription_id BIGINT REFERENCES kol_subscriptions(id), + subscription_prompt_id BIGINT REFERENCES kol_subscription_prompts(id), + package_id BIGINT NOT NULL REFERENCES kol_packages(id), + prompt_id BIGINT NOT NULL REFERENCES kol_prompts(id), + prompt_revision_no INT NOT NULL, + article_id BIGINT REFERENCES articles(id), + generation_task_id BIGINT REFERENCES generation_tasks(id), + status VARCHAR(20) NOT NULL DEFAULT 'pending', + variables_snapshot JSONB, + schema_snapshot JSONB, + rendered_prompt_hash VARCHAR(64), + error_message TEXT, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + finished_at TIMESTAMPTZ +); +CREATE INDEX idx_kol_usage_package ON kol_usage_logs(package_id, created_at DESC); +CREATE INDEX idx_kol_usage_tenant ON kol_usage_logs(tenant_id, created_at DESC); +CREATE INDEX idx_kol_usage_prompt ON kol_usage_logs(prompt_id, created_at DESC); + +CREATE TABLE kol_assist_tasks ( + id VARCHAR(64) PRIMARY KEY, + tenant_id BIGINT NOT NULL REFERENCES tenants(id), + kol_profile_id BIGINT NOT NULL REFERENCES kol_profiles(id), + prompt_id BIGINT REFERENCES kol_prompts(id), + operator_id BIGINT NOT NULL REFERENCES users(id), + task_type VARCHAR(50) NOT NULL, + status VARCHAR(20) NOT NULL DEFAULT 'queued', + request_json JSONB NOT NULL DEFAULT '{}'::jsonb, + result_json JSONB, + error_message TEXT, + started_at TIMESTAMPTZ, + completed_at TIMESTAMPTZ, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); +CREATE INDEX idx_kol_assist_tenant_profile + ON kol_assist_tasks(tenant_id, kol_profile_id, created_at DESC); +CREATE INDEX idx_kol_assist_status + ON kol_assist_tasks(status, created_at DESC);