fix: money strings always carry cents

money() printed whatever scale a Decimal happened to have, so an empty
sum came back as "0" while every other amount read "207.68". Amounts now
have at least two places ("0.00", "1000.00"), padded and never rounded:
an exact FX-converted amount with more places keeps them. Negative zero
normalizes to "0.00".

Test: money_always_has_cents_and_never_rounds; three stdio assertions
that pinned the old "0" now expect "0.00".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MtYEaR6M6Ybdhm6X98BWNu
This commit is contained in:
swaitsandClaude Opus 5.5 committed 2026-10-11 19:38:01 -07:00
1 parent 42e600bbf2
commit f4cb01b3f9
2 files changed
+28 -4

No files matched your search

+25 -1
View File
@@ -204,8 +204,14 @@ fn resolve_class(store: &Store, class: &str) -> Result<u32, String> {
})
}
/// A money amount as a decimal string with at least two places: "0.00",
/// "207.68", "1000.00". Padding only, never rounding: an exact amount with
/// more places (an FX-converted line) keeps them. Never "-0".
fn money(n: Decimal) -> String {
// Decimal's Display never emits floats or "-0" for exact values.
let mut n = if n.is_zero() { Decimal::ZERO } else { n };
if n.scale() < 2 {
n.rescale(2);
}
n.to_string()
}
@@ -2999,3 +3005,21 @@ impl ServerHandler for BooksServer {
)))
}
}
#[cfg(test)]
mod tests {
use super::money;
use rust_decimal::Decimal;
use std::str::FromStr;
#[test]
fn money_always_has_cents_and_never_rounds() {
let m = |s: &str| money(Decimal::from_str(s).unwrap());
assert_eq!(money(Decimal::ZERO), "0.00");
assert_eq!(m("-0"), "0.00");
assert_eq!(m("1000"), "1000.00");
assert_eq!(m("5.8"), "5.80");
assert_eq!(m("-207.68"), "-207.68");
assert_eq!(m("12.3456"), "12.3456");
}
}