127 lines
6.2 KiB
YAML
127 lines
6.2 KiB
YAML
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: {{ include "invy.fullname" . }}-db-schema
|
|
labels:
|
|
{{- include "invy.labels" . | nindent 4 }}
|
|
app.kubernetes.io/component: database
|
|
data:
|
|
init.sql: |
|
|
-- Invy — Full Database Init Schema
|
|
-- Runs only on a FRESH (empty) data directory.
|
|
-- For existing production DBs run migrate_production.sql manually.
|
|
|
|
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
|
|
|
-- ── Users ──────────────────────────────────────────────────────────────
|
|
CREATE TABLE IF NOT EXISTS users (
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
email TEXT NOT NULL UNIQUE,
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
|
|
|
|
-- ── Events ─────────────────────────────────────────────────────────────
|
|
CREATE TABLE IF NOT EXISTS events (
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
name TEXT NOT NULL,
|
|
date TIMESTAMP WITH TIME ZONE,
|
|
location TEXT,
|
|
partner1_name TEXT,
|
|
partner2_name TEXT,
|
|
venue TEXT,
|
|
event_time TEXT,
|
|
guest_link TEXT,
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_events_created_at ON events(created_at);
|
|
CREATE INDEX IF NOT EXISTS idx_events_guest_link ON events(guest_link);
|
|
|
|
-- ── Event members (authorization) ──────────────────────────────────────
|
|
CREATE TABLE IF NOT EXISTS event_members (
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
event_id UUID NOT NULL REFERENCES events(id) ON DELETE CASCADE,
|
|
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
role TEXT NOT NULL DEFAULT 'admin'
|
|
CHECK (role IN ('admin', 'editor', 'viewer')),
|
|
display_name TEXT,
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
UNIQUE(event_id, user_id)
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_event_members_event_id ON event_members(event_id);
|
|
CREATE INDEX IF NOT EXISTS idx_event_members_user_id ON event_members(user_id);
|
|
CREATE INDEX IF NOT EXISTS idx_event_members_event_user ON event_members(event_id, user_id);
|
|
|
|
-- ── Guests v2 ──────────────────────────────────────────────────────────
|
|
CREATE TABLE IF NOT EXISTS guests_v2 (
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
event_id UUID NOT NULL REFERENCES events(id) ON DELETE CASCADE,
|
|
added_by_user_id UUID NOT NULL REFERENCES users(id),
|
|
|
|
first_name TEXT NOT NULL,
|
|
last_name TEXT NOT NULL DEFAULT '',
|
|
email TEXT,
|
|
phone TEXT,
|
|
phone_number TEXT,
|
|
|
|
rsvp_status TEXT NOT NULL DEFAULT 'invited'
|
|
CHECK (rsvp_status IN ('invited', 'confirmed', 'declined')),
|
|
meal_preference TEXT,
|
|
|
|
has_plus_one BOOLEAN DEFAULT FALSE,
|
|
plus_one_name TEXT,
|
|
|
|
table_number TEXT,
|
|
side TEXT,
|
|
|
|
owner_email TEXT,
|
|
source TEXT NOT NULL DEFAULT 'manual'
|
|
CHECK (source IN ('google', 'manual', 'self-service')),
|
|
|
|
notes TEXT,
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_guests_v2_event_id ON guests_v2(event_id);
|
|
CREATE INDEX IF NOT EXISTS idx_guests_v2_added_by ON guests_v2(added_by_user_id);
|
|
CREATE INDEX IF NOT EXISTS idx_guests_v2_phone_number ON guests_v2(phone_number);
|
|
CREATE INDEX IF NOT EXISTS idx_guests_v2_event_phone ON guests_v2(event_id, phone_number);
|
|
CREATE INDEX IF NOT EXISTS idx_guests_v2_event_status ON guests_v2(event_id, rsvp_status);
|
|
CREATE INDEX IF NOT EXISTS idx_guests_v2_owner_email ON guests_v2(event_id, owner_email);
|
|
CREATE INDEX IF NOT EXISTS idx_guests_v2_source ON guests_v2(event_id, source);
|
|
|
|
-- ── RSVP tokens ────────────────────────────────────────────────────────
|
|
CREATE TABLE IF NOT EXISTS rsvp_tokens (
|
|
token TEXT PRIMARY KEY,
|
|
event_id UUID NOT NULL REFERENCES events(id) ON DELETE CASCADE,
|
|
guest_id UUID REFERENCES guests_v2(id) ON DELETE SET NULL,
|
|
phone TEXT,
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
expires_at TIMESTAMP WITH TIME ZONE,
|
|
used_at TIMESTAMP WITH TIME ZONE
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_rsvp_tokens_event_id ON rsvp_tokens(event_id);
|
|
CREATE INDEX IF NOT EXISTS idx_rsvp_tokens_guest_id ON rsvp_tokens(guest_id);
|
|
|
|
-- ── updated_at trigger ─────────────────────────────────────────────────
|
|
CREATE OR REPLACE FUNCTION _update_updated_at()
|
|
RETURNS TRIGGER LANGUAGE plpgsql AS $$
|
|
BEGIN
|
|
NEW.updated_at = CURRENT_TIMESTAMP;
|
|
RETURN NEW;
|
|
END;
|
|
$$;
|
|
|
|
DO $$ BEGIN
|
|
CREATE TRIGGER trg_guests_v2_updated_at
|
|
BEFORE UPDATE ON guests_v2
|
|
FOR EACH ROW EXECUTE FUNCTION _update_updated_at();
|
|
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|
|
|
|
DO $$ BEGIN
|
|
CREATE TRIGGER trg_events_updated_at
|
|
BEFORE UPDATE ON events
|
|
FOR EACH ROW EXECUTE FUNCTION _update_updated_at();
|
|
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|