bug fix for atemschutz

This commit is contained in:
Matthias Hochmeister
2026-03-01 19:19:12 +01:00
parent 2630224edd
commit 6495ca94d1
17 changed files with 5116 additions and 0 deletions

View 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;

View File

@@ -0,0 +1,86 @@
-- =============================================================================
-- Migration 016: Fahrzeugbuchungen (Vehicle Booking System)
-- Allows members to book fire department vehicles for internal use, external
-- events, maintenance slots and reservations. Includes per-user iCal feeds.
-- Depends on: 001_create_users_table.sql (uuid-ossp, pgcrypto extensions,
-- users table, update_updated_at_column trigger function)
-- 005_create_fahrzeuge.sql (fahrzeuge table)
-- =============================================================================
-- -----------------------------------------------------------------------------
-- 1. ENUM: booking type
-- Uses DO-block for idempotent creation (PostgreSQL has no CREATE TYPE IF NOT EXISTS)
-- -----------------------------------------------------------------------------
DO $$
BEGIN
CREATE TYPE fahrzeug_buchung_art AS ENUM (
'intern',
'extern',
'wartung',
'reservierung',
'sonstiges'
);
EXCEPTION
WHEN duplicate_object THEN NULL;
END
$$;
-- -----------------------------------------------------------------------------
-- 2. Vehicle bookings table
-- -----------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS fahrzeug_buchungen (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
fahrzeug_id UUID NOT NULL REFERENCES fahrzeuge(id) ON DELETE CASCADE,
titel VARCHAR(500) NOT NULL,
beschreibung TEXT,
beginn TIMESTAMPTZ NOT NULL,
ende TIMESTAMPTZ NOT NULL,
buchungs_art fahrzeug_buchung_art NOT NULL DEFAULT 'intern',
gebucht_von UUID NOT NULL REFERENCES users(id) ON DELETE RESTRICT,
-- kontakt fields are relevant for external bookings
kontakt_person VARCHAR(255),
kontakt_telefon VARCHAR(50),
abgesagt BOOLEAN NOT NULL DEFAULT FALSE,
abgesagt_grund TEXT,
erstellt_am TIMESTAMPTZ NOT NULL DEFAULT NOW(),
aktualisiert_am TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT buchung_ende_nach_beginn CHECK (ende > beginn)
);
CREATE INDEX IF NOT EXISTS idx_fahrzeug_buchungen_fahrzeug_id
ON fahrzeug_buchungen(fahrzeug_id);
CREATE INDEX IF NOT EXISTS idx_fahrzeug_buchungen_beginn
ON fahrzeug_buchungen(beginn);
CREATE INDEX IF NOT EXISTS idx_fahrzeug_buchungen_ende
ON fahrzeug_buchungen(ende);
CREATE INDEX IF NOT EXISTS idx_fahrzeug_buchungen_gebucht_von
ON fahrzeug_buchungen(gebucht_von);
CREATE INDEX IF NOT EXISTS idx_fahrzeug_buchungen_abgesagt
ON fahrzeug_buchungen(abgesagt) WHERE abgesagt = FALSE;
-- Compound index for availability / overlap checks (fahrzeug + time range)
CREATE INDEX IF NOT EXISTS idx_fahrzeug_buchungen_fahrzeug_beginn_ende
ON fahrzeug_buchungen(fahrzeug_id, beginn, ende);
CREATE TRIGGER update_fahrzeug_buchungen_aktualisiert_am
BEFORE UPDATE ON fahrzeug_buchungen
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
-- -----------------------------------------------------------------------------
-- 3. Per-user iCal subscription tokens for the vehicle booking calendar
-- One token per user — the feed returns all bookings the user has access to.
-- -----------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS fahrzeug_ical_tokens (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID NOT NULL 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,
-- one token per user for the full vehicle booking feed
UNIQUE (user_id)
);
CREATE INDEX IF NOT EXISTS idx_fahrzeug_ical_tokens_token
ON fahrzeug_ical_tokens(token);