Enhance production certificate logic and event handling: Updated the daily recalculation process in FalukantFamilyWorker to decouple it from family migration, ensuring consistent execution. Introduced a new mechanism to reset certificates upon succession without heirs, improving user experience. Refined SQL queries for better data retrieval and event publishing, including distinct character selection logic. Enhanced documentation for clarity on the updated processes and their implications.
All checks were successful
Deploy yourpart (blue-green) / deploy (push) Successful in 2m55s

This commit is contained in:
Torsten Schulz (local)
2026-03-31 10:29:05 +02:00
parent 64080211d1
commit b3578c65b8
5 changed files with 88 additions and 25 deletions

View File

@@ -1,6 +1,6 @@
# Falukant: Produktionszertifikate (Daemon)
Die Zertifikatslogik läuft **ausschließlich im Daily-Tick** von `FalukantFamilyWorker` (`process_daily`, 24h), nicht in einem eigenen Worker-Thread. Sie schreibt `falukant_user.certificate` fort (max. **+1** pro Tag, keine normale Herabstufung).
Die Zertifikatslogik läuft im **24h-Daily-Tick** von `FalukantFamilyWorker` (`run_iteration`), **nicht** in einem eigenen Worker-Thread. Sie ist von der **Familien-Migration** entkoppelt: Schuldturm + Zertifikat laufen **immer** im Daily-Intervall; Liebhaber/Ehe/Monatslogik nur, wenn `QUERY_FAMILY_SCHEMA_READY` (Spalte `relationship_state.last_daily_processed_at`) erfüllt ist. Sie schreibt `falukant_user.certificate` fort (max. **+1** pro Tag, keine normale Herabstufung außer Bankrott / Erbfolge).
Implementierung: `src/worker/falukant_certificate.rs` (`run_daily`).
@@ -27,19 +27,24 @@ Rang aus **`political_office_type.name`** (Substring-Heuristik im Daemon, ohne D
## Abgeschlossene Produktionen
**`COUNT(*)`** aus `falukant_log.production` mit `producer_id = falukant_user.id`.
**`COUNT(*)`** aus `falukant_log.production` mit `producer_id = falukant_user.id` **oder** `character.id` (Backend kann je nach Kontext die eine oder andere ID schreiben).
## Gewählter Charakter pro User
Bei mehreren lebenden Charakteren: **`DISTINCT ON (fu.id) … ORDER BY fu.id, c.id DESC`** — der Charakter mit der **höchsten** `character.id` (typisch zuletzt genutzter Slot), damit Wissen/Ruf/Ämter näher an der UI liegen.
## Events (WebSocket)
Bei Änderung der Stufe:
1. `falukantUpdateProductionCertificate` mit `reason: "daily_recalculation"`, `old_certificate`, `new_certificate`
1. `falukantUpdateProductionCertificate` mit `reason`, `old_certificate`, `new_certificate`
2. `falukantUpdateStatus`
**`reason`:** `daily_recalculation` (normaler Aufstieg), `bankruptcy` (Geld ≤ 5000), `succession_no_heir` (Tod ohne Erben → Stufe 1).
`user_id` in den Events: **`app_user_id`** aus der Query (`COALESCE(fu.user_id, fu.id)`), sonst Fallback `falukant_user_id`.
## Nicht umgesetzt (optional / später)
- **Tod ohne Erben** / Zertifikats-Reset
- Feinere **Bankrott**-Definition
- **`political_office_history`** (nicht im Repo)