diff --git a/YpDaemon/src/worker/base.rs b/YpDaemon/src/worker/base.rs index bea48bd..a32ba82 100644 --- a/YpDaemon/src/worker/base.rs +++ b/YpDaemon/src/worker/base.rs @@ -158,8 +158,8 @@ impl BaseWorker { ))); } - // We must ensure the resulting money fits in numeric(10,2). - // numeric(10,2) max absolute value is < 10^8 (100_000_000) before rounding. + // We must ensure the resulting money fits in numeric(14,2). + // numeric(14,2) max absolute value is < 10^12 before rounding. // Fetch current money for the user and clamp the delta if needed. conn.prepare("get_money_for_clamp", QUERY_GET_MONEY)?; let rows = conn.execute("get_money_for_clamp", &[&falukant_user_id])?; @@ -173,13 +173,13 @@ impl BaseWorker { // compute tentative result let tentative = current_money + money_change; - // numeric(10,2) allows values with absolute < 10^8 (100_000_000) - const MAX_ABS: f64 = 100_000_000.0 - 0.01; // leave room for scale + // numeric(14,2) allows values with absolute < 10^12 + const MAX_ABS: f64 = 1_000_000_000_000.0 - 0.01; // leave room for scale let adjusted_money_change = if tentative >= MAX_ABS { let clipped = MAX_ABS - current_money; eprintln!( - "[BaseWorker] Clamping money_change: tentative {} exceeds numeric(10,2) max, clipping to {}", + "[BaseWorker] Clamping money_change: tentative {} exceeds numeric(14,2) max, clipping to {}", tentative, clipped ); clipped diff --git a/YpDaemon/src/worker/user_character.rs b/YpDaemon/src/worker/user_character.rs index 828bb86..e4e8168 100644 --- a/YpDaemon/src/worker/user_character.rs +++ b/YpDaemon/src/worker/user_character.rs @@ -706,7 +706,7 @@ impl UserCharacterWorker { let clamped = if !new_amount.is_finite() { 1000.0 } else { - const MAX_ABS: f64 = 99_999_999.99; + const MAX_ABS: f64 = 999_999_999_999.99; new_amount.clamp(-MAX_ABS, MAX_ABS) }; let money_str = format!("{:.2}", clamped); diff --git a/migrations/017_falukant_money_precision_14_2.sql b/migrations/017_falukant_money_precision_14_2.sql new file mode 100644 index 0000000..8cb99f9 --- /dev/null +++ b/migrations/017_falukant_money_precision_14_2.sql @@ -0,0 +1,76 @@ +-- Erhoeht Geld-Praezision fuer sehr hohe Kontostaende. +-- Ziel: max. Betrag von 99.999.999,99 auf 999.999.999.999,99 anheben. + +-- Hauptkontostand +ALTER TABLE falukant_data.falukant_user + ALTER COLUMN money TYPE NUMERIC(14,2); + +-- Verlaufseintraege (best effort-Logging im Daemon) +ALTER TABLE falukant_log.money_history + ALTER COLUMN change TYPE NUMERIC(14,2); + +-- Moneyflow auf dieselbe Praezision bringen (falls die Tabelle existiert). +ALTER TABLE IF EXISTS falukant_log.moneyflow + ALTER COLUMN money_before TYPE NUMERIC(14,2), + ALTER COLUMN money_after TYPE NUMERIC(14,2), + ALTER COLUMN change_value TYPE NUMERIC(14,2); + +-- Kernfunktion auf neue Praezision umstellen. +CREATE OR REPLACE FUNCTION falukant_data.update_money( + p_falukant_user_id integer, + p_money_change numeric, + p_activity text, + p_changed_by integer DEFAULT NULL::integer +) +RETURNS void +LANGUAGE plpgsql +AS $function$ +DECLARE + v_money_before numeric(14,2); + v_money_after numeric(14,2); + v_moneyflow_id bigint; +BEGIN + SELECT money + INTO v_money_before + FROM falukant_data.falukant_user + WHERE id = p_falukant_user_id; + + IF NOT FOUND THEN + RAISE EXCEPTION 'FalukantUser mit ID % nicht gefunden', p_falukant_user_id; + END IF; + + v_money_after := v_money_before + p_money_change; + + INSERT INTO falukant_log.moneyflow ( + falukant_user_id, + activity, + money_before, + money_after, + change_value, + changed_by, + time + ) + VALUES ( + p_falukant_user_id, + p_activity, + v_money_before, + NULL, -- wird gleich aktualisiert + p_money_change, + p_changed_by, + NOW() + ) + RETURNING id INTO v_moneyflow_id; + + UPDATE falukant_data.falukant_user + SET money = v_money_after + WHERE id = p_falukant_user_id; + + UPDATE falukant_log.moneyflow + SET money_after = ( + SELECT money + FROM falukant_data.falukant_user + WHERE id = p_falukant_user_id + ) + WHERE id = v_moneyflow_id; +END; +$function$; diff --git a/src/worker/base.rs b/src/worker/base.rs index bea48bd..a32ba82 100644 --- a/src/worker/base.rs +++ b/src/worker/base.rs @@ -158,8 +158,8 @@ impl BaseWorker { ))); } - // We must ensure the resulting money fits in numeric(10,2). - // numeric(10,2) max absolute value is < 10^8 (100_000_000) before rounding. + // We must ensure the resulting money fits in numeric(14,2). + // numeric(14,2) max absolute value is < 10^12 before rounding. // Fetch current money for the user and clamp the delta if needed. conn.prepare("get_money_for_clamp", QUERY_GET_MONEY)?; let rows = conn.execute("get_money_for_clamp", &[&falukant_user_id])?; @@ -173,13 +173,13 @@ impl BaseWorker { // compute tentative result let tentative = current_money + money_change; - // numeric(10,2) allows values with absolute < 10^8 (100_000_000) - const MAX_ABS: f64 = 100_000_000.0 - 0.01; // leave room for scale + // numeric(14,2) allows values with absolute < 10^12 + const MAX_ABS: f64 = 1_000_000_000_000.0 - 0.01; // leave room for scale let adjusted_money_change = if tentative >= MAX_ABS { let clipped = MAX_ABS - current_money; eprintln!( - "[BaseWorker] Clamping money_change: tentative {} exceeds numeric(10,2) max, clipping to {}", + "[BaseWorker] Clamping money_change: tentative {} exceeds numeric(14,2) max, clipping to {}", tentative, clipped ); clipped diff --git a/src/worker/director.rs b/src/worker/director.rs index daec39d..a63ac60 100644 --- a/src/worker/director.rs +++ b/src/worker/director.rs @@ -212,6 +212,19 @@ impl DirectorWorker { continue; } + let resignation_percent = (resignation_probability * 100.0 * 100.0).round() / 100.0; + let resignation_payload = format!( + r#"{{"tr":"director.resigned","event":"director_resigned","director_id":{},"director_character_id":{},"satisfaction":{},"resignation_percent":{}}}"#, + candidate.id, + candidate.director_character_id, + candidate.satisfaction.clamp(0, 100), + resignation_percent + ); + let _ = conn.execute( + "insert_notification", + &[&candidate.employer_user_id, &resignation_payload], + ); + eprintln!( "[DirectorWorker] Director {} kündigt (character_id={}, user_id={}, satisfaction={}, prob={:.4}, roll={:.4})", candidate.id, @@ -230,6 +243,7 @@ impl DirectorWorker { r#"{{"event":"falukantUpdateStatus","user_id":{}}}"#, candidate.employer_user_id )); + self.base.broker.publish(resignation_payload); } self.last_resignation_check = Some(now); diff --git a/src/worker/user_character.rs b/src/worker/user_character.rs index 9cd43a8..1f4c593 100644 --- a/src/worker/user_character.rs +++ b/src/worker/user_character.rs @@ -1057,11 +1057,11 @@ impl UserCharacterWorker { .get() .map_err(|e| DbError::new(format!("DB-Verbindung fehlgeschlagen: {e}")))?; - // Endliche Werte und gültiger Bereich für numeric(10,2), sonst Serialisierungsfehler + // Endliche Werte und gültiger Bereich für numeric(14,2), sonst Serialisierungsfehler let clamped = if !new_amount.is_finite() { 1000.0 } else { - const MAX_ABS: f64 = 99_999_999.99; + const MAX_ABS: f64 = 999_999_999_999.99; new_amount.clamp(-MAX_ABS, MAX_ABS) }; let money_str = format!("{:.2}", clamped);