diff options
-rw-r--r-- | Cargo.lock | 2 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | budget/src/lib.rs | 31 | ||||
-rw-r--r-- | budget/tests/budget.rs | 29 | ||||
-rw-r--r-- | budget/tests/test.toml | 6 | ||||
-rw-r--r-- | src/main.rs | 17 |
6 files changed, 46 insertions, 41 deletions
@@ -82,7 +82,7 @@ dependencies = [ [[package]] name = "finbudg" -version = "0.1.0" +version = "0.1.2" dependencies = [ "budget", "chrono", @@ -1,6 +1,6 @@ [package] name = "finbudg" -version = "0.1.1" +version = "0.1.2" edition = "2018" description = "Quick cli tool to calculate your expenses and balance for a set period of time." license = "MIT" diff --git a/budget/src/lib.rs b/budget/src/lib.rs index e8bb8f3..7d7c390 100644 --- a/budget/src/lib.rs +++ b/budget/src/lib.rs @@ -51,6 +51,7 @@ pub struct Calculated { pub balance: f64, pub days_left: f64, pub days_left_essential: f64, + pub last_day: NaiveDate, } #[derive(PartialEq, Eq, Debug)] @@ -96,7 +97,11 @@ pub fn parse_account(path: &str) -> Result<Account, ParseError> { } } -pub fn calculate(account: &Account) -> Calculated { +pub fn calculate(account: &Account) -> Option<Calculated> { + if account.days.len() < 1 { + return None; + } + let mut calculated = Calculated { all_day_average: 0.0, essential_day_average: 0.0, @@ -107,12 +112,13 @@ pub fn calculate(account: &Account) -> Calculated { balance: 0.0, days_left: 0.0, days_left_essential: 0.0, + last_day: account.days.last().unwrap().date, }; - let mut days_calculated = 0; - for day in account.days.iter() { - days_calculated += 1; + if day.date > calculated.last_day { + calculated.last_day = day.date; + } for expense in day.expenses.iter() { calculated.total += expense.price; @@ -135,15 +141,18 @@ pub fn calculate(account: &Account) -> Calculated { } } - calculated.all_day_average = calculated.total / days_calculated as f64; + let days_elapsed = + (calculated.last_day - account.start_date).num_days() + 1; + + calculated.all_day_average = calculated.total / days_elapsed as f64; calculated.essential_day_average = - calculated.essential_subtotal / days_calculated as f64; + calculated.essential_subtotal / days_elapsed as f64; for (category, subtotal) in calculated.categories_subtotal.iter() { calculated.categories_day_average .insert( category.clone(), - subtotal / days_calculated as f64, + subtotal / days_elapsed as f64, ); } @@ -153,11 +162,5 @@ pub fn calculate(account: &Account) -> Calculated { calculated.days_left_essential = calculated.balance / calculated.essential_day_average; - calculated -} - -pub fn get_calculated(path: &str) -> Result<Calculated, ParseError> { - let account = parse_account(path)?; - - Ok(calculate(&account)) + Some(calculated) } diff --git a/budget/tests/budget.rs b/budget/tests/budget.rs index 1cc02e7..feae240 100644 --- a/budget/tests/budget.rs +++ b/budget/tests/budget.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use chrono::prelude::*; +use chrono::NaiveDate; use budget::*; @@ -62,6 +62,10 @@ fn can_parse_account() -> Result<(), ParseError>{ ], }, Day { + date: NaiveDate::from_ymd(2020, 10, 4), + expenses: Vec::<Expense>::new(), + }, + Day { date: NaiveDate::from_ymd(2020, 10, 2), expenses: vec![ Expense { @@ -82,10 +86,6 @@ fn can_parse_account() -> Result<(), ParseError>{ }, ], }, - Day { - date: NaiveDate::from_ymd(2020, 10, 3), - expenses: Vec::<Expense>::new(), - }, ], }; @@ -99,32 +99,33 @@ fn can_parse_account() -> Result<(), ParseError>{ #[test] fn can_calculate() -> Result<(), ParseError> { let mut should_be = Calculated { - all_day_average: 7.57, - essential_day_average: 6.3, + all_day_average: 5.6775, + essential_day_average: 4.725, categories_day_average: HashMap::<String, f64>::new(), essential_subtotal: 18.9, categories_subtotal: HashMap::<String, f64>::new(), total: 22.71, balance: 397.29, - days_left: 52.48216644649934, - days_left_essential: 63.06190476190476, + days_left: 69.9762219286658, + days_left_essential: 84.08253968253969, + last_day: NaiveDate::from_ymd(2020, 10, 04), }; should_be.categories_day_average.insert( "supplies".to_string(), - 1.27, + 0.9525, ); should_be.categories_day_average.insert( "products".to_string(), - 2.3333333333333335, + 1.75, ); should_be.categories_day_average.insert( "transport".to_string(), - 2.3000000000000003, + 1.725, ); should_be.categories_day_average.insert( "utilities".to_string(), - 1.6666666666666667, + 1.25, ); should_be.categories_subtotal.insert( @@ -145,7 +146,7 @@ fn can_calculate() -> Result<(), ParseError> { ); let account = budget::parse_account("tests/test.toml")?; - let actually_is = budget::calculate(&account); + let actually_is = budget::calculate(&account).unwrap(); assert_eq!(actually_is, should_be); diff --git a/budget/tests/test.toml b/budget/tests/test.toml index 1bb1ce7..a29467e 100644 --- a/budget/tests/test.toml +++ b/budget/tests/test.toml @@ -39,6 +39,9 @@ date = 2020-10-01 shared = 2 [[days]] +date = 2020-10-04 + +[[days]] date = 2020-10-02 [[days.expenses]] @@ -52,6 +55,3 @@ date = 2020-10-02 price = 6.9 category = "transport" -[[days]] -date = 2020-10-03 - diff --git a/src/main.rs b/src/main.rs index 04d5277..5c64959 100644 --- a/src/main.rs +++ b/src/main.rs @@ -33,7 +33,7 @@ fn main() { ::std::process::exit(1); } }; - let calculated = budget::calculate(&account); + let maybe_calculated = budget::calculate(&account); if no_color && !force_color { colored::control::set_override(false); @@ -41,7 +41,7 @@ fn main() { colored::control::set_override(true); } - output(account, calculated); + output(account, maybe_calculated); } fn get_cli_matches() -> ArgMatches<'static> { @@ -68,7 +68,7 @@ fn get_cli_matches() -> ArgMatches<'static> { .get_matches() } -fn output(account: Account, calculated: Calculated) { +fn output(account: Account, maybe_calculated: Option<Calculated>) { println!( "{}", format!( @@ -78,22 +78,23 @@ fn output(account: Account, calculated: Calculated) { ).cyan(), ); - let last_day = match account.days.last() { - Some(day) => day, + let calculated = match maybe_calculated { + Some(data) => data, None => { - println!("{}", "Your expenses are empty...".italic()); + println!(); + println!("{}", "You have no expenses...".italic()); ::std::process::exit(0); } }; - let days_until_end = account.end_date - last_day.date; + let days_until_end = account.end_date - calculated.last_day; println!( "{}", format!( "Last day on entry: {}", - last_day.date.format("%Y-%m-%d"), + calculated.last_day.format("%Y-%m-%d"), ).cyan(), ); |