feat(dokumente): DOC-002 feste Dokumenttypen statt Freitext
Neues Pflichtfeld dokumenttyp (Enum: Prüfprotokoll/Wartungsbericht/ Bedienungsanleitung/Rechnung/Zulassungsdokument/Sonstiges, Migration 0026) - macht Dokumente kategorisier- und filterbar statt nur per Freitext- Beschreibung auffindbar zu sein. Backend: Pflichtfeld beim Upload, optionaler Query-Filter bei GET /dokumente. Frontend: Auswahl-Dropdown beim Upload, Typ-Badge + Filter-Dropdown in der Liste (DokumentePanel). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
This commit is contained in:
@@ -10,7 +10,7 @@ async def test_dokument_hochladen_und_liste(client, objekt_mit_position, mitarbe
|
||||
|
||||
hochgeladen = await client.post(
|
||||
"/api/v1/dokumente",
|
||||
data={"entitaet_typ": "objekt", "entitaet_id": str(objekt.id), "beschreibung": "Zulassung"},
|
||||
data={"entitaet_typ": "objekt", "entitaet_id": str(objekt.id), "dokumenttyp": "zulassungsdokument", "beschreibung": "Zulassung"},
|
||||
files={"datei": ("zulassung.pdf", b"%PDF-1.4 fake", "application/pdf")},
|
||||
headers=auth_header(token),
|
||||
)
|
||||
@@ -31,7 +31,7 @@ async def test_download_liefert_inhalt(client, objekt_mit_position, mitarbeiter_
|
||||
token = await login(client, "mitarbeiter1")
|
||||
hochgeladen = await client.post(
|
||||
"/api/v1/dokumente",
|
||||
data={"entitaet_typ": "objekt", "entitaet_id": str(objekt.id)},
|
||||
data={"entitaet_typ": "objekt", "entitaet_id": str(objekt.id), "dokumenttyp": "sonstiges"},
|
||||
files={"datei": ("foto.png", b"\x89PNG fake", "image/png")},
|
||||
headers=auth_header(token),
|
||||
)
|
||||
@@ -49,7 +49,7 @@ async def test_unerlaubter_dateityp_wird_abgelehnt(client, objekt_mit_position,
|
||||
|
||||
response = await client.post(
|
||||
"/api/v1/dokumente",
|
||||
data={"entitaet_typ": "objekt", "entitaet_id": str(objekt.id)},
|
||||
data={"entitaet_typ": "objekt", "entitaet_id": str(objekt.id), "dokumenttyp": "sonstiges"},
|
||||
files={"datei": ("boese.html", b"<script>alert(1)</script>", "text/html")},
|
||||
headers=auth_header(token),
|
||||
)
|
||||
@@ -64,7 +64,7 @@ async def test_materialverantwortlicher_kann_dokument_loeschen(
|
||||
mitarbeiter_token = await login(client, "mitarbeiter1")
|
||||
hochgeladen = await client.post(
|
||||
"/api/v1/dokumente",
|
||||
data={"entitaet_typ": "objekt", "entitaet_id": str(objekt.id)},
|
||||
data={"entitaet_typ": "objekt", "entitaet_id": str(objekt.id), "dokumenttyp": "sonstiges"},
|
||||
files={"datei": ("bericht.pdf", b"%PDF-1.4 x", "application/pdf")},
|
||||
headers=auth_header(mitarbeiter_token),
|
||||
)
|
||||
@@ -86,7 +86,7 @@ async def test_mitarbeiter_darf_dokument_nicht_loeschen(client, objekt_mit_posit
|
||||
token = await login(client, "mitarbeiter1")
|
||||
hochgeladen = await client.post(
|
||||
"/api/v1/dokumente",
|
||||
data={"entitaet_typ": "objekt", "entitaet_id": str(objekt.id)},
|
||||
data={"entitaet_typ": "objekt", "entitaet_id": str(objekt.id), "dokumenttyp": "sonstiges"},
|
||||
files={"datei": ("x.pdf", b"%PDF-1.4 x", "application/pdf")},
|
||||
headers=auth_header(token),
|
||||
)
|
||||
@@ -105,7 +105,7 @@ async def test_identische_datei_am_gleichen_objekt_wird_abgelehnt(client, objekt
|
||||
|
||||
erster = await client.post(
|
||||
"/api/v1/dokumente",
|
||||
data={"entitaet_typ": "objekt", "entitaet_id": str(objekt.id)},
|
||||
data={"entitaet_typ": "objekt", "entitaet_id": str(objekt.id), "dokumenttyp": "sonstiges"},
|
||||
files={"datei": ("original.pdf", inhalt, "application/pdf")},
|
||||
headers=auth_header(token),
|
||||
)
|
||||
@@ -113,7 +113,7 @@ async def test_identische_datei_am_gleichen_objekt_wird_abgelehnt(client, objekt
|
||||
|
||||
zweiter = await client.post(
|
||||
"/api/v1/dokumente",
|
||||
data={"entitaet_typ": "objekt", "entitaet_id": str(objekt.id)},
|
||||
data={"entitaet_typ": "objekt", "entitaet_id": str(objekt.id), "dokumenttyp": "sonstiges"},
|
||||
files={"datei": ("kopie.pdf", inhalt, "application/pdf")},
|
||||
headers=auth_header(token),
|
||||
)
|
||||
@@ -136,14 +136,62 @@ async def test_identische_datei_an_anderer_entitaet_ist_kein_duplikat(client, ob
|
||||
|
||||
await client.post(
|
||||
"/api/v1/dokumente",
|
||||
data={"entitaet_typ": "objekt", "entitaet_id": str(objekt.id)},
|
||||
data={"entitaet_typ": "objekt", "entitaet_id": str(objekt.id), "dokumenttyp": "sonstiges"},
|
||||
files={"datei": ("anleitung.pdf", inhalt, "application/pdf")},
|
||||
headers=auth_header(token),
|
||||
)
|
||||
andere_entitaet = await client.post(
|
||||
"/api/v1/dokumente",
|
||||
data={"entitaet_typ": "mangel", "entitaet_id": "irgendein-mangel-id"},
|
||||
data={"entitaet_typ": "mangel", "entitaet_id": "irgendein-mangel-id", "dokumenttyp": "sonstiges"},
|
||||
files={"datei": ("anleitung.pdf", inhalt, "application/pdf")},
|
||||
headers=auth_header(token),
|
||||
)
|
||||
assert andere_entitaet.status_code == 201
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_liste_kann_nach_dokumenttyp_gefiltert_werden(client, objekt_mit_position, mitarbeiter_user):
|
||||
"""DOC-002: feste Kategorie statt Freitext - Dokumente pro Typ auffindbar."""
|
||||
objekt, _material = objekt_mit_position
|
||||
token = await login(client, "mitarbeiter1")
|
||||
|
||||
await client.post(
|
||||
"/api/v1/dokumente",
|
||||
data={"entitaet_typ": "objekt", "entitaet_id": str(objekt.id), "dokumenttyp": "rechnung"},
|
||||
files={"datei": ("rechnung.pdf", b"%PDF-1.4 r", "application/pdf")},
|
||||
headers=auth_header(token),
|
||||
)
|
||||
await client.post(
|
||||
"/api/v1/dokumente",
|
||||
data={"entitaet_typ": "objekt", "entitaet_id": str(objekt.id), "dokumenttyp": "pruefprotokoll"},
|
||||
files={"datei": ("pruefung.pdf", b"%PDF-1.4 p", "application/pdf")},
|
||||
headers=auth_header(token),
|
||||
)
|
||||
|
||||
alle = await client.get(
|
||||
f"/api/v1/dokumente?entitaet_typ=objekt&entitaet_id={objekt.id}", headers=auth_header(token)
|
||||
)
|
||||
assert len(alle.json()) == 2
|
||||
|
||||
nur_rechnungen = await client.get(
|
||||
f"/api/v1/dokumente?entitaet_typ=objekt&entitaet_id={objekt.id}&dokumenttyp=rechnung",
|
||||
headers=auth_header(token),
|
||||
)
|
||||
body = nur_rechnungen.json()
|
||||
assert len(body) == 1
|
||||
assert body[0]["dateiname"] == "rechnung.pdf"
|
||||
assert body[0]["dokumenttyp"] == "rechnung"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_unbekannter_dokumenttyp_wird_abgelehnt(client, objekt_mit_position, mitarbeiter_user):
|
||||
objekt, _material = objekt_mit_position
|
||||
token = await login(client, "mitarbeiter1")
|
||||
|
||||
response = await client.post(
|
||||
"/api/v1/dokumente",
|
||||
data={"entitaet_typ": "objekt", "entitaet_id": str(objekt.id), "dokumenttyp": "erfunden"},
|
||||
files={"datei": ("x.pdf", b"%PDF-1.4 x", "application/pdf")},
|
||||
headers=auth_header(token),
|
||||
)
|
||||
assert response.status_code == 422
|
||||
|
||||
Reference in New Issue
Block a user