76 lines
3.6 KiB
SQL
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());
|