feat(inventory): INV-007 Ausgabe/Rückgabe von Material und Leihgeräten
CI / backend-tests (push) Successful in 2m1s
CI / frontend-build (push) Successful in 18s

Personenbezogene Ausgabe ergänzt die reine Standort-/Lagerplatz-Sicht
um "wer hat das Ding gerade": neues Modell ausgabe (Material +
optional geraet_instanz_id), POST /ausgaben, GET /ausgaben (Filter
status/empfaenger), POST /ausgaben/{id}/rueckgabe mit Schutz vor
Doppel-Rueckgabe. Frontend als Admin-Tab "Ausgabe/Rückgabe" +
Command-Palette-Eintrag.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
This commit is contained in:
2026-09-06 13:19:31 +02:00
co-authored by Claude Sonnet 5
parent 16a42c6b85
commit b6ada2b5a1
13 changed files with 495 additions and 7 deletions
+3
View File
@@ -1,3 +1,4 @@
from app.models.ausgabe import Ausgabe, AusgabeStatus
from app.models.auth import Benutzer, BenutzerRolle, RolleTyp, Systemknoten, KnotenTyp
from app.models.dokument import Dokument
from app.models.eskalation import EskalationKonfiguration
@@ -26,6 +27,8 @@ from app.models.vorlage import Beladungsvorlage, VorlageStatus, Vorlagenposition
from app.models.zustaendigkeit import Kontrollverantwortung, Zustaendigkeit
__all__ = [
"Ausgabe",
"AusgabeStatus",
"Benutzer",
"BenutzerRolle",
"RolleTyp",
+41
View File
@@ -0,0 +1,41 @@
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 AusgabeStatus(str, enum.Enum):
offen = "offen"
zurueck = "zurueck"
ausgabe_status_pg = PgEnum(AusgabeStatus, name="ausgabe_status", create_type=False)
class Ausgabe(Base):
"""INV-007: personenbezogene Ausgabe/Rückgabe von Material/Leihgeräten -
ergänzt die reine Standort-/Lagerplatz-Sicht (Lagerbewegung/Materialbewegung)
um "wer hat das Ding gerade", solange die Ausgabe offen ist."""
__tablename__ = "ausgabe"
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
material_id: Mapped[int] = mapped_column(ForeignKey("material.id"), nullable=False)
geraet_instanz_id: Mapped[uuid.UUID | None] = mapped_column(
UUID(as_uuid=True), ForeignKey("geraet_instanz.id")
)
menge: Mapped[Decimal] = mapped_column(Numeric, nullable=False)
empfaenger_id: Mapped[int] = mapped_column(ForeignKey("benutzer.id"), nullable=False)
ausgegeben_von: Mapped[int] = mapped_column(ForeignKey("benutzer.id"), nullable=False)
ausgegeben_am: Mapped[datetime] = mapped_column(TIMESTAMP(timezone=True), nullable=False)
rueckgabe_am: Mapped[datetime | None] = mapped_column(TIMESTAMP(timezone=True))
status: Mapped[AusgabeStatus] = mapped_column(
ausgabe_status_pg, nullable=False, default=AusgabeStatus.offen
)
zweck: Mapped[str | None] = mapped_column(String)