feat(dokumente): DOC-001 Duplikat-Erkennung + Fix Online-Ansicht (Popup-Blocker)
Duplikat-Erkennung: SHA-256-Hash je Dokument (Migration 0024), Upload wird mit 409 abgelehnt, wenn dieselbe Datei bereits an derselben Entität liegt (Vergleich bewusst pro Entität, nicht global - gleiche Datei an zwei Objekten ist kein Duplikat). Frontend zeigt die Backend-Fehlermeldung (Dateiname/Datum des bestehenden Dokuments) statt generischem Text. Nebenbei gefunden+gefixt: "Ansehen" (PDF/JPG/PNG online statt Download) funktionierte nicht zuverlässig, weil window.open() erst nach einem await fetch() aufgerufen wurde - Popup-Blocker werten das nicht mehr als direkte Nutzeraktion. Jetzt öffnet der Tab sofort synchron, die Blob-URL wird nachgeladen. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
This commit is contained in:
@@ -94,3 +94,56 @@ async def test_mitarbeiter_darf_dokument_nicht_loeschen(client, objekt_mit_posit
|
||||
|
||||
response = await client.delete(f"/api/v1/dokumente/{dokument_id}", headers=auth_header(token))
|
||||
assert response.status_code == 403
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_identische_datei_am_gleichen_objekt_wird_abgelehnt(client, objekt_mit_position, mitarbeiter_user):
|
||||
"""DOC-001: gleiche Bytes, gleiche Entität -> 409 statt zweitem Dokument."""
|
||||
objekt, _material = objekt_mit_position
|
||||
token = await login(client, "mitarbeiter1")
|
||||
inhalt = b"%PDF-1.4 identischer inhalt"
|
||||
|
||||
erster = await client.post(
|
||||
"/api/v1/dokumente",
|
||||
data={"entitaet_typ": "objekt", "entitaet_id": str(objekt.id)},
|
||||
files={"datei": ("original.pdf", inhalt, "application/pdf")},
|
||||
headers=auth_header(token),
|
||||
)
|
||||
assert erster.status_code == 201
|
||||
|
||||
zweiter = await client.post(
|
||||
"/api/v1/dokumente",
|
||||
data={"entitaet_typ": "objekt", "entitaet_id": str(objekt.id)},
|
||||
files={"datei": ("kopie.pdf", inhalt, "application/pdf")},
|
||||
headers=auth_header(token),
|
||||
)
|
||||
assert zweiter.status_code == 409
|
||||
assert "original.pdf" in zweiter.json()["detail"]
|
||||
|
||||
liste = await client.get(
|
||||
f"/api/v1/dokumente?entitaet_typ=objekt&entitaet_id={objekt.id}", headers=auth_header(token)
|
||||
)
|
||||
assert len(liste.json()) == 1
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_identische_datei_an_anderer_entitaet_ist_kein_duplikat(client, objekt_mit_position, mitarbeiter_user):
|
||||
"""Gleiche Datei an ZWEI verschiedenen Objekten ist kein Duplikat - Hash-
|
||||
Vergleich ist bewusst pro Entität, nicht global."""
|
||||
objekt, _material = objekt_mit_position
|
||||
token = await login(client, "mitarbeiter1")
|
||||
inhalt = b"%PDF-1.4 gleiche datei anderes objekt"
|
||||
|
||||
await client.post(
|
||||
"/api/v1/dokumente",
|
||||
data={"entitaet_typ": "objekt", "entitaet_id": str(objekt.id)},
|
||||
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"},
|
||||
files={"datei": ("anleitung.pdf", inhalt, "application/pdf")},
|
||||
headers=auth_header(token),
|
||||
)
|
||||
assert andere_entitaet.status_code == 201
|
||||
|
||||
Reference in New Issue
Block a user