Skip to content

Commit

Permalink
Added PDF parser to new morgan&stanley account statement documents (#96)
Browse files Browse the repository at this point in the history
* - implemented recognition of PDF document types

* - excluded borkerage statement to seprate function

* - Writing parser for account statement (WIP)

* - Added sequnce parsing for div and tax of account statement

* - Added parsing (val) format of f32

* - Fixed taxation transaction

* - Fix to tax

* - quantity of stock is f32 now

* - Fixes to detection documents

* - Finished adding parser for new type of PDF (POC)

* - Added ignoring "$"

* - Added UT

* - Added tracing of legacy pdf documents parser

* - Partially done date parsing from new type of PDF

* - Implemented but does not work yet

* - All unit tests works e.g. implemented getting a fiscal date

* - Documents info updated

* - Added picture

* - removed deprecated TODOs

* - Added unit test (ignored e.g. depending on the locally stored data)
  • Loading branch information
jczaja authored Feb 28, 2024
1 parent 4cd7ab8 commit 4d5affe
Show file tree
Hide file tree
Showing 8 changed files with 642 additions and 68 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.4.0"
version = "0.4.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
Binary file added Pictures/GUI.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
# etradeTaxReturnHelper
Project that parse e-trade PDF brokerage statements and Gain and Losses documents and compute total gross gain and tax paid in US that are needed for tax return forms out of US.
Project that parse e-trade PDF account statements and Gain and Losses documents and compute total gross gain and tax paid in US that are needed for tax return forms out of US.

### Data for Tax form from capital gains (PIT-38 in Poland)
1. Install this program: `cargo install etradeTaxReturnHelper`
2. Download PDF documents from a year you are filling your tax return form for example: `Brokerage Statement <xxx>.pdf`:
2. Download PDF documents from a year you are filling your tax return form for example: `Brokerage Statement <xxx>.pdf` and `MS_ClientStatements_<xxx>.pdf`:
1. Login to e-trade, navigate to [Documents/Brokerage Statements](https://edoc.etrade.com/e/t/onlinedocs/docsearch?doc_type=stmt)
2. Select date period
3. Download all `ACCOUNT STATEMENT` documents
3. Run: `etradeTaxReturnHelper <your PDF documents that MAY contains dividends and/or sold transactions e.g. "*.pdf">`
3. Run:
1. `etradeTaxReturnHelper <your PDF documents that MAY contains dividends and/or sold transactions e.g. "*.pdf"> <Gain and Loss XLSX document>`
2. Alternatively you can run `etradeTaxReturnHelper` to have program running with GUI (graphical user interface):
![gui](/Pictures/GUI.png)

### FAQ
1. How to install this project?
Expand All @@ -17,6 +20,9 @@ Project that parse e-trade PDF brokerage statements and Gain and Losses document
`cargo install etradeTaxReturnHelper`
3. For Linux where there is no X server or no priviligies to install system dependencies then you could try to install non-GUI version:
`cargo install etradeTaxReturnHelper --no-default-features`
2. Does it work for other financial institutions apart from etrade ?
There is support for saving accounts statements of Revolut bank (CSV files) , as Revolut does not pay tax on customer behalf and tax from capital gain of saving account should be paid by customer.


2. How does it work?
Here is a [demo(PL)](https://www.youtube.com/watch?v=Juw3KJ1JdcA)
Expand Down
10 changes: 6 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ pub fn run_taxation(
String,
> {
let mut parsed_div_transactions: Vec<(String, f32, f32)> = vec![];
let mut parsed_sold_transactions: Vec<(String, String, i32, f32, f32)> = vec![];
let mut parsed_sold_transactions: Vec<(String, String, f32, f32, f32)> = vec![];
let mut parsed_gain_and_losses: Vec<(String, String, f32, f32, f32)> = vec![];
let mut parsed_revolut_transactions: Vec<(String, Currency)> = vec![];

Expand All @@ -274,15 +274,17 @@ pub fn run_taxation(
// If name contains .pdf then parse as pdf
// if name contains .xlsx then parse as spreadsheet
if x.contains(".pdf") {
let (mut div_t, mut sold_t, _) = pdfparser::parse_brokerage_statement(x)?;
let (mut div_t, mut sold_t, _) = pdfparser::parse_statement(x)?;
parsed_div_transactions.append(&mut div_t);
parsed_sold_transactions.append(&mut sold_t);
} else if x.contains(".xlsx") {
parsed_gain_and_losses.append(&mut xlsxparser::parse_gains_and_losses(x)?);
} else {
} else if x.contains(".csv") {
parsed_revolut_transactions.append(&mut csvparser::parse_revolut_transactions(x)?);
} else {
return Err(format!("Error: Unable to open a file: {x}"));
}
Ok::<(), &str>(())
Ok::<(), String>(())
})?;
// 2. Verify Transactions
verify_dividends_transactions(&parsed_div_transactions)?;
Expand Down
41 changes: 39 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ mod gui;
use etradeTaxReturnHelper::run_taxation;
use logging::ResultExt;

// TODO: Finish parse_revolut_transactions
// TODO: Add UT for parsing investment document
// TODO: Make a parsing of incomplete date
// TODO: Dividends of revolut should combined with dividends not sold
// 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: parse_gain_and_losses expect -> ?
// TODO: GUI : choosing residency
Expand Down Expand Up @@ -327,6 +328,42 @@ mod tests {
}
}

#[test]
#[ignore]
fn test_sold_dividends_taxation_2023() -> 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",
"etrade_data_2023/Brokerage Statement - XXXXX6557 - 202302.pdf",
"etrade_data_2023/Brokerage Statement - XXXXX6557 - 202303.pdf",
"etrade_data_2023/Brokerage Statement - XXXXX6557 - 202306.pdf",
"etrade_data_2023/Brokerage Statement - XXXXX6557 - 202308.pdf",
"etrade_data_2023/Brokerage Statement - XXXXX6557 - 202309.pdf",
"etrade_data_2023/MS_ClientStatements_6557_202309.pdf",
"etrade_data_2023/MS_ClientStatements_6557_202311.pdf",
"etrade_data_2023/MS_ClientStatements_6557_202312.pdf",
"etrade_data_2023/G&L_Collapsed-2023.xlsx",
])?;
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),
(8369.726, 1253.2899, 14983.293, 7701.9253)
);
Ok(())
}
Err(x) => panic!("Error in taxation process"),
}
}

#[test]
#[ignore]
fn test_sold_dividends_only_taxation() -> Result<(), clap::Error> {
Expand Down
Loading

0 comments on commit 4d5affe

Please sign in to comment.