konduto/types/orders/
installments.rs1use 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 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