use chrono::{DateTime, Utc};
use rust_decimal::Decimal;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
use crate::types::wire::wire_enum;
wire_enum! {
pub enum SettlementStatus {
Pending => "PENDING",
AwaitingAdditionalFunds => "AWAITING_ADDITIONAL_FUNDS",
Completed => "COMPLETED",
Failed => "FAILED",
}
}
wire_enum! {
pub enum SettlementAssetClass {
UsEquity => "us_equity",
Crypto => "crypto",
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct TransmitterInfo {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub originator_full_name: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub originator_bank_name: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub originator_bank_account_number: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub originator_street_address: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub originator_city: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub originator_state: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub originator_postal_code: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub originator_country: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub other_identifying_information: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct Settlement {
pub id: Uuid,
pub status: SettlementStatus,
#[serde(with = "crate::types::decimal")]
pub total_amount: Decimal,
#[serde(default, with = "crate::types::option_decimal")]
pub interest_amount: Option<Decimal>,
#[serde(default)]
pub asset_class: Option<SettlementAssetClass>,
#[serde(default)]
pub currency: Option<crate::types::SupportedCurrencies>,
#[serde(default)]
pub source_account_number: Option<String>,
#[serde(default)]
pub reason: Option<String>,
#[serde(default)]
pub additional_info: Option<String>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
#[serde(default)]
pub completed_at: Option<DateTime<Utc>>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct Settlements {
#[serde(
default,
deserialize_with = "crate::types::serde_util::null_as_default"
)]
pub settlements: Vec<Settlement>,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct GetSettlementsRequest {
#[serde(
default,
skip_serializing_if = "Option::is_none",
serialize_with = "crate::types::serde_util::comma_separated"
)]
pub statuses: Option<Vec<SettlementStatus>>,
}
impl GetSettlementsRequest {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn statuses(mut self, statuses: Vec<SettlementStatus>) -> Self {
self.statuses = Some(statuses);
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn settlement_statuses_are_upper_case_and_underscored() {
assert_eq!(
SettlementStatus::AwaitingAdditionalFunds.as_str(),
"AWAITING_ADDITIONAL_FUNDS"
);
}
#[test]
fn statuses_render_as_one_comma_separated_parameter() {
let request = GetSettlementsRequest::new()
.statuses(vec![SettlementStatus::Pending, SettlementStatus::Failed]);
let json = serde_json::to_value(&request).unwrap();
assert_eq!(json["statuses"], "PENDING,FAILED");
}
}