Plugin archiv: 12-Monats-Autopilot mit Sicherungsdatei-Prinzip
- Eigene Migration 0001_archiv_tabellen: Spiegel-Tabellen archiv_neuheiten und archiv_planung (ohne FK, damit Archiv-Zeilen Benutzerlöschung überleben) - Service mit eingefrierbarer Uhr: Stichtag „jetzt minus 12 Monate“ in UTC, strenger Vergleich (genau 12 Monate bleibt aktiv); Neuheiten nach Erscheinungsjahr (großzügig Jahresende) sonst Eintragsdatum, Planung nach Eintragsdatum; Monatsarithmetik mit Klemmung (29. Februar) - Täglicher APScheduler-Cron-Job (Standard 03:00, konfigurierbar über SPIELE_ARCHIV_JOB_UHRZEIT / SPIELE_ARCHIV_JOB_AKTIV); je archiviertem Titel ein Audit-Log-Eintrag als System - Admin-Ansicht /archiv: vereinigte Liste beider Tabellen, Suche über Titel/Verlag/Autor, Herkunftsfilter, Wiederherstellen in die aktive Liste (BGG-Konflikt wird abgelehnt, verwaiste Rezensentenzuordnung übernimmt der Admin — gemeldet und auditiert); Rollen: nur Admin - Kern minimal erweitert: PluginContext.registry stellt Hintergrund-Jobs die Plugin-Registry bereit (keine Fachlogik im Kern) - 30 neue Tests mit eingefrorener Uhr (Grenzfälle, Zeitzonen, Schaltjahr, Job-Lauf, Wiederherstellen, Rollen, Suche/Filter); 171 Tests grün - README aktualisiert: neues Plugin-Kapitel, Env-Variablen, Fortschritt #7 ✅
This commit is contained in:
80
README.md
80
README.md
@@ -4,7 +4,7 @@
|
||||
modularer Plugin-Architektur. Lauffähiger Kern mit Plugin-System,
|
||||
Authentifizierung/Rollen und Migrationen; vollständig implementiert sind
|
||||
bisher **Audit-Log**, **Benachrichtigung**, **Neuheiten (BGG-Sync)**,
|
||||
**Dedup-Prüfung** und **Planungsliste**.
|
||||
**Dedup-Prüfung**, **Planungsliste** und **Archiv (12-Monats-Autopilot)**.
|
||||
|
||||
## Stack
|
||||
|
||||
@@ -54,6 +54,8 @@ Beim ersten Start wird automatisch ein Admin-Konto angelegt:
|
||||
| `SPIELE_BGG_SUCHBEGRIFFE` | `brettspiel` | Komma-getrennte Suchbegriffe für den regelmäßigen Sync |
|
||||
| `SPIELE_BGG_MAX_TREFFER_PRO_SUCHE` | `25` | Obergrenze Treffer je Suchbegriff (schont das BGG-Rate-Limit) |
|
||||
| `SPIELE_DEDUP_BGG_AKTIV` | `1` | BGG-Zusatzdaten für die Dedup-Prüfung an (`1`) oder aus (`0`): Alternate-Names und Erweiterungs-Relationen |
|
||||
| `SPIELE_ARCHIV_JOB_AKTIV` | `1` | Täglicher Archivierungs-Job an (`1`) oder aus (`0`) |
|
||||
| `SPIELE_ARCHIV_JOB_UHRZEIT` | `03:00` | Tageszeit des täglichen Archiv-Laufs im Format `HH:MM` |
|
||||
|
||||
|
||||
## Tests
|
||||
@@ -75,6 +77,11 @@ Fake-BGG-Client, Prüfprotokoll, Prüfseite) und **planung** (beide Eintragswege
|
||||
mit Stub-gemockter dedup-/Benachrichtigungs-/Audit-API, Verlags-Auswahl-
|
||||
Dialog, Statuswechsel, Bearbeiten/Löschen, Rechte pro Rolle) plus ein
|
||||
Integrationstest mit den echten Plugins (In-App-Nachricht + Audit-Eintrag).
|
||||
Dazu das **archiv**-Plugin: 12-Monats-Regel mit eingefrorener Uhr (Grenzfälle
|
||||
„genau 12 Monate“, Schaltjahr/29. Februar, UTC-Konsistenz bei
|
||||
Zeitzonen-Unterschieden), Job-Lauf mit Audit-Einträgen, Wiederherstellen
|
||||
inkl. BGG-Konflikt und Ersatz-Rezensent, Rollen sowie Suche/Filter in der
|
||||
Admin-Ansicht.
|
||||
|
||||
## Architektur
|
||||
|
||||
@@ -94,7 +101,8 @@ plugins/ ein Ordner pro Funktion, ladbar über den Plugin-Load
|
||||
├── benachrichtigung/ VOLL IMPLEMENTIERT: E-Mail/Telegram/In-App
|
||||
├── dedup/ VOLL IMPLEMENTIERT: check_titel-API, Heuristik, Protokoll
|
||||
├── planung/ VOLL IMPLEMENTIERT: Planungsliste, Verschiebung, Dialoge
|
||||
├── archiv/ erinnerung/ export/ (Stubs, ladbar)
|
||||
├── archiv/ VOLL IMPLEMENTIERT: 12-Monats-Autopilot, Job, UI
|
||||
├── erinnerung/ export/ (Stubs, ladbar)
|
||||
└── … je __init__.py + templates/<name>/
|
||||
```
|
||||
|
||||
@@ -122,7 +130,9 @@ class MeinPlugin(BasePlugin):
|
||||
return [NavEntry(label=self.title, url="/meinplugin")]
|
||||
|
||||
def on_load(self, context): # Lifecycle-Hook beim Start
|
||||
super().on_load(context) # context.engine/.session_factory/.templates/.settings
|
||||
super().on_load(context) # context.engine/.session_factory/.templates/
|
||||
# .settings/.registry (Plugin-Registry für
|
||||
# Hintergrund-Jobs ohne Request)
|
||||
|
||||
def on_unload(self): # Lifecycle-Hook beim Herunterfahren
|
||||
super().on_unload()
|
||||
@@ -363,6 +373,64 @@ Rezensenten können **nur ihre eigenen Einträge** bearbeiten (Statuswechsel,
|
||||
Bearbeiten, Löschen); Admins und Redakteure alle. Jede Änderung wird im
|
||||
Audit-Log protokolliert (`erstellt`/`verschoben`/`geaendert`/`geloescht`).
|
||||
|
||||
## Plugin „archiv“ (implementiert)
|
||||
|
||||
Automatische Archivierung nach dem **Sicherungsdatei-Prinzip**: Titel, deren
|
||||
Erscheinungs- bzw. Eintragsdatum länger als 12 Monate zurückliegt, werden
|
||||
vollständig in eigene Archiv-Tabellen verschoben und aus den aktiven Listen
|
||||
entfernt. Nichts wird gelöscht oder verändert — jeder Eintrag lässt sich
|
||||
unverändert zurück in die aktive Liste verschieben.
|
||||
|
||||
### Datentabellen
|
||||
|
||||
Eigene Migration `0001_archiv_tabellen` mit zwei Spiegel-Tabellen
|
||||
(SQLite ↔ Postgres portabel, ohne Fremdschlüssel — archivierte Zeilen
|
||||
überleben auch das Löschen eines Benutzers):
|
||||
|
||||
| Tabelle | Spiegel von | Besondere Spalten |
|
||||
|---------|-------------|-------------------|
|
||||
| `archiv_neuheiten` | `neuheiten` | alle Originalspalten plus `quell_id`, `archiviert_am`, `archiviert_von`, `grund`, `referenz_am` |
|
||||
| `archiv_planung` | `planungsliste` | alle Originalspalten (inkl. `pruefung`-JSON) plus dieselben Archiv-Metadaten |
|
||||
|
||||
### Die 12-Monats-Regel
|
||||
|
||||
- **Stichtag:** „jetzt − 12 Monate“ in UTC; archiviert wird, wer *streng
|
||||
älter* ist — genau 12 Monate gilt noch nicht als „älter als“.
|
||||
- **Referenzdatum:**
|
||||
- Neuheiten: das Erscheinungsdatum. BGG liefert nur das Jahr, daher
|
||||
großzügig das Jahresende (31.12., 23:59:59) — ein Titel von 2023 wird
|
||||
erst ab dem 01.01.2025 archiviert. Ohne Jahr zählt das Eintragsdatum.
|
||||
- Planungseinträge: das Eintragsdatum, unabhängig vom Status.
|
||||
- **Zeitzonen:** verglichen wird durchgängig in UTC; naive Datenbank-
|
||||
Zeitstempel gelten als UTC, zeitzonenbewusste Uhrzeiten werden nach UTC
|
||||
verschoben (per Tests mit eingefrorener Uhr abgedeckt, inkl. 29. Februar).
|
||||
|
||||
### Täglicher Hintergrund-Job
|
||||
|
||||
Beim Start registriert das Plugin einen APScheduler-Cron-Job (Standard
|
||||
täglich **03:00**, konfigurierbar über `SPIELE_ARCHIV_JOB_UHRZEIT`,
|
||||
abschaltbar über `SPIELE_ARCHIV_JOB_AKTIV=0`). Pro archiviertem Titel
|
||||
schreibt der Job einen **Audit-Log-Eintrag** mit dem Akteur „System“
|
||||
(Aktion `verschoben`, Grund und Referenzdatum in den Details). Der
|
||||
Registry-Zugriff aus dem Hintergrund-Job läuft über den neuen
|
||||
`context.registry`-Hook des Plugin-Kontexts.
|
||||
|
||||
### Admin-Ansicht mit Wiederherstellen
|
||||
|
||||
Unter **Archiv** (`/archiv`, nur Rolle **Admin**) werden beide Tabellen als
|
||||
vereinigte Liste angezeigt (neueste Archivierung zuerst):
|
||||
|
||||
- Suche über Titel/Verlag/Autor und Filter nach Herkunft (Neuheiten/Planung).
|
||||
- Pro Eintrag: Herkunfts-Badge, Status, Rezensent, Archivierungszeitpunkt
|
||||
und der Grund (z. B. „älter als 12 Monate (Erscheinungsjahr 2023)“).
|
||||
- **Wiederherstellen** verschiebt den Eintrag vollständig zurück in die
|
||||
aktive Liste und protokolliert dies im Audit-Log (Akteur: der Admin).
|
||||
Konfliktfälle werden sicher abgelehnt: existiert in der Neuheitenliste
|
||||
bereits ein aktiver Eintrag mit derselben BGG-ID (erneuter Sync), wird
|
||||
nicht wiederhergestellt; existiert der zugeordnete Rezensent nicht mehr,
|
||||
übernimmt der wiederherstellende Admin die Zuordnung (gemeldet und
|
||||
auditiert). Rezensenten und Redakteure erhalten 403.
|
||||
|
||||
## Deployment (später)
|
||||
|
||||
Docker/Podman Compose ist vorgesehen (Henry-Lab, danach Kundenhardware).
|
||||
@@ -379,9 +447,9 @@ geschrieben.
|
||||
| 2 | Plugin `benachrichtigung` (E-Mail/Telegram/In-App, User-Präferenzen) | ✅ fertig |
|
||||
| 3 | Plugin `audit-log` (Wer/Was/Wann, Admin-Ansicht, öffentliche API) | ✅ fertig |
|
||||
| 4 | Plugin `neuheiten` (BGG-Sync, APScheduler, Filter) | ✅ fertig |
|
||||
| 5 | Plugin `dedup` (Verlags-Konflikt, deutsche Version, Vorgänger-/Planungs-Check) | ✅ fertig (141 Tests grün) |
|
||||
| 6 | Plugin `planung` (Verschiebung, händischer Eintrag + Prüfungen + Benachrichtigung) | ✅ fertig (141 Tests grün) |
|
||||
| 7 | Plugin `archiv` (12-Monats-Autopilot) | ⏳ offen |
|
||||
| 5 | Plugin `dedup` (Verlags-Konflikt, deutsche Version, Vorgänger-/Planungs-Check) | ✅ fertig |
|
||||
| 6 | Plugin `planung` (Verschiebung, händischer Eintrag + Prüfungen + Benachrichtigung) | ✅ fertig |
|
||||
| 7 | Plugin `archiv` (12-Monats-Autopilot, Wiederherstellen, täglicher Job) | ✅ fertig (171 Tests grün) |
|
||||
| 8 | Plugin `erinnerung` (Redaktionsschluss pro Ausgabe, 4-Wochen-Erinnerung) | ⏳ offen |
|
||||
| 9 | Plugin `export` (CSV + PDF via WeasyPrint) | ⏳ offen |
|
||||
| 10 | Integrationstests über alle Plugins | ⏳ offen |
|
||||
|
||||
Reference in New Issue
Block a user