use crate::v1::{Client, error, BASE_URL, standard};
use serde::Deserialize;
#[derive(Deserialize, Debug)]
pub struct ListAccountsResponse {
pub data: Vec<AccountResource>,
pub links: ResponseLinks,
}
#[derive(Deserialize, Debug)]
pub struct GetAccountResponse {
pub data: AccountResource,
}
#[derive(Deserialize, Debug)]
pub struct AccountResource {
pub r#type: String,
pub id: String,
pub attributes: Attributes,
pub relationships: Relationships,
pub links: Option<AccountResourceLinks>,
}
#[derive(Deserialize, Debug)]
pub struct AccountResourceLinks {
#[serde(rename = "self")]
pub this: Option<String>,
}
#[derive(Deserialize, Debug)]
pub struct ResponseLinks {
pub prev: Option<String>,
pub next: Option<String>,
}
#[derive(Deserialize, Debug)]
pub struct Relationships {
pub transactions: Transactions,
}
#[derive(Deserialize, Debug)]
pub struct Transactions {
pub links: Option<TransactionLinks>,
}
#[derive(Deserialize, Debug)]
pub struct TransactionLinks {
pub related: String,
}
#[derive(Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct Attributes {
pub display_name: String,
pub account_type: AccountType,
pub ownership_type: OwnershipType,
pub balance: standard::MoneyObject,
pub created_at: String,
}
#[derive(Deserialize, Debug)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum AccountType {
Saver,
Transactional,
}
#[derive(Deserialize, Debug)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum OwnershipType {
Individual,
Joint,
}
#[derive(Default)]
pub struct ListAccountsOptions {
page_size: Option<u8>,
filter_account_type: Option<String>,
filter_ownership_type: Option<String>,
}
impl ListAccountsOptions {
pub fn page_size(&mut self, value: u8) {
self.page_size = Some(value);
}
pub fn filter_account_type(&mut self, value: String) {
self.filter_account_type = Some(value);
}
pub fn filter_ownership_type(&mut self, value: String) {
self.filter_ownership_type = Some(value);
}
fn add_params(&self, url: &mut reqwest::Url) {
let mut query = String::new();
if let Some(value) = &self.page_size {
if !query.is_empty() {
query.push('&');
}
query.push_str(&format!("page[size]={}", value));
}
if let Some(value) = &self.filter_account_type {
if !query.is_empty() {
query.push('&');
}
query.push_str(
&format!("filter[accountType]={}", urlencoding::encode(value))
);
}
if let Some(value) = &self.filter_ownership_type {
if !query.is_empty() {
query.push('&');
}
query.push_str(
&format!("filter[ownershipType]={}", urlencoding::encode(value))
);
}
if !query.is_empty() {
url.set_query(Some(&query));
}
}
}
impl Client {
pub async fn list_accounts(
&self,
options: &ListAccountsOptions,
) -> Result<ListAccountsResponse, error::Error> {
let mut url = reqwest::Url::parse(
&format!("{}/accounts", BASE_URL)
).map_err(error::Error::UrlParse)?;
options.add_params(&mut url);
let res = reqwest::Client::new()
.get(url)
.header("Authorization", self.auth_header())
.send()
.await
.map_err(error::Error::Request)?;
match res.status() {
reqwest::StatusCode::OK => {
let body = res.text().await.map_err(error::Error::BodyRead)?;
let account_response: ListAccountsResponse =
serde_json::from_str(&body).map_err(error::Error::Json)?;
Ok(account_response)
},
_ => {
let body = res.text().await.map_err(error::Error::BodyRead)?;
let error: error::ErrorResponse =
serde_json::from_str(&body).map_err(error::Error::Json)?;
Err(error::Error::Api(error))
}
}
}
pub async fn get_account(
&self,
id: &str,
) -> Result<GetAccountResponse, error::Error> {
if id.is_empty() {
panic!("The provided account ID must not be empty.");
}
let url = reqwest::Url::parse(
&format!("{}/accounts/{}", BASE_URL, id)
).map_err(error::Error::UrlParse)?;
let res = reqwest::Client::new()
.get(url)
.header("Authorization", self.auth_header())
.send()
.await
.map_err(error::Error::Request)?;
match res.status() {
reqwest::StatusCode::OK => {
let body = res.text().await.map_err(error::Error::BodyRead)?;
let account_response: GetAccountResponse =
serde_json::from_str(&body).map_err(error::Error::Json)?;
Ok(account_response)
},
_ => {
let body = res.text().await.map_err(error::Error::BodyRead)?;
let error: error::ErrorResponse =
serde_json::from_str(&body).map_err(error::Error::Json)?;
Err(error::Error::Api(error))
}
}
}
}
implement_pagination_v1!(ListAccountsResponse);