1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
use crate::broker_statement::BrokerStatement; use crate::config::Config; use crate::core::EmptyResult; use crate::currency::converter::CurrencyConverter; use crate::db; use crate::localities::Jurisdiction; pub use self::statement::TaxStatement; mod dividends; mod interest; mod statement; mod tax_agent; mod trades; pub fn generate_tax_statement( config: &Config, portfolio_name: &str, year: Option<i32>, tax_statement_path: Option<&str> ) -> EmptyResult { let country = config.get_tax_country(); let portfolio = config.get_portfolio(portfolio_name)?; let broker = portfolio.broker.get_info(config, portfolio.plan.as_ref())?; let broker_statement = BrokerStatement::read( broker, &portfolio.statements, &portfolio.symbol_remapping, &portfolio.instrument_names, portfolio.get_tax_remapping()?, true)?; if let Some(year) = year { broker_statement.check_period_against_tax_year(year)?; } let mut tax_statement = match tax_statement_path { Some(path) => { let year = year.ok_or("Tax year must be specified when tax statement is specified")?; let statement = TaxStatement::read(path)?; if statement.year != year { return Err!("Tax statement year ({}) doesn't match the requested year {}", statement.year, year); } Some(statement) }, None => None, }; let database = db::connect(&config.db_path)?; let converter = CurrencyConverter::new(database, None, true); let trades_tax = trades::process_income( &country, &portfolio, &broker_statement, year, tax_statement.as_mut(), &converter, ).map_err(|e| format!("Failed to process income from stock trading: {}", e))?; let dividends_tax = dividends::process_income( &country, &broker_statement, year, tax_statement.as_mut(), &converter, ).map_err(|e| format!("Failed to process dividend income: {}", e))?; let interest_tax = interest::process_income( &country, &broker_statement, year, tax_statement.as_mut(), &converter, ).map_err(|e| format!("Failed to process income from idle cash interest: {}", e))?; if broker_statement.broker.type_.jurisdiction() == Jurisdiction::Russia { if let Some(mut total_tax) = trades_tax { total_tax.add_assign(dividends_tax).unwrap(); total_tax.add_assign(interest_tax).unwrap(); tax_agent::process_tax_agent_withholdings(&broker_statement, year, total_tax); } } if let Some(ref tax_statement) = tax_statement { tax_statement.save()?; } Ok(()) }