bug fix for atemschutz
This commit is contained in:
118
backend/src/database/migrations/015_create_veranstaltungen.sql
Normal file
118
backend/src/database/migrations/015_create_veranstaltungen.sql
Normal file
@@ -0,0 +1,118 @@
|
||||
-- =============================================================================
|
||||
-- Migration 015: Veranstaltungen (Events / General Calendar)
|
||||
-- General event calendar for Feuerwehr Dashboard, separate from the training
|
||||
-- calendar (uebungen). Supports categories, RSVPs, and iCal subscriptions.
|
||||
-- Depends on: 001_create_users_table.sql (uuid-ossp, pgcrypto extensions,
|
||||
-- users table, update_updated_at_column trigger function)
|
||||
-- =============================================================================
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 1. Event categories table
|
||||
-- -----------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS veranstaltung_kategorien (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
name VARCHAR(255) NOT NULL,
|
||||
beschreibung TEXT,
|
||||
farbe VARCHAR(7) NOT NULL DEFAULT '#1976d2', -- hex colour for UI chips
|
||||
icon VARCHAR(100), -- MUI icon name, e.g. 'Event', 'FireTruck'
|
||||
erstellt_von UUID REFERENCES users(id) ON DELETE SET NULL,
|
||||
erstellt_am TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
aktualisiert_am TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE TRIGGER update_veranstaltung_kategorien_aktualisiert_am
|
||||
BEFORE UPDATE ON veranstaltung_kategorien
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 2. Main events table
|
||||
-- -----------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS veranstaltungen (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
titel VARCHAR(500) NOT NULL,
|
||||
beschreibung TEXT,
|
||||
ort VARCHAR(500),
|
||||
ort_url VARCHAR(1000), -- optional maps/navigation link
|
||||
kategorie_id UUID REFERENCES veranstaltung_kategorien(id) ON DELETE SET NULL,
|
||||
datum_von TIMESTAMPTZ NOT NULL,
|
||||
datum_bis TIMESTAMPTZ NOT NULL,
|
||||
ganztaegig BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
-- zielgruppen: array of Authentik group names, e.g. '{dashboard_mitglied,dashboard_jugend}'
|
||||
zielgruppen TEXT[] NOT NULL DEFAULT '{}',
|
||||
alle_gruppen BOOLEAN NOT NULL DEFAULT FALSE, -- TRUE = visible to all members
|
||||
max_teilnehmer INTEGER CHECK (max_teilnehmer > 0),
|
||||
anmeldung_erforderlich BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
anmeldung_bis TIMESTAMPTZ,
|
||||
erstellt_von UUID NOT NULL REFERENCES users(id) ON DELETE RESTRICT,
|
||||
abgesagt BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
abgesagt_grund TEXT,
|
||||
abgesagt_am TIMESTAMPTZ,
|
||||
erstellt_am TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
aktualisiert_am TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
|
||||
CONSTRAINT veranstaltung_datum_reihenfolge CHECK (datum_bis >= datum_von)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_veranstaltungen_datum_von
|
||||
ON veranstaltungen(datum_von);
|
||||
CREATE INDEX IF NOT EXISTS idx_veranstaltungen_datum_bis
|
||||
ON veranstaltungen(datum_bis);
|
||||
CREATE INDEX IF NOT EXISTS idx_veranstaltungen_kategorie_id
|
||||
ON veranstaltungen(kategorie_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_veranstaltungen_abgesagt
|
||||
ON veranstaltungen(abgesagt) WHERE abgesagt = FALSE;
|
||||
CREATE INDEX IF NOT EXISTS idx_veranstaltungen_alle_gruppen
|
||||
ON veranstaltungen(alle_gruppen);
|
||||
-- Compound index for the most common calendar-range query
|
||||
CREATE INDEX IF NOT EXISTS idx_veranstaltungen_datum_von_bis
|
||||
ON veranstaltungen(datum_von, datum_bis);
|
||||
|
||||
CREATE TRIGGER update_veranstaltungen_aktualisiert_am
|
||||
BEFORE UPDATE ON veranstaltungen
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 3. RSVP / attendance table
|
||||
-- -----------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS veranstaltung_teilnahmen (
|
||||
veranstaltung_id UUID NOT NULL REFERENCES veranstaltungen(id) ON DELETE CASCADE,
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
-- status values: zugesagt, abgesagt, erschienen, unbekannt
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'unbekannt',
|
||||
notiz VARCHAR(500),
|
||||
aktualisiert_am TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
|
||||
PRIMARY KEY (veranstaltung_id, user_id)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_veranstaltung_teilnahmen_veranstaltung_id
|
||||
ON veranstaltung_teilnahmen(veranstaltung_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_veranstaltung_teilnahmen_user_id
|
||||
ON veranstaltung_teilnahmen(user_id);
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 4. Per-user iCal subscription tokens
|
||||
-- One token per user — covers the full events calendar feed for that user.
|
||||
-- -----------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS veranstaltung_ical_tokens (
|
||||
user_id UUID PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
|
||||
token VARCHAR(128) UNIQUE NOT NULL DEFAULT encode(gen_random_bytes(32), 'hex'),
|
||||
erstellt_am TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
zuletzt_verwendet_am TIMESTAMPTZ
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_veranstaltung_ical_tokens_token
|
||||
ON veranstaltung_ical_tokens(token);
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 5. Seed default event categories
|
||||
-- -----------------------------------------------------------------------------
|
||||
INSERT INTO veranstaltung_kategorien (name, farbe, icon) VALUES
|
||||
('Allgemein', '#1976d2', 'Event'),
|
||||
('Ausbildung', '#2e7d32', 'School'),
|
||||
('Gesellschaft', '#e65100', 'People'),
|
||||
('Feuerwehrjugend', '#f57c00', 'ChildCare'),
|
||||
('Kommando', '#6a1b9a', 'Shield')
|
||||
ON CONFLICT DO NOTHING;
|
||||
Reference in New Issue
Block a user