1use std::fmt;
2
3use derive_builder::Builder;
4use serde::{Deserialize, Serialize};
5
6use crate::Domain;
7
8use super::{Authorization, Subscription, TransactionStatusData};
9
10#[derive(Debug, Deserialize, Serialize, Clone, Default)]
12pub struct CustomerResponseData {
13 pub id: u64,
14 pub integration: Option<u64>,
15 pub domain: Option<Domain>,
16 pub identified: Option<bool>,
17 pub first_name: Option<String>,
18 pub last_name: Option<String>,
19 pub email: String,
20 pub customer_code: String,
21 pub phone: Option<String>,
22 pub metadata: Option<CustomerMetaData>,
23 pub risk_action: Option<RiskAction>,
24 pub international_format_phone: Option<String>,
25 pub identification: Option<String>,
26 pub transactions: Option<Vec<TransactionStatusData>>,
27 pub subscriptions: Option<Vec<Subscription>>,
28 pub authorizations: Option<Vec<Authorization>>,
29 #[serde(rename = "createdAt")]
30 pub created_at: Option<String>,
31 #[serde(rename = "updatedAt")]
32 pub updated_at: Option<String>,
33 pub total_transactions: Option<u16>,
34 pub total_transaction_value: Option<Vec<String>>,
35 pub dedicated_account: Option<String>,
36}
37
38#[derive(Debug, Clone, Serialize, Deserialize)]
39pub struct CustomerMetaData {
40 pub calling_code: Option<String>,
41}
42
43#[derive(Debug, Clone, Serialize, Default, Deserialize, Builder)]
45pub struct CreateCustomerRequest {
46 pub email: String,
48 #[builder(setter(strip_option), default)]
50 pub first_name: Option<String>,
51 #[builder(setter(strip_option), default)]
53 pub last_name: Option<String>,
54 #[builder(setter(strip_option), default)]
56 pub phone: Option<String>,
57}
58
59#[derive(Debug, Clone, Serialize, Default, Deserialize, Builder)]
61pub struct UpdateCustomerRequest {
62 #[builder(setter(strip_option), default)]
64 pub first_name: Option<String>,
65 #[builder(setter(strip_option), default)]
67 pub last_name: Option<String>,
68 #[builder(setter(strip_option), default)]
70 pub phone: Option<String>,
71}
72
73#[derive(Debug, Clone, Serialize, Default, Deserialize, Builder)]
74pub struct ValidateCustomerRequest {
75 pub first_name: String,
77 pub last_name: String,
79 #[builder(setter(strip_option), default)]
81 pub middle_name: Option<String>,
82 #[serde(rename = "type")]
84 pub identification_type: IdentificationType,
85 #[builder(setter(strip_option), default)]
87 pub value: Option<String>,
88 pub country: String,
90 pub bvn: String,
92 pub bank_code: String,
94 #[builder(setter(strip_option), default)]
96 pub account_number: Option<String>,
97}
98
99#[derive(Debug, Serialize, Default, Deserialize, Clone, PartialEq)]
103#[serde(rename_all = "lowercase")]
104pub enum IdentificationType {
105 #[default]
106 #[serde(rename = "bank_account")]
107 BankAccount,
108}
109
110impl fmt::Display for IdentificationType {
111 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112 let identification_type = match self {
113 IdentificationType::BankAccount => "bank_account",
114 };
115 write!(f, "{identification_type}")
116 }
117}
118
119#[derive(Debug, Serialize, Default, Deserialize, Clone, PartialEq)]
120#[serde(rename_all = "lowercase")]
121pub enum RiskAction {
122 #[default]
123 Default,
124 Allow,
125 Deny,
126}
127
128impl fmt::Display for RiskAction {
129 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
130 let risk_action = match self {
131 RiskAction::Allow => "allow",
132 RiskAction::Default => "default",
133 RiskAction::Deny => "deny",
134 };
135 write!(f, "{risk_action}")
136 }
137}
138
139#[cfg(test)]
140mod tests {
141 use super::*;
142
143 #[test]
144 fn can_build_customer() {
145 let customer = CreateCustomerRequestBuilder::default()
146 .email("customer@example.com".to_string())
147 .first_name("Zero".to_string())
148 .last_name("Sum".to_string())
149 .phone("+2348123456789".to_string())
150 .build()
151 .expect("unable to build customer request");
152
153 assert_eq!(customer.first_name, Some("Zero".to_string()));
154 assert_eq!(customer.last_name, Some("Sum".to_string()));
155 }
156
157 #[test]
158 fn build_customer_with_invalid_data_fails() {
159 let first_name = "Zero".to_string();
160 let last_name = "Sum".to_string();
161 let phone = "+2348123456789".to_string();
162
163 let body = CreateCustomerRequestBuilder::default()
164 .first_name(first_name)
165 .last_name(last_name)
166 .phone(phone)
167 .build();
168
169 assert!(body.is_err());
170 }
171
172 #[test]
173 fn can_use_identification_type() {
174 let identification = IdentificationType::BankAccount;
175
176 assert_eq!(identification.to_string(), "bank_account".to_string());
177 }
178}