Skip to main content

grid_billing/
rounding.rs

1//! Kaufmännisches Runden — the one rounding mode this crate uses.
2
3use rust_decimal::{Decimal, RoundingStrategy};
4
5/// Kaufmännisches Runden (DIN 1333): round half **away from zero**.
6///
7/// `Decimal::round_dp` rounds half to even. The two modes agree everywhere
8/// except exact midpoints — the values a price quoted in ct with three decimals
9/// produces — so the wrong one misstates a cent without failing any test
10/// written against ordinary numbers. Away-from-zero rather than literal half-up
11/// keeps a Storno symmetric to what it reverses: round(-0.005) = -0.01 mirrors
12/// round(0.005) = 0.01, and it is the strategy the `billing` arithmetic core
13/// applies inside every `Amount` operation.
14///
15/// `cargo xtask check-rounding` refuses a bare `round_dp` workspace-wide, so no
16/// call site can fall back to banker's rounding silently.
17pub trait RoundMoney {
18    /// Round to `dp` decimal places, half away from zero (DIN 1333).
19    #[must_use]
20    fn round_kfm(&self, dp: u32) -> Decimal;
21}
22
23impl RoundMoney for Decimal {
24    fn round_kfm(&self, dp: u32) -> Decimal {
25        self.round_dp_with_strategy(dp, RoundingStrategy::MidpointAwayFromZero)
26    }
27}