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
All checks were successful
Deploy yourpart (blue-green) / deploy (push) Successful in 2m19s
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
76
migrations/017_falukant_money_precision_14_2.sql
Normal file
76
migrations/017_falukant_money_precision_14_2.sql
Normal 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$;
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user