use std::fmt;
use chrono::{DateTime, FixedOffset, NaiveDate};
use rust_decimal::Decimal;
use serde::{Deserialize, Serialize};
macro_rules! redacted_debug {
($name:ident) => {
impl $name {
pub fn populated_fields(&self) -> usize {
populated(self)
}
}
impl fmt::Debug for $name {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
concat!(stringify!($name), "(<redacted, {} field(s) present>)"),
self.populated_fields()
)
}
}
impl fmt::Display for $name {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<redacted {}>", stringify!($name))
}
}
};
}
fn populated(value: &impl Serialize) -> usize {
serde_json::to_value(value)
.ok()
.and_then(|value| match value {
serde_json::Value::Object(map) => Some(map.values().filter(|v| !v.is_null()).count()),
_ => None,
})
.unwrap_or(0)
}
#[derive(Serialize, Deserialize, Clone, Default)]
pub struct PermittedAccountType {
#[serde(default)]
pub name: Option<String>,
#[serde(default)]
pub description: Option<String>,
#[serde(default)]
pub has_multiple_owners: Option<bool>,
#[serde(default)]
pub is_publicly_available: Option<bool>,
#[serde(default)]
pub is_tax_advantaged: Option<bool>,
#[serde(default)]
pub margin_types: Vec<PermittedMarginType>,
}
redacted_debug!(PermittedAccountType);
#[derive(Serialize, Deserialize, Clone, Default)]
pub struct PermittedMarginType {
#[serde(default)]
pub name: Option<String>,
#[serde(default)]
pub is_margin: Option<bool>,
}
redacted_debug!(PermittedMarginType);
#[derive(Serialize, Deserialize, Clone, Default)]
#[serde(rename_all = "kebab-case")]
pub struct CustomerAddress {
#[serde(default)]
pub city: Option<String>,
#[serde(default)]
pub country: Option<String>,
#[serde(default)]
pub is_domestic: Option<bool>,
#[serde(default)]
pub is_foreign: Option<bool>,
#[serde(default)]
pub postal_code: Option<String>,
#[serde(default)]
pub state_region: Option<String>,
#[serde(default)]
pub street_one: Option<String>,
#[serde(default)]
pub street_three: Option<String>,
#[serde(default)]
pub street_two: Option<String>,
}
redacted_debug!(CustomerAddress);
#[derive(Serialize, Deserialize, Clone, Default)]
#[serde(rename_all = "kebab-case")]
pub struct CustomerSuitability {
#[serde(default)]
pub id: Option<String>,
#[serde(default, with = "crate::types::wire::decimal_option")]
pub annual_net_income: Option<Decimal>,
#[serde(default)]
pub covered_options_trading_experience: Option<String>,
#[serde(default)]
pub customer_id: Option<i64>,
#[serde(default)]
pub employer_name: Option<String>,
#[serde(default)]
pub employment_status: Option<String>,
#[serde(default)]
pub futures_trading_experience: Option<String>,
#[serde(default)]
pub job_title: Option<String>,
#[serde(default, with = "crate::types::wire::decimal_option")]
pub liquid_net_worth: Option<Decimal>,
#[serde(default)]
pub marital_status: Option<String>,
#[serde(default, with = "crate::types::wire::decimal_option")]
pub net_worth: Option<Decimal>,
#[serde(default)]
pub number_of_dependents: Option<i64>,
#[serde(default)]
pub occupation: Option<String>,
#[serde(default)]
pub stock_trading_experience: Option<String>,
#[serde(default)]
pub tax_bracket: Option<String>,
#[serde(default)]
pub uncovered_options_trading_experience: Option<String>,
}
redacted_debug!(CustomerSuitability);
#[derive(Serialize, Deserialize, Clone, Default)]
#[serde(rename_all = "kebab-case")]
pub struct CustomerPerson {
#[serde(default)]
pub external_id: Option<String>,
#[serde(default)]
pub first_name: Option<String>,
#[serde(default)]
pub last_name: Option<String>,
#[serde(default)]
pub middle_name: Option<String>,
#[serde(default)]
pub prefix_name: Option<String>,
#[serde(default)]
pub suffix_name: Option<String>,
#[serde(default)]
pub birth_country: Option<String>,
#[serde(default, with = "crate::types::wire::date_option")]
pub birth_date: Option<NaiveDate>,
#[serde(default)]
pub citizenship_country: Option<String>,
#[serde(default)]
pub usa_citizenship_type: Option<String>,
#[serde(default, with = "crate::types::wire::date_option")]
pub visa_expiration_date: Option<NaiveDate>,
#[serde(default)]
pub visa_type: Option<String>,
#[serde(default)]
pub employer_name: Option<String>,
#[serde(default)]
pub employment_status: Option<String>,
#[serde(default)]
pub job_title: Option<String>,
#[serde(default)]
pub marital_status: Option<String>,
#[serde(default)]
pub number_of_dependents: Option<i64>,
#[serde(default)]
pub occupation: Option<String>,
}
redacted_debug!(CustomerPerson);
#[derive(Serialize, Deserialize, Clone, Default)]
#[serde(rename_all = "kebab-case")]
pub struct EntityOfficer {
#[serde(default)]
pub id: Option<String>,
#[serde(default)]
pub external_id: Option<String>,
#[serde(default)]
pub first_name: Option<String>,
#[serde(default)]
pub last_name: Option<String>,
#[serde(default)]
pub middle_name: Option<String>,
#[serde(default)]
pub prefix_name: Option<String>,
#[serde(default)]
pub suffix_name: Option<String>,
#[serde(default)]
pub address: Option<CustomerAddress>,
#[serde(default)]
pub birth_country: Option<String>,
#[serde(default, with = "crate::types::wire::date_option")]
pub birth_date: Option<NaiveDate>,
#[serde(default)]
pub citizenship_country: Option<String>,
#[serde(default)]
pub email: Option<String>,
#[serde(default)]
pub employer_name: Option<String>,
#[serde(default)]
pub employment_status: Option<String>,
#[serde(default)]
pub home_phone_number: Option<String>,
#[serde(default)]
pub is_foreign: Option<String>,
#[serde(default)]
pub job_title: Option<String>,
#[serde(default)]
pub marital_status: Option<String>,
#[serde(default)]
pub mobile_phone_number: Option<String>,
#[serde(default)]
pub number_of_dependents: Option<i64>,
#[serde(default)]
pub occupation: Option<String>,
#[serde(default)]
pub owner_of_record: Option<bool>,
#[serde(default)]
pub relationship_to_entity: Option<String>,
#[serde(default)]
pub tax_number: Option<String>,
#[serde(default)]
pub tax_number_type: Option<String>,
#[serde(default)]
pub usa_citizenship_type: Option<String>,
#[serde(default, with = "crate::types::wire::date_option")]
pub visa_expiration_date: Option<NaiveDate>,
#[serde(default)]
pub visa_type: Option<String>,
#[serde(default)]
pub work_phone_number: Option<String>,
}
redacted_debug!(EntityOfficer);
#[derive(Serialize, Deserialize, Clone, Default)]
#[serde(rename_all = "kebab-case")]
pub struct EntitySuitability {
#[serde(default)]
pub id: Option<String>,
#[serde(default, with = "crate::types::wire::decimal_option")]
pub annual_net_income: Option<Decimal>,
#[serde(default)]
pub covered_options_trading_experience: Option<String>,
#[serde(default)]
pub entity_id: Option<i64>,
#[serde(default)]
pub futures_trading_experience: Option<String>,
#[serde(default, with = "crate::types::wire::decimal_option")]
pub liquid_net_worth: Option<Decimal>,
#[serde(default, with = "crate::types::wire::decimal_option")]
pub net_worth: Option<Decimal>,
#[serde(default)]
pub stock_trading_experience: Option<String>,
#[serde(default)]
pub tax_bracket: Option<String>,
#[serde(default)]
pub uncovered_options_trading_experience: Option<String>,
}
redacted_debug!(EntitySuitability);
#[derive(Serialize, Deserialize, Clone, Default)]
#[serde(rename_all = "kebab-case")]
pub struct CustomerEntity {
#[serde(default)]
pub id: Option<String>,
#[serde(default)]
pub address: Option<CustomerAddress>,
#[serde(default)]
pub business_nature: Option<String>,
#[serde(default, with = "crate::types::wire::date_option")]
pub date_of_trust_creation: Option<NaiveDate>,
#[serde(default)]
pub email: Option<String>,
pub entity_officers: Option<Vec<EntityOfficer>>,
#[serde(default)]
pub entity_suitability: Option<EntitySuitability>,
#[serde(default)]
pub entity_type: Option<String>,
#[serde(default)]
pub foreign_institution: Option<String>,
#[serde(default, with = "crate::types::wire::date_option")]
pub grantor_birth_date: Option<NaiveDate>,
#[serde(default)]
pub grantor_email: Option<String>,
#[serde(default)]
pub grantor_first_name: Option<String>,
#[serde(default)]
pub grantor_last_name: Option<String>,
#[serde(default)]
pub grantor_middle_name: Option<String>,
#[serde(default)]
pub grantor_tax_number: Option<String>,
#[serde(default)]
pub has_foreign_bank_affiliation: Option<String>,
#[serde(default)]
pub has_foreign_institution_affiliation: Option<String>,
#[serde(default)]
pub is_domestic: Option<String>,
#[serde(default)]
pub is_hedge_fund: Option<String>,
#[serde(default)]
pub legal_name: Option<String>,
#[serde(default)]
pub mailing_address: Option<CustomerAddress>,
#[serde(default)]
pub phone_number: Option<String>,
#[serde(default)]
pub secretary_name: Option<String>,
#[serde(default)]
pub tax_election: Option<String>,
#[serde(default)]
pub tax_number: Option<String>,
}
redacted_debug!(CustomerEntity);
#[derive(Serialize, Deserialize, Clone, Default)]
#[serde(rename_all = "kebab-case")]
pub struct Customer {
#[serde(default)]
pub id: Option<String>,
#[serde(default)]
pub first_name: Option<String>,
#[serde(default)]
pub first_surname: Option<String>,
#[serde(default)]
pub last_name: Option<String>,
#[serde(default)]
pub middle_name: Option<String>,
#[serde(default)]
pub prefix_name: Option<String>,
#[serde(default)]
pub second_surname: Option<String>,
#[serde(default)]
pub suffix_name: Option<String>,
#[serde(default, with = "crate::types::wire::date_option")]
pub cherry_club_date: Option<NaiveDate>,
#[serde(default)]
pub address: Option<CustomerAddress>,
#[serde(default)]
pub customer_suitability: Option<CustomerSuitability>,
#[serde(default)]
pub mailing_address: Option<CustomerAddress>,
#[serde(default)]
pub is_foreign: Option<bool>,
#[serde(default)]
pub regulatory_domain: Option<String>,
#[serde(default)]
pub usa_citizenship_type: Option<String>,
#[serde(default)]
pub home_phone_number: Option<String>,
#[serde(default)]
pub home_phone_number_details: Option<String>,
#[serde(default)]
pub mobile_phone_number: Option<String>,
#[serde(default)]
pub mobile_phone_number_details: Option<String>,
#[serde(default)]
pub work_phone_number: Option<String>,
#[serde(default)]
pub work_phone_number_details: Option<String>,
#[serde(default, with = "crate::types::wire::date_option")]
pub birth_date: Option<NaiveDate>,
#[serde(default)]
pub email: Option<String>,
#[serde(default)]
pub external_id: Option<String>,
#[serde(default)]
pub foreign_tax_number: Option<String>,
#[serde(default)]
pub tax_number: Option<String>,
#[serde(default)]
pub tax_number_type: Option<String>,
#[serde(default)]
pub birth_country: Option<String>,
#[serde(default)]
pub citizenship_country: Option<String>,
#[serde(default, with = "crate::types::wire::date_option")]
pub visa_expiration_date: Option<NaiveDate>,
#[serde(default)]
pub visa_type: Option<String>,
#[serde(default)]
pub agreed_to_margining: Option<bool>,
#[serde(default)]
pub subject_to_tax_withholding: Option<bool>,
#[serde(default)]
pub agreed_to_terms: Option<bool>,
#[serde(default)]
pub signature_of_agreement: Option<bool>,
#[serde(default)]
pub desk_customer_id: Option<String>,
#[serde(default)]
pub ext_crm_id: Option<String>,
#[serde(default)]
pub family_member_names: Option<String>,
#[serde(default)]
pub gender: Option<String>,
#[serde(default)]
pub has_industry_affiliation: Option<bool>,
#[serde(default)]
pub has_institutional_assets: Option<String>,
#[serde(default)]
pub has_listed_affiliation: Option<bool>,
#[serde(default)]
pub has_political_affiliation: Option<bool>,
#[serde(default)]
pub industry_affiliation_firm: Option<String>,
#[serde(default)]
pub is_investment_adviser: Option<String>,
#[serde(default)]
pub listed_affiliation_symbol: Option<String>,
#[serde(default)]
pub political_organization: Option<String>,
#[serde(default)]
pub user_id: Option<String>,
#[serde(default)]
pub has_delayed_quotes: Option<bool>,
#[serde(default)]
pub has_pending_or_approved_application: Option<bool>,
#[serde(default)]
pub is_professional: Option<bool>,
#[serde(default)]
pub permitted_account_types: Option<Vec<PermittedAccountType>>,
#[serde(default, with = "crate::types::wire::datetime_option")]
pub created_at: Option<DateTime<FixedOffset>>,
#[serde(default)]
pub entity: Option<CustomerEntity>,
#[serde(default)]
pub identifiable_type: Option<String>,
#[serde(default)]
pub person: Option<CustomerPerson>,
}
redacted_debug!(Customer);