From c5b3b3b045312dc583b3f8a3fdccb9bff82ea693 Mon Sep 17 00:00:00 2001 From: Jacek Czaja Date: Sat, 31 Jan 2026 13:10:45 +0100 Subject: [PATCH] Bumped up version to 0.7.5 - added multi year option --- Cargo.lock | 2 +- Cargo.toml | 4 +--- src/gui.rs | 2 +- src/lib.rs | 23 ++++++++++++--------- src/main.rs | 58 ++++++++++++++++++++++++++++++++++++++++++++++------- 5 files changed, 68 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 55a99c7..503c1e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -630,7 +630,7 @@ checksum = "ca81e6b4777c89fd810c25a4be2b1bd93ea034fbe58e6a75216a34c6b82c539b" [[package]] name = "etradeTaxReturnHelper" -version = "0.7.4" +version = "0.7.5" dependencies = [ "calamine", "chrono", diff --git a/Cargo.toml b/Cargo.toml index 84667ea..d687ea1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ [package] name = "etradeTaxReturnHelper" -version = "0.7.4" +version = "0.7.5" edition = "2021" description = "Parses etrade and revolut financial documents for transaction details (income, tax paid, cost basis) and compute total income and total tax paid according to chosen tax residency (currency)" license = "BSD-3-Clause" @@ -35,9 +35,7 @@ serde = { version = "1.0.104", features = ["derive"] } roxmltree = "0.20.0" simple_logger = "4.0.0" log = "0.4.0" -#clap = "~2.27.0" clap = { version = "4.5.51", features = ["derive"] } -#regex = "1.3.3" regex = "1.12.2" calamine = "0.22.1" wild = "2.2.0" diff --git a/src/gui.rs b/src/gui.rs index 1329e21..789aca9 100644 --- a/src/gui.rs +++ b/src/gui.rs @@ -129,7 +129,7 @@ fn create_execute_documents( revolut_dividends_transactions: revolut_transactions, sold_transactions, revolut_sold_transactions, - } = match run_taxation(&rd, file_names,false) { + } = match run_taxation(&rd, file_names,false, false) { Ok(res) => { nbuffer.set_text("Finished.\n\n (Double check if generated tax data (Summary) makes sense and then copy it to your tax form)"); res diff --git a/src/lib.rs b/src/lib.rs index b6b6324..e5cdd9a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -373,6 +373,7 @@ pub fn run_taxation( rd: &Box, names: Vec, per_company: bool, + multiyear: bool, ) -> Result { validate_file_names(&names)?; @@ -418,15 +419,19 @@ pub fn run_taxation( } Ok::<(), String>(()) })?; - // 2. Verify Transactions - verify_interests_transactions(&parsed_interests_transactions)?; - log::info!("Interests transactions are consistent"); - verify_dividends_transactions(&parsed_div_transactions)?; - log::info!("Dividends transactions are consistent"); - verify_dividends_transactions(&parsed_revolut_dividends_transactions)?; - log::info!("Revolut Dividends transactions are consistent"); - verify_transactions(&parsed_revolut_sold_transactions)?; - log::info!("Revolut Sold transactions are consistent"); + // 2. Verify Transactions (if they all come from same year unless multiyear is enabled) + if multiyear == false { + verify_interests_transactions(&parsed_interests_transactions)?; + log::info!("Interests transactions are consistent"); + verify_dividends_transactions(&parsed_div_transactions)?; + log::info!("Dividends transactions are consistent"); + verify_dividends_transactions(&parsed_revolut_dividends_transactions)?; + log::info!("Revolut Dividends transactions are consistent"); + verify_transactions(&parsed_revolut_sold_transactions)?; + log::info!("Revolut Sold transactions are consistent"); + } else { + log::info!("Multi-year mode enabled, skipping verification of transaction years"); + } // 3. Verify and create full sold transactions info needed for TAX purposes let detailed_sold_transactions = diff --git a/src/main.rs b/src/main.rs index dd65a83..3ddad3e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -52,6 +52,12 @@ fn create_cmd_line_pattern(myapp: Command) -> Command { .help("Enable per-company mode") .action(clap::ArgAction::SetTrue) ) + .arg( + Arg::new("multiyear") + .long("multiyear") + .help("Allow processing documents across more than year") + .action(clap::ArgAction::SetTrue) + ) } fn configure_dataframes_format() { @@ -107,7 +113,12 @@ fn main() { gross_sold, cost_sold, .. - } = match run_taxation(&rd, pdfnames, matches.get_flag("per-company")) { + } = match run_taxation( + &rd, + pdfnames, + matches.get_flag("per-company"), + matches.get_flag("multiyear"), + ) { Ok(res) => res, Err(msg) => panic!("\nError: Unable to compute taxes. \n\nDetails: {msg}"), }; @@ -261,6 +272,39 @@ mod tests { Ok(()) } + #[test] + fn test_cmdline_multiyear() -> Result<(), clap::Error> { + // Init Transactions + let myapp = Command::new("E-trade tax helper"); + let matches = + create_cmd_line_pattern(myapp).get_matches_from(vec!["mytest", "data/example.pdf"]); + let multiyear = matches.get_flag("multiyear"); + match multiyear { + false => (), + true => { + return Err(clap::error::Error::::new( + clap::error::ErrorKind::InvalidValue, + )) + } + }; + let myapp = Command::new("E-trade tax helper"); + let matches = create_cmd_line_pattern(myapp).get_matches_from(vec![ + "mytest", + "--multiyear", + "data/example.pdf", + ]); + let multiyear = matches.get_flag("multiyear"); + match multiyear { + true => (), + false => { + return Err(clap::error::Error::::new( + clap::error::ErrorKind::InvalidValue, + )) + } + }; + Ok(()) + } + #[test] fn test_cmdline_pl() -> Result<(), clap::Error> { // Init Transactions @@ -330,7 +374,7 @@ mod tests { .expect_and_log("error getting financial documents names"); let pdfnames: Vec = pdfnames.map(|x| x.to_string()).collect(); - match etradeTaxReturnHelper::run_taxation(&rd, pdfnames, false) { + match etradeTaxReturnHelper::run_taxation(&rd, pdfnames, false, false) { Ok(_) => panic!("Expected an error from run_taxation, but got Ok"), Err(_) => Ok(()), // Expected error, test passes } @@ -351,7 +395,7 @@ mod tests { .expect_and_log("error getting brokarage statements pdfs names"); let pdfnames: Vec = pdfnames.map(|x| x.to_string()).collect(); - match etradeTaxReturnHelper::run_taxation(&rd, pdfnames, false) { + match etradeTaxReturnHelper::run_taxation(&rd, pdfnames, false, false) { Ok(TaxCalculationResult { gross_income: gross_div, tax: tax_div, @@ -384,7 +428,7 @@ mod tests { .expect_and_log("error getting brokarage statements pdfs names"); let pdfnames: Vec = pdfnames.map(|x| x.to_string()).collect(); - match etradeTaxReturnHelper::run_taxation(&rd, pdfnames, false) { + match etradeTaxReturnHelper::run_taxation(&rd, pdfnames, false, false) { Ok(TaxCalculationResult { gross_income: gross_div, tax: tax_div, @@ -417,7 +461,7 @@ mod tests { .expect_and_log("error getting brokarage statements pdfs names"); let pdfnames: Vec = pdfnames.map(|x| x.to_string()).collect(); - match etradeTaxReturnHelper::run_taxation(&rd, pdfnames, false) { + match etradeTaxReturnHelper::run_taxation(&rd, pdfnames, false, false) { Ok(TaxCalculationResult { gross_income: gross_div, tax: tax_div, @@ -451,7 +495,7 @@ mod tests { .expect_and_log("error getting brokarage statements pdfs names"); let pdfnames: Vec = pdfnames.map(|x| x.to_string()).collect(); - match etradeTaxReturnHelper::run_taxation(&rd, pdfnames, false) { + match etradeTaxReturnHelper::run_taxation(&rd, pdfnames, false, false) { Ok(TaxCalculationResult { gross_income: gross_div, tax: tax_div, @@ -482,7 +526,7 @@ mod tests { .expect_and_log("error getting brokarage statements pdfs names"); let pdfnames: Vec = pdfnames.map(|x| x.to_string()).collect(); - match etradeTaxReturnHelper::run_taxation(&rd, pdfnames, false) { + match etradeTaxReturnHelper::run_taxation(&rd, pdfnames, false, false) { Ok(TaxCalculationResult { gross_income: gross_div, tax: tax_div,