Files
atlas-seller-kit/packages/database/migrations/029_product_ai_autofill.sql
T
2026-09-23 17:18:09 +08:00

76 lines
3.6 KiB
SQL

SET search_path TO atlas, public;
-- SKU 发布标题为空时继承当前平台 SPU 标题;内部展示名不是发布标题。
ALTER TABLE product_variant_platform_listings ADD COLUMN title TEXT;
ALTER TABLE product_variants ADD CONSTRAINT uq_product_variants_workspace_id_product
UNIQUE (workspace_id, id, product_id);
-- 模型任务只保存服务端固化的资料快照;Outbox 仅携带任务 ID。
CREATE TABLE product_ai_tasks (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
workspace_id UUID NOT NULL REFERENCES workspaces(id) ON DELETE RESTRICT,
product_id UUID NOT NULL,
profile_id UUID NOT NULL,
variant_id UUID,
kind TEXT NOT NULL CHECK (kind IN ('autofill', 'sku_copy')),
status TEXT NOT NULL DEFAULT 'queued'
CHECK (status IN ('queued', 'running', 'succeeded', 'partial', 'failed')),
input_snapshot JSONB NOT NULL,
result JSONB NOT NULL DEFAULT '{}'::jsonb,
error_code TEXT,
error_message TEXT,
model_name TEXT,
prompt_version TEXT NOT NULL DEFAULT 'v1',
token_usage JSONB NOT NULL DEFAULT '{}'::jsonb,
created_by_user_id UUID REFERENCES users(id) ON DELETE SET NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
started_at TIMESTAMPTZ,
completed_at TIMESTAMPTZ,
FOREIGN KEY (workspace_id, profile_id, product_id)
REFERENCES product_platform_profiles(workspace_id, id, product_id) ON DELETE CASCADE,
FOREIGN KEY (workspace_id, variant_id, product_id)
REFERENCES product_variants(workspace_id, id, product_id) ON DELETE RESTRICT,
CHECK ((kind = 'autofill' AND variant_id IS NULL)
OR (kind = 'sku_copy' AND variant_id IS NOT NULL)),
UNIQUE (workspace_id, id)
);
CREATE INDEX ix_product_ai_tasks_profile_recent
ON product_ai_tasks (workspace_id, profile_id, created_at DESC);
-- 中文只作编辑对照;发布适配器只读取俄文草稿。
CREATE TABLE product_copy_translations (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
workspace_id UUID NOT NULL REFERENCES workspaces(id) ON DELETE RESTRICT,
product_id UUID NOT NULL,
profile_id UUID NOT NULL,
variant_id UUID,
field TEXT NOT NULL CHECK (field IN ('title', 'tags', 'description')),
russian_value JSONB NOT NULL,
chinese_value JSONB NOT NULL,
source_task_id UUID,
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
FOREIGN KEY (workspace_id, profile_id, product_id)
REFERENCES product_platform_profiles(workspace_id, id, product_id) ON DELETE CASCADE,
FOREIGN KEY (workspace_id, variant_id, product_id)
REFERENCES product_variants(workspace_id, id, product_id) ON DELETE CASCADE,
FOREIGN KEY (workspace_id, source_task_id)
REFERENCES product_ai_tasks(workspace_id, id) ON DELETE SET NULL (source_task_id)
);
CREATE UNIQUE INDEX ux_product_copy_translations_spu
ON product_copy_translations (workspace_id, profile_id, field)
WHERE variant_id IS NULL;
CREATE UNIQUE INDEX ux_product_copy_translations_sku
ON product_copy_translations (workspace_id, profile_id, variant_id, field)
WHERE variant_id IS NOT NULL;
ALTER TABLE product_ai_tasks ENABLE ROW LEVEL SECURITY;
ALTER TABLE product_ai_tasks FORCE ROW LEVEL SECURITY;
CREATE POLICY workspace_isolation ON product_ai_tasks
USING (workspace_id = app_current_workspace_id())
WITH CHECK (workspace_id = app_current_workspace_id());
ALTER TABLE product_copy_translations ENABLE ROW LEVEL SECURITY;
ALTER TABLE product_copy_translations FORCE ROW LEVEL SECURITY;
CREATE POLICY workspace_isolation ON product_copy_translations
USING (workspace_id = app_current_workspace_id())
WITH CHECK (workspace_id = app_current_workspace_id());