diff --git a/.gitignore b/.gitignore index eedaf19..3bbba3e 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ __pycache__/ /telefon/ansage.wav /telefon/verlauf.log /telefon/*.log +/telefon/verlauf-archiv/ # Laufzeit-Zustand (aktive Modell-Auswahl aus dem Leitstand-Dropdown), kein Quellcode /telefon/modell.json # Trainingsdaten-Export (pipe.export) - enthaelt volle Transkripte/Namen diff --git a/pipe/protokoll.py b/pipe/protokoll.py index 2edfd1c..e04ddfe 100644 --- a/pipe/protokoll.py +++ b/pipe/protokoll.py @@ -11,12 +11,15 @@ jedes Ereignis zusaetzlich unveraenderlich nach audit.log, siehe pipe.audit. from __future__ import annotations import json +import shutil from datetime import datetime +from pathlib import Path from . import audit, config DATEI = config.TELEFON / "verlauf.log" MAX_ZEILEN = 2000 # darüber wird beim Schreiben gekürzt +ARCHIV_ORDNER = config.TELEFON / "verlauf-archiv" def schreibe(art: str, text: str, **felder) -> None: @@ -59,3 +62,20 @@ def kuerze() -> None: DATEI.write_text("\n".join(zeilen[-MAX_ZEILEN:]) + "\n", encoding="utf-8") except Exception: pass + + +def archiviere_und_leere() -> Path | None: + """Sichert den aktuellen Verlauf als Kopie und leert ihn danach - fuer + einen frischen Verlauf nach "Tag archivieren". Das dauerhafte audit.log + ist davon unberuehrt (behaelt ohnehin alles). Wirft nie. Gibt den Pfad + der Archivkopie zurueck, oder None wenn nichts zu sichern war.""" + try: + if not DATEI.is_file() or not DATEI.stat().st_size: + return None + ARCHIV_ORDNER.mkdir(parents=True, exist_ok=True) + ziel = ARCHIV_ORDNER / f"verlauf_{datetime.now():%Y%m%d-%H%M%S}.log" + shutil.copy2(DATEI, ziel) + DATEI.write_text("", encoding="utf-8") + return ziel + except Exception: + return None diff --git a/pipe/server.py b/pipe/server.py index e0cb440..c971c01 100644 --- a/pipe/server.py +++ b/pipe/server.py @@ -298,7 +298,13 @@ class Handler(BaseHTTPRequestHandler): _, export_anzahl = export.exportiere() if export_anzahl: protokoll.schreibe("export", f"{export_anzahl} bewertete Anrufe exportiert") - self._json({"ok": True, "anzahl": anzahl, "simuliert": True, "export_anzahl": export_anzahl}) + # Verlauf-Log sichern + leeren, fuer eine frische Ansicht ab jetzt. + # audit.log (dauerhaft, unveraenderlich) ist davon nicht betroffen. + log_archiv = protokoll.archiviere_und_leere() + if log_archiv: + protokoll.schreibe("system", f"Verlauf archiviert nach {log_archiv.name} und geleert") + self._json({"ok": True, "anzahl": anzahl, "simuliert": True, "export_anzahl": export_anzahl, + "log_archiviert": log_archiv.name if log_archiv else None}) return if pfad == "/api/export": ziel, anzahl = export.exportiere() @@ -546,7 +552,7 @@ color:var(--gut);border-radius:999px;padding:1px 8px;font-size:11px;font-weight:

Logpy:AgentOne — Anruf-Leitstand

- + @@ -863,6 +869,7 @@ document.getElementById('archivBtn').onclick=async()=>{ if(d&&d.ok){ let text=`✓ ${d.anzahl} Anruf(e) archiviert (simuliert)`; if(d.export_anzahl)text+=` · ${d.export_anzahl} bewertete Anrufe exportiert`; + if(d.log_archiviert)text+=' · Verlauf gesichert & geleert'; toast(text);takt(); } else{toast('Archivieren fehlgeschlagen.')} };