diff --git a/YpDaemon/src/worker/sql.rs b/YpDaemon/src/worker/sql.rs index 3627240..28de7b3 100644 --- a/YpDaemon/src/worker/sql.rs +++ b/YpDaemon/src/worker/sql.rs @@ -1462,11 +1462,13 @@ pub const QUERY_INSERT_UPDATE_PRODUCTION_LOG: &str = r#" product_id, quantity, producer_id, - production_date - ) VALUES ($1, $2, $3, $4, CURRENT_DATE) + production_date, + completion_count + ) VALUES ($1, $2, $3, $4, CURRENT_DATE, 1) ON CONFLICT (producer_id, product_id, region_id, production_date) DO UPDATE - SET quantity = falukant_log.production.quantity + EXCLUDED.quantity; + SET quantity = falukant_log.production.quantity + EXCLUDED.quantity, + completion_count = falukant_log.production.completion_count + 1; "#; pub const QUERY_ADD_OVERPRODUCTION_NOTIFICATION: &str = r#" diff --git a/docs/FALUKANT_PRODUCTION_CERTIFICATE.md b/docs/FALUKANT_PRODUCTION_CERTIFICATE.md index 90c84c8..60d9d75 100644 --- a/docs/FALUKANT_PRODUCTION_CERTIFICATE.md +++ b/docs/FALUKANT_PRODUCTION_CERTIFICATE.md @@ -40,7 +40,7 @@ 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` **oder** `character.id`, und **Zeitstempel** `>= certificate_productions_count_since` (Spalte auf `falukant_user`, Migration **`014_falukant_certificate_productions_count_since.sql`**). **`NULL`** bei dieser Spalte: alle passenden Log-Zeilen (Bestand bis zur ersten Stufenänderung nach Migration). +**`SUM(completion_count)`** aus `falukant_log.production` mit `producer_id = falukant_user.id` **oder** `character.id`, und **Zeitstempel** `>= certificate_productions_count_since` (Spalte auf `falukant_user`, Migration **`014`**). **`completion_count`** (Migration **`015`**): pro abgeschlossener Produktion +1; das Log **aggregiert** noch immer pro Tag/Produkt/Region (`quantity` per UPSERT), daher reicht **`COUNT(*)`** der Zeilen nicht — ohne Summe bliebe der Zähler bei vielen Abschlüssen gleich. **`NULL`** bei `certificate_productions_count_since`: alle passenden Log-Zeilen (Bestand bis zur ersten Stufenänderung nach Migration). Bei jedem **Aufstieg**, **Bankrott** (Stufe 1) und **Erbfolge ohne Erben** setzt der Daemon **`certificate_productions_count_since = NOW()`** — die Mindestanforderungen für die **nächste** Stufe gelten damit nur für **neu** abgeschlossene Produktionen. **Logs werden dafür nicht gelöscht** (bleiben u. a. für Wissens-Updates / Preise); optional räumt `QUERY_DELETE_OLD_PRODUCTIONS` nur sehr alte Zeilen auf (aktuell **30 Tage** Retention, Speicherbegrenzung). diff --git a/migrations/015_falukant_log_production_completion_count.sql b/migrations/015_falukant_log_production_completion_count.sql new file mode 100644 index 0000000..d5e8cb2 --- /dev/null +++ b/migrations/015_falukant_log_production_completion_count.sql @@ -0,0 +1,16 @@ +-- Abgeschlossene Produktionen für Zertifikat: pro tatsächlichem Abschluss +1 (UPSERT erhöht Menge, +-- ohne diese Spalte bliebe COUNT(*) der Log-Zeilen bei zusammengefassten Tageszeilen falsch niedrig). + +ALTER TABLE falukant_log.production + ADD COLUMN IF NOT EXISTS completion_count integer; + +UPDATE falukant_log.production + SET completion_count = 1 + WHERE completion_count IS NULL; + +ALTER TABLE falukant_log.production + ALTER COLUMN completion_count SET DEFAULT 1, + ALTER COLUMN completion_count SET NOT NULL; + +COMMENT ON COLUMN falukant_log.production.completion_count IS + 'Anzahl abgeschlossener Produktionen in dieser aggregierten Log-Zeile; beim Einfügen 1, bei Konflikt +1 pro Abschluss (YpDaemon produce, Zertifikat: SUM(completion_count)).'; diff --git a/migrations/README.md b/migrations/README.md index 324e247..8bb444b 100644 --- a/migrations/README.md +++ b/migrations/README.md @@ -37,3 +37,7 @@ Spalte **`falukant_data.falukant_user.last_political_daily_salary_on`** (Datum): ## `014_falukant_certificate_productions_count_since.sql` Spalte **`falukant_data.falukant_user.certificate_productions_count_since`**: Zertifikats-**Produktionszählung** (Mindestwerte + Produktionspunkte) ab diesem Zeitpunkt; Daemon setzt bei **Aufstieg/Bankrott/Erbfolge** auf `NOW()`. **`NULL`** = bis zur ersten Änderung weiterhin alle passenden Log-Zeilen zählen. + +## `015_falukant_log_production_completion_count.sql` + +Spalte **`falukant_log.production.completion_count`**: zählt **abgeschlossene Produktionen** pro aggregierter Log-Zeile (bei gleichem Tag/Produkt/Region wird die Menge per UPSERT summiert; ohne `completion_count` bliebe `COUNT(*)` über die Zeilen fälschlich niedrig). Zertifikatsabfrage nutzt **`SUM(completion_count)`** (Migration **`015`** vor Deploy des aktualisierten Produce-Workers ausführen). diff --git a/src/worker/sql.rs b/src/worker/sql.rs index 1775397..6354193 100644 --- a/src/worker/sql.rs +++ b/src/worker/sql.rs @@ -2640,11 +2640,13 @@ pub const QUERY_INSERT_UPDATE_PRODUCTION_LOG: &str = r#" product_id, quantity, producer_id, - production_date - ) VALUES ($1, $2, $3, $4, CURRENT_DATE) + production_date, + completion_count + ) VALUES ($1, $2, $3, $4, CURRENT_DATE, 1) ON CONFLICT (producer_id, product_id, region_id, production_date) DO UPDATE - SET quantity = falukant_log.production.quantity + EXCLUDED.quantity; + SET quantity = falukant_log.production.quantity + EXCLUDED.quantity, + completion_count = falukant_log.production.completion_count + 1; "#; pub const QUERY_ADD_OVERPRODUCTION_NOTIFICATION: &str = r#" @@ -3900,7 +3902,7 @@ pub const QUERY_HAS_MOTHER_BIRTH_TODAY: &str = r#" /// Ein Spielercharakter pro Falukant-User (bei mehreren lebenden: **höchste** `character.id`, /// typischerweise zuletzt aktiver Slot — konsistent mit UI, das oft den Hauptcharakter nutzt). -/// `completed_production_count`: Produktionen seit `certificate_productions_count_since` (Migration `014`); **NULL** = alle Log-Zeilen (Bestand vor erstem Aufstieg nach Migration). +/// `completed_production_count`: Summe `completion_count` in `falukant_log.production` seit `certificate_productions_count_since` (Migration `014`; Spalte `completion_count` Migration `015`); **NULL** = alle passenden Log-Zeilen (Bestand vor erstem Aufstieg nach Migration). pub const QUERY_GET_PRODUCTION_CERTIFICATE_INPUT_ROWS: &str = r#" SELECT DISTINCT ON (fu.id) fu.id AS falukant_user_id, @@ -3916,7 +3918,7 @@ pub const QUERY_GET_PRODUCTION_CERTIFICATE_INPUT_ROWS: &str = r#" WHERE k.character_id = c.id ), 0.0) AS avg_knowledge, COALESCE(( - SELECT COUNT(*)::bigint + SELECT SUM(pl.completion_count)::bigint FROM falukant_log.production pl WHERE (pl.producer_id = fu.id OR pl.producer_id = c.id) AND (