Skip to content

Commit

Permalink
- Added support for interest adjustment
Browse files Browse the repository at this point in the history
  • Loading branch information
jczaja committed Apr 3, 2024
1 parent 4865618 commit 12786d3
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 3 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "etradeTaxReturnHelper"
version = "0.5.0"
version = "0.5.1"
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"
Expand Down
26 changes: 26 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use logging::ResultExt;
// TODO: Make a parsing of incomplete date
// TODO: When I sold on Dec there was EST cost (0.04). Make sure it is included in your results
// TODO: async to get currency
// TODO: make UT using rounded vlaues of f32
// TODO: parse_gain_and_losses expect -> ?
// TODO: GUI : choosing residency
// TODO: Drag&Drop to work on MultiBrowser field
Expand Down Expand Up @@ -438,4 +439,29 @@ mod tests {
Err(x) => panic!("Error in taxation process"),
}
}

#[test]
#[ignore]
fn test_interest_adjustment_taxation() -> Result<(), clap::Error> {
// Get all brokerage with dividends only
let myapp = App::new("E-trade tax helper").setting(AppSettings::ArgRequiredElseHelp);
let rd: Box<dyn etradeTaxReturnHelper::Residency> = Box::new(pl::PL {});
let matches = create_cmd_line_pattern(myapp)
.get_matches_from_safe(vec!["mytest", "data/example-interest-adj.pdf"])?;
let pdfnames = matches
.values_of("financial documents")
.expect_and_log("error getting brokarage statements pdfs names");
let pdfnames: Vec<String> = pdfnames.map(|x| x.to_string()).collect();

match etradeTaxReturnHelper::run_taxation(&rd, pdfnames) {
Ok((gross_div, tax_div, gross_sold, cost_sold, _, _, _, _)) => {
assert_eq!(
(gross_div, tax_div, gross_sold, cost_sold),
(0.66164804, 0.0, 0.0, 0.0),
);
Ok(())
}
Err(x) => panic!("Error in taxation process"),
}
}
}
36 changes: 35 additions & 1 deletion src/pdfparser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,10 @@ impl Entry for StringEntry {
fn getstring(&self) -> Option<String> {
Some(self.val.clone())
}
// Either match parsed token against any of patterns or in case no patterns are there
// just return match (true)
fn is_pattern(&self) -> bool {
self.patterns.iter().find(|&x| self.val == *x).is_some()
self.patterns.len() == 0 || self.patterns.iter().find(|&x| self.val == *x).is_some()
}
}

Expand Down Expand Up @@ -165,6 +167,24 @@ fn create_interests_fund_parsing_sequence(
sequence.push_back(Box::new(F32Entry { val: 0.0 })); // Income Entry
}

fn create_interest_adjustment_parsing_sequence(
sequence: &mut std::collections::VecDeque<Box<dyn Entry>>,
) {
sequence.push_back(Box::new(StringEntry {
val: String::new(),
patterns: vec![],
}));
sequence.push_back(Box::new(StringEntry {
val: String::new(),
patterns: vec![],
}));
sequence.push_back(Box::new(StringEntry {
val: String::new(),
patterns: vec![],
}));
sequence.push_back(Box::new(F32Entry { val: 0.0 })); // Income Entry
}

fn create_qualified_dividend_parsing_sequence(
sequence: &mut std::collections::VecDeque<Box<dyn Entry>>,
) {
Expand Down Expand Up @@ -685,6 +705,10 @@ fn check_if_transaction(
create_interests_fund_parsing_sequence(sequence);
state = ParserState::ProcessingTransaction(TransactionType::Interests);
log::info!("Starting to parse Interests Fund transaction");
} else if candidate_string == "INTEREST INCOME-ADJ" {
create_interest_adjustment_parsing_sequence(sequence);
state = ParserState::ProcessingTransaction(TransactionType::Interests);
log::info!("Starting to parse Interest adjustment transaction");
} else if candidate_string == "QUALIFIED DIVIDEND" {
create_qualified_dividend_parsing_sequence(sequence);
state = ParserState::ProcessingTransaction(TransactionType::Dividends);
Expand Down Expand Up @@ -940,6 +964,16 @@ mod tests {
patterns: vec!["INTC".to_owned(), "DLB".to_owned()],
};
s.parse(&pdf::primitive::PdfString::new(data));
assert_eq!(s.is_pattern(), true);

// unimportant string
let data: Vec<u8> = vec!['K' as u8, 'L' as u8, 'M' as u8];
let mut s = StringEntry {
val: String::new(),
patterns: vec![],
};
s.parse(&pdf::primitive::PdfString::new(data));
assert_eq!(s.is_pattern(), true);
Ok(())
}

Expand Down

0 comments on commit 12786d3

Please sign in to comment.