use serde::{Deserialize, Serialize};
use crate::{AccountId, AuthorizationId, BankAccountNumber};
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
pub struct Account {
#[serde(rename = "_id")]
pub id: AccountId,
#[serde(default, skip_serializing_if = "Option::is_none", rename = "_migrated")]
pub migrated: Option<String>,
#[serde(rename = "_authorisation")]
pub authorisation: AuthorizationId,
#[deprecated(note = "Please use `authorisation` instead.")]
#[serde(
rename = "_credentials",
default,
skip_serializing_if = "Option::is_none"
)]
pub credentials: Option<AuthorizationId>,
pub name: String,
pub status: Active,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub formatted_acount: Option<String>,
pub refreshed: RefreshDetails,
pub balance: BalanceDetails,
#[serde(rename = "type")]
pub kind: BankAccountKind,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub attributes: Vec<Attribute>,
}
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
#[serde(rename_all = "UPPERCASE")]
pub enum Active {
Active,
Inactive,
}
impl Active {
pub const fn as_str(&self) -> &'static str {
match self {
Self::Active => "ACTIVE",
Self::Inactive => "INACTIVE",
}
}
pub const fn as_bytes(&self) -> &'static [u8] {
self.as_str().as_bytes()
}
}
impl std::str::FromStr for Active {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"ACTIVE" => Ok(Self::Active),
"INACTIVE" => Ok(Self::Inactive),
_ => Err(()),
}
}
}
impl std::convert::TryFrom<String> for Active {
type Error = ();
fn try_from(value: String) -> Result<Self, Self::Error> {
value.parse()
}
}
impl std::convert::TryFrom<&str> for Active {
type Error = ();
fn try_from(value: &str) -> Result<Self, Self::Error> {
value.parse()
}
}
impl std::fmt::Display for Active {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.as_str())
}
}
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
pub struct AccountMetadata {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub holder: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub has_unlisted_holders: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub payment_details: Option<PaymentDetails>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub loan_details: Option<LoanDetails>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub breakdown: Option<serde_json::Value>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub portfolio: Option<serde_json::Value>,
}
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
pub struct PaymentDetails {
pub account_holder: String,
pub account_number: BankAccountNumber,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub particulars: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub code: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub reference: Option<String>,
#[serde(
default,
skip_serializing_if = "Option::is_none",
with = "rust_decimal::serde::arbitrary_precision_option"
)]
pub minimum_amount: Option<rust_decimal::Decimal>,
}
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
pub struct LoanDetails {
pub purpose: String,
#[serde(rename = "type")]
pub loan_type: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub interest: Option<InterestDetails>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub is_interest_only: Option<bool>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub interest_only_expires_at: Option<chrono::DateTime<chrono::Utc>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub term: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub matures_at: Option<chrono::DateTime<chrono::Utc>>,
#[serde(
default,
skip_serializing_if = "Option::is_none",
with = "rust_decimal::serde::arbitrary_precision_option"
)]
pub initial_principal: Option<rust_decimal::Decimal>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub repayment: Option<RepaymentDetails>,
}
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
pub struct InterestDetails {
#[serde(with = "rust_decimal::serde::arbitrary_precision")]
pub rate: rust_decimal::Decimal,
#[serde(rename = "type")]
pub interest_type: String,
pub expires_at: Option<chrono::DateTime<chrono::Utc>>,
}
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
pub struct RepaymentDetails {
pub frequency: String,
pub next_date: Option<chrono::DateTime<chrono::Utc>>,
#[serde(with = "rust_decimal::serde::arbitrary_precision")]
pub next_amount: rust_decimal::Decimal,
}
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
pub struct RefreshDetails {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub balance: Option<chrono::DateTime<chrono::Utc>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub meta: Option<chrono::DateTime<chrono::Utc>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub transactions: Option<chrono::DateTime<chrono::Utc>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub party: Option<chrono::DateTime<chrono::Utc>>,
}
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
pub struct BalanceDetails {
#[serde(with = "rust_decimal::serde::arbitrary_precision")]
pub current: rust_decimal::Decimal,
#[serde(
default,
skip_serializing_if = "Option::is_none",
with = "rust_decimal::serde::arbitrary_precision_option"
)]
pub available: Option<rust_decimal::Decimal>,
#[serde(
default,
skip_serializing_if = "Option::is_none",
with = "rust_decimal::serde::arbitrary_precision_option"
)]
pub limit: Option<rust_decimal::Decimal>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub overdrawn: Option<bool>,
pub currency: iso_currency::Currency,
}
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
#[serde(rename_all = "UPPERCASE")]
pub enum BankAccountKind {
Checking,
Savings,
#[serde(rename = "CREDITCARD")]
CreditCard,
Loan,
Kiwisaver,
Investment,
#[serde(rename = "TERMDEPOSIT")]
TermDeposit,
Foreign,
Tax,
Rewards,
Wallet,
}
impl BankAccountKind {
pub const fn as_str(&self) -> &'static str {
match self {
Self::Checking => "CHECKING",
Self::Savings => "SAVINGS",
Self::CreditCard => "CREDITCARD",
Self::Loan => "LOAN",
Self::Kiwisaver => "KIWISAVER",
Self::Investment => "INVESTMENT",
Self::TermDeposit => "TERMDEPOSIT",
Self::Foreign => "FOREIGN",
Self::Tax => "TAX",
Self::Rewards => "REWARDS",
Self::Wallet => "WALLET",
}
}
pub const fn as_bytes(&self) -> &'static [u8] {
self.as_str().as_bytes()
}
}
impl std::str::FromStr for BankAccountKind {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"CHECKING" => Ok(Self::Checking),
"SAVINGS" => Ok(Self::Savings),
"CREDITCARD" => Ok(Self::CreditCard),
"LOAN" => Ok(Self::Loan),
"KIWISAVER" => Ok(Self::Kiwisaver),
"INVESTMENT" => Ok(Self::Investment),
"TERMDEPOSIT" => Ok(Self::TermDeposit),
"FOREIGN" => Ok(Self::Foreign),
"TAX" => Ok(Self::Tax),
"REWARDS" => Ok(Self::Rewards),
"WALLET" => Ok(Self::Wallet),
_ => Err(()),
}
}
}
impl std::convert::TryFrom<String> for BankAccountKind {
type Error = ();
fn try_from(value: String) -> Result<Self, Self::Error> {
value.parse()
}
}
impl std::convert::TryFrom<&str> for BankAccountKind {
type Error = ();
fn try_from(value: &str) -> Result<Self, Self::Error> {
value.parse()
}
}
impl std::fmt::Display for BankAccountKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.as_str())
}
}
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum Attribute {
Transactions,
TransferTo,
TransferFrom,
PaymentTo,
PaymentFrom,
}
impl Attribute {
pub const fn as_str(&self) -> &'static str {
match self {
Self::Transactions => "TRANSACTIONS",
Self::TransferTo => "TRANSFER_TO",
Self::TransferFrom => "TRANSFER_FROM",
Self::PaymentTo => "PAYMENT_TO",
Self::PaymentFrom => "PAYMENT_FROM",
}
}
pub const fn as_bytes(&self) -> &'static [u8] {
self.as_str().as_bytes()
}
}
impl std::str::FromStr for Attribute {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"TRANSACTIONS" => Ok(Self::Transactions),
"TRANSFER_TO" => Ok(Self::TransferTo),
"TRANSFER_FROM" => Ok(Self::TransferFrom),
"PAYMENT_TO" => Ok(Self::PaymentTo),
"PAYMENT_FROM" => Ok(Self::PaymentFrom),
_ => Err(()),
}
}
}
impl std::convert::TryFrom<String> for Attribute {
type Error = ();
fn try_from(value: String) -> Result<Self, Self::Error> {
value.parse()
}
}
impl std::convert::TryFrom<&str> for Attribute {
type Error = ();
fn try_from(value: &str) -> Result<Self, Self::Error> {
value.parse()
}
}
impl std::fmt::Display for Attribute {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.as_str())
}
}