1#![doc = include_str!("../README.md")]
2#![deny(unsafe_code)]
3#![deny(clippy::pedantic)]
4#![allow(
5 clippy::struct_excessive_bools,
6 reason = "structs cannot be changed due to serialization"
7)]
8
9use chrono::{DateTime, Utc};
10use serde::Deserialize;
11
12use std::collections::HashMap;
13
14#[cfg(test)]
15mod tests;
16
17#[cfg(feature = "decode_everything")]
18pub type ExtraValues = HashMap<String, serde_json::Value>;
19
20#[derive(Clone, Debug, Deserialize)]
22pub struct Webhook {
23 pub r#type: String,
28 pub data: WebhookData,
29 #[cfg(feature = "decode_everything")]
30 #[cfg_attr(feature = "decode_everything", serde(flatten))]
31 pub extra: ExtraValues,
32}
33
34#[derive(Clone, Debug, Deserialize)]
35pub struct WebhookData {
36 pub id: String,
37 pub created: DateTime<Utc>,
38 pub description: String,
39 pub amount: i64,
41 pub currency: String,
43 pub is_load: bool,
44 pub settled: SettledTimestamp,
45 pub local_amount: i64,
47 pub local_currency: String,
49 pub merchant: Option<Merchant>,
50 pub merchant_feedback_uri: String,
51 pub notes: String,
52 pub metadata: WebhookMetadata,
53 pub category: String,
54 pub updated: DateTime<Utc>,
55 pub account_id: String,
56 pub user_id: String,
57 pub counterparty: CounterpartyOrNone,
58 pub scheme: String,
59 pub dedupe_id: String,
60 pub originator: bool,
61 pub include_in_spending: bool,
62 pub can_be_excluded_from_breakdown: bool,
63 pub can_be_made_subscription: bool,
64 pub can_split_the_bill: bool,
65 pub can_add_to_tab: bool,
66 pub can_match_transactions_in_categorization: bool,
67 pub amount_is_pending: bool,
68 pub parent_account_id: String,
69 pub categories: Option<HashMap<String, i64>>,
70 #[cfg(feature = "decode_everything")]
71 #[cfg_attr(feature = "decode_everything", serde(flatten))]
72 pub extra: ExtraValues,
73}
74
75#[derive(Clone, Debug, Deserialize)]
76#[serde(untagged)]
77pub enum SettledTimestamp {
78 Settled(DateTime<Utc>),
79 NotYetSettled(String),
81 #[cfg(feature = "decode_everything")]
82 SomethingElse(std::collections::HashMap<String, serde_json::Value>),
83}
84
85#[derive(Clone, Debug, Deserialize)]
86pub struct Merchant {
87 pub id: String,
88 pub group_id: String,
89 pub name: String,
90 pub logo: String,
91 pub emoji: String,
92 pub category: String,
93 pub online: bool,
94 pub atm: bool,
95 pub address: MerchantAddress,
96 pub disable_feedback: bool,
97 pub suggested_tags: String,
98 pub metadata: MerchantMetadata,
99 #[cfg(feature = "decode_everything")]
100 #[cfg_attr(feature = "decode_everything", serde(flatten))]
101 pub extra: ExtraValues,
102}
103
104#[derive(Clone, Debug, Deserialize)]
105pub struct MerchantAddress {
106 pub short_formatted: String,
107 pub city: String,
108 pub latitude: f64,
109 pub longitude: f64,
110 pub zoom_level: u64,
111 pub approximate: bool,
112 pub formatted: String,
113 pub address: String,
114 pub region: String,
115 pub country: String,
116 pub postcode: String,
117 #[cfg(feature = "decode_everything")]
118 #[cfg_attr(feature = "decode_everything", serde(flatten))]
119 pub extra: ExtraValues,
120}
121
122#[derive(Clone, Debug, Deserialize)]
123pub struct MerchantMetadata {
124 pub suggested_tags: String,
125 pub website: String,
126 #[cfg(feature = "decode_everything")]
127 #[cfg_attr(feature = "decode_everything", serde(flatten))]
128 pub extra: ExtraValues,
129}
130
131#[derive(Clone, Debug, Deserialize)]
132pub struct WebhookMetadata {
133 #[serde(flatten)]
134 pub subtype: WebhookMetadataSubtype,
135 pub ledger_committed_timestamp_earliest: DateTime<Utc>,
136 pub ledger_committed_timestamp_latest: DateTime<Utc>,
137 #[cfg(feature = "decode_everything")]
138 #[cfg_attr(feature = "decode_everything", serde(flatten))]
139 pub extra: ExtraValues,
140}
141
142#[derive(Clone, Debug, Deserialize)]
143#[serde(untagged)]
144pub enum WebhookMetadataSubtype {
145 FasterPayment(FasterPayment),
146 MoneyTransfer(MoneyTransfer),
147 MerchantTransaction(MerchantTransaction),
148 #[cfg(feature = "decode_everything")]
149 SomethingElse(std::collections::HashMap<String, serde_json::Value>),
150}
151
152#[derive(Clone, Debug, Deserialize)]
153#[serde(untagged)]
154pub enum CounterpartyOrNone {
155 Counterparty(Counterparty),
156 None {},
157 #[cfg(feature = "decode_everything")]
158 SomethingElse(std::collections::HashMap<String, serde_json::Value>),
159}
160
161#[derive(Clone, Debug, Deserialize)]
162pub struct Counterparty {
163 pub account_number: String,
164 pub name: String,
165 pub sort_code: String,
166 pub user_id: String,
167 #[cfg(feature = "decode_everything")]
168 #[cfg_attr(feature = "decode_everything", serde(flatten))]
169 pub extra: ExtraValues,
170}
171
172#[derive(Clone, Debug, Deserialize)]
174pub struct FasterPayment {
175 pub faster_payment: String,
176 pub fps_fpid: String,
177 pub fps_payment_id: String,
178 pub insertion: String,
179 pub notes: String,
180 pub standin_correlation_id: String,
181 pub trn: String,
182 #[cfg(feature = "decode_everything")]
183 #[cfg_attr(feature = "decode_everything", serde(flatten))]
184 pub extra: ExtraValues,
185}
186
187#[derive(Clone, Debug, Deserialize)]
189pub struct MoneyTransfer {
190 #[serde(flatten)]
191 pub subtype: MoneyTransferSubtype,
192 pub external_id: String,
193 pub ledger_insertion_id: String,
194 pub move_money_transfer_id: String,
195 pub pot_account_id: String,
196 pub pot_id: String,
197 pub transaction_description_localised: String,
198 pub transaction_locale_country: String,
199 pub trigger: String,
200 pub user_id: String,
201 #[cfg(feature = "decode_everything")]
202 #[cfg_attr(feature = "decode_everything", serde(flatten))]
203 pub extra: ExtraValues,
204}
205
206#[derive(Clone, Debug, Deserialize)]
207#[serde(untagged)]
208pub enum MoneyTransferSubtype {
209 PotWithdrawal(PotWithdrawal),
210 PotDeposit(PotDeposit),
211 #[cfg(feature = "decode_everything")]
212 SomethingElse(std::collections::HashMap<String, serde_json::Value>),
213}
214
215#[derive(Clone, Debug, Deserialize)]
216pub struct PotWithdrawal {
217 pub money_transfer_id: String,
218 pub pot_withdrawal_id: String,
219 #[cfg(feature = "decode_everything")]
220 #[cfg_attr(feature = "decode_everything", serde(flatten))]
221 pub extra: ExtraValues,
222}
223
224#[derive(Clone, Debug, Deserialize)]
225pub struct PotDeposit {
226 pub pot_deposit_id: String,
227 #[cfg(feature = "decode_everything")]
228 #[cfg_attr(feature = "decode_everything", serde(flatten))]
229 pub extra: ExtraValues,
230}
231
232#[derive(Clone, Debug, Deserialize)]
233pub struct MerchantTransaction {
234 pub mcc: String,
235 pub token_transaction_identifier: String,
236 pub tokenization_method: String,
237 pub transaction_description_localised: String,
238 pub transaction_locale_country: String,
239 pub standin_correlation_id: String,
240 pub token_unique_reference: String,
241 pub ledger_insertion_id: String,
242 pub mastercard_lifecycle_id: String,
243 pub mastercard_approval_type: String,
244 pub mastercard_auth_message_id: String,
245 pub mastercard_card_id: String,
246}