Merged wizard branch which pulled wizard() and skip_wizard() from main().

This commit is contained in:
scoobybejesus 2019-09-22 01:49:07 -04:00
parent 2e843db058
commit 89cec47bac
4 changed files with 223 additions and 147 deletions

View File

@ -82,7 +82,7 @@ pub(crate) fn import_accounts(
let account_num = item.parse::<u16>()?; let account_num = item.parse::<u16>()?;
assert_eq!((idx + 1) as u16, account_num, "Found improper Account Number usage: {}", warn); 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 name:String = header2.clone().unwrap()[ind].trim().to_string();
let ticker:String = header3.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]; let margin_string = &header4.clone()[ind];
let is_margin:bool = match margin_string.trim().to_lowercase().as_str() { let is_margin:bool = match margin_string.trim().to_lowercase().as_str() {

View File

@ -11,8 +11,6 @@
use std::ffi::OsString; use std::ffi::OsString;
use structopt::StructOpt; use structopt::StructOpt;
use std::path::PathBuf; use std::path::PathBuf;
use std::process;
use std::io::{self, BufRead};
use std::error::Error; use std::error::Error;
mod account; mod account;
@ -27,13 +25,13 @@ mod txt_export;
mod string_utils; mod string_utils;
mod decimal_utils; mod decimal_utils;
mod tests; mod tests;
mod wizard;
use crate::core_functions::ImportProcessParameters; mod skip_wizard;
#[derive(StructOpt, Debug)] #[derive(StructOpt, Debug)]
#[structopt(name = "cryptools")] #[structopt(name = "cryptools")]
struct Cli { pub(crate) struct Cli {
/// File to be imported. (Currently, the only supported date format is %m/%d/%y.) /// File to be imported. (Currently, the only supported date format is %m/%d/%y.)
#[structopt(name = "file", parse(from_os_str))] #[structopt(name = "file", parse(from_os_str))]
@ -86,183 +84,60 @@ fn main() -> Result<(), Box<dyn Error>> {
Note: it is designed to import a full history. Gains and losses may be incorrect otherwise. Note: it is designed to import a full history. Gains and losses may be incorrect otherwise.
"); ");
let input_file_path;
let output_dir_path = args.output_dir_path;
let should_export;
let account_map; let account_map;
let raw_acct_map; let raw_acct_map;
let action_records_map; let action_records_map;
let transactions_map; let transactions_map;
let mut settings; let settings;
let like_kind_settings; let like_kind_settings;
let should_export;
let home_currency_choice = args.home_currency
.into_string()
.expect("Home currency should be in the form of a ticker in CAPS.")
.to_uppercase();
let costing_method_choice;
if !args.accept_args { if !args.accept_args {
shall_we_proceed()?;
fn shall_we_proceed() -> Result<(), Box<dyn Error>> {
println!("Shall we proceed? [Y/n] ");
_proceed()?;
fn _proceed() -> Result<(), Box<dyn Error>> {
let mut input = String::new();
let stdin = io::stdin();
stdin.lock().read_line(&mut input)?;
match input.trim().to_ascii_lowercase().as_str() {
"y" | "ye" | "yes" | "" => { Ok(()) },
"n" | "no" => { println!("We have NOT proceeded..."); process::exit(0); },
_ => { println!("Please respond with 'y' or 'n' (or 'yes' or 'no')."); _proceed() }
}
}
Ok(())
}
if let Some(file) = args.file_to_import {
input_file_path = file
} else {
input_file_path = cli_user_choices::choose_file_for_import()?;
}
costing_method_choice = cli_user_choices::choose_inventory_costing_method()?;
let lk_cutoff_date_opt_string;
if let Some(lk_cutoff) = args.cutoff_date {
lk_cutoff_date_opt_string = Some(lk_cutoff.into_string().unwrap())
} else {
lk_cutoff_date_opt_string = None
};
let (like_kind_election, like_kind_cutoff_date) = cli_user_choices::elect_like_kind_treatment(&lk_cutoff_date_opt_string)?;
settings = ImportProcessParameters {
export_path: output_dir_path,
home_currency: home_currency_choice,
costing_method: costing_method_choice,
enable_like_kind_treatment: like_kind_election,
lk_cutoff_date_string: like_kind_cutoff_date,
};
let ( let (
account_map1, account_map1,
raw_acct_map1, raw_acct_map1,
action_records_map1, action_records_map1,
transactions_map1, transactions_map1,
like_kind_settings1 like_kind_settings1,
) = core_functions::import_and_process_final(input_file_path, &settings)?; settings1,
should_export1
) = wizard::wizard(args)?;
account_map = account_map1; account_map = account_map1;
raw_acct_map = raw_acct_map1; raw_acct_map = raw_acct_map1;
action_records_map = action_records_map1; action_records_map = action_records_map1;
transactions_map = transactions_map1; transactions_map = transactions_map1;
settings = settings1;
like_kind_settings = like_kind_settings1; like_kind_settings = like_kind_settings1;
should_export = should_export1;
should_export = export_reports_to_output_dir(&mut settings)?;
fn export_reports_to_output_dir(settings: &mut ImportProcessParameters) -> Result<(bool), Box<dyn Error>> {
println!("\nThe directory currently selected for exporting reports is: {}", settings.export_path.to_str().unwrap());
if &settings.export_path.to_str().unwrap() == &"." {
println!(" (A 'dot' denotes the default value: current working directory.)");
}
println!("\nExport reports to selected directory? [Y/n/c] ('c' to 'change') ");
let choice = _export(settings)?;
fn _export(settings: &mut ImportProcessParameters) -> Result<(bool), Box<dyn Error>> {
let mut input = String::new();
let stdin = io::stdin();
stdin.lock().read_line(&mut input)?;
match input.trim().to_ascii_lowercase().as_str() {
"y" | "ye" | "yes" | "" => { println!("Creating reports now."); Ok(true) },
"n" | "no" => { println!("Okay, no reports were created."); Ok(false) },
"c" | "change" => {
let new_dir = cli_user_choices::choose_export_dir()?;
settings.export_path = PathBuf::from(new_dir);
println!("Creating reports now in newly chosen path.");
Ok(true)
},
_ => { println!("Please respond with 'y', 'n', or 'c' (or 'yes' or 'no' or 'change').");
_export(settings)
}
}
}
Ok(choice)
}
} else { } else {
if let Some(file) = args.file_to_import {
input_file_path = file
} else {
println!("Flag to 'accept args' was set, but 'file' is missing, though it is a required field. Exiting.");
process::exit(66); // EX_NOINPUT (66) An input file (not a system file) did not exist or was not readable
}
let like_kind_election;
let like_kind_cutoff_date_string: String;
if let Some(date) = args.cutoff_date {
like_kind_election = true;
like_kind_cutoff_date_string = date.into_string().unwrap();
} else {
like_kind_election = false;
like_kind_cutoff_date_string = "1-1-1".to_string();
};
let clean_inv_costing_arg = match args.inv_costing_method.clone().into_string().expect("Invalid choice on costing method. Aborting.").trim() {
"1" => {"1"} "2" => {"2"} "3" => {"3"} "4" => {"4"}
_ => { println!("WARN: Invalid command line arg passed for 'inv_costing_method'. Using default."); "1" }
};
let clean_inv_costing_arg_string = clean_inv_costing_arg.to_owned();
let costing_method_choice = cli_user_choices::inv_costing_from_cmd_arg(clean_inv_costing_arg_string)?;
settings = ImportProcessParameters {
export_path: output_dir_path,
home_currency: home_currency_choice,
costing_method: costing_method_choice,
enable_like_kind_treatment: like_kind_election,
lk_cutoff_date_string: like_kind_cutoff_date_string,
};
let ( let (
account_map1, account_map1,
raw_acct_map1, raw_acct_map1,
action_records_map1, action_records_map1,
transactions_map1, transactions_map1,
like_kind_settings1 like_kind_settings1,
) = core_functions::import_and_process_final(input_file_path, &settings)?; settings1,
should_export1
) = skip_wizard::skip_wizard(args)?;
account_map = account_map1; account_map = account_map1;
raw_acct_map = raw_acct_map1; raw_acct_map = raw_acct_map1;
action_records_map = action_records_map1; action_records_map = action_records_map1;
transactions_map = transactions_map1; transactions_map = transactions_map1;
settings = settings1;
like_kind_settings = like_kind_settings1; like_kind_settings = like_kind_settings1;
should_export = should_export1;
should_export = !args.suppress_reports;
} }
if should_export { if should_export {
println!("Creating reports now.");
csv_export::_1_account_sums_to_csv( csv_export::_1_account_sums_to_csv(
&settings, &settings,
&raw_acct_map, &raw_acct_map,
@ -336,7 +211,5 @@ fn main() -> Result<(), Box<dyn Error>> {
Ok(()) Ok(())
// // csv_export::transactions_to_csv(&transactions);
// csv_export::accounts_to_csv(&accounts);
} }

74
src/skip_wizard.rs Normal file
View File

@ -0,0 +1,74 @@
// Copyright (c) 2017-2019, scoobybejesus
// Redistributions must include the license: https://github.com/scoobybejesus/cryptools/blob/master/LEGAL.txt
use std::error::Error;
use std::process;
use std::collections::{HashMap};
use crate::cli_user_choices;
use crate::core_functions::{self, LikeKindSettings, ImportProcessParameters};
use crate::account::{Account, RawAccount};
use crate::transaction::{Transaction, ActionRecord};
pub(crate) fn skip_wizard(args: super::Cli) -> Result<(
HashMap<u16, Account>,
HashMap<u16, RawAccount>,
HashMap<u32, ActionRecord>,
HashMap<u32, Transaction>,
Option<LikeKindSettings>,
ImportProcessParameters,
bool
), Box<dyn Error>> {
let input_file_path;
if let Some(file) = args.file_to_import {
input_file_path = file
} else {
println!("Flag to 'accept args' was set, but 'file' is missing, though it is a required field. Exiting.");
process::exit(66); // EX_NOINPUT (66) An input file (not a system file) did not exist or was not readable
}
let home_currency_choice = args.home_currency.into_string().unwrap().to_uppercase();
let output_dir_path = args.output_dir_path;
let like_kind_election;
let like_kind_cutoff_date_string: String;
if let Some(date) = args.cutoff_date {
like_kind_election = true;
like_kind_cutoff_date_string = date.into_string().unwrap();
} else {
like_kind_election = false;
like_kind_cutoff_date_string = "1-1-1".to_string();
};
let clean_inv_costing_arg = match args.inv_costing_method.clone().into_string().expect("Invalid choice on costing method. Aborting.").trim() {
"1" => {"1"} "2" => {"2"} "3" => {"3"} "4" => {"4"}
_ => { println!("WARN: Invalid command line arg passed for 'inv_costing_method'. Using default."); "1" }
};
let clean_inv_costing_arg_string = clean_inv_costing_arg.to_owned();
let costing_method_choice = cli_user_choices::inv_costing_from_cmd_arg(clean_inv_costing_arg_string)?;
let settings = ImportProcessParameters {
export_path: output_dir_path,
home_currency: home_currency_choice,
costing_method: costing_method_choice,
enable_like_kind_treatment: like_kind_election,
lk_cutoff_date_string: like_kind_cutoff_date_string,
};
let (
account_map1,
raw_acct_map1,
action_records_map1,
transactions_map1,
like_kind_settings1
) = core_functions::import_and_process_final(input_file_path, &settings)?;
let should_export = !args.suppress_reports;
Ok((account_map1, raw_acct_map1, action_records_map1, transactions_map1, like_kind_settings1, settings, should_export))
}

129
src/wizard.rs Normal file
View File

@ -0,0 +1,129 @@
// Copyright (c) 2017-2019, scoobybejesus
// Redistributions must include the license: https://github.com/scoobybejesus/cryptools/blob/master/LEGAL.txt
use std::error::Error;
use std::process;
use std::io::{self, BufRead};
use std::path::PathBuf;
use std::collections::{HashMap};
use crate::cli_user_choices;
use crate::core_functions::{self, LikeKindSettings, ImportProcessParameters};
use crate::account::{Account, RawAccount};
use crate::transaction::{Transaction, ActionRecord};
pub(crate) fn wizard(args: super::Cli) -> Result<(
HashMap<u16, Account>,
HashMap<u16, RawAccount>,
HashMap<u32, ActionRecord>,
HashMap<u32, Transaction>,
Option<LikeKindSettings>,
ImportProcessParameters,
bool
), Box<dyn Error>> {
shall_we_proceed()?;
let input_file_path;
if let Some(file) = args.file_to_import {
input_file_path = file
} else {
input_file_path = cli_user_choices::choose_file_for_import()?;
}
let output_dir_path = args.output_dir_path;
let costing_method_choice = cli_user_choices::choose_inventory_costing_method()?;
let home_currency_choice = args.home_currency.into_string().unwrap().to_uppercase();
let lk_cutoff_date_opt_string;
if let Some(lk_cutoff) = args.cutoff_date {
lk_cutoff_date_opt_string = Some(lk_cutoff.into_string().unwrap())
} else {
lk_cutoff_date_opt_string = None
};
let (like_kind_election, like_kind_cutoff_date) = cli_user_choices::elect_like_kind_treatment(&lk_cutoff_date_opt_string)?;
let mut settings = ImportProcessParameters {
export_path: output_dir_path,
home_currency: home_currency_choice,
costing_method: costing_method_choice,
enable_like_kind_treatment: like_kind_election,
lk_cutoff_date_string: like_kind_cutoff_date,
};
let (
account_map1,
raw_acct_map1,
action_records_map1,
transactions_map1,
like_kind_settings1
) = core_functions::import_and_process_final(input_file_path, &settings)?;
let should_export = export_reports_to_output_dir(&mut settings)?;
Ok((account_map1, raw_acct_map1, action_records_map1, transactions_map1, like_kind_settings1, settings, should_export))
}
fn shall_we_proceed() -> Result<(), Box<dyn Error>> {
println!("Shall we proceed? [Y/n] ");
_proceed()?;
fn _proceed() -> Result<(), Box<dyn Error>> {
let mut input = String::new();
let stdin = io::stdin();
stdin.lock().read_line(&mut input)?;
match input.trim().to_ascii_lowercase().as_str() {
"y" | "ye" | "yes" | "" => { Ok(()) },
"n" | "no" => { println!("We have NOT proceeded..."); process::exit(0); },
_ => { println!("Please respond with 'y' or 'n' (or 'yes' or 'no')."); _proceed() }
}
}
Ok(())
}
fn export_reports_to_output_dir(settings: &mut ImportProcessParameters) -> Result<(bool), Box<dyn Error>> {
println!("\nThe directory currently selected for exporting reports is: {}", settings.export_path.to_str().unwrap());
if settings.export_path.to_str().unwrap() == "." {
println!(" (A 'dot' denotes the default value: current working directory.)");
}
println!("\nExport reports to selected directory? [Y/n/c] ('c' to 'change') ");
let choice = _export(settings)?;
fn _export(settings: &mut ImportProcessParameters) -> Result<(bool), Box<dyn Error>> {
let mut input = String::new();
let stdin = io::stdin();
stdin.lock().read_line(&mut input)?;
match input.trim().to_ascii_lowercase().as_str() {
"y" | "ye" | "yes" | "" => { Ok(true) },
"n" | "no" => { println!("Okay, no reports will be created."); Ok(false) },
"c" | "change" => {
let new_dir = cli_user_choices::choose_export_dir()?;
settings.export_path = PathBuf::from(new_dir);
Ok(true)
},
_ => { println!("Please respond with 'y', 'n', or 'c' (or 'yes' or 'no' or 'change').");
_export(settings)
}
}
}
Ok(choice)
}