1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
//! Transaction Split
//! =================
//! This file contains the structs and definitions need to create
//! transaction splits for the Paystack API.
use crate::{error::PaystackError, BearerType, Currency, PaystackResult, SplitType};
use serde::Serialize;
/// This struct is used to create a split payment on your integration.
///
/// IMPORTANT: This class can obly be created using the TransactionSplitBuilder.
/// THe struct has the following fields:
/// - name: Name of the transaction split
/// - type: The type of transaction split you want to create.
/// You can use one of the following: percentage | flat.
/// - currency: Any of NGN, GHS, ZAR, or USD
/// - subaccounts: A list of object containing subaccount
/// code and number of shares
/// - bearer_type: Any of subaccount | account | all-proportional | all
/// - bearer_subaccount: Subaccount code
#[derive(Serialize, Debug, Default)]
pub struct TransactionSplit {
name: String,
#[serde(rename = "type")]
split_type: SplitType,
currency: Currency,
subaccounts: Vec<Subaccount>,
bearer_type: BearerType,
bearer_subaccount: String,
}
/// This struct represents the subacount that bears the transaction split
#[derive(Serialize, Debug, Clone)]
pub struct Subaccount {
/// This is the sub account code
pub subaccount: String,
/// This is the transaction share for the subaccount
pub share: u32,
}
impl Subaccount {
/// Creates a new subaccount for the Paystack API
pub fn new(subaccount: impl Into<String>, share: u32) -> Self {
Subaccount {
subaccount: subaccount.into(),
share,
}
}
}
/// A builder pattern implementation for constructing `PercentageSplit` instances.
///
/// The `PercentageSplitBuilder` struct provides a fluent and readable way to construct
/// instances of the `PercentageSplit` struct.
///
/// # Errors
///
/// Returns a `PaystackResult` with an `Err` variant if any required fields are missing,
/// including email, amount, and currency. The error indicates which field is missing.
///
/// # Examples
///
/// ```rust
/// use paystack::{Currency, SplitType, BearerType, PercentageSplitBuilder, Subaccount};
///
/// let sub_accounts = vec![
/// Subaccount::new(
/// "ACCT_z3x6z3nbo14xsil",
/// 20,
/// ),
/// Subaccount::new(
/// "ACCT_pwwualwty4nhq9d",
/// 30,
/// ),
/// ];
///
/// let percentage_split = PercentageSplitBuilder::new()
/// .name("Percentage Split")
/// .split_type(SplitType::Percentage)
/// .currency(Currency::NGN)
/// .add_subaccount(sub_accounts)
/// .bearer_type(BearerType::Subaccount)
/// .bearer_subaccount("ACCT_hdl8abxl8drhrl3")
/// .build();
/// ```
#[derive(Debug, Default, Clone)]
pub struct PercentageSplitBuilder {
name: Option<String>,
split_type: Option<SplitType>,
currency: Option<Currency>,
subaccounts: Option<Vec<Subaccount>>,
bearer_type: Option<BearerType>,
bearer_subaccount: Option<String>,
}
impl PercentageSplitBuilder {
/// Create a new instance of the Percentage Split builder with default properties
pub fn new() -> Self {
PercentageSplitBuilder::default()
}
/// Specify the transaction split name
pub fn name(mut self, name: impl Into<String>) -> Self {
self.name = Some(name.into());
self
}
/// Specify the transaction split amount
pub fn split_type(mut self, split_type: SplitType) -> Self {
self.split_type = Some(split_type);
self
}
/// Specify the transaction split currency
pub fn currency(mut self, currency: Currency) -> Self {
self.currency = Some(currency);
self
}
/// Specify the subaccount for the transaction split
pub fn add_subaccount(mut self, sub_accounts: Vec<Subaccount>) -> Self {
self.subaccounts = Some(sub_accounts);
self
}
/// Specify the bearer type for the transaction split
pub fn bearer_type(mut self, bearer_type: BearerType) -> Self {
self.bearer_type = Some(bearer_type);
self
}
/// Specify the bearer subaccount code
pub fn bearer_subaccount(mut self, code: impl Into<String>) -> Self {
self.bearer_subaccount = Some(code.into());
self
}
/// Build the TransactionSplit object
pub fn build(self) -> PaystackResult<TransactionSplit> {
let Some(name) = self.name else {
return Err(
PaystackError::TransactionSplit("name is required to create a transaction split".to_string())
)
};
let Some(split_type) = self.split_type else {
return Err(
PaystackError::TransactionSplit("split type is required to create a transaction split".to_string())
)
};
let Some(currency) = self.currency else {
return Err(
PaystackError::Transaction(
"currency is required to create a transaction split".to_string()
)
)
};
let Some(subaccounts) = self.subaccounts else {
return Err(
PaystackError::TransactionSplit(
"sub accounts are required to create a transaction split".to_string()
)
)
};
let Some(bearer_type) = self.bearer_type else {
return Err(
PaystackError::TransactionSplit(
"bearer type is required to create a transaction split".to_string()
)
)
};
let Some(bearer_subaccount) = self.bearer_subaccount else {
return Err(
PaystackError::TransactionSplit(
"bearer subaccount is required to create a transaction split".to_string()
)
)
};
Ok(TransactionSplit {
name,
split_type,
currency,
subaccounts,
bearer_type,
bearer_subaccount,
})
}
}