use chrono::Utc;
use clap::{value_parser, Arg, Command};
use colored::Colorize;
use vz_tools_cli::db;
fn main() {
let matches = Command::new("vz-tools/cli")
.version("0.1.0")
.author("notgiorgi <notgiorgi@gmail.com>")
.about("Virtual zone dividend tracker for easy tax filling")
.subcommand(
Command::new("dividend")
.arg(
Arg::new("amount") .help("Net money amount")
.value_parser(value_parser!(f64))
.required(true),
)
.arg(
Arg::new("dry")
.long("dry")
.short('d')
.value_parser(value_parser!(bool))
.default_value("false")
.default_missing_value("true")
.num_args(0..=1)
.help("if true tx wont be persisted"),
)
.about("Calculates dividend from net amount and optionally persists it locally"),
)
.subcommand(
Command::new("get-latest")
.arg(
Arg::new("instructions")
.short('i')
.long("instructions")
.default_value("false")
.default_missing_value("true")
.num_args(0..=1)
.value_parser(value_parser!(bool))
.help("Prints declaration filling instructions if set to true"),
)
.about("Retrieves latest persisted transaction"),
)
.subcommand(Command::new("get-all").about("Prints out all the past persisted transactions"))
.get_matches();
match matches.subcommand() {
Some(("dividend", args)) => {
let amount = *args.get_one::<f64>("amount").expect("amount is required");
let dry = *args
.get_one::<bool>("dry")
.expect("dry has a default value");
let (amount, reminder) = round_down(amount);
let (dividend, tax) = calculate_dividend(amount);
if dry {
println!("{}", "Dry run, transaction won't be persisted".bold());
print!("{}", format_dividend_instructions(dividend, tax, reminder));
return;
}
let date = Utc::now().to_rfc3339();
let conn = db::db_connect().expect("Couldn't connect to db");
let tx = db::Tx::new(date, amount, dividend, tax, reminder);
db::insert_tx(&conn, &tx).expect("Couldn't insert tx, try again");
println!("{}", "Transaction persisted".bold());
println!();
print_header();
println!("{}", tx);
}
Some(("get-latest", args)) => {
let instructions = *args
.get_one::<bool>("instructions")
.expect("instructions has a default value");
let conn = db::db_connect().expect("Couldn't connect to db");
let tx = db::find_latest_tx(&conn).expect("Couldn't find latest tx");
println!("{}", "Latest tx".bold());
println!();
print_header();
println!("{}", tx);
if instructions {
print_instructions();
}
}
Some(("get-all", _args)) => {
let conn = db::db_connect().expect("Couldn't connect to db");
let txs = db::find_all_tx(&conn).expect("Couldn't find txs");
println!("{}", "Last 20 txs".bold());
println!();
print_header();
for tx in txs {
println!("{}", tx);
}
}
_ => println!("no commands"),
}
}
fn round_down(net: f64) -> (f64, f64) {
let net_int = net as i32;
let new_net = net_int - net_int % 20;
let mut remainder = 0.0;
if new_net != net_int {
remainder = net - (new_net as f64);
}
return (new_net as f64, remainder);
}
fn calculate_dividend(net: f64) -> (f64, f64) {
return (net * 0.95, net * 0.05);
}
fn format_dividend_instructions(dividend: f64, tax: f64, remainder: f64) -> String {
return format!(
r#"
{}: {}
{}: {}
{}: {}
"#,
"Dividend".bold(),
dividend.to_string().underline(),
"Tax".bold(),
tax.to_string().underline(),
"Remainder".bold(),
remainder.to_string().underline()
);
}
fn print_header() {
println!(
"| {0: <15} | {1: <15} | {2: <15} | {3: <15} | {4: <15}",
"Date".bold(),
"Net amount".bold(),
"Dividend".bold(),
"Tax".bold(),
"Remainder".bold()
);
}
fn print_instructions() {
println!(
"\
დეკლარაციის ტიპი: საშემოსავლო (გადახდის წყაროსთან დაკავებული გადასახადი)
საქმიანობის კოდი: 62020
დანარჩენი: https://virtualzonetools.github.io/virtual-person-taxes/
"
);
}