crypto_pay_api/models/stats/
builder.rs1use chrono::{DateTime, Utc};
2
3use crate::{
4 error::{CryptoBotError, CryptoBotResult, ValidationErrorKind},
5 validation::FieldValidate,
6};
7
8use super::GetStatsParams;
9
10#[derive(Debug, Default)]
11pub struct GetStatsParamsBuilder {
12 start_at: Option<DateTime<Utc>>,
13 end_at: Option<DateTime<Utc>>,
14}
15
16impl GetStatsParamsBuilder {
17 pub fn new() -> Self {
19 Self::default()
20 }
21
22 pub fn start_at(mut self, start_at: DateTime<Utc>) -> Self {
25 self.start_at = Some(start_at);
26 self
27 }
28
29 pub fn end_at(mut self, end_at: DateTime<Utc>) -> Self {
32 self.end_at = Some(end_at);
33 self
34 }
35}
36
37impl FieldValidate for GetStatsParamsBuilder {
38 fn validate(&self) -> CryptoBotResult<()> {
39 let now = Utc::now();
40
41 if let Some(start) = self.start_at {
42 if start > now {
43 return Err(CryptoBotError::ValidationError {
44 kind: ValidationErrorKind::Range,
45 message: "start_at cannot be in the future".to_string(),
46 field: Some("start_at".to_string()),
47 });
48 }
49 }
50
51 if let (Some(start), Some(end)) = (self.start_at, self.end_at) {
52 if end < start {
53 return Err(CryptoBotError::ValidationError {
54 kind: ValidationErrorKind::Range,
55 message: "end_at cannot be earlier than start_at".to_string(),
56 field: Some("end_at".to_string()),
57 });
58 }
59 }
60
61 Ok(())
62 }
63}
64
65impl GetStatsParamsBuilder {
66 pub fn build(self) -> CryptoBotResult<GetStatsParams> {
67 self.validate()?;
68 Ok(GetStatsParams {
69 start_at: self.start_at,
70 end_at: self.end_at,
71 })
72 }
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78
79 #[test]
80 fn test_get_stats_params_builder() {
81 let params = GetStatsParamsBuilder::new().start_at(Utc::now()).build();
82
83 assert!(params.is_ok());
84 }
85
86 #[test]
87 fn test_get_stats_params_builder_invalid_start_at() {
88 let params = GetStatsParamsBuilder::new()
89 .start_at(Utc::now() + chrono::Duration::days(1))
90 .build();
91
92 assert!(matches!(
93 params,
94 Err(CryptoBotError::ValidationError {
95 kind: ValidationErrorKind::Range,
96 field: Some(field),
97 ..
98 }) if field == "start_at"
99 ));
100 }
101 #[test]
102 fn test_get_stats_params_builder_invalid_end_at() {
103 let params = GetStatsParamsBuilder::new()
104 .start_at(Utc::now())
105 .end_at(Utc::now() - chrono::Duration::days(1))
106 .build();
107
108 assert!(matches!(
109 params,
110 Err(CryptoBotError::ValidationError {
111 kind: ValidationErrorKind::Range,
112 field: Some(field),
113 ..
114 }) if field == "end_at"
115 ));
116 }
117
118 #[test]
119 fn test_get_stats_params_builder_invalid_end_at_and_start_at() {
120 let params = GetStatsParamsBuilder::new()
121 .start_at(Utc::now() - chrono::Duration::days(2))
122 .end_at(Utc::now() - chrono::Duration::days(3))
123 .build();
124
125 assert!(matches!(
126 params,
127 Err(CryptoBotError::ValidationError {
128 kind: ValidationErrorKind::Range,
129 field: Some(field),
130 ..
131 }) if field == "end_at"
132 ));
133 }
134}