Files
flatrender/backend/db/migrations/05_content_taxonomy.sql
T

160 lines
6.8 KiB
SQL
Raw Normal View History

-- =====================================================================
-- CONTENT SCHEMA — Part 1: Taxonomy & Assets (categories, tags, fonts, music)
-- =====================================================================
SET search_path TO content, public;
-- ---------------------------------------------------------------------
-- categories — hierarchical
-- ---------------------------------------------------------------------
CREATE TABLE categories (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
parent_id UUID REFERENCES categories(id) ON DELETE SET NULL,
name TEXT NOT NULL,
slug CITEXT NOT NULL UNIQUE,
description TEXT,
image_url TEXT,
icon TEXT,
-- SEO
meta_title TEXT,
meta_description TEXT,
meta_keywords TEXT,
bot_follow BOOLEAN NOT NULL DEFAULT TRUE,
sort INT NOT NULL DEFAULT 0,
is_active BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
deleted_at TIMESTAMPTZ
);
CREATE INDEX idx_categories_parent ON categories(parent_id);
CREATE INDEX idx_categories_active ON categories(is_active) WHERE deleted_at IS NULL;
CREATE TRIGGER tg_categories_updated_at
BEFORE UPDATE ON categories FOR EACH ROW EXECUTE FUNCTION public.tg_set_updated_at();
-- ---------------------------------------------------------------------
-- container_categories — many-to-many
-- ---------------------------------------------------------------------
-- Will be created after project_containers table
-- ---------------------------------------------------------------------
-- tags
-- ---------------------------------------------------------------------
CREATE TYPE choose_mode AS ENUM ('FIX','FLEXIBLE','MockUp','MusicVisualizer','VoiceOver');
CREATE TABLE tags (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL,
latin_name TEXT,
slug CITEXT NOT NULL UNIQUE,
applies_to_mode choose_mode,
is_active BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
deleted_at TIMESTAMPTZ
);
CREATE INDEX idx_tags_active ON tags(is_active) WHERE deleted_at IS NULL;
CREATE TRIGGER tg_tags_updated_at
BEFORE UPDATE ON tags FOR EACH ROW EXECUTE FUNCTION public.tg_set_updated_at();
-- ---------------------------------------------------------------------
-- fonts
-- ---------------------------------------------------------------------
CREATE TABLE fonts (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL, -- display name
original_name TEXT, -- as registered in AE
system_name TEXT, -- exact OS family name
family TEXT,
weight INT, -- 100-900
style TEXT, -- 'normal' | 'italic'
direction TEXT NOT NULL DEFAULT 'LTR', -- LTR/RTL/Auto
file_url TEXT, -- .ttf/.otf URL
sample_image_url TEXT,
is_premium BOOLEAN NOT NULL DEFAULT FALSE,
is_active BOOLEAN NOT NULL DEFAULT TRUE,
installed_on_nodes BOOLEAN NOT NULL DEFAULT FALSE,
sort INT NOT NULL DEFAULT 0,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
deleted_at TIMESTAMPTZ
);
CREATE INDEX idx_fonts_active ON fonts(is_active) WHERE deleted_at IS NULL;
CREATE TRIGGER tg_fonts_updated_at
BEFORE UPDATE ON fonts FOR EACH ROW EXECUTE FUNCTION public.tg_set_updated_at();
-- ---------------------------------------------------------------------
-- music_tracks
-- ---------------------------------------------------------------------
CREATE TABLE music_tracks (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL,
caption TEXT,
keywords TEXT,
url TEXT NOT NULL,
waveform_data JSONB, -- precomputed visualization
duration_sec NUMERIC(8,2) NOT NULL,
bpm INT,
genre TEXT,
mood TEXT,
is_premium BOOLEAN NOT NULL DEFAULT FALSE,
is_active BOOLEAN NOT NULL DEFAULT TRUE,
sort INT NOT NULL DEFAULT 0,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
deleted_at TIMESTAMPTZ
);
CREATE INDEX idx_music_active ON music_tracks(is_active) WHERE deleted_at IS NULL;
CREATE INDEX idx_music_genre ON music_tracks(genre);
CREATE TRIGGER tg_music_updated_at
BEFORE UPDATE ON music_tracks FOR EACH ROW EXECUTE FUNCTION public.tg_set_updated_at();
-- ---------------------------------------------------------------------
-- project_servers — render server configs (multi-region)
-- ---------------------------------------------------------------------
CREATE TABLE project_servers (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL,
region TEXT NOT NULL, -- 'tehran','frankfurt',...
ip INET,
physical_path_output TEXT,
default_project_address TEXT,
render_output_location TEXT,
pre_need_folder_address TEXT,
minio_endpoint TEXT,
minio_bucket_templates TEXT,
minio_bucket_outputs TEXT,
is_active BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_project_servers_region ON project_servers(region) WHERE is_active = TRUE;
CREATE TRIGGER tg_project_servers_updated_at
BEFORE UPDATE ON project_servers FOR EACH ROW EXECUTE FUNCTION public.tg_set_updated_at();
-- ---------------------------------------------------------------------
-- admin_files — admin-uploaded resources
-- ---------------------------------------------------------------------
CREATE TABLE admin_files (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT,
url TEXT NOT NULL,
thumbnail_url TEXT,
file_type TEXT,
size_bytes BIGINT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);