Complete dashboard loose ends and reconcile blocked pilot work
All checks were successful
All checks were successful
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a0e394-2a69-7df0-8980-22a0ebe55216
This commit is contained in:
parent
387b7e9782
commit
35df9bb772
13 changed files with 325 additions and 55 deletions
|
|
@ -5,6 +5,7 @@ title: Dashboard und Ausschreibungen-CRUD
|
|||
status: finished
|
||||
phase: 4-of-12
|
||||
created: "2026-05-08"
|
||||
updated: "2026-09-27"
|
||||
depends_on: WP-0003
|
||||
domain: communication
|
||||
repo: vergabe-teilnahme
|
||||
|
|
@ -21,10 +22,13 @@ Entscheidungsregel-Auswertung, Archivierung und historische Erfassung.
|
|||
|
||||
---
|
||||
|
||||
## Dashboard-View mit Kacheln und Fristenliste
|
||||
|
||||
```task
|
||||
id: VT-WP-0004-T01
|
||||
title: Dashboard-View mit Kacheln und Fristenliste
|
||||
status: todo
|
||||
status: done
|
||||
priority: medium
|
||||
```
|
||||
|
||||
`ausschreibungen/views.py` — Dashboard-View:
|
||||
```python
|
||||
|
|
@ -67,12 +71,14 @@ Jede Kachel: Überschrift, Anzahl-Badge, Liste der Einträge mit Direktlinks.
|
|||
Nutze `.card`-Klasse, `status_badge`-Tag und relative Fristangaben (z. B. "in 3 Tagen").
|
||||
|
||||
Ablaufende Nachweise: Nachweis-Modell aus Bibliothek mit `gueltig_bis ≤ heute + 60 Tage`.
|
||||
```
|
||||
|
||||
## Ausschreibungsliste mit Filter und HTMX-Suche
|
||||
|
||||
```task
|
||||
id: VT-WP-0004-T02
|
||||
title: Ausschreibungsliste mit Filter und HTMX-Suche
|
||||
status: todo
|
||||
status: done
|
||||
priority: medium
|
||||
```
|
||||
|
||||
`ausschreibungen/views.py` — ListView:
|
||||
```python
|
||||
|
|
@ -107,12 +113,14 @@ Alle Filter-Änderungen: `hx-get="/ausschreibungen/" hx-target="#ausschreibungen
|
|||
|
||||
Tabelle: Titel, Ausschreiber, Status (status_badge), Abgabefrist (farbig wenn < 14 Tage),
|
||||
Verantwortlicher, Link zum Detail.
|
||||
```
|
||||
|
||||
## Ausschreibung anlegen — Form und View (UC-AS-01)
|
||||
|
||||
```task
|
||||
id: VT-WP-0004-T03
|
||||
title: Ausschreibung anlegen — Form und View (UC-AS-01)
|
||||
status: todo
|
||||
status: done
|
||||
priority: medium
|
||||
```
|
||||
|
||||
`ausschreibungen/forms.py`:
|
||||
```python
|
||||
|
|
@ -158,12 +166,14 @@ def ausschreibung_neu(request):
|
|||
`ausschreibungen/form.html` — einfaches, gut gelayoutetes Formular.
|
||||
Sections: Stammdaten, Fristen. Alle Felder nutzen `form-input` und `form-label`.
|
||||
Submit: "Speichern" (btn-primary), "Abbrechen" (btn-ghost, zurück zur Liste).
|
||||
```
|
||||
|
||||
## Ausschreibung-Detailseite (Phase 1 — Stammdaten)
|
||||
|
||||
```task
|
||||
id: VT-WP-0004-T04
|
||||
title: Ausschreibung-Detailseite (Phase 1 — Stammdaten)
|
||||
status: todo
|
||||
status: done
|
||||
priority: medium
|
||||
```
|
||||
|
||||
`ausschreibungen/views.py` — Detailview:
|
||||
```python
|
||||
|
|
@ -192,12 +202,14 @@ def ausschreibung_detail(request, pk):
|
|||
- Tab-Navigation zu Unterseiten (Lose, Anforderungen, Aufgaben, Bieterfragen, Preise, Abgabe, Nachbetrachtung)
|
||||
als horizontale Link-Leiste unterhalb des Titels
|
||||
- "Weitere Attribute" CustomAttribute-Panel (HTMX lazy-load, Implementierung in WP-0012)
|
||||
```
|
||||
|
||||
## Ausschreibung bearbeiten (Edit-View) und Status inline wechseln
|
||||
|
||||
```task
|
||||
id: VT-WP-0004-T05
|
||||
title: Ausschreibung bearbeiten (Edit-View) und Status inline wechseln
|
||||
status: todo
|
||||
status: done
|
||||
priority: medium
|
||||
```
|
||||
|
||||
`ausschreibungen/views.py`:
|
||||
|
||||
|
|
@ -236,12 +248,14 @@ def ausschreibung_status(request, pk):
|
|||
</select>
|
||||
</div>
|
||||
```
|
||||
```
|
||||
|
||||
## Teilnahmeentscheidung-Seite (Phase 2, UC-AS-04)
|
||||
|
||||
```task
|
||||
id: VT-WP-0004-T06
|
||||
title: Teilnahmeentscheidung-Seite (Phase 2, UC-AS-04)
|
||||
status: todo
|
||||
status: done
|
||||
priority: medium
|
||||
```
|
||||
|
||||
`ausschreibungen/views.py` — Teilnahmeentscheidungs-View:
|
||||
```python
|
||||
|
|
@ -272,12 +286,14 @@ def ausschreibung_entscheidung(request, pk):
|
|||
- Zeigt Regelergebnis aus dem Katalog als strukturierte Liste
|
||||
- Formular: Radio-Buttons für Teilnahme/Nichtteilnahme/Weitere Prüfung, Begründungsfeld
|
||||
- "Freigabe erteilen"-Button (öffnet Freigabe-Modal, Implementierung in WP-0012)
|
||||
```
|
||||
|
||||
## Entscheidungsregel-Auswertungs-Service
|
||||
|
||||
```task
|
||||
id: VT-WP-0004-T07
|
||||
title: Entscheidungsregel-Auswertungs-Service
|
||||
status: todo
|
||||
status: done
|
||||
priority: medium
|
||||
```
|
||||
|
||||
`vergabe_teilnahme/apps/ausschreibungen/services.py`:
|
||||
|
||||
|
|
@ -321,12 +337,14 @@ def _wende_regel_an(regel, ausschreibung):
|
|||
'begruendung': f'Restlaufzeit {delta} Tage unter Schwellenwert.'}
|
||||
return {'empfehlung': 'pruefen', 'begruendung': regel.begruendung or '—'}
|
||||
```
|
||||
```
|
||||
|
||||
## Ausschreibung archivieren und historisch erfassen (UC-AS-06, UC-AS-07)
|
||||
|
||||
```task
|
||||
id: VT-WP-0004-T08
|
||||
title: Ausschreibung archivieren und historisch erfassen (UC-AS-06, UC-AS-07)
|
||||
status: todo
|
||||
status: done
|
||||
priority: medium
|
||||
```
|
||||
|
||||
**Archivieren:**
|
||||
```python
|
||||
|
|
@ -351,12 +369,14 @@ zugänglich — keine Einschränkung.
|
|||
|
||||
URL für historische Erfassung: `/ausschreibungen/neu/?historisch=1`
|
||||
Die View prüft diesen Parameter und setzt `historisch_erfassen` im initialen Form-Context.
|
||||
```
|
||||
|
||||
## Globale Suchleiste — HTMX-Endpunkt und Ergebnis-Template
|
||||
|
||||
```task
|
||||
id: VT-WP-0004-T09
|
||||
title: Globale Suchleiste — HTMX-Endpunkt und Ergebnis-Template
|
||||
status: todo
|
||||
status: done
|
||||
priority: medium
|
||||
```
|
||||
|
||||
`core/views.py`:
|
||||
```python
|
||||
|
|
@ -397,12 +417,14 @@ def global_search(request):
|
|||
|
||||
URL: `path('suche/', core_views.global_search, name='global_search')`
|
||||
Topbar-Formular (aus WP-0003-T02) zeigt Ergebnisse in `#search-results`.
|
||||
```
|
||||
|
||||
## Ausschreibungen-URL-Verkabelung und App-Namespace
|
||||
|
||||
```task
|
||||
id: VT-WP-0004-T10
|
||||
title: Ausschreibungen-URL-Verkabelung und App-Namespace
|
||||
status: todo
|
||||
status: done
|
||||
priority: medium
|
||||
```
|
||||
|
||||
`vergabe_teilnahme/apps/ausschreibungen/urls.py`:
|
||||
```python
|
||||
|
|
@ -436,12 +458,14 @@ Jede referenzierte App-URL-Datei wird hier als leere Stub-Datei angelegt
|
|||
|
||||
Prüfe: `uv run manage.py check --deploy` → keine URL-Fehler.
|
||||
Smoke-Test: alle Hauptseiten (/ausschreibungen/, /ausschreibungen/neu/) laden ohne 500.
|
||||
```
|
||||
|
||||
## Ausschreibungs-Tests (Models und Views)
|
||||
|
||||
```task
|
||||
id: VT-WP-0004-T11
|
||||
title: Ausschreibungs-Tests (Models und Views)
|
||||
status: todo
|
||||
status: done
|
||||
priority: medium
|
||||
```
|
||||
|
||||
Erstelle `vergabe_teilnahme/apps/ausschreibungen/tests/`:
|
||||
|
||||
|
|
@ -468,12 +492,14 @@ class AusschreibungFactory(factory.django.DjangoModelFactory):
|
|||
ausschreiber = "Testausschreiber GmbH"
|
||||
status = 1
|
||||
```
|
||||
```
|
||||
|
||||
## Seed-Daten prüfen und Dashboard-Kacheln verifizieren
|
||||
|
||||
```task
|
||||
id: VT-WP-0004-T12
|
||||
title: Seed-Daten prüfen und Dashboard-Kacheln verifizieren
|
||||
status: todo
|
||||
status: done
|
||||
priority: medium
|
||||
```
|
||||
|
||||
Führe die gesamte Integrations-Smoke-Test-Sequenz durch:
|
||||
|
||||
|
|
@ -493,4 +519,37 @@ Führe die gesamte Integrations-Smoke-Test-Sequenz durch:
|
|||
10. `uv run pytest vergabe_teilnahme/apps/ausschreibungen/` → alle Tests grün
|
||||
|
||||
Erst wenn alle 10 Punkte erfüllt sind: Task als done markieren.
|
||||
```
|
||||
|
||||
## Completion review — 2026-09-27
|
||||
|
||||
The finished plan retained twelve stale todo blocks with nested Markdown fences.
|
||||
Reconciled the existing task IDs into one valid task block per section; no new
|
||||
tasks were created. T03–T07 and T10–T11 already had application implementations
|
||||
and model/view acceptance. T01 now includes the missing 60-day evidence-expiry
|
||||
card (including expired evidence). T02 now searches title and issuing authority
|
||||
alongside status/manager/archive filters with HTMX. T08 now validates and saves
|
||||
a historical result atomically in the existing Nachbetrachtung model and sets
|
||||
the corresponding terminal tender status. T09 now includes issuing authority,
|
||||
tasks and partners alongside the already implemented search categories.
|
||||
|
||||
The old illustrative fields are superseded by the current model: bid_manager
|
||||
replaces hauptverantwortung, and ergebnis belongs to Nachbetrachtung. Historical
|
||||
entry uses those models without a schema change. Existing approval, decision,
|
||||
archive, detail and URL implementations remain in place.
|
||||
|
||||
Validation: all 131 application tests pass on disposable SQLite; all 20 tender
|
||||
model/view tests also pass on disposable PostgreSQL 16. Vite build, Django system
|
||||
check and migration-drift check pass. Changed Python passes Ruff excluding the
|
||||
pre-existing E501 long lines. Local tests retain the pre-existing naive-datetime
|
||||
fixture and uncollected-static-directory warnings. T12 uses freshly migrated/seeded disposable PostgreSQL and local
|
||||
Chromium for dashboard/navigation, tender list/detail, HTMX search/status and
|
||||
historical creation. This is local source acceptance, not pilot-user evidence.
|
||||
|
||||
|
||||
The final T12 server-log review exposed a missing CSRF header on inline status
|
||||
POSTs. T05 now inherits the rendered Django CSRF token through base.html's
|
||||
HTMX headers. A CSRF-enforcing regression proves missing-token rejection and
|
||||
valid-token mutation. The Chromium check now changes to a different status,
|
||||
requires HTTP 200 for the POST, and checks persistence after reload; an unchanged
|
||||
seeded value is not accepted as proof. This supersedes the initial browser
|
||||
script's false-positive status assertion.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue