Sprint 5: Mindermengen-Genehmigung + automatischer Ablauf, Historie für Kernkette
CI / backend-tests (push) Successful in 47s

- MindermengenGenehmigung-Modell/Service (Prompt 04): reine fachliche Bewertung,
  ändert NIEMALS Ist-Menge/Fehlmenge/Fehlbestand-Status (Leitplanke, U2)
- Automatischer Ablauf bei Start der nächsten Kontrolle desselben Objekts (Karte 08,
  U6) - kein Zeit-Trigger, der Kontrollstart selbst ist der Ablauf-Zeitpunkt
- Genehmigung endet gemeinsam mit dem Fehlbestand, wenn dieser durch Nachfüllung
  erledigt wird (U7), unabhängig davon ob vorher eine neue Kontrolle stattfand
- Historie-Service (app/services/historie.py) + Verdrahtung in die komplette
  Kernkette: kontrolle_gestartet/-abgeschlossen/-abgebrochen/-uebernommen,
  istmenge_erfasst, fehlbestand_entstanden/-erledigt, nachfuellung_erfasst,
  mindermenge_genehmigt/-abgelaufen/-beendet_durch_erledigung (U14)
  Hinweis: Stammdaten-/Vorlagen-/Benutzerverwaltung noch nicht retrofittet -
  Sprint 5 deckt bewusst die im Testkonzept referenzierte Kernkette ab, keine
  flächendeckende Audit-Abdeckung aller CRUD-Endpunkte.
- Tests: U2, U6, U7, vollständige Historie-Kette nach Prompt-13.3-Beispiel (U14)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L85hmKbvX7Cqkq47KnQhFt
This commit is contained in:
2026-09-03 23:53:14 +02:00
co-authored by Claude Sonnet 5
parent 18fba28eae
commit 1e9012cba3
13 changed files with 716 additions and 21 deletions
+3
View File
@@ -2,6 +2,7 @@ from app.models.auth import Benutzer, BenutzerRolle, RolleTyp, Systemknoten, Kno
from app.models.fehlbestand import Fehlbestand, FehlbestandStatus
from app.models.historie import Historie
from app.models.kontrolle import Kontrolle, KontrollStatus, Kontrollposition
from app.models.mindermenge import MindermengeStatus, MindermengenGenehmigung
from app.models.nachfuellung import Nachfuellung
from app.models.objekt import Objekt, ObjektStatus
from app.models.objektposition import Objektposition, ObjektpositionStatus
@@ -21,6 +22,8 @@ __all__ = [
"Kontrolle",
"KontrollStatus",
"Kontrollposition",
"MindermengeStatus",
"MindermengenGenehmigung",
"Nachfuellung",
"Objekt",
"ObjektStatus",
+45
View File
@@ -0,0 +1,45 @@
import enum
import uuid
from datetime import datetime
from sqlalchemy import 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 MindermengeStatus(str, enum.Enum):
aktiv = "aktiv"
abgelaufen = "abgelaufen"
beendet_durch_erledigung = "beendet_durch_erledigung"
mindermenge_status_pg = PgEnum(MindermengeStatus, name="mindermenge_status", create_type=False)
class MindermengenGenehmigung(Base):
"""Prompt 04: reine fachliche Bewertung, ändert NIEMALS Ist-Menge/Fehlmenge/
Fehlbestand-Status (Leitplanke, U2). Gilt automatisch nur bis zur nächsten
Kontrolle desselben Objekts (Karte 08, U6) oder bis der Fehlbestand durch
Nachfüllung erledigt wird (U7) - beides ohne separaten Zeit-Trigger."""
__tablename__ = "mindermengen_genehmigung"
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
fehlbestand_id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True), ForeignKey("fehlbestand.id"), nullable=False
)
genehmigt_von: Mapped[int] = mapped_column(ForeignKey("benutzer.id"), nullable=False)
begruendung: Mapped[str] = mapped_column(String, nullable=False)
genehmigt_am: Mapped[datetime] = mapped_column(TIMESTAMP(timezone=True), nullable=False)
ausloesende_kontrolle_id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True), ForeignKey("kontrolle.id"), nullable=False
)
status: Mapped[MindermengeStatus] = mapped_column(
mindermenge_status_pg, nullable=False, default=MindermengeStatus.aktiv
)
beendet_am: Mapped[datetime | None] = mapped_column(TIMESTAMP(timezone=True))
beendende_kontrolle_id: Mapped[uuid.UUID | None] = mapped_column(
UUID(as_uuid=True), ForeignKey("kontrolle.id")
)