From 604c8ba3009460c73f7b4dbe5278d01b5c98196c Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Mon, 5 Jan 2026 15:46:54 +0100 Subject: [PATCH] Add character user clearing logic in EventsWorker: Implement a new SQL query to clear the user association from a deceased character before assigning a new heir. This ensures compliance with unique constraints and prevents errors during user reassignment. Enhance error handling and logging for better debugging. --- src/worker/events.rs | 27 +++++++++++++++++++++++---- src/worker/sql.rs | 6 ++++++ src/worker/user_character.rs | 15 +++++++++++++++ 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/worker/events.rs b/src/worker/events.rs index 81b6e44..19afb6d 100644 --- a/src/worker/events.rs +++ b/src/worker/events.rs @@ -46,6 +46,7 @@ use crate::worker::sql::{ QUERY_DELETE_CHARACTER, QUERY_GET_HEIR, QUERY_SET_CHARACTER_USER, + QUERY_CLEAR_CHARACTER_USER, QUERY_GET_CURRENT_MONEY, QUERY_GET_HOUSE_VALUE, QUERY_GET_SETTLEMENT_VALUE, @@ -1600,11 +1601,29 @@ impl EventsWorker { } }; - // 2) Setze den Erben als neuen Spieler-Charakter - conn.prepare("set_character_user", QUERY_SET_CHARACTER_USER)?; - conn.execute("set_character_user", &[&falukant_user_id, &heir_id])?; + // 2) Wichtig: erst die alte User-Zuordnung am verstorbenen Charakter lösen. + // Falls es einen Unique-Constraint auf `character.user_id` gibt, würde das + // direkte Setzen am Erben sonst fehlschlagen. + conn.prepare("clear_character_user", QUERY_CLEAR_CHARACTER_USER)?; + if let Err(err) = conn.execute("clear_character_user", &[&deceased_character_id]) { + eprintln!( + "[EventsWorker] Erben-Logik: Konnte user_id vom verstorbenen Charakter {} nicht lösen: {}", + deceased_character_id, err + ); + } - // 3) Berechne das neue Vermögen basierend auf dem gesamten Vermögen + // 3) Setze den Erben als neuen Spieler-Charakter + conn.prepare("set_character_user", QUERY_SET_CHARACTER_USER)?; + if let Err(err) = conn.execute("set_character_user", &[&falukant_user_id, &heir_id]) { + eprintln!( + "[EventsWorker] Erben-Logik: Konnte user_id={} nicht auf Erben {} setzen (verstorbener Charakter {}): {}", + falukant_user_id, heir_id, deceased_character_id, err + ); + // Abbrechen, damit wir nicht still ohne Character weiterlaufen. + return Err(err); + } + + // 4) Berechne das neue Vermögen basierend auf dem gesamten Vermögen // Hole alle Vermögenswerte (analog zu UserCharacterWorker::calculate_new_money) conn.prepare("get_current_money", QUERY_GET_CURRENT_MONEY)?; conn.prepare("get_house_value", QUERY_GET_HOUSE_VALUE)?; diff --git a/src/worker/sql.rs b/src/worker/sql.rs index 33b1b33..d2f1aab 100644 --- a/src/worker/sql.rs +++ b/src/worker/sql.rs @@ -743,6 +743,12 @@ pub const QUERY_SET_CHARACTER_USER: &str = r#" UPDATE falukant_data.character SET user_id = $1, updated_at = NOW() WHERE id = $2; "#; +// Erben-Logik: erst alte User-Zuordnung lösen (für Unique-Constraints auf character.user_id), +// dann den Erben übernehmen lassen. +pub const QUERY_CLEAR_CHARACTER_USER: &str = r#" +UPDATE falukant_data.character SET user_id = NULL, updated_at = NOW() WHERE id = $1; +"#; + pub const QUERY_GET_CURRENT_MONEY: &str = r#" SELECT money FROM falukant_data.falukant_user WHERE id = $1; "#; diff --git a/src/worker/user_character.rs b/src/worker/user_character.rs index c5c76f4..201bf05 100644 --- a/src/worker/user_character.rs +++ b/src/worker/user_character.rs @@ -29,6 +29,7 @@ use crate::worker::sql::{ QUERY_GET_HEIR, QUERY_RANDOM_HEIR, QUERY_SET_CHARACTER_USER, + QUERY_CLEAR_CHARACTER_USER, QUERY_UPDATE_USER_MONEY, QUERY_GET_FALUKANT_USER_ID, QUERY_AUTOBATISM, @@ -608,6 +609,8 @@ impl UserCharacterWorker { } if heir_id > 0 { + // Erst die alte Zuordnung lösen (Unique-Constraint safety), dann den Erben zuweisen. + self.clear_character_user(character_id)?; self.set_new_character(falukant_user_id, heir_id)?; } self.set_new_money(falukant_user_id, new_money)?; @@ -685,6 +688,18 @@ impl UserCharacterWorker { Ok(()) } + fn clear_character_user(&mut self, deceased_character_id: i32) -> Result<(), DbError> { + let mut conn = self + .base + .pool + .get() + .map_err(|e| DbError::new(format!("DB-Verbindung fehlgeschlagen: {e}")))?; + + conn.prepare("clear_character_user", QUERY_CLEAR_CHARACTER_USER)?; + conn.execute("clear_character_user", &[&deceased_character_id])?; + Ok(()) + } + fn set_new_money(&mut self, falukant_user_id: i32, new_amount: f64) -> Result<(), DbError> { let mut conn = self .base