import enum import uuid from datetime import datetime from decimal import Decimal from sqlalchemy import Boolean, 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 KontrollStatus(str, enum.Enum): nicht_gestartet = "nicht_gestartet" in_bearbeitung = "in_bearbeitung" abgeschlossen = "abgeschlossen" abgebrochen = "abgebrochen" kontroll_status_pg = PgEnum(KontrollStatus, name="kontroll_status", create_type=False) class Kontrolle(Base): """Prompt 02: Kontrolle ändert NIEMALS Ist-Menge, ist reine Erfassung (Punkt 9, Vier-Kernbegriffe-Tabelle). Status='in_bearbeitung' IST die Objekt-Sperre (Punkt 8) – kein separates Sperr-Modell nötig.""" __tablename__ = "kontrolle" 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) benutzer_id: Mapped[int] = mapped_column(ForeignKey("benutzer.id"), nullable=False) status: Mapped[KontrollStatus] = mapped_column( kontroll_status_pg, nullable=False, default=KontrollStatus.in_bearbeitung ) gestartet_am: Mapped[datetime] = mapped_column(TIMESTAMP(timezone=True), nullable=False) beendet_am: Mapped[datetime | None] = mapped_column(TIMESTAMP(timezone=True)) abbruch_grund: Mapped[str | None] = mapped_column(String) signatur: Mapped[bytes | None] = mapped_column() class Kontrollposition(Base): __tablename__ = "kontrollposition" id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) kontrolle_id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), ForeignKey("kontrolle.id"), nullable=False ) material_id: Mapped[int] = mapped_column(ForeignKey("material.id"), nullable=False) sollmenge_snapshot: Mapped[Decimal] = mapped_column(Numeric, nullable=False) istmenge_erfasst: Mapped[Decimal] = mapped_column(Numeric, nullable=False) abweichung: Mapped[bool] = mapped_column(Boolean, nullable=False)