use derive_builder::Builder;
use serde::{Deserialize, Serialize};
use crate::{Authorization, Channel, Currency, CustomerResponseData};
#[derive(Clone, Default, Debug, Serialize, Builder)]
pub struct TransactionRequest {
pub amount: String,
pub email: String,
#[builder(setter(strip_option), default)]
pub currency: Option<Currency>,
#[builder(setter(strip_option), default)]
pub reference: Option<String>,
#[builder(setter(strip_option), default)]
pub callback_url: Option<String>,
#[builder(setter(strip_option), default)]
pub plan: Option<String>,
#[builder(setter(strip_option), default)]
pub invoice_limit: Option<u8>,
#[builder(setter(strip_option), default)]
pub metadata: Option<String>,
#[builder(setter(strip_option), default)]
pub channel: Option<Vec<Channel>>,
#[builder(setter(strip_option), default)]
pub split_code: Option<String>,
#[builder(setter(strip_option), default)]
pub subaccount: Option<String>,
#[builder(setter(strip_option), default)]
pub transaction_charge: Option<String>,
#[builder(setter(strip_option), default)]
pub bearer: Option<String>,
}
#[derive(Debug, Clone, Serialize, Default, Builder)]
pub struct PartialDebitTransactionRequest {
authorization_code: String,
currency: Currency,
amount: String,
email: String,
#[builder(default)]
reference: Option<String>,
#[builder(default)]
at_least: Option<String>,
}
#[derive(Deserialize, Debug, Clone, Default)]
pub struct TransactionResponseData {
pub authorization_url: String,
pub access_code: String,
pub reference: String,
}
#[derive(Deserialize, Serialize, Debug, Clone, Default)]
pub struct TransactionStatusData {
pub id: u64,
pub status: String,
pub reference: String,
pub amount: u32,
pub message: Option<String>,
pub gateway_response: String,
pub paid_at: Option<String>,
pub created_at: String,
pub channel: String,
pub currency: String,
pub ip_address: Option<String>,
pub metadata: Option<String>,
pub fees: Option<i32>,
pub customer: CustomerResponseData,
pub authorization: Authorization,
}
#[derive(Deserialize, Serialize, Debug, Clone, Default)]
pub struct TransactionTimelineData {
pub time_spent: Option<u32>,
pub attempts: Option<u32>,
pub authentication: Option<String>,
pub errors: Option<u32>,
pub success: Option<bool>,
pub mobile: Option<bool>,
pub input: Option<String>,
pub channel: Option<String>,
pub history: Option<Vec<TransactionHistoryResponse>>,
}
#[derive(Deserialize, Serialize, Debug, Clone)]
pub struct TransactionHistoryResponse {
#[serde(rename = "type")]
pub action_type: String,
pub message: String,
pub time: u32,
}
#[derive(Debug, Deserialize, Serialize, Default)]
pub struct TransactionTotalData {
pub total_transactions: Option<u32>,
pub unique_customers: Option<u32>,
pub total_volume: Option<u32>,
pub total_volume_by_currency: Option<Vec<VolumeByCurrency>>,
pub pending_transfers: Option<u32>,
pub pending_transfers_by_currency: Option<Vec<VolumeByCurrency>>,
}
#[derive(Debug, Deserialize, Serialize, Default)]
pub struct VolumeByCurrency {
pub currency: String,
pub amount: u32,
}
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct ExportTransactionData {
pub path: String,
}
pub enum TransactionIdentifier {
Id(u64),
Reference(String),
}
#[cfg(test)]
mod test {
use super::*;
use std::error::Error;
#[test]
fn can_create_transaction_body_with_builder() -> Result<(), Box<dyn Error>> {
let transaction = TransactionRequestBuilder::default()
.amount(String::from("10000"))
.email(String::from("email@example.com"))
.currency(Currency::NGN)
.build()?;
assert_eq!(transaction.email, "email@example.com");
assert_eq!(transaction.amount, "10000");
assert_eq!(transaction.currency, Some(Currency::NGN));
assert_eq!(transaction.bearer, None);
Ok(())
}
#[test]
fn cannot_create_transaction_body_without_compulsory_field() -> Result<(), Box<dyn Error>> {
let transaction = TransactionRequestBuilder::default()
.currency(Currency::GHS)
.build();
assert!(transaction.is_err());
Ok(())
}
}