import enum import uuid from datetime import datetime from sqlalchemy import CheckConstraint, ForeignKey, String from sqlalchemy.dialects.postgresql import ENUM as PgEnum, TIMESTAMP, UUID from sqlalchemy.orm import Mapped, mapped_column from app.db.base import Base class MangelStatus(str, enum.Enum): neu = "neu" in_bearbeitung = "in_bearbeitung" ersatzteil_bestellt = "ersatzteil_bestellt" reparatur_geplant = "reparatur_geplant" erledigt = "erledigt" class MangelPrioritaet(str, enum.Enum): niedrig = "niedrig" normal = "normal" hoch = "hoch" mangel_status_pg = PgEnum(MangelStatus, name="mangel_status", create_type=False) mangel_prioritaet_pg = PgEnum(MangelPrioritaet, name="mangel_prioritaet", create_type=False) class Mangel(Base): """Roadmap Phase 2: Schäden/Defekte als eigener Workflow, getrennt von Fehlbestand (Mengen-Abweichung). entitaet_typ/entitaet_id optional und als String-Polymorphie geführt (Muster wie historie.entitaet_typ/-id) - verweist z.B. auf 'objektposition'/uuid oder 'geraet_instanz'/uuid, wenn der Mangel eine konkrete Teilressource betrifft statt das ganze Objekt. objekt_id ist immer gesetzt (auch bei feingranularem Verweis), damit die Einsatzbereitschaft (Dashboard) direkt filtern kann, ohne die polymorphe Spalte auflösen zu müssen.""" __tablename__ = "mangel" id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) objekt_id: Mapped[int] = mapped_column(ForeignKey("objekt.id"), nullable=False) entitaet_typ: Mapped[str | None] = mapped_column(String) entitaet_id: Mapped[str | None] = mapped_column(String) beschreibung: Mapped[str] = mapped_column(String, nullable=False) prioritaet: Mapped[MangelPrioritaet] = mapped_column( mangel_prioritaet_pg, nullable=False, default=MangelPrioritaet.normal ) status: Mapped[MangelStatus] = mapped_column(mangel_status_pg, nullable=False, default=MangelStatus.neu) gemeldet_von: Mapped[int] = mapped_column(ForeignKey("benutzer.id"), nullable=False) gemeldet_am: Mapped[datetime] = mapped_column(TIMESTAMP(timezone=True), nullable=False) erledigt_von: Mapped[int | None] = mapped_column(ForeignKey("benutzer.id")) erledigt_am: Mapped[datetime | None] = mapped_column(TIMESTAMP(timezone=True)) __table_args__ = ( CheckConstraint( "(entitaet_typ IS NULL AND entitaet_id IS NULL) OR (entitaet_typ IS NOT NULL AND entitaet_id IS NOT NULL)", name="mangel_entitaet_beide_oder_keins", ), )