fix(kontrolle): doppelten Fehlbestand bei Folge-Kontrolle vermieden
_synchronisiere_fehlbestand suchte nur nach Fehlbeständen der eigenen
Kontroll-Sitzung. Ein bereits offener Fehlbestand aus einer früheren
Kontrolle für dasselbe Objekt+Material wurde nicht wiedergefunden -
es entstand ein zweiter, paralleler Fehlbestand mit eigener (neuerer)
Sollmenge, der alte blieb mit veralteter Sollmenge offen liegen.
Lookup jetzt über objekt_id+material_id+status=offen statt
kontrolle_id; kontrolle_id am gefundenen Datensatz bleibt unverändert,
damit ein Abbruch der aktuellen Kontrolle ihn nicht fälschlich
mitlöscht. Löst sich die Abweichung über eine andere Kontrolle als
die erzeugende auf, wird der Fehlbestand jetzt sauber als erledigt
markiert (inkl. Mindermenge-Abschluss) statt stillschweigend gelöscht.
Nebenbei: Kommentare mit Kachel-/Datums-Referenzen ("Bug-Fund
2026-09-06", "UI-00X (Epic 20)") aus dem Code dieser Session entfernt.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
This commit is contained in:
@@ -204,9 +204,6 @@ async def test_offener_fehlbestand_macht_objekt_nicht_einsatzbereit(
|
||||
body = response.json()
|
||||
assert body["einsatzbereit"] == 0
|
||||
assert body["nicht_einsatzbereit"] == 1
|
||||
# Bug-Fund 2026-09-06: "nie kontrolliert" darf nicht verloren gehen, nur
|
||||
# weil das Objekt zusätzlich einen anderen Grund hat (objekt_mit_position
|
||||
# hat nie eine abgeschlossene Kontrolle).
|
||||
assert body["details"][0]["gruende"] == ["fehlbestand_offen", "noch_nie_kontrolliert"]
|
||||
assert body["nie_kontrolliert_gesamt"] == 1
|
||||
|
||||
|
||||
@@ -306,3 +306,70 @@ async def test_verschiedene_objekte_parallel_kontrollierbar(
|
||||
|
||||
zweiter = await _starte(client, token2, objekt_b.id)
|
||||
assert zweiter.status_code == 201
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_zweite_kontrolle_aktualisiert_offenen_fehlbestand_statt_duplikat(
|
||||
client, db_session, objekt_mit_position, mitarbeiter_user
|
||||
):
|
||||
"""Ein offener Fehlbestand aus einer früheren Kontrolle wird aktualisiert
|
||||
statt einen zweiten parallelen zu erzeugen."""
|
||||
objekt, material = objekt_mit_position
|
||||
token = await login(client, "mitarbeiter1")
|
||||
|
||||
erste_kontrolle = (await _starte(client, token, objekt.id)).json()["id"]
|
||||
await client.put(
|
||||
f"/api/v1/kontrollen/{erste_kontrolle}/positionen/{material.id}",
|
||||
json={"istmenge": "8"},
|
||||
headers=auth_header(token),
|
||||
)
|
||||
await client.post(f"/api/v1/kontrollen/{erste_kontrolle}/abschliessen", headers=auth_header(token))
|
||||
|
||||
zweite_kontrolle = (await _starte(client, token, objekt.id)).json()["id"]
|
||||
await client.put(
|
||||
f"/api/v1/kontrollen/{zweite_kontrolle}/positionen/{material.id}",
|
||||
json={"istmenge": "7"},
|
||||
headers=auth_header(token),
|
||||
)
|
||||
|
||||
result = await db_session.execute(
|
||||
select(Fehlbestand).where(Fehlbestand.objekt_id == objekt.id, Fehlbestand.material_id == material.id)
|
||||
)
|
||||
fehlbestaende = result.scalars().all()
|
||||
assert len(fehlbestaende) == 1
|
||||
assert float(fehlbestaende[0].istmenge) == 7
|
||||
assert float(fehlbestaende[0].fehlmenge) == 3
|
||||
assert fehlbestaende[0].kontrolle_id == erste_kontrolle
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_zweite_kontrolle_erledigt_offenen_fehlbestand_bei_korrektur(
|
||||
client, db_session, objekt_mit_position, mitarbeiter_user
|
||||
):
|
||||
"""Ergänzend: löst die Folge-Kontrolle die Abweichung auf, wird der
|
||||
Fehlbestand aus der früheren Kontrolle als erledigt markiert (nicht
|
||||
gelöscht - er war bereits real, anders als der Same-Session-Fall)."""
|
||||
objekt, material = objekt_mit_position
|
||||
token = await login(client, "mitarbeiter1")
|
||||
|
||||
erste_kontrolle = (await _starte(client, token, objekt.id)).json()["id"]
|
||||
await client.put(
|
||||
f"/api/v1/kontrollen/{erste_kontrolle}/positionen/{material.id}",
|
||||
json={"istmenge": "8"},
|
||||
headers=auth_header(token),
|
||||
)
|
||||
await client.post(f"/api/v1/kontrollen/{erste_kontrolle}/abschliessen", headers=auth_header(token))
|
||||
|
||||
zweite_kontrolle = (await _starte(client, token, objekt.id)).json()["id"]
|
||||
await client.put(
|
||||
f"/api/v1/kontrollen/{zweite_kontrolle}/positionen/{material.id}",
|
||||
json={"istmenge": "10"},
|
||||
headers=auth_header(token),
|
||||
)
|
||||
|
||||
result = await db_session.execute(
|
||||
select(Fehlbestand).where(Fehlbestand.objekt_id == objekt.id, Fehlbestand.material_id == material.id)
|
||||
)
|
||||
fehlbestand = result.scalar_one()
|
||||
assert fehlbestand.status.value == "erledigt"
|
||||
assert fehlbestand.fehlmenge == 0
|
||||
|
||||
Reference in New Issue
Block a user