Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Transaction to avoid serde errors #16

Merged
merged 5 commits into from
Jul 9, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
337 changes: 292 additions & 45 deletions src/endpoints/transactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@ pub(crate) use get::Request as Get;
#[non_exhaustive]
#[derive(Deserialize, Debug)]
pub struct Transaction {
/// The account balance after the transation
pub account_balance: i64,
danieleades marked this conversation as resolved.
Show resolved Hide resolved

/// The unique ID of the account associated with the transaction
pub account_id: String,

Expand All @@ -41,7 +38,7 @@ pub struct Transaction {
pub can_split_the_bill: bool,

/// The transaction category
pub category: Category,
pub category: String,

/// The timestamp when the transaction was created
pub created: DateTime<Utc>,
Expand All @@ -58,9 +55,9 @@ pub struct Transaction {
/// Whether transaction is included in spending
pub include_in_spending: bool,

/// This can be either the merchant ID, or an object containing the merchant
/// details
pub merchant: MerchantInfo,
/// This can be either None, the merchant ID, or an object containing the
/// merchant details
pub merchant: Option<MerchantInfo>,

/// Any custom metadata which has been added to the transaction
pub metadata: HashMap<String, String>,
Expand Down Expand Up @@ -104,43 +101,6 @@ pub enum DeclineReason {
Other,
}

/// The set of categories by which Monzo transactions and merchants can be
/// categorised
#[derive(Deserialize, Debug, Clone, Copy)]
#[non_exhaustive]
#[serde(rename_all = "snake_case")]
pub enum Category {
/// General expenses
General,

/// Restaurants, Cafes, etc
EatingOut,

/// Work-related expenses
Expenses,

/// Getting around
Transport,

/// Cash withdrawals
Cash,

/// Bills and regular expenses
Bills,

/// Fun and Entertainment
Entertainment,

/// Treat yourself
Shopping,

/// Holiday expenses
Holidays,

/// Food and household items
Groceries,
}

/// Merchant information which might be returned in transactions data.
///
/// An id or a struct may be returned depending on whether the 'expand merchant'
Expand All @@ -166,7 +126,7 @@ pub struct Merchant {
pub logo: String,
pub emoji: String,
pub name: String,
pub category: Category,
pub category: String,
}

/// Address details
Expand Down Expand Up @@ -205,3 +165,290 @@ pub enum Since {
/// An id of an object
ObjectId(String),
}

#[cfg(test)]
mod tests {
use super::Transaction;

#[test]
fn deserialise_expanded_transaction() {
let raw = r##"
{
"id": "tx_0000A1aBC2Dbc34Ede5fEH",
"created": "2021-06-29T13:10:09.992Z",
"description": "Online Subscription",
"amount": -5000,
"fees": {},
"currency": "GBP",
"merchant": {
"id": "merch_000000abcABCDEFGdHIeJ0",
"group_id": "grp_000000abc1ABde2fChDE34",
"created": "2016-01-08T00:20:13.969Z",
"name": "Online Service",
"logo": "https://mondo-logo-cache.appspot.com/twitter/ServiceUk/?size=large",
"emoji": "💻",
"category": "entertainment",
"online": true,
"atm": false,
"address": {
"short_formatted": "Somewhere in the world",
"formatted": "world",
"address": "",
"city": "",
"region": "",
"country": "GLO",
"postcode": "",
"latitude": 50.99999999999999,
"longitude": 5.111111111111111,
"zoom_level": 5,
"approximate": true
},
"updated": "2021-06-17T14:21:38.608Z",
"metadata": {
"created_for_merchant": "merch_000000abcABCDEFGdHIeJ0",
"created_for_transaction": "tx_0000A1aBC2Dbc34Ede5fEH",
"provider": "user",
"provider_id": "",
"suggested_tags": "#subscription #personal",
"twitter_id": "ServiceUk",
"website": "service.co.uk"
},
"disable_feedback": false
},
"notes": "Subscription to online service",
"metadata": {
"ledger_insertion_id": "entryset_0000A2bBcDEF3HdIJK4LMe",
"mastercard_approval_type": "full",
"mastercard_auth_message_id": "mcauthmsg_0000A2bBcDEF3HdIJK4LMe",
"mastercard_card_id": "mccard_0000A2bBcDEF3HdIJK4LMe",
"mastercard_lifecycle_id": "mclifecycle_0000A2bBcDEF3HdIJK4LMe",
"mcc": "1234"
},
"labels": null,
"attachments": null,
"international": null,
"category": "bills",
"categories": {
"bills": -5000
},
"is_load": false,
"settled": "2021-06-30T00:46:44.233Z",
"local_amount": -3900,
"local_currency": "GBP",
"updated": "2021-06-30T00:46:44.589Z",
"account_id": "acc_99999aAbBc0DEFH1I2JdKL",
"user_id": "user_000000abcABCDEFGdHIeJ",
"counterparty": {},
"scheme": "mastercard",
"dedupe_id": "mclifecycle",
"originator": false,
"include_in_spending": true,
"can_be_excluded_from_breakdown": true,
"can_be_made_subscription": true,
"can_split_the_bill": true,
"can_add_to_tab": true,
"amount_is_pending": false,
"atm_fees_detailed": null
}
"##;

serde_json::from_str::<Transaction>(raw).expect("couldn't decode Transaction from json");
}

#[test]
// Tests for null merchant
fn deserialise_topup_transaction() {
let raw = r#"
{
"id": "tx_0000A1aBC2Dbc34Ede5fEF",
"created": "2021-07-01T00:21:30.935Z",
"description": "USER",
"amount": 2000,
"fees": {},
"currency": "GBP",
"merchant": null,
"notes": "USER",
"metadata": {
"faster_payment": "true",
"fps_fpid": "FP123456789123456789123456789123456",
"fps_payment_id": "FP123456789123456789123456789123456",
"insertion": "entryset_0000A1aBC2Dbc34Ede5fEF",
"notes": "USER",
"trn": "FP12345678912345"
},
"labels": null,
"attachments": null,
"international": null,
"category": "general",
"categories": null,
"is_load": false,
"settled": "2021-07-01T06:00:00Z",
"local_amount": 2000,
"local_currency": "GBP",
"updated": "2021-07-01T00:21:31.022Z",
"account_id": "acc_99999aAbBc0DEFH1I2JdKL",
"user_id": "",
"counterparty": {
"account_number": "12345678",
"name": "John Smith",
"sort_code": "987654",
"user_id": "anonuser_1234567a89b123456cd7e8"
},
"scheme": "payport_faster_pajments",
"dedupe_id": "com.monzo.fps:1234:FP123456789123456789123456789123456:INBOUND",
"originator": false,
"include_in_spending": false,
"can_be_excluded_from_breakdown": false,
"can_be_made_subscription": false,
"can_split_the_bill": false,
"can_add_to_tab": false,
"amount_is_pending": false,
"atm_fees_detailed": null
}
"#;

serde_json::from_str::<Transaction>(raw).expect("couldn't decode Transaction from json");
}

#[test]
fn deserialise_list() {
use serde::Deserialize;
#[derive(Deserialize)]
#[allow(dead_code)]
struct Response {
transactions: Vec<Transaction>,
}

let raw = r##"
{
"transactions": [
{
"id": "tx_0000A1aBC2Dbc34Ede5fEH",
"created": "2021-06-29T13:10:09.992Z",
"description": "Online Subscription",
"amount": -3900,
"fees": {},
"currency": "GBP",
"merchant": {
"id": "merch_000000abcABCDEFGdHIeJ0",
"group_id": "grp_000000abc1ABde2fChDE34",
"created": "2016-01-08T00:20:13.969Z",
"name": "Online Service",
"logo": "https://mondo-logo-cache.appspot.com/twitter/ServiceUk/?size=large",
"emoji": "💻",
"category": "entertainment",
"online": true,
"atm": false,
"address": {
"short_formatted": "Somewhere in the world",
"formatted": "world",
"address": "",
"city": "",
"region": "",
"country": "GLO",
"postcode": "",
"latitude": 50.99999999999999,
"longitude": 5.111111111111111,
"zoom_level": 5,
"approximate": true
},
"updated": "2021-06-17T14:21:38.608Z",
"metadata": {
"created_for_merchant": "merch_000000abcABCDEFGdHIeJ0",
"created_for_transaction": "tx_0000A1aBC2Dbc34Ede5fEH",
"provider": "user",
"provider_id": "",
"suggested_tags": "#subscription #personal",
"twitter_id": "ServiceUk",
"website": "service.co.uk"
},
"disable_feedback": false
},
"notes": "Subscription to online service",
"metadata": {
"ledger_insertion_id": "entryset_0000A2bBcDEF3HdIJK4LMe",
"mastercard_approval_type": "full",
"mastercard_auth_message_id": "mcauthmsg_0000A2bBcDEF3HdIJK4LMe",
"mastercard_card_id": "mccard_0000A2bBcDEF3HdIJK4LMe",
"mastercard_lifecycle_id": "mclifecycle_0000A2bBcDEF3HdIJK4LMe",
"mcc": "1234"
},
"labels": null,
"attachments": null,
"international": null,
"category": "bills",
"categories": {
"bills": -3900
},
"is_load": false,
"settled": "2021-06-30T00:46:44.233Z",
"local_amount": -3900,
"local_currency": "GBP",
"updated": "2021-06-30T00:46:44.589Z",
"account_id": "acc_99999aAbBc0DEFH1I2JdKL",
"user_id": "user_000000abcABCDEFGdHIeJ",
"counterparty": {},
"scheme": "mastercard",
"dedupe_id": "mclifecycle",
"originator": false,
"include_in_spending": true,
"can_be_excluded_from_breakdown": true,
"can_be_made_subscription": true,
"can_split_the_bill": true,
"can_add_to_tab": true,
"amount_is_pending": false,
"atm_fees_detailed": null
},
{
"id": "tx_0000A1aBC2Dbc34Ede5fEF",
"created": "2021-07-01T00:21:30.935Z",
"description": "USER",
"amount": 2000,
"fees": {},
"currency": "GBP",
"merchant": null,
"notes": "USER",
"metadata": {
"faster_payment": "true",
"fps_fpid": "FP123456789123456789123456789123456",
"fps_payment_id": "FP123456789123456789123456789123456",
"insertion": "entryset_0000A1aBC2Dbc34Ede5fEF",
"notes": "USER",
"trn": "FP12345678912345"
},
"labels": null,
"attachments": null,
"international": null,
"category": "general",
"categories": null,
"is_load": false,
"settled": "2021-07-01T06:00:00Z",
"local_amount": 2000,
"local_currency": "GBP",
"updated": "2021-07-01T00:21:31.022Z",
"account_id": "acc_99999aAbBc0DEFH1I2JdKL",
"user_id": "",
"counterparty": {
"account_number": "12345678",
"name": "John Smith",
"sort_code": "987654",
"user_id": "anonuser_1234567a89b123456cd7e8"
},
"scheme": "payport_faster_pajments",
"dedupe_id": "com.monzo.fps:1234:FP123456789123456789123456789123456:INBOUND",
"originator": false,
"include_in_spending": false,
"can_be_excluded_from_breakdown": false,
"can_be_made_subscription": false,
"can_split_the_bill": false,
"can_add_to_tab": false,
"amount_is_pending": false,
"atm_fees_detailed": null
}
]
}
"##;

serde_json::from_str::<Response>(raw).expect("couldn't decode Transaction from json");
}
}