Files
MABEA/backend/tests/test_fahrzeugdetails.py
T
patrickandClaude Sonnet 5 11ad747136
CI / backend-tests (push) Failing after 1m47s
CI / frontend-build (push) Successful in 17s
fix(historie): Audit-Lücke bei Mangel/Personal/Objekt-Änderungen geschlossen
Bisher waren nur Kontrolle/Fehlbestand/Nachfüllung/Mindermenge/Geräteinstanz
im append-only Audit-Log (historie.log() war seit Prompt 13 nie flächendeckend
verdrahtet, docstring sagte das bereits so). Drei neue Ereignisse ergänzt:

- mangel_gemeldet / mangel_status_geaendert (Mangel-Modul)
- qualifikation_erfasst (Personal-Modul, sicherheitsrelevant: "wer hat wem
  wann eine Qualifikation bestätigt" hängt fachlich direkt an "wer darf
  fahren")
- objekt_geaendert (Status-/Fahrzeug-Zuordnungsänderungen via PATCH /objekte)

Lagerbewegung bewusst NICHT zusätzlich in historie dupliziert - hat bereits
eigenes vollständiges Audit-Trail (Wer/Wann/Von/Nach/Grund in eigener
Tabelle).

Frontend: Änderungslog-Filter um geraet_instanz/mangel/benutzer_qualifikation/
objekt ergänzt (geraet_instanz fehlte dort zuvor ebenfalls).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KC8HYvv6UkCVYheYiTw9DD
2026-09-05 13:50:48 +02:00

115 lines
4.5 KiB
Python

from datetime import date, timedelta
import pytest
from tests.conftest import auth_header, login
@pytest.mark.asyncio
async def test_fahrzeugdetails_upsert(client, objekt_mit_position, admin_user):
objekt, _material = objekt_mit_position
token = await login(client, "admin1")
fehlend = await client.get(f"/api/v1/objekte/{objekt.id}/fahrzeugdetails", headers=auth_header(token))
assert fehlend.status_code == 404
gesetzt = await client.put(
f"/api/v1/objekte/{objekt.id}/fahrzeugdetails",
json={"kennzeichen": "XX-YY 123", "kilometerstand": 42315, "naechste_hu": "2027-05-01"},
headers=auth_header(token),
)
assert gesetzt.status_code == 200
assert gesetzt.json()["kennzeichen"] == "XX-YY 123"
assert gesetzt.json()["kilometerstand"] == 42315
aktualisiert = await client.put(
f"/api/v1/objekte/{objekt.id}/fahrzeugdetails",
json={"kilometerstand": 42500},
headers=auth_header(token),
)
assert aktualisiert.json()["kilometerstand"] == 42500
assert aktualisiert.json()["kennzeichen"] is None # PUT ersetzt komplett, kein Merge
@pytest.mark.asyncio
async def test_mitarbeiter_darf_fahrzeugdetails_nicht_setzen(client, objekt_mit_position, mitarbeiter_user):
objekt, _material = objekt_mit_position
token = await login(client, "mitarbeiter1")
response = await client.put(
f"/api/v1/objekte/{objekt.id}/fahrzeugdetails", json={"kennzeichen": "X"}, headers=auth_header(token)
)
assert response.status_code == 403
@pytest.mark.asyncio
async def test_ausser_dienst_objekt_zaehlt_nicht_in_einsatzbereitschaft(
client, objekt_mit_position, admin_user, materialverantwortlicher_user
):
objekt, _material = objekt_mit_position
token = await login(client, "admin1")
await client.patch(f"/api/v1/objekte/{objekt.id}", json={"status": "ausser_dienst"}, headers=auth_header(token))
verantwortlicher_token = await login(client, "materialverantwortlicher1")
response = await client.get(
"/api/v1/dashboard/einsatzbereitschaft", headers=auth_header(verantwortlicher_token)
)
body = response.json()
assert body["gesamt"] == 0
@pytest.mark.asyncio
async def test_in_wartung_macht_objekt_nicht_einsatzbereit(
client, objekt_mit_position, admin_user, materialverantwortlicher_user
):
objekt, _material = objekt_mit_position
token = await login(client, "admin1")
await client.patch(f"/api/v1/objekte/{objekt.id}", json={"status": "in_wartung"}, headers=auth_header(token))
verantwortlicher_token = await login(client, "materialverantwortlicher1")
response = await client.get(
"/api/v1/dashboard/einsatzbereitschaft", headers=auth_header(verantwortlicher_token)
)
body = response.json()
assert body["nicht_einsatzbereit"] == 1
assert body["details"][0]["gruende"] == ["in_wartung"]
@pytest.mark.asyncio
async def test_ueberfaellige_hu_macht_objekt_nicht_einsatzbereit_und_erscheint_in_prueftermine(
client, objekt_mit_position, admin_user, materialverantwortlicher_user
):
objekt, _material = objekt_mit_position
token = await login(client, "admin1")
await client.put(
f"/api/v1/objekte/{objekt.id}/fahrzeugdetails",
json={"naechste_hu": (date.today() - timedelta(days=10)).isoformat()},
headers=auth_header(token),
)
verantwortlicher_token = await login(client, "materialverantwortlicher1")
bereitschaft = await client.get(
"/api/v1/dashboard/einsatzbereitschaft", headers=auth_header(verantwortlicher_token)
)
assert bereitschaft.json()["details"][0]["gruende"] == ["hu_uvv_ueberfaellig"]
prueftermine = await client.get("/api/v1/dashboard/prueftermine", headers=auth_header(verantwortlicher_token))
body = prueftermine.json()
assert len(body) == 1
assert body[0]["typ"] == "fahrzeug_hu"
assert body[0]["status"] == "abgelaufen"
@pytest.mark.asyncio
async def test_objekt_status_aenderung_steht_in_historie(client, objekt_mit_position, admin_user):
objekt, _material = objekt_mit_position
token = await login(client, "admin1")
await client.patch(f"/api/v1/objekte/{objekt.id}", json={"status": "in_wartung"}, headers=auth_header(token))
historie = await client.get(
f"/api/v1/historie?entitaet_typ=objekt&entitaet_id={objekt.id}", headers=auth_header(token)
)
body = historie.json()
assert len(body) == 1
assert body[0]["ereignistyp"] == "objekt_geaendert"
assert body[0]["neuer_wert"]["status"] == "in_wartung"