125 lines
4.3 KiB
SQL
125 lines
4.3 KiB
SQL
-- Wedding website bootstrap schema
|
|
-- Requires: PostgreSQL 13+
|
|
|
|
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
|
|
|
CREATE TABLE IF NOT EXISTS invitations (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
token text NOT NULL,
|
|
display_name text NOT NULL,
|
|
language text NOT NULL,
|
|
contact_email text NULL,
|
|
contact_phone text NULL,
|
|
max_party_size integer NOT NULL DEFAULT 1,
|
|
allow_member_edits boolean NOT NULL DEFAULT false,
|
|
notes text NULL,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
CONSTRAINT invitations_max_party_size_positive CHECK (max_party_size > 0)
|
|
);
|
|
|
|
CREATE UNIQUE INDEX IF NOT EXISTS invitations_token_unique ON invitations (token);
|
|
|
|
CREATE TABLE IF NOT EXISTS invitation_members (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
invitation_id uuid NOT NULL REFERENCES invitations(id) ON DELETE CASCADE,
|
|
name text NOT NULL,
|
|
is_primary_contact boolean NOT NULL DEFAULT false,
|
|
attending boolean NULL,
|
|
meal_preference text NULL,
|
|
dietary_restrictions text NULL,
|
|
notes text NULL,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS invitation_members_invitation_id_idx
|
|
ON invitation_members (invitation_id);
|
|
|
|
CREATE TABLE IF NOT EXISTS invitation_responses (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
invitation_id uuid NOT NULL REFERENCES invitations(id) ON DELETE CASCADE,
|
|
submitted_at timestamptz NULL,
|
|
arrival_date date NULL,
|
|
departure_date date NULL,
|
|
stay_location text NULL,
|
|
coming_from text NULL,
|
|
needs_transport_help boolean NULL,
|
|
message_to_couple text NULL,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE UNIQUE INDEX IF NOT EXISTS invitation_responses_invitation_id_unique
|
|
ON invitation_responses (invitation_id);
|
|
|
|
CREATE TABLE IF NOT EXISTS photo_uploads (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
invitation_id uuid NOT NULL REFERENCES invitations(id) ON DELETE CASCADE,
|
|
bucket text NOT NULL,
|
|
object_key text NOT NULL,
|
|
original_filename text NULL,
|
|
content_type text NULL,
|
|
size_bytes integer NULL,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
CONSTRAINT photo_uploads_size_bytes_non_negative
|
|
CHECK (size_bytes IS NULL OR size_bytes >= 0)
|
|
);
|
|
|
|
CREATE UNIQUE INDEX IF NOT EXISTS photo_uploads_invitation_id_unique
|
|
ON photo_uploads (invitation_id);
|
|
|
|
CREATE TABLE IF NOT EXISTS song_requests (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
invitation_id uuid NOT NULL REFERENCES invitations(id) ON DELETE CASCADE,
|
|
title text NOT NULL,
|
|
artist text NULL,
|
|
note text NULL,
|
|
created_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS song_requests_invitation_id_idx
|
|
ON song_requests (invitation_id);
|
|
|
|
CREATE TABLE IF NOT EXISTS toast_requests (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
invitation_id uuid NOT NULL REFERENCES invitations(id) ON DELETE CASCADE,
|
|
member_id uuid NULL REFERENCES invitation_members(id) ON DELETE SET NULL,
|
|
speaker_name text NOT NULL,
|
|
estimated_minutes integer NULL,
|
|
note text NULL,
|
|
status text NOT NULL DEFAULT 'pending',
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
CONSTRAINT toast_requests_status_valid
|
|
CHECK (status IN ('pending', 'accepted', 'declined', 'scheduled')),
|
|
CONSTRAINT toast_requests_estimated_minutes_positive
|
|
CHECK (estimated_minutes IS NULL OR estimated_minutes > 0)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS toast_requests_invitation_id_idx
|
|
ON toast_requests (invitation_id);
|
|
|
|
CREATE TABLE IF NOT EXISTS guest_messages (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
invitation_id uuid NOT NULL REFERENCES invitations(id) ON DELETE CASCADE,
|
|
type text NOT NULL,
|
|
message text NOT NULL,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
CONSTRAINT guest_messages_type_valid CHECK (type IN ('advice', 'memory', 'wish'))
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS guest_messages_invitation_id_idx
|
|
ON guest_messages (invitation_id);
|
|
|
|
CREATE TABLE IF NOT EXISTS admin_audit_events (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
admin_email text NOT NULL,
|
|
action text NOT NULL,
|
|
target_type text NULL,
|
|
target_id uuid NULL,
|
|
metadata jsonb NULL,
|
|
created_at timestamptz NOT NULL DEFAULT now()
|
|
);
|