Ablauf/Charge/SN gehören zur Kontroll-Erfassung, nicht nur zur Admin-Pflege
CI / backend-tests (push) Successful in 54s
CI / frontend-build (push) Successful in 18s

Nutzer-Vorgabe: "Ablauf/Charge/SN gehört mit zu den Kontrollen wie auch die
Menge". PUT .../positionen/{material_id} akzeptiert jetzt optional
ablaufdatum/chargennummer/seriennummer und schreibt sie auf die
Objektposition (Vier-Kernbegriffe bleiben unberührt: nur diese drei Felder,
niemals istmenge - das bleibt exklusiv Nachfüllung vorbehalten). Offline-
Queue und PositionCard erweitert: Felder erscheinen nur passend zum
Materialtyp (ablauf_charge -> Datum+Charge, geraet_sn -> SN). Admin-Panel
(ObjektPositionenPanel) bleibt zusätzlich für nachträgliche Korrekturen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L85hmKbvX7Cqkq47KnQhFt
This commit is contained in:
2026-09-04 01:11:17 +02:00
co-authored by Claude Sonnet 5
parent a6e68b0a94
commit 0988f8d026
8 changed files with 138 additions and 18 deletions
@@ -134,6 +134,9 @@ async def erfasse_kontrollposition(
material_id=material_id,
istmenge=payload.istmenge,
zustaendiger_server_id=zustaendiger_server_id,
ablaufdatum=payload.ablaufdatum,
chargennummer=payload.chargennummer,
seriennummer=payload.seriennummer,
)
return KontrollpositionRead(
id=kontrollposition.id,
+9 -1
View File
@@ -1,5 +1,5 @@
import uuid
from datetime import datetime
from datetime import date, datetime
from decimal import Decimal
from pydantic import BaseModel, ConfigDict
@@ -24,6 +24,14 @@ class KontrolleRead(BaseModel):
class KontrollpositionInput(BaseModel):
istmenge: Decimal
# Nutzer-Vorgabe: Ablauf/Charge/SN gehören zur Erfassung während der
# Kontrolle dazu, wie die Menge - werden hier optional mitgegeben und auf
# der Objektposition gespeichert (Vier-Kernbegriffe bleiben unberührt:
# nur Objektposition.istmenge darf ausschließlich Nachfüllung ändern,
# diese drei Felder sind unabhängig davon).
ablaufdatum: date | None = None
chargennummer: str | None = None
seriennummer: str | None = None
class KontrollpositionRead(BaseModel):
+18 -2
View File
@@ -1,5 +1,5 @@
import uuid
from datetime import datetime, timezone
from datetime import date, datetime, timezone
from decimal import Decimal
from sqlalchemy import select
@@ -22,12 +22,20 @@ async def erfasse_position(
material_id: int,
istmenge: Decimal,
zustaendiger_server_id: int,
ablaufdatum: date | None = None,
chargennummer: str | None = None,
seriennummer: str | None = None,
) -> tuple[Kontrollposition, uuid.UUID | None]:
"""Prompt 02.3/09 Vier-Kernbegriffe: Kontrolle erfasst nur, ändert nie die
persistente Objektposition.istmenge. Bei Ist < Soll entsteht automatisch ein
Fehlbestand (nie bei Überbestand, Prompt 02.4). Gibt zusätzlich die
Fehlbestand-ID zurück (falls einer aktiv ist), damit die UI direkt eine
Sofort-Nachfüllung (Karte 07) anbieten kann, ohne separat nachzufragen."""
Sofort-Nachfüllung (Karte 07) anbieten kann, ohne separat nachzufragen.
Ablaufdatum/Chargennummer/Seriennummer sind KEINE Kernbegriffe-Verletzung:
sie beschreiben das physische Exemplar, nicht die Ist-Menge, und werden
daher hier - auf Wunsch als Teil der normalen Kontroll-Erfassung, nicht nur
als separate Admin-Pflege - direkt mitgepflegt."""
vorlagen_sollmengen = await sollmenge_map(db, objekt.vorlage_id)
result = await db.execute(
select(Objektposition).where(
@@ -37,6 +45,14 @@ async def erfasse_position(
objektposition = result.scalar_one_or_none()
sollmenge = sollmenge_effektiv(objektposition, vorlagen_sollmengen) if objektposition else Decimal(0)
if objektposition is not None:
if ablaufdatum is not None:
objektposition.ablaufdatum = ablaufdatum
if chargennummer is not None:
objektposition.chargennummer = chargennummer
if seriennummer is not None:
objektposition.seriennummer = seriennummer
abweichung = istmenge != sollmenge
result = await db.execute(