Implement political office history logging: Added SQL logic to archive political office records upon expiration and deletion, ensuring historical tracking of office terms. Updated relevant queries to insert records into falukant_log.political_office_history for better compliance with data retention policies.
All checks were successful
Deploy yourpart (blue-green) / deploy (push) Successful in 1m33s
All checks were successful
Deploy yourpart (blue-green) / deploy (push) Successful in 1m33s
This commit is contained in:
28
migrations/016_falukant_log_political_office_history.sql
Normal file
28
migrations/016_falukant_log_political_office_history.sql
Normal file
@@ -0,0 +1,28 @@
|
||||
-- Abgeschlossene politische Ämter (Amtsende, Neubesetzung, Entfernung) für Auswertung „Karrierehöchstwert“ / UI.
|
||||
-- Wird vom YpDaemon vor Löschen aus falukant_data.political_office befüllt.
|
||||
|
||||
CREATE TABLE IF NOT EXISTS falukant_log.political_office_history (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
character_id INTEGER NOT NULL,
|
||||
office_type_id INTEGER NOT NULL,
|
||||
region_id INTEGER,
|
||||
start_date TIMESTAMPTZ NOT NULL,
|
||||
end_date TIMESTAMPTZ NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Tabelle kann bereits vom Backend existieren (ohne region_id o. Ä.): CREATE TABLE IF NOT EXISTS ergänzt keine Spalten.
|
||||
ALTER TABLE falukant_log.political_office_history
|
||||
ADD COLUMN IF NOT EXISTS region_id INTEGER;
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_pol_office_hist_character
|
||||
ON falukant_log.political_office_history (character_id);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_pol_office_hist_office_type
|
||||
ON falukant_log.political_office_history (office_type_id);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_pol_office_hist_region
|
||||
ON falukant_log.political_office_history (region_id);
|
||||
|
||||
COMMENT ON TABLE falukant_log.political_office_history IS
|
||||
'Politische Amtszeiten nach Ende; start_date/end_date aus Amtszeile bzw. NOW() bei vorzeitigem Ende (YpDaemon).';
|
||||
@@ -41,3 +41,7 @@ Spalte **`falukant_data.falukant_user.certificate_productions_count_since`**: Ze
|
||||
## `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).
|
||||
|
||||
## `016_falukant_log_political_office_history.sql`
|
||||
|
||||
Tabelle **`falukant_log.political_office_history`**: Archiv abgeschlossener politischer Amtszeiten (`character_id`, `office_type_id`, `region_id`, `start_date`, `end_date`). Der Daemon schreibt **vor** jedem relevanten `DELETE` auf **`falukant_data.political_office`** (Amtsende/Neuwahl-Pfad, Übersitz-Trim, Charaktertod). **`falukant_data.process_elections()`** (PostgreSQL) liegt außerhalb des Rust-Repos — falls dort Zeilen gelöscht werden, analog **`INSERT` in diese Historie** in der DB-Funktion ergänzen.
|
||||
|
||||
@@ -1040,15 +1040,28 @@ pub const QUERY_SELECT_NEEDED_ELECTIONS: &str = r#"
|
||||
target_date AS (
|
||||
SELECT NOW()::date AS election_date
|
||||
),
|
||||
offices_ending_today AS (
|
||||
SELECT po.id,
|
||||
po.character_id,
|
||||
po.office_type_id,
|
||||
po.region_id,
|
||||
po.created_at AS start_date,
|
||||
(po.created_at + (pot.term_length * INTERVAL '1 day')) AS end_date
|
||||
FROM falukant_data.political_office po
|
||||
JOIN falukant_type.political_office_type pot ON po.office_type_id = pot.id
|
||||
CROSS JOIN target_date td
|
||||
WHERE (po.created_at + (pot.term_length * INTERVAL '1 day'))::date = td.election_date
|
||||
),
|
||||
archived_expiring AS (
|
||||
INSERT INTO falukant_log.political_office_history (character_id, office_type_id, region_id, start_date, end_date)
|
||||
SELECT character_id, office_type_id, region_id, start_date, end_date
|
||||
FROM offices_ending_today
|
||||
),
|
||||
expired_today AS (
|
||||
DELETE FROM falukant_data.political_office AS po
|
||||
USING falukant_type.political_office_type AS pot
|
||||
WHERE po.office_type_id = pot.id
|
||||
AND (po.created_at + (pot.term_length * INTERVAL '1 day'))::date
|
||||
= (SELECT election_date FROM target_date)
|
||||
RETURNING
|
||||
pot.id AS office_type_id,
|
||||
po.region_id AS region_id
|
||||
DELETE FROM falukant_data.political_office po
|
||||
WHERE po.id IN (SELECT id FROM offices_ending_today)
|
||||
RETURNING po.office_type_id AS office_type_id,
|
||||
po.region_id AS region_id
|
||||
),
|
||||
gaps_per_region AS (
|
||||
SELECT
|
||||
@@ -1151,14 +1164,27 @@ pub const QUERY_SELECT_ELECTIONS_NEEDING_CANDIDATES: &str = r#"
|
||||
|
||||
pub const QUERY_PROCESS_EXPIRED_AND_FILL: &str = r#"
|
||||
WITH
|
||||
doomed AS (
|
||||
SELECT po.id,
|
||||
po.character_id,
|
||||
po.office_type_id,
|
||||
po.region_id,
|
||||
po.created_at AS start_date,
|
||||
(po.created_at + (pot.term_length * INTERVAL '1 day')) AS term_end
|
||||
FROM falukant_data.political_office po
|
||||
JOIN falukant_type.political_office_type pot ON po.office_type_id = pot.id
|
||||
WHERE (po.created_at + (pot.term_length * INTERVAL '1 day')) <= NOW()
|
||||
),
|
||||
archived_expired AS (
|
||||
INSERT INTO falukant_log.political_office_history (character_id, office_type_id, region_id, start_date, end_date)
|
||||
SELECT character_id, office_type_id, region_id, start_date, term_end
|
||||
FROM doomed
|
||||
),
|
||||
expired_offices AS (
|
||||
DELETE FROM falukant_data.political_office AS po
|
||||
USING falukant_type.political_office_type AS pot
|
||||
WHERE po.office_type_id = pot.id
|
||||
AND (po.created_at + (pot.term_length * INTERVAL '1 day')) <= NOW()
|
||||
RETURNING
|
||||
pot.id AS office_type_id,
|
||||
po.region_id AS region_id
|
||||
DELETE FROM falukant_data.political_office po
|
||||
WHERE po.id IN (SELECT id FROM doomed)
|
||||
RETURNING po.office_type_id AS office_type_id,
|
||||
po.region_id AS region_id
|
||||
),
|
||||
distinct_types AS (
|
||||
SELECT DISTINCT office_type_id, region_id FROM expired_offices
|
||||
@@ -1617,8 +1643,10 @@ pub const QUERY_TRIM_EXCESS_OFFICES_GLOBAL: &str = r#"
|
||||
ranked AS (
|
||||
SELECT
|
||||
po.id,
|
||||
po.character_id,
|
||||
po.office_type_id,
|
||||
po.region_id,
|
||||
po.created_at,
|
||||
s.seats_total,
|
||||
ROW_NUMBER() OVER (
|
||||
PARTITION BY po.office_type_id, po.region_id
|
||||
@@ -1630,9 +1658,14 @@ pub const QUERY_TRIM_EXCESS_OFFICES_GLOBAL: &str = r#"
|
||||
AND s.region_id = po.region_id
|
||||
),
|
||||
to_delete AS (
|
||||
SELECT id
|
||||
SELECT id, character_id, office_type_id, region_id, created_at
|
||||
FROM ranked
|
||||
WHERE rn > seats_total
|
||||
),
|
||||
archived_trim AS (
|
||||
INSERT INTO falukant_log.political_office_history (character_id, office_type_id, region_id, start_date, end_date)
|
||||
SELECT character_id, office_type_id, region_id, created_at, NOW()
|
||||
FROM to_delete
|
||||
)
|
||||
DELETE FROM falukant_data.political_office
|
||||
WHERE id IN (SELECT id FROM to_delete);
|
||||
@@ -2485,7 +2518,12 @@ pub const QUERY_DELETE_POLITICAL_OFFICE: &str = r#"
|
||||
WITH removed AS (
|
||||
DELETE FROM falukant_data.political_office
|
||||
WHERE character_id = $1
|
||||
RETURNING office_type_id, region_id
|
||||
RETURNING character_id, office_type_id, region_id, created_at
|
||||
),
|
||||
archived_removed AS (
|
||||
INSERT INTO falukant_log.political_office_history (character_id, office_type_id, region_id, start_date, end_date)
|
||||
SELECT character_id, office_type_id, region_id, created_at, NOW()
|
||||
FROM removed
|
||||
),
|
||||
affected AS (
|
||||
SELECT DISTINCT office_type_id, region_id
|
||||
@@ -2506,8 +2544,10 @@ pub const QUERY_DELETE_POLITICAL_OFFICE: &str = r#"
|
||||
ranked AS (
|
||||
SELECT
|
||||
po.id,
|
||||
po.character_id,
|
||||
po.office_type_id,
|
||||
po.region_id,
|
||||
po.created_at,
|
||||
s.seats_total,
|
||||
ROW_NUMBER() OVER (
|
||||
PARTITION BY po.office_type_id, po.region_id
|
||||
@@ -2519,9 +2559,14 @@ pub const QUERY_DELETE_POLITICAL_OFFICE: &str = r#"
|
||||
AND s.region_id = po.region_id
|
||||
),
|
||||
to_delete AS (
|
||||
SELECT id
|
||||
SELECT id, character_id, office_type_id, region_id, created_at
|
||||
FROM ranked
|
||||
WHERE rn > seats_total
|
||||
),
|
||||
archived_trim AS (
|
||||
INSERT INTO falukant_log.political_office_history (character_id, office_type_id, region_id, start_date, end_date)
|
||||
SELECT character_id, office_type_id, region_id, created_at, NOW()
|
||||
FROM to_delete
|
||||
)
|
||||
DELETE FROM falukant_data.political_office
|
||||
WHERE id IN (SELECT id FROM to_delete);
|
||||
@@ -3903,6 +3948,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`: 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).
|
||||
/// `max_church_hierarchy`: `GREATEST(character.highest_church_hierarchy_ever, MAX aktuelles kirchliches Amt)` (Migration `007` / Kirchen-Daemon).
|
||||
pub const QUERY_GET_PRODUCTION_CERTIFICATE_INPUT_ROWS: &str = r#"
|
||||
SELECT DISTINCT ON (fu.id)
|
||||
fu.id AS falukant_user_id,
|
||||
@@ -3929,12 +3975,15 @@ pub const QUERY_GET_PRODUCTION_CERTIFICATE_INPUT_ROWS: &str = r#"
|
||||
) >= fu.certificate_productions_count_since
|
||||
)
|
||||
), 0) AS completed_production_count,
|
||||
COALESCE((
|
||||
SELECT MAX(cot.hierarchy_level)::int
|
||||
FROM falukant_data.church_office co
|
||||
JOIN falukant_type.church_office_type cot ON cot.id = co.office_type_id
|
||||
WHERE co.character_id = c.id
|
||||
), 0) AS max_church_hierarchy,
|
||||
GREATEST(
|
||||
COALESCE(c.highest_church_hierarchy_ever, 0)::int,
|
||||
COALESCE((
|
||||
SELECT MAX(cot.hierarchy_level)::int
|
||||
FROM falukant_data.church_office co
|
||||
JOIN falukant_type.church_office_type cot ON cot.id = co.office_type_id
|
||||
WHERE co.character_id = c.id
|
||||
), 0)
|
||||
) AS max_church_hierarchy,
|
||||
COALESCE((
|
||||
SELECT STRING_AGG(DISTINCT pot.name, '|')
|
||||
FROM falukant_data.political_office po
|
||||
|
||||
Reference in New Issue
Block a user