-- Wird pro Tenant-Schema ausgeführt (SET search_path = tenant_, public vorher) CREATE TABLE IF NOT EXISTS campaigns ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), name TEXT NOT NULL, subject TEXT NOT NULL, html_body TEXT NOT NULL, plain_body TEXT NOT NULL, status TEXT NOT NULL DEFAULT 'draft' CHECK (status IN ('draft','scheduled','sending','sent','paused','cancelled')), scheduled_at TIMESTAMPTZ, cron_expression TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE TABLE IF NOT EXISTS campaign_recipients ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), campaign_id UUID NOT NULL REFERENCES campaigns(id) ON DELETE CASCADE, list_id UUID, segment_id UUID, CONSTRAINT recipient_has_one CHECK ( (list_id IS NOT NULL AND segment_id IS NULL) OR (segment_id IS NOT NULL AND list_id IS NULL) ) ); CREATE INDEX IF NOT EXISTS idx_campaign_recipients_campaign_id ON campaign_recipients(campaign_id); CREATE TABLE IF NOT EXISTS campaign_triggers ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), campaign_id UUID NOT NULL REFERENCES campaigns(id) ON DELETE CASCADE, trigger_type TEXT NOT NULL CHECK (trigger_type IN ('cron', 'event')), trigger_value TEXT NOT NULL ); CREATE INDEX IF NOT EXISTS idx_campaign_triggers_campaign_id ON campaign_triggers(campaign_id); CREATE OR REPLACE FUNCTION update_updated_at() RETURNS TRIGGER AS $$ BEGIN NEW.updated_at = now(); RETURN NEW; END; $$ LANGUAGE plpgsql; CREATE OR REPLACE TRIGGER campaigns_updated_at BEFORE UPDATE ON campaigns FOR EACH ROW EXECUTE FUNCTION update_updated_at();