From ff52fac1309d45a08e272962b7c1a10d6361ebfb Mon Sep 17 00:00:00 2001 From: scoobybejesus Date: Wed, 28 Aug 2019 10:05:42 -0400 Subject: [PATCH] Added error handling. Started with impl Transaction TxType, but it would have been quite verbose to not return more result types in other parts of the code, so did that as well. Resolves #18. --- src/account.rs | 25 +++++++++++++------------ src/create_lots_mvmts.rs | 14 +++++++------- src/csv_export.rs | 13 ++++++++----- src/import_cost_proceeds_etc.rs | 8 ++++---- src/main.rs | 2 +- src/transaction.rs | 25 +++++++++++++------------ 6 files changed, 46 insertions(+), 41 deletions(-) diff --git a/src/account.rs b/src/account.rs index 5897639..b81d1de 100644 --- a/src/account.rs +++ b/src/account.rs @@ -5,6 +5,7 @@ use std::rc::{Rc, Weak}; use std::cell::{Cell, RefCell}; use std::fmt; use std::collections::{HashMap}; +use std::error::Error; use chrono::{NaiveDate, NaiveTime, NaiveDateTime, DateTime, Utc, TimeZone}; use chrono_tz::US::Eastern; @@ -178,19 +179,19 @@ impl Movement { raw_accts: &HashMap, acct_map: &HashMap, txns_map: &HashMap, - )-> d128 { + )-> Result> { let txn = txns_map.get(&self.transaction_key).expect("Couldn't get txn. Tx num invalid?"); - match txn.transaction_type(ar_map, raw_accts, acct_map) { + match txn.transaction_type(ar_map, raw_accts, acct_map)? { TxType::Flow => { let ar = ar_map.get(&self.action_record_key).unwrap(); if ar.direction() == Polarity::Incoming { - self.proceeds.get() + Ok(self.proceeds.get()) } - else { d128!(0) } + else { Ok(d128!(0)) } } - TxType::Exchange => { d128!(0) } - TxType::ToSelf => { d128!(0) } + TxType::Exchange => { Ok(d128!(0)) } + TxType::ToSelf => { Ok(d128!(0)) } } } @@ -200,19 +201,19 @@ impl Movement { raw_accts: &HashMap, acct_map: &HashMap, txns_map: &HashMap, - )-> d128 { + )-> Result> { let txn = txns_map.get(&self.transaction_key).expect("Couldn't get txn. Tx num invalid?"); - match txn.transaction_type(ar_map, raw_accts, acct_map) { + match txn.transaction_type(ar_map, raw_accts, acct_map)? { TxType::Flow => { let ar = ar_map.get(&self.action_record_key).unwrap(); if ar.direction() == Polarity::Outgoing { - self.proceeds.get() + Ok(self.proceeds.get()) } - else { d128!(0) } + else { Ok(d128!(0)) } } - TxType::Exchange => { d128!(0) } - TxType::ToSelf => { d128!(0) } + TxType::Exchange => { Ok(d128!(0)) } + TxType::ToSelf => { Ok(d128!(0)) } } } diff --git a/src/create_lots_mvmts.rs b/src/create_lots_mvmts.rs index 52e5dcf..07f394c 100644 --- a/src/create_lots_mvmts.rs +++ b/src/create_lots_mvmts.rs @@ -49,10 +49,10 @@ pub fn create_lots_and_movements( let txn_num = num as u32; let txn = txns_map.get(&(txn_num)).expect("Couldn't get txn. Tx num invalid?"); if txn.marginness(&ar_map, &raw_acct_map, &acct_map) == TxHasMargin::TwoARs { - assert_eq!(txn.transaction_type(&ar_map, &raw_acct_map, &acct_map), TxType::Exchange); + assert_eq!(txn.transaction_type(&ar_map, &raw_acct_map, &acct_map)?, TxType::Exchange); assert_eq!(txn.action_record_idx_vec.len(), 2); - let the_raw_pair_keys = txn.get_base_and_quote_raw_acct_keys(&ar_map, &raw_acct_map, &acct_map); + let the_raw_pair_keys = txn.get_base_and_quote_raw_acct_keys(&ar_map, &raw_acct_map, &acct_map)?; let base_acct = acct_map.get(&the_raw_pair_keys.0).expect("Couldn't get acct. Raw pair keys invalid?"); let quote_acct = acct_map.get(&the_raw_pair_keys.1).expect("Couldn't get acct. Raw pair keys invalid?"); @@ -217,7 +217,7 @@ pub fn create_lots_and_movements( } // Note: a_r is not in home currency if here or below let polarity = ar.direction(); - let tx_type = txn.transaction_type(&ar_map, &raw_acct_map, &acct_map); + let tx_type = txn.transaction_type(&ar_map, &raw_acct_map, &acct_map)?; match polarity { Polarity::Outgoing => { @@ -409,7 +409,7 @@ pub fn create_lots_and_movements( &raw_acct_map, &acct_map, &txns_map, - ); + )?; let base_acct = acct_map.get(&base_acct_key).unwrap(); let base_acct_lot = base_acct.list_of_lots.borrow().last().unwrap().clone(); @@ -579,7 +579,7 @@ fn get_base_and_quote_acct_for_dual_actionrecord_flow_tx( raw_acct_map: &HashMap, acct_map: &HashMap, txns_map: &HashMap, -) -> (u16, u16) { +) -> Result<(u16, u16), Box> { let txn = txns_map.get(&txn_num).expect("Couldn't get txn. Tx num invalid?"); let og_flow_ar = ar_map.get(txn.action_record_idx_vec.first().unwrap()).unwrap(); @@ -597,8 +597,8 @@ fn get_base_and_quote_acct_for_dual_actionrecord_flow_tx( let (base_key,quote_key) = txn_of_og_mvmt_lot_first_mvmt.get_base_and_quote_raw_acct_keys( ar_map, &raw_acct_map, - &acct_map); // TODO: should this panic on margin loss? - (base_key, quote_key) + &acct_map)?; // TODO: should this panic on margin loss? + Ok((base_key, quote_key)) } fn get_base_and_quote_ar_idxs( diff --git a/src/csv_export.rs b/src/csv_export.rs index b72fdb6..e85327b 100644 --- a/src/csv_export.rs +++ b/src/csv_export.rs @@ -4,6 +4,7 @@ use std::fs::File; use std::collections::{HashMap}; use std::path::PathBuf; +use std::error::Error; use decimal::d128; @@ -201,7 +202,7 @@ pub fn _5_transaction_mvmt_summaries_to_csv( raw_acct_map: &HashMap, acct_map: &HashMap, txns_map: &HashMap, -) { +) -> Result<(), Box> { let mut rows: Vec> = [].to_vec(); let mut header: Vec = [].to_vec(); @@ -230,7 +231,7 @@ pub fn _5_transaction_mvmt_summaries_to_csv( let txn = txns_map.get(&(txn_num)).unwrap(); let txn_date_string = txn.date.format("%Y/%m/%d").to_string(); let tx_num_string = txn.tx_number.to_string(); - let tx_type_string = txn.transaction_type(ars, &raw_acct_map, &acct_map).to_string(); + let tx_type_string = txn.transaction_type(ars, &raw_acct_map, &acct_map)?.to_string(); let tx_memo_string = txn.memo.to_string(); let mut term_st: Option = None; let mut term_lt: Option = None; @@ -257,7 +258,7 @@ pub fn _5_transaction_mvmt_summaries_to_csv( raw_acct_map, acct_map, txns_map - ); + )?; for mvmt in flow_or_outgoing_exchange_movements.iter() { let lot = mvmt.get_lot(acct_map, ars); @@ -294,7 +295,7 @@ pub fn _5_transaction_mvmt_summaries_to_csv( } } - if (txn.transaction_type(ars, &raw_acct_map, &acct_map) == TxType::Flow) & (polarity == Some(Polarity::Incoming)) { + if (txn.transaction_type(ars, &raw_acct_map, &acct_map)? == TxType::Flow) & (polarity == Some(Polarity::Incoming)) { // println!("Incoming flow {}", txn.tx_number); income_st = proceeds_st; proceeds_st = d128!(0); @@ -304,7 +305,7 @@ pub fn _5_transaction_mvmt_summaries_to_csv( cost_basis_lt = d128!(0); } - if (txn.transaction_type(ars, &raw_acct_map, &acct_map) == TxType::Flow) & (polarity == Some(Polarity::Outgoing)) { + if (txn.transaction_type(ars, &raw_acct_map, &acct_map)? == TxType::Flow) & (polarity == Some(Polarity::Outgoing)) { // println!("Outgoing flow {}, proceeds_st {}, proceeds_lt {}", txn.tx_number, proceeds_st, proceeds_lt); expense_st -= proceeds_st; expense_lt -= proceeds_lt; @@ -361,6 +362,8 @@ pub fn _5_transaction_mvmt_summaries_to_csv( wtr.write_record(row).expect("Could not write row to CSV file"); } wtr.flush().expect("Could not flush Writer, though file should exist and be complete"); + + Ok(()) } // pub fn accounts_to_csv( diff --git a/src/import_cost_proceeds_etc.rs b/src/import_cost_proceeds_etc.rs index 0e5612c..696f210 100644 --- a/src/import_cost_proceeds_etc.rs +++ b/src/import_cost_proceeds_etc.rs @@ -37,7 +37,7 @@ pub fn add_cost_basis_to_movements( for mvmt in movements.iter() { let polarity = ar.direction(); - let tx_type = txn.transaction_type(ars, raw_acct_map, acct_map); + let tx_type = txn.transaction_type(ars, raw_acct_map, acct_map)?; let is_home_curr = raw_acct.is_home_currency(&settings.home_currency); let mvmt_copy = mvmt.clone(); let borrowed_mvmt = mvmt_copy.clone(); @@ -169,7 +169,7 @@ pub fn add_proceeds_to_movements( for mvmt in movements.iter() { let polarity = ar.direction(); - let tx_type = txn.transaction_type(ars, raw_acct_map, acct_map); + let tx_type = txn.transaction_type(ars, raw_acct_map, acct_map)?; let mvmt_copy = mvmt.clone(); let borrowed_mvmt = mvmt_copy.clone(); @@ -249,7 +249,7 @@ fn update_current_txn_for_prior_likekind_treatment( for mvmt in movements.iter() { let polarity = ar.direction(); - let tx_type = txn.transaction_type(ars, raw_acct_map, acct_map); + let tx_type = txn.transaction_type(ars, raw_acct_map, acct_map)?; let is_home_curr = raw_acct.is_home_currency(&settings.home_currency); let mvmt_copy = mvmt.clone(); @@ -303,7 +303,7 @@ fn perform_likekind_treatment_on_txn( ) -> Result<(), Box> { let txn = txns_map.get(&txn_num).unwrap(); - let tx_type = txn.transaction_type(ars, raw_acct_map, acct_map); + let tx_type = txn.transaction_type(ars, raw_acct_map, acct_map)?; let og_ar = ars.get(&txn.action_record_idx_vec.first().unwrap()).unwrap(); let ic_ar = ars.get(&txn.action_record_idx_vec.last().unwrap()).unwrap(); diff --git a/src/main.rs b/src/main.rs index f513ad9..c185856 100644 --- a/src/main.rs +++ b/src/main.rs @@ -291,7 +291,7 @@ fn main() -> Result<(), Box> { &raw_acct_map, &account_map, &transactions_map - ); + )?; } diff --git a/src/transaction.rs b/src/transaction.rs index 65ddc7f..baa2ded 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -6,6 +6,7 @@ use std::cell::{RefCell}; use std::process::exit; use std::fmt; use std::collections::{HashMap}; +use std::error::Error; use decimal::d128; use chrono::NaiveDate; @@ -30,10 +31,10 @@ impl Transaction { ars: &HashMap, raw_acct_map: &HashMap, acct_map: &HashMap, - ) -> TxType { + ) -> Result> { if self.action_record_idx_vec.len() == 1 { - TxType::Flow + Ok(TxType::Flow) } else if self.action_record_idx_vec.len() == 2 { // This exercise of splitting the strings is because of margin accounts, where BTC borrowed to buy XMR would reflect as BTC_xmr @@ -55,14 +56,14 @@ impl Transaction { } if ar1_ticker == ar2_ticker { if ar1_raw_acct.is_margin != ar2_raw_acct.is_margin { - TxType::Flow + Ok(TxType::Flow) } else { - TxType::ToSelf + Ok(TxType::ToSelf) } } else { - TxType::Exchange + Ok(TxType::Exchange) } } else if self.action_record_idx_vec.len() > 2 { @@ -111,9 +112,9 @@ impl Transaction { ars: &HashMap, raw_accts: &HashMap, acct_map: &HashMap - ) -> (u16, u16) { + ) -> Result<(u16, u16), Box> { - assert_eq!(self.transaction_type(ars, raw_accts, acct_map), TxType::Exchange, + assert_eq!(self.transaction_type(ars, raw_accts, acct_map)?, TxType::Exchange, "This can only be called on exchange transactions."); let first_ar = ars.get(&self.action_record_idx_vec[0]).unwrap(); @@ -134,11 +135,11 @@ impl Transaction { if first_raw_acct.ticker.contains('_') { quote = first_acct_raw_key; base = second_acct_raw_key; - (base, quote) + Ok((base, quote)) } else if second_raw_acct.ticker.contains('_') { base = first_acct_raw_key; quote = second_acct_raw_key; - (base, quote) + Ok((base, quote)) } else { println!("{}", VariousErrors::MarginNoUnderbar); use std::process::exit; exit(1) } @@ -151,7 +152,7 @@ impl Transaction { raw_acct_map: &HashMap, acct_map: &HashMap, txns_map: &HashMap, - ) -> Vec> { + ) -> Result>, Box> { let mut flow_or_outgoing_exchange_movements = [].to_vec(); @@ -165,7 +166,7 @@ impl Transaction { let movements = ar.get_mvmts_in_ar(acct_map, txns_map); - match self.transaction_type(ars, raw_acct_map, acct_map) { + match self.transaction_type(ars, raw_acct_map, acct_map)? { TxType::Exchange => { if Polarity::Outgoing == ar.direction() { for mvmt in movements.iter() { @@ -182,7 +183,7 @@ impl Transaction { } } } - flow_or_outgoing_exchange_movements + Ok(flow_or_outgoing_exchange_movements) } }