feat(user): add certificate production tracking and update localization
All checks were successful
Deploy to production / deploy (push) Successful in 2m50s

- Introduced a new field `certificateProductionsCountSince` in the `FalukantUser` model to track the date from which production logs are counted for certificate requirements.
- Updated the `FalukantService` to utilize the new field for calculating completed productions since the specified date.
- Enhanced the UI to display the count of productions since the last promotion, with corresponding translations added for multiple languages including Cebuano, German, English, Spanish, and French.
- Implemented a method to delete old production logs, ensuring efficient data management while maintaining necessary historical records for certificate calculations.
This commit is contained in:
Torsten Schulz (local)
2026-04-09 08:19:19 +02:00
parent f7030bbabe
commit 360bb59a4e
18 changed files with 200 additions and 25 deletions

View File

@@ -0,0 +1,56 @@
# Falukant: Produktions-Log und Zertifikatszählung (Abgleich Daemon ↔ Backend/UI)
## Ziel
Die sichtbare Zertifikatsvorschau (Backend `buildCertificateProgress` / UI) soll dieselbe **abgeschlossene Produktionen**-Logik verwenden wie der Zertifikats-Daemon. Außerdem soll klar sein, wie Log-Zeilen aufbewahrt und bereinigt werden **ohne** breites Löschen nur zum Zurücksetzen der Zählung.
## Spalte `certificate_productions_count_since`
- Tabelle: `falukant_data.falukant_user`
- Typ: `TIMESTAMPTZ`, nullable
- **Semantik:** Nach einem **Zertifikatsaufstieg**, **Bankrott** oder **Erbfolge** (und gleichartigen Stufenänderungen im Daemon) wird der Zeitpunkt auf `NOW()` gesetzt. Alle Zählungen für Mindestanforderungen / Produktionspunkte berücksichtigen nur noch Log-Zeilen mit effektivem Zeitpunkt **≥** diesem Wert.
- **`NULL`:** Wie bisher die gesamte relevante Historie zählen (Bestand bis zur ersten Stufenänderung nach Einführung der Spalte).
Daemon-seitig typisch: `QUERY_UPDATE_FALUKANT_USER_CERTIFICATE` setzt bei jeder Stufenänderung `certificate_productions_count_since = NOW()`.
## Effektiver Zeitpunkt einer Log-Zeile
Überall, wo der Daemon und das Backend dieselbe Bedeutung brauchen:
```sql
COALESCE(pl.production_timestamp, pl.production_date::timestamp)
```
- `production_timestamp` fehlt oder ist unzuverlässig (z.B. ältere Upserts): Fallback auf Kalendertag `production_date`.
- So wird **nicht** nur „Produktionen für den laufenden Kalendertag“ gewertet, sondern konsistent der gespeicherte Zeitbezug der Zeile abgestimmt mit dem Daemon (`QUERY_GET_PRODUCTION_CERTIFICATE_INPUT_ROWS`).
Backend-Implementierung: `getCertificateCompletedProductionCount` in `backend/services/falukantService.js` filtert bei gesetztem `certificateProductionsCountSince` mit derselben `COALESCE`-Bedingung.
## Log-Retention (30 Tage)
`falukant_log.production` wird u.a. für Wissens-Updates, Preis-/Producer-Events und Zertifikatszählung genutzt. **Nicht** sinnvoll: alle Logs nach einem Aufstieg löschen, nur um neu zu zählen.
Stattdessen:
- Zähler-Reset über **`certificate_productions_count_since`** (siehe oben).
- Alte Zeilen werden mit **Retention 30 Tage** bereinigt, damit die Tabelle nicht unbegrenzt wächst.
In diesem Repo: **`UserCharacterWorker`** führt stündlich `QUERY_DELETE_OLD_PRODUCTIONS` aus:
```sql
DELETE FROM falukant_log.production
WHERE COALESCE(production_timestamp, production_date::timestamp) < NOW() - INTERVAL '30 days';
```
Parallel löscht derselbe Worker weiterhin einzelne Zeilen nach dem Wissens-Update (`QUERY_DELETE_LOG_ENTRY`), sobald die Zeile „vom Vortag“ verarbeitet wurde (`QUERY_UPDATE_GET_ITEMS_TO_UPDATE` mit `COALESCE` für das Datumsfenster).
## Migrationen
- **Sequelize (dieses Repo):** `backend/migrations/20260402140000-add-certificate-productions-count-since.cjs` fügt die Spalte und den DB-Kommentar hinzu.
- **Externer Daemon / SQL-Pfad:** falls vorhanden z.B. `migrations/014_falukant_certificate_productions_count_since.sql` inhaltlich dieselbe Spalte; nur eine Quelle der Wahrheit fürs Schema nötig.
Weitere Hinweise: `backend/migrations/README.md`.
## Verwandte Spezifikation
Ausführlicheres Fachkonzept (Stufen, Score, Events): [`FALUKANT_PRODUCTION_CERTIFICATE_SPEC.md`](./FALUKANT_PRODUCTION_CERTIFICATE_SPEC.md).

