konduto/types/orders/
installments.rs

1use crate::types::validation_errors::ValidationError;
2use serde::{Deserialize, Serialize};
3use std::fmt;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
6#[repr(transparent)]
7pub struct Installments(u16);
8
9impl Installments {
10    const MIN: u16 = 1;
11    const MAX: u16 = 999;
12
13    pub fn new(value: u16) -> Result<Self, ValidationError> {
14        if !(Self::MIN..=Self::MAX).contains(&value) {
15            return Err(ValidationError::InvalidFormat {
16                field: "installments".to_string(),
17                message: format!(
18                    "installments must be between {} and {}, received: {}",
19                    Self::MIN,
20                    Self::MAX,
21                    value
22                ),
23            });
24        }
25
26        Ok(Self(value))
27    }
28
29    pub fn value(&self) -> u16 {
30        self.0
31    }
32
33    /// Verifica se é à vista (1 parcela)
34    pub fn is_cash(&self) -> bool {
35        self.0 == 1
36    }
37
38    pub fn is_installment(&self) -> bool {
39        self.0 > 1
40    }
41}
42
43impl fmt::Display for Installments {
44    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45        if self.0 == 1 {
46            write!(f, "à vista")
47        } else {
48            write!(f, "{}x", self.0)
49        }
50    }
51}
52
53#[cfg(test)]
54mod tests {
55    use super::*;
56
57    #[test]
58    fn test_installments_valid() {
59        let installments = Installments::new(2).unwrap();
60        assert_eq!(installments.value(), 2);
61    }
62
63    #[test]
64    fn test_installments_cash() {
65        let installments = Installments::new(1).unwrap();
66        assert!(installments.is_cash());
67        assert!(!installments.is_installment());
68    }
69
70    #[test]
71    fn test_installments_multiple() {
72        let installments = Installments::new(12).unwrap();
73        assert!(!installments.is_cash());
74        assert!(installments.is_installment());
75    }
76
77    #[test]
78    fn test_installments_min() {
79        let installments = Installments::new(1).unwrap();
80        assert_eq!(installments.value(), 1);
81    }
82
83    #[test]
84    fn test_installments_max() {
85        let installments = Installments::new(999).unwrap();
86        assert_eq!(installments.value(), 999);
87    }
88
89    #[test]
90    fn test_installments_zero() {
91        let result = Installments::new(0);
92        assert!(result.is_err());
93    }
94
95    #[test]
96    fn test_installments_too_high() {
97        let result = Installments::new(1000);
98        assert!(result.is_err());
99    }
100
101    #[test]
102    fn test_installments_display() {
103        let cash = Installments::new(1).unwrap();
104        assert_eq!(cash.to_string(), "à vista");
105
106        let installment = Installments::new(3).unwrap();
107        assert_eq!(installment.to_string(), "3x");
108    }
109}
110