Skip to main content

up_bank_api/
transactions.rs

1use restson::RestPath;
2use serde::{Deserialize, Serialize};
3
4use crate::{
5    accounts::AccountId,
6    categories::CategoryRelationship,
7    general::{
8        CashbackObject, MoneyObject, PageLink, Pagination, RelationLink, RelationshipsLink,
9        RoundUp, TimeObject,
10    },
11    tags::TagId,
12};
13
14#[derive(Serialize, Debug)]
15pub struct TransactionId {
16    id: String,
17}
18
19impl TransactionId {
20    pub fn id(&self) -> &str {
21        &self.id
22    }
23}
24
25impl<'de> Deserialize<'de> for TransactionId {
26    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
27    where
28        D: serde::Deserializer<'de>,
29    {
30        let s: String = Deserialize::deserialize(deserializer)?;
31        Ok(TransactionId { id: s })
32    }
33}
34
35#[derive(Serialize, Deserialize, Debug)]
36pub struct TransactionHoldInfo {
37    pub amount: MoneyObject,
38    #[serde(alias = "foreignAmount")]
39    pub foreign_amount: MoneyObject,
40}
41
42#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
43pub enum TransactionStatus {
44    #[serde(alias = "held")]
45    HELD,
46    #[serde(alias = "settled")]
47    SETTLED,
48}
49
50#[derive(Serialize, Deserialize, Debug)]
51pub struct TransactionAttributes {
52    pub status: TransactionStatus,
53    #[serde(alias = "rawText")]
54    pub raw_text: Option<String>,
55    pub description: String,
56    pub message: Option<String>,
57    #[serde(alias = "isCategorizable")]
58    pub is_categorizable: bool,
59    #[serde(alias = "holdAmount")]
60    pub hold_info: Option<TransactionHoldInfo>,
61    #[serde(alias = "roundUp")]
62    pub round_up: Option<RoundUp>,
63    pub cashback: Option<CashbackObject>,
64    pub amount: MoneyObject,
65    #[serde(alias = "foreignAmount")]
66    pub foreign_amount: Option<MoneyObject>,
67    #[serde(alias = "settledAt")]
68    pub settled_at: Option<TimeObject>,
69    #[serde(alias = "createdAt")]
70    pub created_at: TimeObject,
71}
72
73#[derive(Serialize, Deserialize, Debug)]
74pub struct AccountRelationship {
75    pub id: AccountId,
76}
77
78#[derive(Serialize, Deserialize, Debug)]
79pub struct AccountObject {
80    pub data: Option<AccountRelationship>,
81    pub links: Option<RelationshipsLink>,
82}
83
84#[derive(Serialize, Deserialize, Debug, Clone)]
85pub struct CategoryLinks {
86    #[serde(rename = "self")]
87    pub self_link: Option<String>,
88    pub related: Option<String>,
89}
90
91#[derive(Serialize, Deserialize, Debug, Clone)]
92pub struct CategoryObject {
93    pub data: Option<CategoryRelationship>,
94    pub links: Option<CategoryLinks>,
95}
96
97#[derive(Serialize, Deserialize, Debug)]
98pub struct TransactionTagsData {
99    pub id: TagId,
100}
101
102#[derive(Serialize, Deserialize, Debug)]
103pub struct TransactionTagLink {
104    #[serde(rename = "self")]
105    pub self_link: RelationLink,
106}
107
108#[derive(Serialize, Deserialize, Debug)]
109pub struct TransactionTags {
110    pub data: Vec<TransactionTagsData>,
111    pub links: Option<TransactionTagLink>,
112}
113
114#[derive(Serialize, Deserialize, Debug)]
115pub struct TransactionRelationships {
116    pub account: AccountObject,
117    #[serde(alias = "transferAccount")]
118    pub transfer_account: Option<AccountObject>,
119    pub category: CategoryObject,
120    #[serde(alias = "parentCategory")]
121    pub parent_category: CategoryObject,
122    pub tags: TransactionTags,
123}
124
125#[derive(Serialize, Deserialize, Debug)]
126pub struct TransactionData {
127    pub id: TransactionId,
128    pub attributes: TransactionAttributes,
129    pub relationships: TransactionRelationships,
130}
131
132#[derive(Serialize, Deserialize, Debug)]
133pub struct TransactionListResponse {
134    pub data: Vec<TransactionData>,
135    pub links: Pagination<TransactionListResponse>,
136}
137
138#[derive(Serialize, Deserialize, Debug)]
139pub struct TransactionResponse {
140    pub data: TransactionData,
141}
142
143impl RestPath<()> for TransactionListResponse {
144    fn get_path(_: ()) -> Result<String, restson::Error> {
145        Ok(String::from("transactions"))
146    }
147}
148
149impl RestPath<&PageLink<TransactionListResponse>> for TransactionListResponse {
150    fn get_path(link: &PageLink<TransactionListResponse>) -> Result<String, restson::Error> {
151        let url = String::from("transactions?") + link.params();
152        println!("Link: {}", url);
153        Ok(url)
154    }
155}
156
157impl RestPath<&AccountId> for TransactionListResponse {
158    fn get_path(par: &AccountId) -> Result<String, restson::Error> {
159        let url = format!("accounts/{}/transactions", par.id());
160        Ok(url)
161    }
162}
163
164impl RestPath<TransactionId> for TransactionResponse {
165    fn get_path(id: TransactionId) -> Result<String, restson::Error> {
166        Ok(String::from("transactions/") + &id.id)
167    }
168}