Files
vergabe-teilnahme/workplans/WP-0007-dokumente.md
2026-05-08 18:33:04 +02:00

5.8 KiB

id, title, status, phase, created, depends_on
id title status phase created depends_on
WP-0007 Dokumentenmanagement done 7-of-12 2026-05-08 WP-0006

WP-0007 — Dokumentenmanagement

Upload, Kategorisierung, Versionierung, Statusworkflow und Standarddokument-Zuordnung für alle Dokumente. Referenz: UC-DO-01 bis UC-DO-05.


id: WP-0007-T01
title: Dokument-Upload und Kategorisierung (UC-DO-01)
status: done

`dokumente/views.py` — dokument_upload:

`DokumentForm(ModelForm)`:
Felder: datei (FileInput), kategorie (Select), version (Text, default='1.0'),
quelle (Text, blank), verantwortlicher (Select), pruefer (Select, blank), los (Select, blank).
`clean_datei()` prüft Dateiendung (.pdf, .docx, .xlsx, .zip, .png, .jpg, .jpeg) und
Dateigröße ≤ settings.MAX_UPLOAD_SIZE. Fehler: ValidationError mit klarer Meldung.

Nach erfolgreichem Upload:
- `dateiname` wird aus `datei.name` befüllt (`os.path.basename(form.instance.datei.name)`)
- Redirect zur Dokumentenliste der Ausschreibung

Multi-Upload: Zeige Dropzone (`<input type="file" multiple>`) mit Alpine.js-Preview der
gewählten Dateien (Dateinamen-Liste). Für jede Datei eigenes Formular-Submit
(vereinfacht: ein File at a time in v1).
id: WP-0007-T02
title: Dokumentenliste und Dokumentdetail
status: done

`dokumente/views.py` — dokumente_liste:
Zeigt alle Dokumente einer Ausschreibung, gruppiert nach Kategorie.
Filter: Status, Kategorie, Verantwortlicher.
Template `dokumente/liste.html`:
- Akkordeon nach Kategorie (Alpine.js)
- Tabelle: Dateiname (Download-Link), Version, Status-Badge, Verantwortlicher, Prüfer, Datum
- Rote Markierung für `finale_abgabeversion=True`

`dokument_detail`:
- Alle Felder via render_field
- Download-Button für Datei
- Versionshistorie (alle Dokumente gleicher Kategorie + Name, geordnet nach Version)
- Freigaben-Liste via GenericRelation
- CustomAttribute-Panel
id: WP-0007-T03
title: Neue Dokumentversion hochladen (UC-DO-02)
status: done

`dokument_neue_version (POST)`:
```python
def dokument_neue_version(request, ausschreibung_id, pk):
    altes_dokument = get_object_or_404(Dokument, pk=pk, ausschreibung_id=ausschreibung_id)
    form = DokumentVersionForm(request.POST, request.FILES)
    if form.is_valid():
        neues_dok = form.save(commit=False)
        neues_dok.ausschreibung = altes_dokument.ausschreibung
        neues_dok.los = altes_dokument.los
        neues_dok.kategorie = altes_dokument.kategorie
        neues_dok.verantwortlicher = altes_dokument.verantwortlicher
        neues_dok.save()
        altes_dokument.status = 'ersetzt'
        altes_dokument.save(update_fields=['status'])
        return redirect('dokumente:detail', ausschreibung_id=ausschreibung_id, pk=neues_dok.pk)
    return render(request, 'dokumente/neue_version.html', {'form': form, 'dokument': altes_dokument})

DokumentVersionForm: Nur datei + version (vorausgefüllt mit inkrementierter Versionsnummer). Logik naechste_version(alte_version_str): "1.0" → "2.0", "2.3" → "3.0" (Major-Inkrement für neue Versionen).


```task
id: WP-0007-T04
title: Dokumentstatus-Workflow und finale Abgabeversion (UC-DO-03, UC-DO-04)
status: done

**Status-Workflow** — HTMX-Widget analog zum Aufgaben-Status.
Statusübergänge: hochgeladen → zu_pruefen → in_bearbeitung → geprueft → freigegeben → final_abgegeben.

`dokument_status (POST)`:
Bei Übergang auf 'final_abgegeben': Setze automatisch `finale_abgabeversion=True`.
Bei Übergang auf 'final_abgegeben': Sperre weitere Status-Änderungen
(Widget rendert dann nur readonly Status-Badge ohne Dropdown).

**Finale Abgabeversion kennzeichnen** (UC-DO-04):
Zusätzlicher Button "Als finale Abgabeversion kennzeichnen" (außerhalb des normalen Workflows):
`dokument_finale_version (POST)`:
```python
def dokument_finale_version(request, ausschreibung_id, pk):
    dok = get_object_or_404(Dokument, pk=pk)
    dok.finale_abgabeversion = True
    dok.status = 'final_abgegeben'
    dok.save(update_fields=['finale_abgabeversion', 'status'])
    return render(request, 'dokumente/partials/finaler_status_badge.html', {'dokument': dok})

Nach Kennzeichnung erscheint grüner "Final" Badge; weitere Uploads zu dieser Version gesperrt.


```task
id: WP-0007-T05
title: Standarddokument aus Bibliothek zuordnen (UC-DO-05)
status: done

`dokument_bibliothek_zuordnen`:
HTMX-Modal mit Suchfeld. Suche in `bibliothek.Nachweis` und Bibliothek-Dokumente.
Jeder Treffer zeigt: Titel, Kategorie, Version, Ablaufdatum, Freigabestatus.

Zuordnung erstellt **keinen** neuen Upload, sondern einen Dokument-Datensatz mit:
- `datei` = leer (null)
- `quelle` = "Bibliothek: <Nachweis-Titel>"
- `dateiname` = Nachweis-Titel
- Referenz auf Nachweis via FK (`bibliothek_nachweis` FK(Nachweis, null=True, SET_NULL) — ergänze Feld im Dokument-Modell + Migration)

Ablaufende/abgelaufene Nachweise: Zeige Warnung in orange/rot.
id: WP-0007-T06
title: Dokument-URL-Verkabelung und Tests
status: done

`dokumente/urls.py`:
```python
app_name = 'dokumente'
urlpatterns = [
    path('', views.dokumente_liste, name='liste'),
    path('hochladen/', views.dokument_upload, name='upload'),
    path('<int:pk>/', views.dokument_detail, name='detail'),
    path('<int:pk>/version/', views.dokument_neue_version, name='neue_version'),
    path('<int:pk>/status/', views.dokument_status, name='status'),
    path('<int:pk>/final/', views.dokument_finale_version, name='finale_version'),
    path('<int:pk>/bibliothek/', views.dokument_bibliothek_zuordnen, name='bibliothek_zuordnen'),
]

Tests:

  • Test: Upload mit gültigem PDF → Dokument in DB, Datei im Dateisystem
  • Test: Upload mit ungültiger Dateierweiterung → ValidationError
  • Test: Upload zu groß → ValidationError
  • Test: Neue Version hochladen → altes Dokument hat status='ersetzt'
  • Test: Finale Abgabeversion → finale_abgabeversion=True, Status gesperrt