Eigener Workflow für Schäden/Defekte, getrennt von Fehlbestand (Mengen- Abweichung Soll/Ist). Status: neu → in_bearbeitung → ersatzteil_bestellt/ reparatur_geplant → erledigt. entitaet_typ/entitaet_id optional (Objektposition oder Geräteinstanz), analog zum bestehenden historie.entitaet_typ-Muster, objekt_id immer gesetzt für Dashboard-Abfragen. Ein offener Mangel mit prioritaet=hoch macht das Objekt "nicht einsatzbereit" (neuer Grund mangel_kritisch_offen in dashboard.einsatzbereitschaft) - niedrige/normale Mängel blockieren nicht. Melden/Lesen: alle Mitarbeiter+. Status ändern: Materialverantwortliche+. Neue Seite /maengel für alle eingeloggten Nutzer (Nav-Link "Mängel"). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KC8HYvv6UkCVYheYiTw9DD
63 lines
2.4 KiB
Python
63 lines
2.4 KiB
Python
"""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")
|