From f728388286f29f63918a30673b26ed21964ea961 Mon Sep 17 00:00:00 2001 From: Dotty Dotter Date: Fri, 10 Apr 2026 21:10:33 +0200 Subject: [PATCH] #97 Neu bewerten: manueller Re-Analyse-Button + Bewertungsdatum MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fußzeile unter jedem Assessment-Detail jetzt mit: - Bewertungsdatum ("Bewertet am DD.MM.YYYY") aus updated_at - Quelle + Modell (batch-reanalyze / webapp, qwen-plus) - "Neu bewerten"-Button (Auth-pflichtig, ausgegraut ohne Login) Flow: Klick → DELETE /api/assessment/delete → POST /api/analyze-drucksache → Queue → pollAnalysis → Detail neu laden Neuer DELETE-Endpoint /api/assessment/delete mit require_auth. API-Response erweitert um updatedAt, source, model für beide Endpoints (list + single assessment). Tests: 206 passed. Refs: #97 --- app/main.py | 20 ++++++++++++++++++++ app/templates/index.html | 41 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/app/main.py b/app/main.py index c9ce1e9..a7abcd9 100644 --- a/app/main.py +++ b/app/main.py @@ -335,6 +335,9 @@ async def list_assessments(bundesland: Optional[str] = None): "themen": row.get("themen", []), "antragZusammenfassung": row.get("antrag_zusammenfassung"), "antragKernpunkte": row.get("antrag_kernpunkte", []), + "updatedAt": row.get("updated_at"), + "source": row.get("source"), + "model": row.get("model"), }) return assessments @@ -370,9 +373,26 @@ async def get_single_assessment(drucksache: str): "themen": row.get("themen", []), "antragZusammenfassung": row.get("antrag_zusammenfassung"), "antragKernpunkte": row.get("antrag_kernpunkte", []), + "updatedAt": row.get("updated_at"), + "source": row.get("source"), + "model": row.get("model"), } +# API: Delete assessment for re-analysis (#97) +@app.delete("/api/assessment/delete") +async def delete_assessment_endpoint( + drucksache: str, + user: dict = Depends(require_auth), +): + """Löscht ein Assessment, damit es neu analysiert werden kann.""" + drucksache = validate_drucksache(drucksache) + deleted = await delete_assessment(drucksache) + if not deleted: + raise HTTPException(status_code=404, detail="Assessment nicht gefunden") + return {"status": "deleted", "drucksache": drucksache} + + # API: Generate PDF on demand for an assessment @app.get("/api/assessment/pdf") async def download_assessment_pdf(drucksache: str): diff --git a/app/templates/index.html b/app/templates/index.html index 0497239..5e429b4 100644 --- a/app/templates/index.html +++ b/app/templates/index.html @@ -1240,6 +1240,31 @@ } } + async function reAnalyze(drucksache, bundesland, btn) { + btn.disabled = true; + btn.textContent = '⏳ Wird neu bewertet...'; + try { + // Altes Assessment löschen + await fetch(`/api/assessment/delete?drucksache=${encodeURIComponent(drucksache)}`, {method: 'DELETE'}); + // Neue Analyse enqueuen + const resp = await fetch('/api/analyze-drucksache', { + method: 'POST', + headers: {'Content-Type': 'application/x-www-form-urlencoded'}, + body: `drucksache=${encodeURIComponent(drucksache)}&bundesland=${encodeURIComponent(bundesland)}` + }); + const data = await resp.json(); + if (data.status === 'queued') { + pollAnalysis(data.job_id, drucksache, btn); + } else { + btn.textContent = '❌ Fehler'; + setTimeout(() => { btn.textContent = '🔄 Neu bewerten'; btn.disabled = false; }, 3000); + } + } catch (e) { + btn.textContent = '❌ Fehler'; + setTimeout(() => { btn.textContent = '🔄 Neu bewerten'; btn.disabled = false; }, 3000); + } + } + async function pollAnalysis(jobId, drucksache, btn) { try { const resp = await fetch(`/status/${jobId}`); @@ -1673,8 +1698,20 @@ ${item.empfehlungSymbol || ''} ${item.empfehlung || '-'} - 📄 Original-PDF öffnen - 📥 GWÖ-Report als PDF +
+ 📄 Original-PDF + 📥 GWÖ-Report + +
+
+ Bewertet am ${item.updatedAt ? new Date(item.updatedAt).toLocaleDateString('de-DE') : '–'} + ${item.source ? ` · Quelle: ${item.source}` : ''} + ${item.model ? ` · Modell: ${item.model}` : ''} +
`;