CI / backend-tests (push) Successful in 40s
- Nachfuellung-Modell: einzige Aktion, die Objektposition.istmenge tatsächlich ändert (Vier-Kernbegriffe). Deckt Sofort-Nachfüllung während Kontrolle (Karte 07) und spätere/externe Nachfüllung (Prompt 02.5) mit derselben Logik ab - Wichtiger Fix vor dem ersten Testlauf: Objektposition.istmenge wird bei Nachfüllung auf den neuen Wert GESETZT (fehlbestand.istmenge + menge), nicht unabhängig inkrementiert - sonst bliebe sie beim initialen "nicht kontrolliert"-Stand (0) stehen, obwohl die Kontrolle bereits einen realen Zählwert kennt - Statusübergänge: offen -> nachgefuellt_teilweise (Fehlmenge>0) -> erledigt (Fehlmenge=0), ausschließlich automatisch bei Ist=Soll (U3) - Überbestand durch Nachfüllung erlaubt, als Info gekennzeichnet, kein Fehler (E4) - KontrollpositionRead liefert jetzt fehlbestand_id mit, damit die UI direkt eine Sofort-Nachfüllung anbieten kann, ohne separat nachzufragen - Tests: U3, U4 (Sofort-Nachfüllung ohne Zwischenstatus), U5 (Teilnachfüllung), Überbestand-Fall, Nachfüllung auf bereits erledigten Fehlbestand -> 409 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L85hmKbvX7Cqkq47KnQhFt
139 lines
5.0 KiB
Python
139 lines
5.0 KiB
Python
import pytest
|
|
from sqlalchemy import select
|
|
|
|
from app.models.objektposition import Objektposition
|
|
from tests.conftest import auth_header, login
|
|
|
|
|
|
async def _fehlbestand_erzeugen(client, token, objekt, material, istmenge: str):
|
|
start = await client.post(
|
|
f"/api/v1/objekte/{objekt.id}/kontrollen", json={"uebernehmen": False}, headers=auth_header(token)
|
|
)
|
|
kontrolle_id = start.json()["id"]
|
|
put_response = await client.put(
|
|
f"/api/v1/kontrollen/{kontrolle_id}/positionen/{material.id}",
|
|
json={"istmenge": istmenge},
|
|
headers=auth_header(token),
|
|
)
|
|
return put_response.json()["fehlbestand_id"]
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_sofort_nachfuellung_erledigt_ohne_zwischenstatus(
|
|
client, db_session, objekt_mit_position, mitarbeiter_user
|
|
):
|
|
"""U4: Sofort-Nachfüllung während der Kontrolle - Fehlbestand entsteht und
|
|
wird im selben Moment erledigt, Ist-Menge wird auf Soll korrigiert."""
|
|
objekt, material = objekt_mit_position
|
|
token = await login(client, "mitarbeiter1")
|
|
fehlbestand_id = await _fehlbestand_erzeugen(client, token, objekt, material, "7")
|
|
|
|
response = await client.post(
|
|
f"/api/v1/fehlbestaende/{fehlbestand_id}/nachfuellungen",
|
|
json={"menge": "3"},
|
|
headers=auth_header(token),
|
|
)
|
|
assert response.status_code == 201
|
|
body = response.json()
|
|
assert body["fehlbestand"]["status"] == "erledigt"
|
|
assert float(body["fehlbestand"]["fehlmenge"]) == 0
|
|
assert float(body["ueberbestand"]) == 0
|
|
|
|
objektposition = (
|
|
await db_session.execute(
|
|
select(Objektposition).where(
|
|
Objektposition.objekt_id == objekt.id, Objektposition.material_id == material.id
|
|
)
|
|
)
|
|
).scalar_one()
|
|
assert float(objektposition.istmenge) == 10
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_teilnachfuellung_bleibt_offen_mit_reduzierter_fehlmenge(
|
|
client, db_session, objekt_mit_position, mitarbeiter_user
|
|
):
|
|
"""U5: Teilnachfüllung reduziert Fehlmenge, Status bleibt (fachlich weiterhin) offen."""
|
|
objekt, material = objekt_mit_position
|
|
token = await login(client, "mitarbeiter1")
|
|
fehlbestand_id = await _fehlbestand_erzeugen(client, token, objekt, material, "6")
|
|
|
|
response = await client.post(
|
|
f"/api/v1/fehlbestaende/{fehlbestand_id}/nachfuellungen",
|
|
json={"menge": "2"},
|
|
headers=auth_header(token),
|
|
)
|
|
assert response.status_code == 201
|
|
body = response.json()["fehlbestand"]
|
|
assert body["status"] == "nachgefuellt_teilweise"
|
|
assert float(body["fehlmenge"]) == 2
|
|
assert float(body["istmenge"]) == 8
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_erledigt_ausschliesslich_bei_ist_gleich_soll(
|
|
client, db_session, objekt_mit_position, mitarbeiter_user
|
|
):
|
|
"""U3: Fehlbestand wird ausschließlich automatisch bei Ist=Soll erledigt."""
|
|
objekt, material = objekt_mit_position
|
|
token = await login(client, "mitarbeiter1")
|
|
fehlbestand_id = await _fehlbestand_erzeugen(client, token, objekt, material, "4")
|
|
|
|
teil = await client.post(
|
|
f"/api/v1/fehlbestaende/{fehlbestand_id}/nachfuellungen",
|
|
json={"menge": "3"},
|
|
headers=auth_header(token),
|
|
)
|
|
assert teil.json()["fehlbestand"]["status"] == "nachgefuellt_teilweise"
|
|
|
|
rest = await client.post(
|
|
f"/api/v1/fehlbestaende/{fehlbestand_id}/nachfuellungen",
|
|
json={"menge": "3"},
|
|
headers=auth_header(token),
|
|
)
|
|
assert rest.json()["fehlbestand"]["status"] == "erledigt"
|
|
assert float(rest.json()["fehlbestand"]["fehlmenge"]) == 0
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_ueberbestand_durch_nachfuellung_kein_fehler(
|
|
client, db_session, objekt_mit_position, mitarbeiter_user
|
|
):
|
|
"""E4/Prompt 21.9: Nachfüllung über Soll hinaus erlaubt, als Überbestand markiert."""
|
|
objekt, material = objekt_mit_position
|
|
token = await login(client, "mitarbeiter1")
|
|
fehlbestand_id = await _fehlbestand_erzeugen(client, token, objekt, material, "7")
|
|
|
|
response = await client.post(
|
|
f"/api/v1/fehlbestaende/{fehlbestand_id}/nachfuellungen",
|
|
json={"menge": "5"},
|
|
headers=auth_header(token),
|
|
)
|
|
assert response.status_code == 201
|
|
body = response.json()
|
|
assert body["fehlbestand"]["status"] == "erledigt"
|
|
assert float(body["ueberbestand"]) == 2
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_nachfuellung_auf_erledigten_fehlbestand_ist_409(
|
|
client, objekt_mit_position, mitarbeiter_user
|
|
):
|
|
objekt, material = objekt_mit_position
|
|
token = await login(client, "mitarbeiter1")
|
|
fehlbestand_id = await _fehlbestand_erzeugen(client, token, objekt, material, "7")
|
|
|
|
erste = await client.post(
|
|
f"/api/v1/fehlbestaende/{fehlbestand_id}/nachfuellungen",
|
|
json={"menge": "3"},
|
|
headers=auth_header(token),
|
|
)
|
|
assert erste.json()["fehlbestand"]["status"] == "erledigt"
|
|
|
|
zweite = await client.post(
|
|
f"/api/v1/fehlbestaende/{fehlbestand_id}/nachfuellungen",
|
|
json={"menge": "1"},
|
|
headers=auth_header(token),
|
|
)
|
|
assert zweite.status_code == 409
|