Added CLI arg for indicating input file date separator character. Also cleaned up Cli struct. Takes care of one item from #48.
This commit is contained in:
parent
8dfb79ed9b
commit
8567dd04b0
|
@ -52,6 +52,7 @@ pub struct ImportProcessParameters {
|
||||||
pub enable_like_kind_treatment: bool,
|
pub enable_like_kind_treatment: bool,
|
||||||
pub costing_method: InventoryCostingMethod,
|
pub costing_method: InventoryCostingMethod,
|
||||||
pub lk_cutoff_date_string: String,
|
pub lk_cutoff_date_string: String,
|
||||||
|
pub date_separator: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn import_and_process_final(
|
pub(crate) fn import_and_process_final(
|
||||||
|
@ -62,7 +63,7 @@ pub(crate) fn import_and_process_final(
|
||||||
HashMap<u16, RawAccount>,
|
HashMap<u16, RawAccount>,
|
||||||
HashMap<u32, ActionRecord>,
|
HashMap<u32, ActionRecord>,
|
||||||
HashMap<u32, Transaction>,
|
HashMap<u32, Transaction>,
|
||||||
Option<LikeKindSettings>
|
Option<LikeKindSettings>,
|
||||||
), Box<dyn Error>> {
|
), Box<dyn Error>> {
|
||||||
|
|
||||||
let mut transactions_map: HashMap<u32, Transaction> = HashMap::new();
|
let mut transactions_map: HashMap<u32, Transaction> = HashMap::new();
|
||||||
|
@ -76,7 +77,8 @@ pub(crate) fn import_and_process_final(
|
||||||
&mut transactions_map,
|
&mut transactions_map,
|
||||||
&mut action_records_map,
|
&mut action_records_map,
|
||||||
&mut raw_account_map,
|
&mut raw_account_map,
|
||||||
&mut account_map
|
&mut account_map,
|
||||||
|
&settings.date_separator,
|
||||||
) {
|
) {
|
||||||
Ok(()) => { println!("Successfully imported csv file."); }
|
Ok(()) => { println!("Successfully imported csv file."); }
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
@ -93,6 +95,7 @@ pub(crate) fn import_and_process_final(
|
||||||
action_records: &mut HashMap<u32, ActionRecord>,
|
action_records: &mut HashMap<u32, ActionRecord>,
|
||||||
raw_acct_map: &mut HashMap<u16, RawAccount>,
|
raw_acct_map: &mut HashMap<u16, RawAccount>,
|
||||||
acct_map: &mut HashMap<u16, Account>,
|
acct_map: &mut HashMap<u16, Account>,
|
||||||
|
date_separator: &str,
|
||||||
) -> Result<(), Box<dyn Error>> {
|
) -> Result<(), Box<dyn Error>> {
|
||||||
|
|
||||||
let file = File::open(import_file_path)?; println!("CSV ledger file opened successfully.\n");
|
let file = File::open(import_file_path)?; println!("CSV ledger file opened successfully.\n");
|
||||||
|
@ -107,6 +110,7 @@ pub(crate) fn import_and_process_final(
|
||||||
&mut rdr,
|
&mut rdr,
|
||||||
transactions_map,
|
transactions_map,
|
||||||
action_records,
|
action_records,
|
||||||
|
date_separator,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -111,6 +111,7 @@ pub(crate) fn import_transactions(
|
||||||
rdr: &mut csv::Reader<File>,
|
rdr: &mut csv::Reader<File>,
|
||||||
txns_map: &mut HashMap<u32, Transaction>,
|
txns_map: &mut HashMap<u32, Transaction>,
|
||||||
action_records: &mut HashMap<u32, ActionRecord>,
|
action_records: &mut HashMap<u32, ActionRecord>,
|
||||||
|
sep: &str,
|
||||||
) -> Result<(), Box<dyn Error>> {
|
) -> Result<(), Box<dyn Error>> {
|
||||||
|
|
||||||
let mut this_tx_number = 0;
|
let mut this_tx_number = 0;
|
||||||
|
@ -199,9 +200,12 @@ pub(crate) fn import_transactions(
|
||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
let tx_date = NaiveDate::parse_from_str(this_tx_date, "%m/%d/%y")
|
let format_yy: &str = &("%m".to_owned() + sep + &"%d" + sep + "%y");
|
||||||
.unwrap_or(NaiveDate::parse_from_str(this_tx_date, "%m/%d/%Y")
|
let format_yyyy: &str = &("%m".to_owned() + sep + &"%d" + sep + "%Y");
|
||||||
.expect("%m/%d/%y (or %Y) format required for ledger import")
|
|
||||||
|
let tx_date = NaiveDate::parse_from_str(this_tx_date, format_yy)
|
||||||
|
.unwrap_or(NaiveDate::parse_from_str(this_tx_date, format_yyyy)
|
||||||
|
.expect("\nFailed to parse date in input file. Check date separator character. Also %m/%d/%y (or %Y) format is required.\n")
|
||||||
);
|
);
|
||||||
|
|
||||||
let transaction = Transaction {
|
let transaction = Transaction {
|
||||||
|
|
34
src/main.rs
34
src/main.rs
|
@ -33,6 +33,9 @@ mod skip_wizard;
|
||||||
#[structopt(name = "cryptools")]
|
#[structopt(name = "cryptools")]
|
||||||
pub(crate) struct Cli {
|
pub(crate) struct Cli {
|
||||||
|
|
||||||
|
#[structopt(flatten)]
|
||||||
|
flags: Flags,
|
||||||
|
|
||||||
/// 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))]
|
||||||
file_to_import: Option<PathBuf>,
|
file_to_import: Option<PathBuf>,
|
||||||
|
@ -41,16 +44,18 @@ pub(crate) struct Cli {
|
||||||
#[structopt(name = "output directory", short, long = "output", default_value = ".", parse(from_os_str))]
|
#[structopt(name = "output directory", short, long = "output", default_value = ".", parse(from_os_str))]
|
||||||
output_dir_path: PathBuf,
|
output_dir_path: PathBuf,
|
||||||
|
|
||||||
/// This will prevent the program from writing the CSV to file. This will be ignored if -a is not set (the wizard will always ask to output).
|
/// Choose "h" or "s" for hyphen or slash (i.e., "-" or "/") to indicate the separator character used
|
||||||
#[structopt(name = "suppress reports", short, long = "suppress")]
|
/// in the input file txDate column (i.e. 2017/12/31 or 2017-12-31).
|
||||||
suppress_reports: bool,
|
#[structopt(name = "date separator character", short, long = "date-separator", default_value = "h", parse(from_os_str))]
|
||||||
|
date_separator: OsString,
|
||||||
|
|
||||||
/// Cutoff date through which like-kind exchange treatment should be applied.
|
/// Cutoff date through which like-kind exchange treatment should be applied.
|
||||||
/// Please use %y-%m-%d (or %Y-%m-%d) format for like-kind cutoff date entry.
|
/// Please use %y-%m-%d (or %Y-%m-%d) format for like-kind cutoff date entry.
|
||||||
#[structopt(name = "like-kind cutoff date", short, long = "cutoff", parse(from_os_str))]
|
#[structopt(name = "like-kind cutoff date", short, long = "lk-cutoff", parse(from_os_str))]
|
||||||
cutoff_date: Option<OsString>,
|
lk_cutoff_date: Option<OsString>,
|
||||||
|
|
||||||
/// Inventory costing method (in terms of lot selection, i.e., LIFO, FIFO, etc.). There are currently four options (1 through 4).
|
/// Inventory costing method (in terms of lot selection, i.e., LIFO, FIFO, etc.).
|
||||||
|
/// There are currently four options (1 through 4).
|
||||||
#[structopt(name = "method", short, long, default_value = "1", parse(from_os_str), long_help =
|
#[structopt(name = "method", short, long, default_value = "1", parse(from_os_str), long_help =
|
||||||
r" 1. LIFO according to the order the lot was created.
|
r" 1. LIFO according to the order the lot was created.
|
||||||
2. LIFO according to the basis date of the lot.
|
2. LIFO according to the basis date of the lot.
|
||||||
|
@ -59,13 +64,24 @@ pub(crate) struct Cli {
|
||||||
")]
|
")]
|
||||||
inv_costing_method: OsString,
|
inv_costing_method: OsString,
|
||||||
|
|
||||||
/// Home currency (currency in which all resulting reports are denominated). (Only available as a command line setting.)
|
/// Home currency (currency in which all resulting reports are denominated).
|
||||||
|
/// (Only available as a command line setting.)
|
||||||
#[structopt(name = "home currency", short = "c", long = "currency", default_value = "USD", parse(from_os_str))]
|
#[structopt(name = "home currency", short = "c", long = "currency", default_value = "USD", parse(from_os_str))]
|
||||||
home_currency: OsString,
|
home_currency: OsString,
|
||||||
|
}
|
||||||
|
|
||||||
/// User is instructing the program to skip the data entry wizard. When set, program will error without required command-line args.
|
#[derive(StructOpt, Debug)]
|
||||||
|
pub(crate) struct Flags {
|
||||||
|
|
||||||
|
/// User is instructing the program to skip the data entry wizard.
|
||||||
|
/// When set, program will error without required command-line args.
|
||||||
#[structopt(name = "accept args", short, long = "accept")]
|
#[structopt(name = "accept args", short, long = "accept")]
|
||||||
accept_args: bool,
|
accept_args: bool,
|
||||||
|
|
||||||
|
/// This will prevent the program from writing reports to files.
|
||||||
|
/// This will be ignored if -a is not set (the wizard will always ask to output).
|
||||||
|
#[structopt(name = "suppress reports", short, long = "suppress")]
|
||||||
|
suppress_reports: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -92,7 +108,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||||
let like_kind_settings;
|
let like_kind_settings;
|
||||||
let should_export;
|
let should_export;
|
||||||
|
|
||||||
if !args.accept_args {
|
if !args.flags.accept_args {
|
||||||
|
|
||||||
let (
|
let (
|
||||||
account_map1,
|
account_map1,
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::collections::{HashMap};
|
use std::collections::{HashMap};
|
||||||
|
use std::process;
|
||||||
|
|
||||||
use crate::cli_user_choices;
|
use crate::cli_user_choices;
|
||||||
use crate::core_functions::{self, LikeKindSettings, ImportProcessParameters};
|
use crate::core_functions::{self, LikeKindSettings, ImportProcessParameters};
|
||||||
|
@ -19,6 +20,12 @@ pub(crate) fn skip_wizard(args: super::Cli) -> Result<(
|
||||||
bool
|
bool
|
||||||
), Box<dyn Error>> {
|
), Box<dyn Error>> {
|
||||||
|
|
||||||
|
let date_separator = match args.date_separator.into_string().unwrap().as_str() {
|
||||||
|
"h" => {"-"}
|
||||||
|
"s" => {"/"}
|
||||||
|
_ => { println!("\nFATAL: The date-separator arg requires either an 'h' or an 's'.\n"); process::exit(1) }
|
||||||
|
};
|
||||||
|
|
||||||
let input_file_path;
|
let input_file_path;
|
||||||
|
|
||||||
if let Some(file) = args.file_to_import {
|
if let Some(file) = args.file_to_import {
|
||||||
|
@ -37,7 +44,7 @@ pub(crate) fn skip_wizard(args: super::Cli) -> Result<(
|
||||||
let like_kind_election;
|
let like_kind_election;
|
||||||
let like_kind_cutoff_date_string: String;
|
let like_kind_cutoff_date_string: String;
|
||||||
|
|
||||||
if let Some(date) = args.cutoff_date {
|
if let Some(date) = args.lk_cutoff_date {
|
||||||
like_kind_election = true;
|
like_kind_election = true;
|
||||||
like_kind_cutoff_date_string = date.into_string().unwrap();
|
like_kind_cutoff_date_string = date.into_string().unwrap();
|
||||||
} else {
|
} else {
|
||||||
|
@ -51,6 +58,7 @@ pub(crate) fn skip_wizard(args: super::Cli) -> Result<(
|
||||||
costing_method: costing_method_choice,
|
costing_method: costing_method_choice,
|
||||||
enable_like_kind_treatment: like_kind_election,
|
enable_like_kind_treatment: like_kind_election,
|
||||||
lk_cutoff_date_string: like_kind_cutoff_date_string,
|
lk_cutoff_date_string: like_kind_cutoff_date_string,
|
||||||
|
date_separator: date_separator.to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let (
|
let (
|
||||||
|
@ -61,7 +69,7 @@ pub(crate) fn skip_wizard(args: super::Cli) -> Result<(
|
||||||
like_kind_settings1
|
like_kind_settings1
|
||||||
) = core_functions::import_and_process_final(input_file_path, &settings)?;
|
) = core_functions::import_and_process_final(input_file_path, &settings)?;
|
||||||
|
|
||||||
let should_export = !args.suppress_reports;
|
let should_export = !args.flags.suppress_reports;
|
||||||
|
|
||||||
Ok((account_map1, raw_acct_map1, action_records_map1, transactions_map1, like_kind_settings1, settings, should_export))
|
Ok((account_map1, raw_acct_map1, action_records_map1, transactions_map1, like_kind_settings1, settings, should_export))
|
||||||
}
|
}
|
|
@ -24,6 +24,12 @@ pub(crate) fn wizard(args: super::Cli) -> Result<(
|
||||||
|
|
||||||
shall_we_proceed()?;
|
shall_we_proceed()?;
|
||||||
|
|
||||||
|
let date_separator = match args.date_separator.into_string().unwrap().as_str() {
|
||||||
|
"h" => {"-"}
|
||||||
|
"s" => {"/"}
|
||||||
|
_ => { println!("\nFATAL: The date-separator arg requires either an 'h' or an 's'.\n"); process::exit(1) }
|
||||||
|
};
|
||||||
|
|
||||||
let input_file_path;
|
let input_file_path;
|
||||||
|
|
||||||
if let Some(file) = args.file_to_import {
|
if let Some(file) = args.file_to_import {
|
||||||
|
@ -40,7 +46,7 @@ pub(crate) fn wizard(args: super::Cli) -> Result<(
|
||||||
|
|
||||||
let lk_cutoff_date_opt_string;
|
let lk_cutoff_date_opt_string;
|
||||||
|
|
||||||
if let Some(lk_cutoff) = args.cutoff_date {
|
if let Some(lk_cutoff) = args.lk_cutoff_date {
|
||||||
lk_cutoff_date_opt_string = Some(lk_cutoff.into_string().unwrap())
|
lk_cutoff_date_opt_string = Some(lk_cutoff.into_string().unwrap())
|
||||||
} else {
|
} else {
|
||||||
lk_cutoff_date_opt_string = None
|
lk_cutoff_date_opt_string = None
|
||||||
|
@ -54,6 +60,7 @@ pub(crate) fn wizard(args: super::Cli) -> Result<(
|
||||||
costing_method: costing_method_choice,
|
costing_method: costing_method_choice,
|
||||||
enable_like_kind_treatment: like_kind_election,
|
enable_like_kind_treatment: like_kind_election,
|
||||||
lk_cutoff_date_string: like_kind_cutoff_date,
|
lk_cutoff_date_string: like_kind_cutoff_date,
|
||||||
|
date_separator: date_separator.to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let (
|
let (
|
||||||
|
|
Loading…
Reference in New Issue