View File

@@ -16,9 +16,8 @@ Dieses Dokument beschreibt:
Wichtig:
- Die nötigen DB-Grundlagen sind bereits vorhanden.
- Der Daemon muss keine neuen Schemaänderungen erwarten.
- Bestehende Felder wie `falukant_data.falukant_user.certificate` und `falukant_type.product.category` bleiben die führende Basis.
- Zusätzlich zu `falukant_user.certificate` gibt es `falukant_user.certificate_productions_count_since` (Zeitpunkt, ab dem Produktions-Log-Zeilen für Zertifikats-Mindestanforderungen zählen; siehe [`FALUKANT_PRODUCTION_CERTIFICATE.md`](./FALUKANT_PRODUCTION_CERTIFICATE.md)).
- Bestehende Felder wie `falukant_data.falukant_user.certificate` und `falukant_type.product.category` bleiben die führende Basis für die Produktfreigabe.
## 2. Bestehende technische Basis
@@ -26,6 +25,8 @@ Bereits vorhanden:
- `falukant_data.falukant_user.certificate`
- aktuelle Produktionsfreigabe des Spielers
- `falukant_data.falukant_user.certificate_productions_count_since` (optional, empfohlen)
- ab diesem Zeitpunkt zählen Produktions-Log-Zeilen für Zertifikats-Mindestanforderungen (`NULL` = volle Historie); Details: [`FALUKANT_PRODUCTION_CERTIFICATE.md`](./FALUKANT_PRODUCTION_CERTIFICATE.md)
- `falukant_type.product.category`
- erforderliche Zertifikatsstufe des Produkts
- `falukant_data.knowledge`
@@ -109,7 +110,7 @@ Für jeden Spielercharakter mit `falukant_user`:
- `avgKnowledge`
- Durchschnitt aus `falukant_data.knowledge.knowledge` des Spielercharakters
- `completedProductions`
- Anzahl abgeschlossener Produktionen des Spielers
- Anzahl abgeschlossener Produktionen des Spielers (Daemon und Backend/UI: aus `falukant_log.production`, gruppiert nach Produkt und Kalendertag, gefiltert ab `certificate_productions_count_since` mit `COALESCE(production_timestamp, production_date::timestamp)`; siehe [`FALUKANT_PRODUCTION_CERTIFICATE.md`](./FALUKANT_PRODUCTION_CERTIFICATE.md))
- `highestPoliticalOfficeRank`
- höchster politischer Amtsrang
- `highestChurchOfficeRank`
@@ -317,11 +318,10 @@ Diese Aktionen verändern nur die Eingangsgrößen. Die eigentliche Zertifikatsa
## 5.2 Daemon-Hinweis
Für den Daemon gilt ausdrücklich:
Für den Daemon gilt:
- die relevanten DB-Felder sind bereits vorhanden
- es müssen für diese Funktion keine zusätzlichen Schemaänderungen mehr eingeplant werden
- der Daemon soll direkt mit den vorhandenen Tabellen arbeiten
- Zertifikatsstufe und Produktkategorien wie oben; für die Produktionszählung nach Stufenwechsel ist `certificate_productions_count_since` vorgesehen (Migration siehe Repo / [`FALUKANT_PRODUCTION_CERTIFICATE.md`](./FALUKANT_PRODUCTION_CERTIFICATE.md)).
- Der Daemon soll dieselbe `COALESCE(production_timestamp, production_date::timestamp)`-Logik wie Backend und UI verwenden, damit Daily-Prüfung und Oberfläche übereinstimmen.
## 5.3 Empfohlener Daily-Ablauf
@@ -482,6 +482,6 @@ Fertig ist die erste Version, wenn:
- nur Produkte mit `product.category <= falukant_user.certificate` produzierbar sind
- der Daemon die Zertifikatsprüfung genau einmal täglich ausführt
- der Daemon bei Aufstieg das Zertifikat fortschreibt
- der Daemon bei Aufstieg das Zertifikat fortschreibt und `certificate_productions_count_since` setzt
- die UI auf das Zertifikats-Event gezielt reagiert
- keine neuen DB-Änderungen für diese Funktion nötig sind
- Backend/UI dieselbe Produktionszählung wie der Daemon verwenden (siehe [`FALUKANT_PRODUCTION_CERTIFICATE.md`](./FALUKANT_PRODUCTION_CERTIFICATE.md))