db: tenants-db schema — per-brand operational tables
This commit is contained in:
@@ -0,0 +1,135 @@
|
|||||||
|
-- manar-tenants-db: per-brand operational schemas
|
||||||
|
-- Creates brand_alsalama and brand_asktam with identical table structure
|
||||||
|
|
||||||
|
DO $$
|
||||||
|
DECLARE
|
||||||
|
schemas TEXT[] := ARRAY['brand_alsalama', 'brand_asktam'];
|
||||||
|
s TEXT;
|
||||||
|
BEGIN
|
||||||
|
FOREACH s IN ARRAY schemas LOOP
|
||||||
|
EXECUTE format('CREATE SCHEMA IF NOT EXISTS %I', s);
|
||||||
|
|
||||||
|
EXECUTE format('CREATE TABLE IF NOT EXISTS %I.ad_accounts (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
platform_slug TEXT NOT NULL,
|
||||||
|
external_id TEXT NOT NULL,
|
||||||
|
name TEXT,
|
||||||
|
currency TEXT DEFAULT ''SAR'',
|
||||||
|
status TEXT DEFAULT ''active'',
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
UNIQUE (platform_slug, external_id)
|
||||||
|
)', s);
|
||||||
|
|
||||||
|
EXECUTE format('CREATE TABLE IF NOT EXISTS %I.ad_credentials (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
ad_account_id UUID REFERENCES %I.ad_accounts(id) ON DELETE CASCADE,
|
||||||
|
platform_slug TEXT NOT NULL,
|
||||||
|
access_token TEXT,
|
||||||
|
refresh_token TEXT,
|
||||||
|
token_expiry TIMESTAMPTZ,
|
||||||
|
developer_token TEXT,
|
||||||
|
login_customer_id TEXT,
|
||||||
|
credential_type TEXT DEFAULT ''oauth'',
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||||
|
)', s, s);
|
||||||
|
|
||||||
|
EXECUTE format('CREATE TABLE IF NOT EXISTS %I.recommendations (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
ad_account_id UUID REFERENCES %I.ad_accounts(id),
|
||||||
|
type TEXT NOT NULL,
|
||||||
|
priority TEXT DEFAULT ''medium'',
|
||||||
|
title TEXT NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
payload JSONB,
|
||||||
|
estimated_impact JSONB,
|
||||||
|
status TEXT DEFAULT ''pending'',
|
||||||
|
trust_level INT DEFAULT 1,
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
expires_at TIMESTAMPTZ,
|
||||||
|
actioned_at TIMESTAMPTZ,
|
||||||
|
actioned_by UUID
|
||||||
|
)', s, s);
|
||||||
|
|
||||||
|
EXECUTE format('CREATE TABLE IF NOT EXISTS %I.approvals (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
recommendation_id UUID REFERENCES %I.recommendations(id),
|
||||||
|
decision TEXT NOT NULL,
|
||||||
|
notes TEXT,
|
||||||
|
decided_by UUID,
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||||
|
)', s, s);
|
||||||
|
|
||||||
|
EXECUTE format('CREATE TABLE IF NOT EXISTS %I.audit_log (
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
user_id UUID,
|
||||||
|
action TEXT NOT NULL,
|
||||||
|
entity_type TEXT,
|
||||||
|
entity_id TEXT,
|
||||||
|
payload JSONB,
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||||
|
)', s);
|
||||||
|
|
||||||
|
EXECUTE format('CREATE TABLE IF NOT EXISTS %I.brand_context (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
key TEXT UNIQUE NOT NULL,
|
||||||
|
value JSONB NOT NULL,
|
||||||
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||||
|
)', s);
|
||||||
|
|
||||||
|
EXECUTE format('CREATE TABLE IF NOT EXISTS %I.kpi_targets (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
ad_account_id UUID REFERENCES %I.ad_accounts(id),
|
||||||
|
metric TEXT NOT NULL,
|
||||||
|
target_value NUMERIC,
|
||||||
|
period TEXT,
|
||||||
|
active BOOLEAN DEFAULT TRUE,
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||||
|
)', s, s);
|
||||||
|
|
||||||
|
EXECUTE format('CREATE TABLE IF NOT EXISTS %I.alert_rules (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
metric TEXT NOT NULL,
|
||||||
|
condition TEXT NOT NULL,
|
||||||
|
threshold NUMERIC,
|
||||||
|
window_mins INT DEFAULT 60,
|
||||||
|
severity TEXT DEFAULT ''warning'',
|
||||||
|
active BOOLEAN DEFAULT TRUE,
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||||
|
)', s);
|
||||||
|
|
||||||
|
EXECUTE format('CREATE TABLE IF NOT EXISTS %I.alert_history (
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
rule_id UUID REFERENCES %I.alert_rules(id),
|
||||||
|
triggered_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
value NUMERIC,
|
||||||
|
resolved_at TIMESTAMPTZ,
|
||||||
|
payload JSONB
|
||||||
|
)', s, s);
|
||||||
|
|
||||||
|
EXECUTE format('CREATE TABLE IF NOT EXISTS %I.search_term_decisions (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
search_term TEXT NOT NULL,
|
||||||
|
decision TEXT NOT NULL,
|
||||||
|
match_type TEXT,
|
||||||
|
ad_group_id TEXT,
|
||||||
|
campaign_id TEXT,
|
||||||
|
decided_by TEXT DEFAULT ''ai'',
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||||
|
)', s);
|
||||||
|
|
||||||
|
EXECUTE format('CREATE TABLE IF NOT EXISTS %I.ai_memory (
|
||||||
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
|
scope TEXT NOT NULL,
|
||||||
|
scope_id TEXT,
|
||||||
|
key TEXT NOT NULL,
|
||||||
|
value JSONB NOT NULL,
|
||||||
|
ttl TIMESTAMPTZ,
|
||||||
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||||
|
UNIQUE (scope, scope_id, key)
|
||||||
|
)', s);
|
||||||
|
|
||||||
|
RAISE NOTICE ''Schema % initialized'', s;
|
||||||
|
END LOOP;
|
||||||
|
END $$;
|
||||||
Reference in New Issue
Block a user