feat(lager): Lagerbewegung-Protokoll (Roadmap Phase 4, Modul Lager)
CI / backend-tests (push) Failing after 1m47s
CI / frontend-build (push) Successful in 17s

Objekt bleibt der Materialträger (Rucksack/Gerät/Fahrzeug, Karte 11) -
"Material verschieben" heißt: das Objekt bekommt einen neuen Standort, jede
Bewegung wird append-only protokolliert (Wer/Wann/Von/Nach/Grund, Nutzer-
Vorgabe Modul 5).

POST /objekte/{id}/lagerbewegungen setzt Standort + protokolliert in einem
Zug, GET /lagerbewegungen (Filter objekt_id/standort_id) für die Historie.
Rollen wie beim Mangel-Modul: Materialverantwortliche+Leitung+Admin dürfen
verschieben, alle Eingeloggten dürfen lesen.

Frontend: "Verschieben"-Aktion in ObjektSection, neuer Admin-Tab
"Lagerbewegungen" (reine Anzeige, analog HistorieSection).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KC8HYvv6UkCVYheYiTw9DD
This commit is contained in:
2026-09-05 13:46:33 +02:00
co-authored by Claude Sonnet 5
parent 8fbb356c34
commit 417df2beb6
12 changed files with 467 additions and 1 deletions
+26
View File
@@ -0,0 +1,26 @@
from datetime import datetime, timezone
from sqlalchemy.ext.asyncio import AsyncSession
from app.models.lagerbewegung import Lagerbewegung
from app.models.objekt import Objekt
async def verschiebe_objekt(
db: AsyncSession, *, objekt: Objekt, nach_standort_id: int, benutzer_id: int, grund: str | None
) -> Lagerbewegung:
"""Roadmap Phase 4 (Modul Lager): setzt objekt.standort_id und protokolliert
die Bewegung in einem Zug - von_standort_id ist der ALTE Stand vor dem
Setzen (muss vor der Zuweisung gelesen werden)."""
bewegung = Lagerbewegung(
objekt_id=objekt.id,
von_standort_id=objekt.standort_id,
nach_standort_id=nach_standort_id,
benutzer_id=benutzer_id,
zeitpunkt=datetime.now(timezone.utc),
grund=grund,
)
objekt.standort_id = nach_standort_id
db.add(bewegung)
await db.flush()
return bewegung