Error handling. Added user warning and exit()'s in place of asserts. Related formatting.

This commit is contained in:
scoobybejesus 2020-11-27 11:50:45 -05:00
parent 999b46a904
commit 4faab11ed3
5 changed files with 68 additions and 38 deletions

View File

@ -1,6 +1,6 @@
[package]
name = "cryptools"
version = "0.9.1"
version = "0.9.2"
authors = ["scoobybejesus <scoobybejesus@users.noreply.github.com>"]
edition = "2018"
description = "Command-line utility for processing cryptocurrency transactions into 'lots' and 'movements'."

View File

@ -242,6 +242,12 @@ pub(crate) fn create_lots_and_movements(
wrap_mvmt_and_push(whole_mvmt, &ar, &lot, &chosen_home_currency, &raw_acct_map, &acct_map);
continue
} else {
if acct.list_of_lots.borrow().len() == 0 {
println!("FATAL: There are zero lots to spend from in transaction:\n{:#?}",txn);
std::process::exit(1);
}
let list_of_lots_to_use = acct.list_of_lots.clone();
// the following returns vec to be iterated from beginning to end, which provides the index for the correct lot
@ -557,7 +563,8 @@ pub(crate) fn create_lots_and_movements(
}
TxType::ToSelf => {
if raw_acct.is_margin {
{ println!("\n Found margin actionrecord in toself txn # {} \n", txn.tx_number); use std::process::exit; exit(1) };
println!("FATAL: Consult developer. Found margin actionrecord in ToSelf transaction:\n{:#?}", txn);
std::process::exit(1);
} else {
process_multiple_incoming_lots_and_mvmts(
txn_num,
@ -729,7 +736,7 @@ fn fit_into_lots(
&chosen_home_currency,
&ar_map,
&raw_acct_map,
&acct_map
&acct_map,
);
return;
}
@ -777,6 +784,14 @@ fn fit_into_lots(
wrap_mvmt_and_push(mvmt_that_fits_in_lot, &spawning_ar, &lot, &chosen_home_currency, &raw_acct_map, &acct_map);
let remainder_amt_to_recurse = remainder_amt + sum_of_mvmts_in_lot;
// println!("Remainder amount to recurse: {}", remainder_amt_to_recurse);
if vec_of_ordered_index_values.len() == current_index_position + 1 {
println!("FATAL: Txn {} on {} spending {} {} has run out of lots to spend from.",
txn_num, lot.date_as_string, ar.amount, raw_acct.ticker);
println!("Account balance is only: {}", acct.get_sum_of_amts_in_lots());
std::process::exit(1);
}
current_index_position += 1;
let lot_index = vec_of_ordered_index_values[current_index_position];
let newly_chosen_lot = list_of_lots_to_use.borrow()[lot_index].clone();
@ -806,7 +821,7 @@ fn fit_into_lots(
&chosen_home_currency,
&ar_map,
&raw_acct_map,
&acct_map
&acct_map,
);
}

View File

@ -55,14 +55,7 @@ fn import_accounts(
let mut header3: Option<csv::StringRecord> = None; // ticker
let header4: csv::StringRecord; // is_margin
// A StringRecord doesn't accept the same range indexing we need below, so we create our own
let mut headerstrings: Vec<String> = Vec::with_capacity(header1.len());
for element in header1.into_iter() {
headerstrings.push(element.to_string())
}
// Account Creation loop. We set hasheaders() to true above, so the first record here is the second row of the CSV
// Account Creation loop. With rdr.has_headers() set to true above, the first record here is the second row of the CSV
for result in rdr.records() {
// This initial iteration through records will break after the 4th row, after accounts have been created
let record = result?;
@ -78,32 +71,32 @@ fn import_accounts(
header4 = record.clone();
// println!("Assigned last header, record: {:?}", record);
let warn = "FATAL: Transactions will not import correctly if account numbers in the CSV import file aren't
// A StringRecord doesn't accept the same range indexing needed below, so a Vec of Strings will be used
let mut headerstrings: Vec<String> = Vec::with_capacity(header1.len());
for field in header1.into_iter() {
headerstrings.push(field.to_string())
}
let acct_num_warn = "Transactions will not import correctly if account numbers in the CSV import file aren't
ordered chronologically (i.e., beginning in column 4 - the 1st account column - the value should be 1.
The next column's value should be 2, then 3, etc, until the final account).";
// We've got all our header rows. It's now that we set up the accounts.
// Header row variables have been set. It's now time to set up the accounts.
println!("Attempting to create accounts...");
let mut no_dup_acct_nums = HashMap::new();
let length = &headerstrings.len();
for num in headerstrings[3..*length].iter().enumerate() {
let counter = no_dup_acct_nums.entry(num).or_insert(0);
*counter += 1;
for (idx, field) in headerstrings[3..*length].iter().enumerate() {
// Parse account numbers.
let account_num = field.parse::<u16>().expect("Header row account number should parse into u16.");
// For now, their columns aren't remembered. Instead, they must have a particular index. 0th idx is the 1st account, and so on.
if account_num != ((idx + 1) as u16) {
println!("FATAL: CSV Import: {}", acct_num_warn);
std::process::exit(1);
}
for acct_num in no_dup_acct_nums.keys() {
assert_eq!(no_dup_acct_nums[acct_num], 1, "Found accounts with duplicate numbers during import.");
}
for (idx, item) in headerstrings[3..*length].iter().enumerate() {
// println!("Headerstrings value: {:?}", item);
let ind = idx+3; // Add three because the idx skips the first three 'key' columns
let account_num = item.parse::<u16>()?;
assert_eq!((idx + 1) as u16, account_num, "Found improper Account Number usage: {}", warn);
let name:String = header2.clone().unwrap()[ind].trim().to_string();
let ticker:String = header3.clone().unwrap()[ind].trim().to_string(); // no .to_uppercase() b/c margin...
let margin_string = &header4.clone()[ind];
@ -111,7 +104,10 @@ The next column's value should be 2, then 3, etc, until the final account).";
let is_margin:bool = match margin_string.trim().to_lowercase().as_str() {
"no" | "non" | "false" => false,
"yes" | "margin" | "true" => true,
_ => { println!("\n Couldn't parse margin value for acct {} {} \n",account_num, name); process::exit(1) }
_ => {
println!("\n FATAL: CSV Import: Couldn't parse margin value for account {} {} \n",account_num, name);
process::exit(1)
}
};
let just_account: RawAccount = RawAccount {

View File

@ -52,7 +52,8 @@ impl Transaction {
let ar2_ticker = ar2_ticker_comp[0];
if first_ar.direction() == second_ar.direction() {
println!("Program exiting. Found transaction with two actionRecords with the same polarity: {:?}", self); process::exit(1);
println!("FATAL: TxType: Found transaction with two actionRecords with the same polarity: \n{:#?}", self);
process::exit(1);
}
if ar1_ticker == ar2_ticker {
if ar1_raw_acct.is_margin != ar2_raw_acct.is_margin {
@ -67,10 +68,12 @@ impl Transaction {
}
}
else if self.action_record_idx_vec.len() > 2 {
println!("Program exiting. Found transaction with too many actionRecords: {:?}", self); process::exit(1);
println!("FATAL: TxType: Found transaction with too many actionRecords: \n{:#?}", self);
process::exit(1);
}
else {
println!("Program exiting. Found transaction with no actionRecords: {:?}", self); process::exit(1);
println!("FATAL: TxType: Found transaction with no actionRecords: \n{:#?}", self);
process::exit(1);
}
}
@ -92,11 +95,23 @@ impl Transaction {
}
} else {
assert_eq!(self.action_record_idx_vec.len(),2,
"Each txn can only have one or two ARs. Txn has {} ARs.", self.action_record_idx_vec.len());
if self.action_record_idx_vec.len() != 2 {
println!("FATAL: Each transaction may have up to two actionrecords, and there are {} actionrecords in transaction:\n{:#?}",
self.action_record_idx_vec.len(), self);
}
let first_ar = ars.get(&self.action_record_idx_vec[0]).unwrap();
let second_ar = ars.get(&self.action_record_idx_vec[1]).unwrap();
let first_ar = match ars.get(&self.action_record_idx_vec[0]) {
Some(x) => x,
None => {
println!("FATAL: ActionRecord not found for: \n{:#?}", self);
process::exit(1)}
};
let second_ar = match ars.get(&self.action_record_idx_vec[1]) {
Some(x) => x,
None => {
println!("FATAL: ActionRecord not found for: \n{:#?}", self);
process::exit(1)}
};
let first_acct = acct_map.get(&first_ar.account_key).unwrap();
let second_acct = acct_map.get(&second_ar.account_key).unwrap();
@ -144,7 +159,8 @@ impl Transaction {
quote = second_acct_raw_key;
Ok((base, quote))
} else {
println!("{}", VariousErrors::MarginNoUnderbar); use std::process::exit; exit(1)
println!("FATAL: {}", VariousErrors::MarginNoUnderbar);
std::process::exit(1);
}
}

View File

@ -94,7 +94,10 @@ pub (crate) fn run_setup(cmd_args: super::Cli, cfg: super::Cfg) -> Result<(PathB
"h" => { "-" }
"s" => { "/" }
"p" => { "." }
_ => { println!("\nFATAL: The date-separator arg requires either an 'h', an 's', or a 'p'.\n"); process::exit(1) }
_ => {
println!("\nFATAL: ENV: The date-separator arg requires either an 'h', an 's', or a 'p'.\n");
process::exit(1)
}
};
let input_file_path = match cmd_args.file_to_import {