Skip to main content

domain/money/
mod.rs

1use serde::{Deserialize, Deserializer, Serialize};
2
3/// Result type returned by fallible money operations.
4pub type Result<T> = std::result::Result<T, Error>;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
7/// Validation failures returned by money domain constructors.
8pub enum Error {
9    #[error("money amount must contain at least one minor unit")]
10    /// Signals that amount was blank or missing during money validation.
11    EmptyAmount,
12}
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
15/// Typed minor units domain value that keeps raw primitives out of money workflows.
16pub struct MinorUnits(u32);
17
18impl MinorUnits {
19    /// Promotes a positive minor-unit amount into a money value for resort charges.
20    pub fn try_new(value: u32) -> Result<Self> {
21        if value == 0 {
22            return Err(Error::EmptyAmount);
23        }
24        Ok(Self(value))
25    }
26
27    /// Exposes the validated scalar for serialization and adapter boundaries.
28    pub const fn get(self) -> u32 {
29        self.0
30    }
31}
32
33impl<'de> Deserialize<'de> for MinorUnits {
34    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
35    where
36        D: Deserializer<'de>,
37    {
38        Self::try_new(u32::deserialize(deserializer)?).map_err(serde::de::Error::custom)
39    }
40}
41
42#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
43/// Domain vocabulary for currency decisions in money workflows.
44pub enum Currency {
45    /// US dollars, the supported currency for resort charges.
46    Usd,
47}
48
49#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
50/// Typed money domain value that keeps raw primitives out of money workflows.
51pub struct Money {
52    minor_units: MinorUnits,
53    currency: Currency,
54}
55
56impl Money {
57    /// Assembles a resort money amount from validated minor units and currency.
58    pub const fn new(minor_units: MinorUnits, currency: Currency) -> Self {
59        Self {
60            minor_units,
61            currency,
62        }
63    }
64
65    /// Returns the minor units carried by this money amount.
66    pub const fn minor_units(&self) -> MinorUnits {
67        self.minor_units
68    }
69
70    /// Returns the currency carried by this money amount.
71    pub const fn currency(&self) -> Currency {
72        self.currency
73    }
74}