import enum import uuid from datetime import datetime from decimal import Decimal from sqlalchemy import ForeignKey, Numeric, 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 FehlbestandStatus(str, enum.Enum): offen = "offen" in_bearbeitung = "in_bearbeitung" nachgefuellt_teilweise = "nachgefuellt_teilweise" erledigt = "erledigt" fehlbestand_status_pg = PgEnum(FehlbestandStatus, name="fehlbestand_status", create_type=False) class Fehlbestand(Base): """Prompt 03: automatisch entstandener Vorgang bei Ist < Soll, ändert selbst NIEMALS die Ist-Menge (nur Nachfüllung tut das, Sprint 4). Sollmenge/Istmenge/ Fehlmenge hier sind Snapshot-Werte zum Feststellungszeitpunkt, nicht live referenziert (Prompt 03 Punkt 2: "Sollmenge zum Zeitpunkt der Feststellung").""" __tablename__ = "fehlbestand" id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) erzeugt_von_server_id: Mapped[int] = mapped_column(ForeignKey("systemknoten.id"), nullable=False) objekt_id: Mapped[int] = mapped_column(ForeignKey("objekt.id"), nullable=False) material_id: Mapped[int] = mapped_column(ForeignKey("material.id"), nullable=False) standort_id: Mapped[int] = mapped_column(ForeignKey("standort.id"), nullable=False) sollmenge: Mapped[Decimal] = mapped_column(Numeric, nullable=False) istmenge: Mapped[Decimal] = mapped_column(Numeric, nullable=False) fehlmenge: Mapped[Decimal] = mapped_column(Numeric, nullable=False) entstanden_am: Mapped[datetime] = mapped_column(TIMESTAMP(timezone=True), nullable=False) festgestellt_von: Mapped[int] = mapped_column(ForeignKey("benutzer.id"), nullable=False) kontrolle_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("kontrolle.id")) ursache: Mapped[str | None] = mapped_column(String) verantwortlicher_id: Mapped[int | None] = mapped_column(ForeignKey("benutzer.id")) status: Mapped[FehlbestandStatus] = mapped_column( fehlbestand_status_pg, nullable=False, default=FehlbestandStatus.offen ) erledigt_am: Mapped[datetime | None] = mapped_column(TIMESTAMP(timezone=True)) # Karte 12: Eskalationsstufen-Tracking, damit dieselbe Stufe nicht bei jedem # Prüflauf erneut verschickt wird (NULL = Stufe noch nicht ausgelöst). erinnerung_gesendet_am: Mapped[datetime | None] = mapped_column(TIMESTAMP(timezone=True)) eskalation_gesendet_am: Mapped[datetime | None] = mapped_column(TIMESTAMP(timezone=True))