Update monetary limits for numeric precision in BaseWorker and UserCharacterWorker: Changed maximum absolute values from numeric(10,2) to numeric(14,2) to accommodate larger monetary amounts. Adjusted related comments and clamping logic to reflect the new limits, ensuring accurate handling of monetary values.
All checks were successful
Deploy yourpart (blue-green) / deploy (push) Successful in 2m19s

This commit is contained in:
Torsten Schulz (local)
2026-05-06 11:04:45 +02:00
parent 43eb6ed0ab
commit 8509a7e171
6 changed files with 103 additions and 13 deletions

View File

@@ -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

View File

@@ -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);

View File

@@ -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$;

View File

@@ -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

View File

@@ -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);

View File

@@ -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);