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}