feat(dokumente): DOC-004 Original-vs-Kopie-Kennzeichnung
CI / backend-tests (push) Successful in 2m16s
CI / frontend-build (push) Successful in 27s

Neues Feld ist_original (Boolean, Migration 0029) - explizit beim Upload
und beim Ersetzen (DOC-003) setzbar, kein Default in eine Richtung erraten.
Wird beim Ersetzen bewusst NICHT vom Vorgänger übernommen (neue Version
könnte ein nachgereichtes Original sein, das eine bisherige Kopie ersetzt,
oder umgekehrt). Frontend: Checkbox "Original (nicht nur Kopie/Scan)" im
Upload-Formular, "Original"-Badge in der Dokumentenliste.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
This commit is contained in:
2026-09-08 12:16:25 +02:00
co-authored by Claude Sonnet 5
parent 17cac8543f
commit ae09433c11
10 changed files with 118 additions and 5 deletions
+4
View File
@@ -72,6 +72,7 @@ async def lade_dokument_hoch(
entitaet_id: str = Form(...),
dokumenttyp: DokumentTyp = Form(...),
beschreibung: str | None = Form(None),
ist_original: bool = Form(False),
datei: UploadFile = File(...),
db: AsyncSession = Depends(get_db),
current_user=Depends(_mitarbeiter_plus),
@@ -88,6 +89,7 @@ async def lade_dokument_hoch(
dokumenttyp=dokumenttyp,
beschreibung=beschreibung,
hochgeladen_von=current_user.id,
ist_original=ist_original,
)
except DateityperlaubtError as exc:
raise HTTPException(
@@ -128,6 +130,7 @@ async def lade_dokument_herunter(
async def dokument_ersetzen(
dokument_id: uuid.UUID,
beschreibung: str | None = Form(None),
ist_original: bool = Form(False),
datei: UploadFile = File(...),
db: AsyncSession = Depends(get_db),
current_user=Depends(_mitarbeiter_plus),
@@ -148,6 +151,7 @@ async def dokument_ersetzen(
inhalt=inhalt,
beschreibung=beschreibung,
hochgeladen_von=current_user.id,
ist_original=ist_original,
)
except DateityperlaubtError as exc:
raise HTTPException(
+6 -1
View File
@@ -2,7 +2,7 @@ import enum
import uuid
from datetime import datetime
from sqlalchemy import ForeignKey, Integer, String
from sqlalchemy import Boolean, ForeignKey, Integer, String
from sqlalchemy.dialects.postgresql import ENUM as PgEnum, TIMESTAMP, UUID
from sqlalchemy.orm import Mapped, mapped_column
@@ -67,3 +67,8 @@ class Dokument(Base):
vorgaenger_id: Mapped[uuid.UUID | None] = mapped_column(
UUID(as_uuid=True), ForeignKey("dokument.id"), nullable=True
)
# DOC-004: rechtlich/organisatorisch relevant bei Zulassungsdokumenten/
# Rechnungen - ist das hier das Original (z.B. eingescannt vom Papier-
# Original) oder nur eine Kopie/ein Duplikat davon? Explizite Angabe beim
# Upload statt Annahme, kein Default in eine Richtung.
ist_original: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
+1
View File
@@ -27,3 +27,4 @@ class DokumentRead(BaseModel):
hochgeladen_von: int
hochgeladen_am: datetime
vorgaenger_id: uuid.UUID | None
ist_original: bool
+9 -1
View File
@@ -56,6 +56,7 @@ async def _pruefe_und_speichere(
beschreibung: str | None,
hochgeladen_von: int,
vorgaenger_id: uuid.UUID | None,
ist_original: bool,
) -> Dokument:
if mime_type not in ERLAUBTE_MIME_TYPES:
raise DateityperlaubtError(mime_type)
@@ -94,6 +95,7 @@ async def _pruefe_und_speichere(
hochgeladen_von=hochgeladen_von,
hochgeladen_am=datetime.now(timezone.utc),
vorgaenger_id=vorgaenger_id,
ist_original=ist_original,
)
db.add(dokument)
await db.flush()
@@ -111,6 +113,7 @@ async def speichere_dokument(
dokumenttyp: DokumentTyp,
beschreibung: str | None,
hochgeladen_von: int,
ist_original: bool,
) -> Dokument:
return await _pruefe_und_speichere(
db,
@@ -123,6 +126,7 @@ async def speichere_dokument(
beschreibung=beschreibung,
hochgeladen_von=hochgeladen_von,
vorgaenger_id=None,
ist_original=ist_original,
)
@@ -135,11 +139,14 @@ async def ersetze_dokument(
inhalt: bytes,
beschreibung: str | None,
hochgeladen_von: int,
ist_original: bool,
) -> Dokument:
"""DOC-003: neue Version anlegen statt zu überschreiben - altes_dokument
bleibt unverändert als Historieneintrag erhalten, entitaet_typ/entitaet_id/
dokumenttyp werden von ihm übernommen (nicht neu wählbar, es ist dieselbe
Sache in neuer Fassung)."""
Sache in neuer Fassung). ist_original wird bewusst NICHT vom Vorgänger
übernommen (DOC-004) - die neue Version könnte z.B. ein nachgereichtes
Original sein, das die bisherige Kopie ersetzt."""
return await _pruefe_und_speichere(
db,
entitaet_typ=altes_dokument.entitaet_typ,
@@ -151,6 +158,7 @@ async def ersetze_dokument(
beschreibung=beschreibung,
hochgeladen_von=hochgeladen_von,
vorgaenger_id=altes_dokument.id,
ist_original=ist_original,
)