use std::fmt;
use derive_builder::Builder;
use serde::{Deserialize, Serialize};
use crate::Domain;
use super::{Authorization, Subscription, TransactionStatusData};
#[derive(Debug, Deserialize, Serialize, Clone, Default)]
pub struct CustomerResponseData {
pub id: u64,
pub integration: Option<u64>,
pub domain: Option<Domain>,
pub identified: Option<bool>,
pub first_name: Option<String>,
pub last_name: Option<String>,
pub email: String,
pub customer_code: String,
pub phone: Option<String>,
pub metadata: Option<CustomerMetaData>,
pub risk_action: Option<RiskAction>,
pub international_format_phone: Option<String>,
pub identification: Option<String>,
pub transactions: Option<Vec<TransactionStatusData>>,
pub subscriptions: Option<Vec<Subscription>>,
pub authorizations: Option<Vec<Authorization>>,
#[serde(rename = "createdAt")]
pub created_at: Option<String>,
#[serde(rename = "updatedAt")]
pub updated_at: Option<String>,
pub total_transactions: Option<u16>,
pub total_transaction_value: Option<Vec<String>>,
pub dedicated_account: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CustomerMetaData {
pub calling_code: Option<String>,
}
#[derive(Debug, Clone, Serialize, Default, Deserialize, Builder)]
pub struct CreateCustomerRequest {
pub email: String,
#[builder(setter(strip_option), default)]
pub first_name: Option<String>,
#[builder(setter(strip_option), default)]
pub last_name: Option<String>,
#[builder(setter(strip_option), default)]
pub phone: Option<String>,
}
#[derive(Debug, Clone, Serialize, Default, Deserialize, Builder)]
pub struct UpdateCustomerRequest {
#[builder(setter(strip_option), default)]
pub first_name: Option<String>,
#[builder(setter(strip_option), default)]
pub last_name: Option<String>,
#[builder(setter(strip_option), default)]
pub phone: Option<String>,
}
#[derive(Debug, Clone, Serialize, Default, Deserialize, Builder)]
pub struct ValidateCustomerRequest {
pub first_name: String,
pub last_name: String,
#[builder(setter(strip_option), default)]
pub middle_name: Option<String>,
#[serde(rename = "type")]
pub identification_type: IdentificationType,
#[builder(setter(strip_option), default)]
pub value: Option<String>,
pub country: String,
pub bvn: String,
pub bank_code: String,
#[builder(setter(strip_option), default)]
pub account_number: Option<String>,
}
#[derive(Debug, Serialize, Default, Deserialize, Clone, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum IdentificationType {
#[default]
#[serde(rename = "bank_account")]
BankAccount,
}
impl fmt::Display for IdentificationType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let identification_type = match self {
IdentificationType::BankAccount => "bank_account",
};
write!(f, "{identification_type}")
}
}
#[derive(Debug, Serialize, Default, Deserialize, Clone, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum RiskAction {
#[default]
Default,
Allow,
Deny,
}
impl fmt::Display for RiskAction {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let risk_action = match self {
RiskAction::Allow => "allow",
RiskAction::Default => "default",
RiskAction::Deny => "deny",
};
write!(f, "{risk_action}")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn can_build_customer() {
let customer = CreateCustomerRequestBuilder::default()
.email("customer@example.com".to_string())
.first_name("Zero".to_string())
.last_name("Sum".to_string())
.phone("+2348123456789".to_string())
.build()
.expect("unable to build customer request");
assert_eq!(customer.first_name, Some("Zero".to_string()));
assert_eq!(customer.last_name, Some("Sum".to_string()));
}
#[test]
fn build_customer_with_invalid_data_fails() {
let first_name = "Zero".to_string();
let last_name = "Sum".to_string();
let phone = "+2348123456789".to_string();
let body = CreateCustomerRequestBuilder::default()
.first_name(first_name)
.last_name(last_name)
.phone(phone)
.build();
assert!(body.is_err());
}
#[test]
fn can_use_identification_type() {
let identification = IdentificationType::BankAccount;
assert_eq!(identification.to_string(), "bank_account".to_string());
}
}