"""Mangel-Ticket-System (Roadmap Phase 2, BOS-Ressourcenplattform-Erweiterung). Eigener Workflow für Schäden/Defekte - getrennt von Fehlbestand (Mengen- Abweichung Soll/Ist), da fachlich verschieden (Nutzer-Beispiel: "Blaulicht vorne rechts defekt" ist kein Fehlbestand). entitaet_typ/entitaet_id als String-Polymorphie analog historie.entitaet_typ/entitaet_id (bestehendes Muster, keine FK-Integrität nötig - Mangel bleibt auch dann lesbar, wenn die konkrete Objektposition/Geraet-Instanz später gelöscht wird). objekt_id zusätzlich direkt/redundant gespeichert (wie fehlbestand.objekt_id), damit die Einsatzbereitschafts-Abfrage (Dashboard) nicht über die polymorphe Spalte joinen muss. Revision ID: 0013_mangel Revises: 0012_personal_qualifikationen Create Date: 2026-09-05 """ from typing import Sequence, Union from alembic import op revision: str = "0013_mangel" down_revision: Union[str, None] = "0012_personal_qualifikationen" branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: op.execute( "CREATE TYPE mangel_status AS ENUM " "('neu', 'in_bearbeitung', 'ersatzteil_bestellt', 'reparatur_geplant', 'erledigt')" ) op.execute("CREATE TYPE mangel_prioritaet AS ENUM ('niedrig', 'normal', 'hoch')") op.execute( """ CREATE TABLE mangel ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), objekt_id INTEGER NOT NULL REFERENCES objekt(id), entitaet_typ TEXT, entitaet_id TEXT, beschreibung TEXT NOT NULL, prioritaet mangel_prioritaet NOT NULL DEFAULT 'normal', status mangel_status NOT NULL DEFAULT 'neu', gemeldet_von INTEGER NOT NULL REFERENCES benutzer(id), gemeldet_am TIMESTAMPTZ NOT NULL, erledigt_von INTEGER REFERENCES benutzer(id), erledigt_am TIMESTAMPTZ, CONSTRAINT mangel_entitaet_beide_oder_keins CHECK ( (entitaet_typ IS NULL AND entitaet_id IS NULL) OR (entitaet_typ IS NOT NULL AND entitaet_id IS NOT NULL) ) ) """ ) op.execute("CREATE INDEX idx_mangel_objekt ON mangel (objekt_id)") op.execute("CREATE INDEX idx_mangel_status ON mangel (status)") def downgrade() -> None: op.execute("DROP TABLE mangel") op.execute("DROP TYPE IF EXISTS mangel_prioritaet") op.execute("DROP TYPE IF EXISTS mangel_status")