diff --git a/backend/app/services/kontrolle/lifecycle.py b/backend/app/services/kontrolle/lifecycle.py index efdfb00..1476e9c 100644 --- a/backend/app/services/kontrolle/lifecycle.py +++ b/backend/app/services/kontrolle/lifecycle.py @@ -3,7 +3,7 @@ from datetime import datetime, timezone from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession -from app.models.fehlbestand import Fehlbestand +from app.models.fehlbestand import Fehlbestand, FehlbestandStatus from app.models.kontrolle import Kontrolle, KontrollStatus, Kontrollposition from app.models.mindermenge import MindermengeStatus, MindermengenGenehmigung from app.models.objektposition import Objektposition, ObjektpositionStatus @@ -110,6 +110,12 @@ async def _lasse_mindermengen_ablaufen( async def _verwirf_kontrolldaten(db: AsyncSession, kontrolle_id) -> None: fehlbestaende = await db.execute(select(Fehlbestand).where(Fehlbestand.kontrolle_id == kontrolle_id)) for fehlbestand in fehlbestaende.scalars().all(): + if fehlbestand.status != FehlbestandStatus.offen: + # Bereits (teilweise) nachgefüllt (Karte 07 Sofort-Nachfüllung während + # der Kontrolle) - das ist eine echte, dokumentierte Bestandsbewegung + # und darf beim Verwerfen/Abbruch der Kontrolle NICHT gelöscht werden + # (FK-Verweis aus nachfuellung + Historie müssen erhalten bleiben). + continue await db.delete(fehlbestand) positionen = await db.execute(select(Kontrollposition).where(Kontrollposition.kontrolle_id == kontrolle_id)) for position in positionen.scalars().all(): diff --git a/backend/tests/test_kontrolle.py b/backend/tests/test_kontrolle.py index c9df84c..476c1e9 100644 --- a/backend/tests/test_kontrolle.py +++ b/backend/tests/test_kontrolle.py @@ -157,6 +157,46 @@ async def test_abbruch_verwirft_fehlbestand_und_positionen( assert kontrolle.status == KontrollStatus.abgebrochen +@pytest.mark.asyncio +async def test_abbruch_nach_sofort_nachfuellung_loescht_fehlbestand_nicht( + client, db_session, objekt_mit_position, mitarbeiter_user +): + """Karte 07: wird während der laufenden Kontrolle sofort nachgefüllt und die + Kontrolle danach abgebrochen (z. B. Einsatzalarmierung), darf der bereits + nachgefüllte Fehlbestand NICHT gelöscht werden - er ist eine echte + dokumentierte Bestandsbewegung, kein reiner Kontroll-Zwischenstand.""" + objekt, material = objekt_mit_position + token = await login(client, "mitarbeiter1") + start = await _starte(client, token, objekt.id) + kontrolle_id = start.json()["id"] + + erfassung = await client.put( + f"/api/v1/kontrollen/{kontrolle_id}/positionen/{material.id}", + json={"istmenge": "8"}, + headers=auth_header(token), + ) + fehlbestand_id = erfassung.json()["fehlbestand_id"] + assert fehlbestand_id is not None + + nf = await client.post( + f"/api/v1/fehlbestaende/{fehlbestand_id}/nachfuellungen", + json={"menge": "2"}, + headers=auth_header(token), + ) + assert nf.status_code == 201 + + response = await client.post( + f"/api/v1/kontrollen/{kontrolle_id}/abbrechen", + json={"grund": "Einsatzalarmierung"}, + headers=auth_header(token), + ) + assert response.status_code == 200 + + fehlbestand = await db_session.get(Fehlbestand, fehlbestand_id) + assert fehlbestand is not None + assert fehlbestand.status.value == "erledigt" + + @pytest.mark.asyncio async def test_objekt_sperre_zweiter_zugriff_ist_409( client, objekt_mit_position, mitarbeiter_user, mitarbeiter2_user