From 3504c03f5dc53c3767876d37f4b9b8a8879593a6 Mon Sep 17 00:00:00 2001 From: Jacek Czaja Date: Wed, 6 Mar 2024 15:43:19 +0100 Subject: [PATCH] Adapted code to single digits format of new PDF (#101) * - changed to way dates were compares * - bumped up version --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/transactions.rs | 81 +++++++++++++++++++++++++++++++++++++++------ 3 files changed, 72 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3f0a6e7..453716d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -571,7 +571,7 @@ checksum = "b90ca2580b73ab6a1f724b76ca11ab632df820fd6040c336200d2c1df7b3c82c" [[package]] name = "etradeTaxReturnHelper" -version = "0.4.4" +version = "0.4.5" dependencies = [ "calamine", "chrono", diff --git a/Cargo.toml b/Cargo.toml index 0b7fba2..75b8c90 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "etradeTaxReturnHelper" -version = "0.4.4" +version = "0.4.5" edition = "2021" description = "Parses etrade 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" diff --git a/src/transactions.rs b/src/transactions.rs index 9d5fca4..e2d914e 100644 --- a/src/transactions.rs +++ b/src/transactions.rs @@ -88,9 +88,14 @@ pub fn reconstruct_sold_transactions( // match trade date and gross with principal and trade date of trade confirmation log::info!("Reconstructing G&L sold transaction: trade date: {tr_date}, acquisition date: {acquisition_date}, cost basis: {cost_basis}, income: {inc}"); - let (_, settlement_date, _, _, _) = sold_transactions.iter().find(|(trade_dt, _, _, _, _income)|{ - *trade_dt == chrono::NaiveDate::parse_from_str(&tr_date, "%m/%d/%Y").expect_and_log(&format!("Unable to parse trade date: {tr_date}")).format("%m/%d/%y").to_string() - }).expect_and_log(&format!("\n\nERROR: Sold transaction:\n (trade_date: {tr_date}, acquisition date: {acquisition_date}, cost basis: {cost_basis}, income: {inc}) detected,\n but corressponding data from PDF document is missing. You can download account statements PDF documents at:\n + let trade_date = chrono::NaiveDate::parse_from_str(&tr_date, "%m/%d/%Y") + .expect_and_log(&format!("Unable to parse trade date: {tr_date}")); + + let (_, settlement_date, _, _, _) = sold_transactions.iter().find(|(trade_dt, _, _, _, income)|{ + log::info!("Candidate Sold transaction from PDF: trade_date: {trade_dt} income: {income}"); + let trade_date_pdf = chrono::NaiveDate::parse_from_str(&trade_dt, "%m/%d/%y").expect_and_log(&format!("Unable to parse trade date: {trade_dt}")); + trade_date == trade_date_pdf + }).expect_and_log(&format!("\n\nERROR: Sold transaction in Gain&Losses:\n (trade_date: {tr_date}, acquisition date: {acquisition_date}, cost basis: {cost_basis}, income: {inc}) exist,\n but corressponding data from PDF document is missing. You can download account statements PDF documents at:\n https://edoc.etrade.com/e/t/onlinedocs/docsearch?doc_type=stmt\n\n")); detailed_sold_transactions.push(( @@ -638,6 +643,60 @@ mod tests { Ok(()) } + #[test] + fn test_sold_transaction_reconstruction_single_digits_ok() -> Result<(), String> { + let parsed_sold_transactions: Vec<(String, String, f32, f32, f32)> = vec![ + ("6/1/21".to_string(), "6/3/21".to_string(), 1.0, 25.0, 24.8), + ("3/1/21".to_string(), "3/3/21".to_string(), 2.0, 10.0, 19.8), + ]; + + let parsed_gains_and_losses: Vec<(String, String, f32, f32, f32)> = vec![ + ( + "01/01/2019".to_string(), + "06/01/2021".to_string(), + 10.0, + 10.0, + 24.8, + ), + ( + "01/01/2021".to_string(), + "03/01/2021".to_string(), + 20.0, + 20.0, + 19.8, + ), + ]; + + let detailed_sold_transactions = + reconstruct_sold_transactions(&parsed_sold_transactions, &parsed_gains_and_losses)?; + + // 1. trade date + // 2. settlement date + // 3. date of purchase + // 4. net income + // 5. cost cost basis + assert_eq!( + detailed_sold_transactions, + vec![ + ( + "06/01/21".to_string(), + "6/3/21".to_string(), + "01/01/19".to_string(), + 24.8, + 10.0 + ), + ( + "03/01/21".to_string(), + "3/3/21".to_string(), + "01/01/21".to_string(), + 19.8, + 20.0 + ), + ] + ); + Ok(()) + } + #[test] #[should_panic] fn test_sold_transaction_reconstruction_second_fail() { @@ -697,29 +756,29 @@ mod tests { let parsed_gains_and_losses: Vec<(String, String, f32, f32, f32)> = vec![ ( - "08/19/21".to_string(), - "12/19/22".to_string(), + "08/19/2021".to_string(), + "12/19/2022".to_string(), 4336.4874, 4758.6971, 2711.0954, ), ( - "05/03/21".to_string(), - "12/21/22".to_string(), + "05/03/2021".to_string(), + "12/21/2022".to_string(), 0.0, 3876.918, 2046.61285, ), ( - "08/19/22".to_string(), - "12/19/22".to_string(), + "08/19/2022".to_string(), + "12/19/2022".to_string(), 5045.6257, 5936.0274, 3986.9048, ), ( - "05/02/22".to_string(), - "12/21/22".to_string(), + "05/02/2022".to_string(), + "12/21/2022".to_string(), 0.0, 4013.65, 2285.82733,