feat: Migrationen für campaigns-Tabellen (PostgreSQL) und email_events (ClickHouse)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-17 08:57:37 +00:00
parent 3c3088e66b
commit 5a144e0ce4
2 changed files with 53 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
CREATE TABLE IF NOT EXISTS newsletter.email_events (
event_type LowCardinality(String),
tenant_id String,
campaign_id UUID,
recipient_hash String,
timestamp DateTime64(3, 'UTC'),
metadata Map(String, String)
)
ENGINE = MergeTree()
PARTITION BY toYYYYMM(timestamp)
ORDER BY (tenant_id, campaign_id, event_type, timestamp);

View File

@@ -0,0 +1,42 @@
-- Wird pro Tenant-Schema ausgeführt (SET search_path = tenant_<id>, 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 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 OR REPLACE FUNCTION update_updated_at()
RETURNS TRIGGER AS $$
BEGIN NEW.updated_at = now(); RETURN NEW; END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER campaigns_updated_at
BEFORE UPDATE ON campaigns
FOR EACH ROW EXECUTE FUNCTION update_updated_at();