"""Personal/Qualifikationen-Modul (Roadmap-Erweiterung, Phase 1 nach BOS- Ressourcenplattform-Anforderung): Einheit-Hierarchie, Qualifikationstypen (Führerschein/Lehrgang/Berechtigung), Benutzer-Qualifikationszuordnung mit Gültigkeit, sowie welche Qualifikation ein Objekttyp (z.B. Fahrzeug) zum Bedienen voraussetzt - beantwortet "wer darf dieses Fahrzeug fahren?". Revision ID: 0012_personal_qualifikationen Revises: 0011_objekttyp_zugfahrzeug Create Date: 2026-09-05 """ from typing import Sequence, Union from alembic import op revision: str = "0012_personal_qualifikationen" down_revision: Union[str, None] = "0011_objekttyp_zugfahrzeug" branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: op.execute("CREATE TYPE qualifikationskategorie AS ENUM ('fuehrerschein', 'lehrgang', 'berechtigung')") op.execute( """ CREATE TABLE einheit ( id SERIAL PRIMARY KEY, name TEXT NOT NULL, uebergeordnete_einheit_id INTEGER REFERENCES einheit(id), standort_id INTEGER REFERENCES standort(id), CONSTRAINT einheit_kein_selbstbezug CHECK (uebergeordnete_einheit_id <> id) ) """ ) op.execute("CREATE INDEX idx_einheit_uebergeordnet ON einheit (uebergeordnete_einheit_id)") op.execute("ALTER TABLE benutzer ADD COLUMN einheit_id INTEGER REFERENCES einheit(id)") # Fahrzeuge/Objekte künftig einer Einheit zuordenbar (analog fahrzeug_id-Muster # aus Migration 0010: additiv, NULL = keiner Einheit zugeordnet). op.execute("ALTER TABLE objekt ADD COLUMN einheit_id INTEGER REFERENCES einheit(id)") op.execute( """ CREATE TABLE qualifikationstyp ( id SERIAL PRIMARY KEY, name TEXT NOT NULL, kategorie qualifikationskategorie NOT NULL, gueltigkeit_monate INTEGER ) """ ) op.execute( """ CREATE TABLE benutzer_qualifikation ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), benutzer_id INTEGER NOT NULL REFERENCES benutzer(id), qualifikationstyp_id INTEGER NOT NULL REFERENCES qualifikationstyp(id), erworben_am DATE NOT NULL, gueltig_bis DATE, nachweis_nummer TEXT, UNIQUE (benutzer_id, qualifikationstyp_id, erworben_am) ) """ ) op.execute("CREATE INDEX idx_benutzer_qualifikation_benutzer ON benutzer_qualifikation (benutzer_id)") op.execute( """ CREATE TABLE objekttyp_qualifikationsanforderung ( objekttyp_id INTEGER NOT NULL REFERENCES objekttyp(id), qualifikationstyp_id INTEGER NOT NULL REFERENCES qualifikationstyp(id), PRIMARY KEY (objekttyp_id, qualifikationstyp_id) ) """ ) def downgrade() -> None: op.execute("DROP TABLE objekttyp_qualifikationsanforderung") op.execute("DROP TABLE benutzer_qualifikation") op.execute("DROP TABLE qualifikationstyp") op.execute("ALTER TABLE objekt DROP COLUMN einheit_id") op.execute("ALTER TABLE benutzer DROP COLUMN einheit_id") op.execute("DROP TABLE einheit") op.execute("DROP TYPE IF EXISTS qualifikationskategorie")