diff --git a/src/worker/events.rs b/src/worker/events.rs index 9f73048..97902a1 100644 --- a/src/worker/events.rs +++ b/src/worker/events.rs @@ -1482,7 +1482,29 @@ impl EventsWorker { } } - // 3) Child-Relations löschen und Eltern benachrichtigen + // 3) Erben-Logik für Spieler-Charaktere (VOR dem Löschen der Child-Relations!) + // Prüfe, ob der Charakter ein Spieler-Charakter ist + const QUERY_GET_USER_ID: &str = r#" + SELECT user_id + FROM falukant_data.character + WHERE id = $1; + "#; + + conn.prepare("get_user_id", QUERY_GET_USER_ID)?; + let user_rows = conn.execute("get_user_id", &[&character_id])?; + + let user_id: Option = user_rows + .get(0) + .and_then(|r| r.get("user_id")) + .and_then(|v| v.parse::().ok()); + + if let Some(falukant_user_id) = user_id { + // Spieler-Charakter: Erben-Logik ausführen + // WICHTIG: Dies muss VOR dem Löschen der Child-Relations passieren! + Self::handle_inheritance(pool, broker, &mut conn, character_id, falukant_user_id)?; + } + + // 4) Child-Relations löschen und Eltern benachrichtigen const QUERY_DELETE_CHILD_RELATION: &str = r#" WITH deleted AS ( DELETE FROM falukant_data.child_relation @@ -1518,7 +1540,7 @@ impl EventsWorker { } } - // 4) Charakter löschen + // 5) Charakter löschen const QUERY_DELETE_CHARACTER: &str = r#" DELETE FROM falukant_data.character WHERE id = $1; @@ -1530,6 +1552,184 @@ impl EventsWorker { Ok(()) } + fn handle_inheritance( + pool: &ConnectionPool, + broker: &MessageBroker, + conn: &mut DbConnection, + deceased_character_id: i32, + falukant_user_id: i32, + ) -> Result<(), DbError> { + // 1) Finde den Erben (bevorzugt is_heir = TRUE) + const QUERY_GET_HEIR: &str = r#" + SELECT child_character_id + FROM falukant_data.child_relation + WHERE father_character_id = $1 + OR mother_character_id = $1 + ORDER BY (is_heir IS TRUE) DESC, + updated_at DESC + LIMIT 1; + "#; + + conn.prepare("get_heir", QUERY_GET_HEIR)?; + let heir_rows = conn.execute("get_heir", &[&deceased_character_id])?; + + let heir_id: Option = heir_rows + .get(0) + .and_then(|r| r.get("child_character_id")) + .and_then(|v| v.parse::().ok()); + + let heir_id = match heir_id { + Some(id) if id > 0 => id, + _ => { + // Kein Erbe gefunden - Vermögen geht verloren + eprintln!( + "[EventsWorker] Kein Erbe für Charakter {} gefunden, Vermögen geht verloren", + deceased_character_id + ); + return Ok(()); + } + }; + + // 2) Setze den Erben als neuen Spieler-Charakter + const QUERY_SET_CHARACTER_USER: &str = r#" + UPDATE falukant_data.character + SET user_id = $1, + updated_at = NOW() + WHERE id = $2; + "#; + + conn.prepare("set_character_user", QUERY_SET_CHARACTER_USER)?; + conn.execute("set_character_user", &[&falukant_user_id, &heir_id])?; + + // 3) Berechne das neue Vermögen basierend auf dem gesamten Vermögen + // Hole alle Vermögenswerte (analog zu UserCharacterWorker::calculate_new_money) + const QUERY_GET_CURRENT_MONEY: &str = r#" + SELECT money + FROM falukant_data.falukant_user + WHERE id = $1; + "#; + + const QUERY_GET_HOUSE_VALUE: &str = r#" + SELECT COALESCE(SUM(h.cost), 0) AS sum + FROM falukant_data.user_house AS uh + JOIN falukant_type.house AS h ON uh.house_type_id = h.id + WHERE uh.user_id = $1; + "#; + + const QUERY_GET_SETTLEMENT_VALUE: &str = r#" + SELECT COALESCE(SUM(b.base_cost), 0) AS sum + FROM falukant_data.branch AS br + JOIN falukant_type.branch AS b ON br.branch_type_id = b.id + WHERE br.falukant_user_id = $1; + "#; + + const QUERY_GET_INVENTORY_VALUE: &str = r#" + SELECT COALESCE(SUM(i.quantity * p.sell_cost), 0) AS sum + FROM falukant_data.inventory AS i + JOIN falukant_type.product AS p ON i.product_id = p.id + JOIN falukant_data.stock AS s ON i.stock_id = s.id + JOIN falukant_data.branch AS br ON s.branch_id = br.id + WHERE br.falukant_user_id = $1; + "#; + + const QUERY_GET_CREDIT_DEBT: &str = r#" + SELECT COALESCE(SUM(remaining_amount), 0) AS sum + FROM falukant_data.credit + WHERE falukant_user_id = $1; + "#; + + const QUERY_COUNT_CHILDREN: &str = r#" + SELECT COUNT(*) AS cnt + FROM falukant_data.child_relation + WHERE (father_character_id = $1 OR mother_character_id = $1) + AND child_character_id != $2; + "#; + + conn.prepare("get_current_money", QUERY_GET_CURRENT_MONEY)?; + conn.prepare("get_house_value", QUERY_GET_HOUSE_VALUE)?; + conn.prepare("get_settlement_value", QUERY_GET_SETTLEMENT_VALUE)?; + conn.prepare("get_inventory_value", QUERY_GET_INVENTORY_VALUE)?; + conn.prepare("get_credit_debt", QUERY_GET_CREDIT_DEBT)?; + conn.prepare("count_children", QUERY_COUNT_CHILDREN)?; + + let cash: f64 = conn + .execute("get_current_money", &[&falukant_user_id])? + .get(0) + .and_then(|r| r.get("money")) + .and_then(|v| v.parse::().ok()) + .unwrap_or(0.0); + + let houses: f64 = conn + .execute("get_house_value", &[&falukant_user_id])? + .get(0) + .and_then(|r| r.get("sum")) + .and_then(|v| v.parse::().ok()) + .unwrap_or(0.0); + + let settlements: f64 = conn + .execute("get_settlement_value", &[&falukant_user_id])? + .get(0) + .and_then(|r| r.get("sum")) + .and_then(|v| v.parse::().ok()) + .unwrap_or(0.0); + + let inventory: f64 = conn + .execute("get_inventory_value", &[&falukant_user_id])? + .get(0) + .and_then(|r| r.get("sum")) + .and_then(|v| v.parse::().ok()) + .unwrap_or(0.0); + + let debt: f64 = conn + .execute("get_credit_debt", &[&falukant_user_id])? + .get(0) + .and_then(|r| r.get("sum")) + .and_then(|v| v.parse::().ok()) + .unwrap_or(0.0); + + let child_count: i32 = conn + .execute("count_children", &[&deceased_character_id, &heir_id])? + .get(0) + .and_then(|r| r.get("cnt")) + .and_then(|v| v.parse::().ok()) + .unwrap_or(0); + + // Berechne das neue Vermögen (analog zu UserCharacterWorker::calculate_new_money) + let total_assets = cash + houses + settlements + inventory - debt; + let single = child_count <= 0; // Nur der Erbe bleibt + + let heir_share = if single { + total_assets + } else { + total_assets * 0.8 + }; + + let new_money = heir_share - (houses + settlements + inventory + debt); + let final_money = if new_money <= 1000.0 { + 1000.0 + } else { + new_money + }; + + // 4) Aktualisiere das Vermögen über die update_money Funktion + // Verwende die BaseWorker-Funktion für konsistente Geld-Updates + use crate::worker::base::BaseWorker; + let base = BaseWorker::new("EventsWorker", pool.clone(), broker.clone()); + let money_change = final_money - cash; + base.change_falukant_user_money( + falukant_user_id, + money_change, + &format!("Erbe für Charakter {}", deceased_character_id), + )?; + + eprintln!( + "[EventsWorker] Erbe {} übernimmt Vermögen von Charakter {} (User {}): {:.2} (von {:.2} Gesamtvermögen, {} weitere Kinder)", + heir_id, deceased_character_id, falukant_user_id, final_money, total_assets, child_count + ); + + Ok(()) + } + fn notify_user( pool: &ConnectionPool, broker: &MessageBroker,