Skip to main content

core_invoice/
amount.rs

1use rust_decimal::Decimal;
2use std::fmt;
3use std::str::FromStr;
4
5/// Monetary amount. Never `f64`. Scale is two decimals unless noted (BR-DEC).
6#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
7pub struct Amount(Decimal);
8
9impl Amount {
10    pub const ZERO: Self = Self(Decimal::ZERO);
11
12    pub fn new(value: Decimal) -> Self {
13        Self(value.round_dp(2))
14    }
15
16    pub fn from_minor(cents: i64) -> Self {
17        Self(Decimal::new(cents, 2))
18    }
19
20    pub fn parse(s: &str) -> Result<Self, rust_decimal::Error> {
21        Ok(Self::new(Decimal::from_str(s)?))
22    }
23
24    pub fn raw(self) -> Decimal {
25        self.0
26    }
27
28    pub fn is_zero(self) -> bool {
29        self.0.is_zero()
30    }
31
32    pub fn saturating_add(self, other: Self) -> Self {
33        Self::new(self.0 + other.0)
34    }
35
36    pub fn saturating_sub(self, other: Self) -> Self {
37        Self::new(self.0 - other.0)
38    }
39}
40
41impl fmt::Display for Amount {
42    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43        write!(f, "{}", self.0.round_dp(2))
44    }
45}
46
47impl From<Decimal> for Amount {
48    fn from(value: Decimal) -> Self {
49        Self::new(value)
50    }
51}