Sprint 3: Kontroll-Kern (Statusmaschine, Objekt-Sperre, automatische Fehlbestand-Erzeugung)
CI / backend-tests (push) Successful in 38s
CI / backend-tests (push) Successful in 38s
- Kontrolle/Kontrollposition-Modelle: Kontrolle ändert NIEMALS Objektposition.istmenge (Vier-Kernbegriffe-Tabelle, Prompt 02.9) - reine Erfassung/Snapshot - Objekt-Sperre (Prompt 02.8): Kontrolle.status='in_bearbeitung' + benutzer_id IST die Sperre, kein separates Sperr-Modell. Zweiter Zugriff -> 409 mit wer/seit; Übernahme bricht alte Kontrolle ab (Datensatz bleibt, Prompt 16.6-Analogie) und protokolliert das Ereignis in einer neuen, minimalen Historie-Tabelle (volle Ausbaustufe Sprint 5) - Automatische Fehlbestand-Erzeugung bei Ist < Soll (U1), Überbestand erzeugt ausdrücklich KEINEN Fehlbestand (Prompt 02.4); Korrektur vor Abschluss möglich (von derselben Kontrolle erzeugter Fehlbestand ist bis zum Abschluss nicht final) - Abschluss verweigert bei unbestätigten Positionen, liefert deren IDs (U11) - Abbruch verwirft Kontrollpositionen UND von dieser Kontrolle erzeugte Fehlbestände, Kontrolle selbst bleibt als Datensatz mit Status "abgebrochen" erhalten (U12) - Tests: U1, U11, U12, Sperre/409, Übernahme, Fremdzugriff/403, parallele Objekte Mitarbeiter-UI (PWA-Frontend) ist bewusst noch nicht Teil dieses Commits - eigenes Techstack-Setup, wird als nächster Schritt separat angegangen. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L85hmKbvX7Cqkq47KnQhFt
This commit is contained in:
@@ -76,6 +76,21 @@ async def mitarbeiter_user(db_session):
|
||||
return benutzer
|
||||
|
||||
|
||||
@pytest_asyncio.fixture
|
||||
async def mitarbeiter2_user(db_session):
|
||||
benutzer = Benutzer(
|
||||
name="Test Mitarbeiter 2",
|
||||
login="mitarbeiter2",
|
||||
passwort_hash=hash_password("test-passwort-123"),
|
||||
aktiv=True,
|
||||
)
|
||||
db_session.add(benutzer)
|
||||
await db_session.flush()
|
||||
db_session.add(BenutzerRolle(benutzer_id=benutzer.id, rolle=RolleTyp.mitarbeiter))
|
||||
await db_session.flush()
|
||||
return benutzer
|
||||
|
||||
|
||||
@pytest_asyncio.fixture
|
||||
async def admin_user(db_session):
|
||||
benutzer = Benutzer(
|
||||
@@ -173,3 +188,40 @@ async def objekttyp_factory(db_session):
|
||||
return objekttyp
|
||||
|
||||
return _make
|
||||
|
||||
|
||||
@pytest_asyncio.fixture
|
||||
async def objekt_mit_position(db_session, hauptserver_id):
|
||||
"""Fertiges Objekt mit einer Vorlagen-Position (Sollmenge 10) für Kontroll-Tests."""
|
||||
from app.services.objekte import objekt_aus_vorlage
|
||||
from app.services.vorlagen import erstelle_vorlage
|
||||
from app.schemas.vorlage import VorlagenpositionCreate
|
||||
|
||||
bereich = Bereich(name="Bereich-KT")
|
||||
db_session.add(bereich)
|
||||
await db_session.flush()
|
||||
objekttyp = Objekttyp(bereich_id=bereich.id, name="Rucksack-KT")
|
||||
db_session.add(objekttyp)
|
||||
await db_session.flush()
|
||||
material = Material(name="Kompresse", einheit="Stück", materialtyp=MaterialTyp.standard)
|
||||
db_session.add(material)
|
||||
await db_session.flush()
|
||||
standort = Standort(name="Wache-KT")
|
||||
db_session.add(standort)
|
||||
await db_session.flush()
|
||||
|
||||
vorlage = await erstelle_vorlage(
|
||||
db_session,
|
||||
objekttyp_id=objekttyp.id,
|
||||
name="Vorlage-KT",
|
||||
positionen=[VorlagenpositionCreate(material_id=material.id, sollmenge=10)],
|
||||
)
|
||||
objekt = await objekt_aus_vorlage(
|
||||
db_session,
|
||||
code="KT-01",
|
||||
name="Kontroll-Test-Objekt",
|
||||
standort_id=standort.id,
|
||||
vorlage=vorlage,
|
||||
zustaendiger_server_id=hauptserver_id,
|
||||
)
|
||||
return objekt, material
|
||||
|
||||
Reference in New Issue
Block a user