aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYaroslav <contact@yaroslavps.com>2020-10-06 14:13:14 +0300
committerYaroslav <contact@yaroslavps.com>2020-10-06 14:13:14 +0300
commit742b9fa46d74762f58ae939afd980a532cc4636f (patch)
tree0cd372442e5518dece1a9ec371ae71dccc5faae4
parentcc688c4dc73d3b13be5aba1bd292cc31265c5d04 (diff)
downloadfinbudg-742b9fa46d74762f58ae939afd980a532cc4636f.tar.gz
finbudg-742b9fa46d74762f58ae939afd980a532cc4636f.zip
Account for days elapsed based on latest datev0.1.2
Instead of counting the number of days for the averge through the number of iterations, let it be the difference between the latest date on entry and the start of the period. Id est: * 'Missing' dates from the input are implicit. * The order of the days doesn't affect the output (although it doesn't make sense to put the days out of order).
-rw-r--r--Cargo.lock2
-rw-r--r--Cargo.toml2
-rw-r--r--budget/src/lib.rs31
-rw-r--r--budget/tests/budget.rs29
-rw-r--r--budget/tests/test.toml6
-rw-r--r--src/main.rs17
6 files changed, 46 insertions, 41 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 70f1fc3..1471663 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -82,7 +82,7 @@ dependencies = [
[[package]]
name = "finbudg"
-version = "0.1.0"
+version = "0.1.2"
dependencies = [
"budget",
"chrono",
diff --git a/Cargo.toml b/Cargo.toml
index 418a9ad..caecf3a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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(),
);