summaryrefslogtreecommitdiff
path: root/backend/core/src/utils
diff options
context:
space:
mode:
Diffstat (limited to 'backend/core/src/utils')
-rw-r--r--backend/core/src/utils/calculate_budgets_accrual.rs67
-rw-r--r--backend/core/src/utils/calculate_category_balance.rs35
2 files changed, 53 insertions, 49 deletions
diff --git a/backend/core/src/utils/calculate_budgets_accrual.rs b/backend/core/src/utils/calculate_budgets_accrual.rs
index 22061ee..56171ca 100644
--- a/backend/core/src/utils/calculate_budgets_accrual.rs
+++ b/backend/core/src/utils/calculate_budgets_accrual.rs
@@ -1,10 +1,9 @@
-use crate::models::{
- budget_update::BudgetUpdate,
- category::Category,
- date_time_utc::DateTimeUtc
-};
+use anyhow::Result;
+use crate::{models::{
+ budget_update::BudgetUpdate, category::Category, date_utc::DateUtc
+}, traits::nowlike::Nowlike};
-pub fn calculate_budgets_accrual(category: &Category, budget_updates: &[BudgetUpdate]) -> i64 {
+pub fn calculate_budgets_accrual(category: &Category, budget_updates: &[BudgetUpdate]) -> Result<i64> {
let mut budget_updates = budget_updates
.iter()
.filter(|bu| bu.category_id == category.id)
@@ -13,28 +12,30 @@ pub fn calculate_budgets_accrual(category: &Category, budget_updates: &[BudgetUp
budget_updates.reverse();
let mut budgets_accrual = 0.0_f64;
- let mut calculated_back_to_date = DateTimeUtc::now();
+ let mut calculated_back_to_date = DateUtc::now();
for budget_update in budget_updates {
let days_on_this_budget = calculated_back_to_date.day_diff(&budget_update.date);
if days_on_this_budget == 0_u32 {
- continue;
+ return Err(anyhow::Error::msg(format!(
+ "failed to calculate budgets accrual since two budget updates had the same date ({})",
+ budget_update.date,
+ )));
}
let budget_per_day = budget_update.new_budget as f64 / budget_update.new_period as f64;
budgets_accrual += days_on_this_budget as f64 * budget_per_day;
calculated_back_to_date = budget_update.date.clone();
}
- budgets_accrual.floor() as i64
+ Ok(budgets_accrual.floor() as i64)
}
#[cfg(test)]
mod test {
- use chrono::{Days, Timelike, Utc};
+ use chrono::{Days, Utc};
use crate::{
- models::{budget_update::BudgetUpdate, category::Category, date_time_utc::DateTimeUtc},
- utils::calculate_budgets_accrual,
+ models::{budget_update::BudgetUpdate, category::Category, date_utc::DateUtc}, traits::nowlike::Nowlike, utils::calculate_budgets_accrual
};
#[test]
@@ -47,7 +48,8 @@ mod test {
let result = calculate_budgets_accrual(&category, &budget_updates);
- assert_eq!(result, 0_i64);
+ assert!(result.is_ok());
+ assert_eq!(result.unwrap(), 0_i64);
}
#[test]
@@ -59,14 +61,15 @@ mod test {
let budget_updates = [BudgetUpdate {
id: 0,
category_id: 1,
- date: DateTimeUtc::now(),
+ date: DateUtc::now(),
new_budget: 100,
new_period: 1,
}];
let result = calculate_budgets_accrual(&category, &budget_updates);
- assert_eq!(result, 0_i64);
+ assert!(result.is_ok());
+ assert_eq!(result.unwrap(), 0_i64);
}
#[test]
@@ -78,14 +81,15 @@ mod test {
let budget_updates = [BudgetUpdate {
id: 0,
category_id: 0,
- date: DateTimeUtc::new(&Utc::now().checked_sub_days(Days::new(120)).unwrap()),
+ date: DateUtc::from(Utc::now().checked_sub_days(Days::new(120)).unwrap()),
new_budget: 100,
new_period: 1,
}];
let result = calculate_budgets_accrual(&category, &budget_updates);
- assert_eq!(result, 12_000);
+ assert!(result.is_ok());
+ assert_eq!(result.unwrap(), 12_000);
}
#[test]
@@ -98,14 +102,14 @@ mod test {
BudgetUpdate {
id: 0,
category_id: 0,
- date: DateTimeUtc::new(&Utc::now().checked_sub_days(Days::new(60)).unwrap()),
+ date: DateUtc::from(&Utc::now().checked_sub_days(Days::new(60)).unwrap()),
new_budget: 200,
new_period: 1,
},
BudgetUpdate {
id: 0,
category_id: 0,
- date: DateTimeUtc::new(&Utc::now().checked_sub_days(Days::new(120)).unwrap()),
+ date: DateUtc::from(&Utc::now().checked_sub_days(Days::new(120)).unwrap()),
new_budget: 100,
new_period: 1,
},
@@ -113,11 +117,12 @@ mod test {
let result = calculate_budgets_accrual(&category, &budget_updates);
- assert_eq!(result, 18_000);
+ assert!(result.is_ok());
+ assert_eq!(result.unwrap(), 18_000);
}
#[test]
- fn when_two_budget_updates_on_same_day_then_uses_latest_only() {
+ fn when_two_budget_updates_on_same_day_then_returns_err() {
let category = Category {
id: 0,
name: String::from("Groceries"),
@@ -126,26 +131,14 @@ mod test {
BudgetUpdate {
id: 0,
category_id: 0,
- date: DateTimeUtc::new(
- &Utc::now()
- .checked_sub_days(Days::new(120))
- .unwrap()
- .with_hour(13)
- .unwrap(),
- ),
+ date: DateUtc::from_ymd(2020, 12, 25).unwrap(),
new_budget: 200,
new_period: 1,
},
BudgetUpdate {
id: 0,
category_id: 0,
- date: DateTimeUtc::new(
- &Utc::now()
- .checked_sub_days(Days::new(120))
- .unwrap()
- .with_hour(12)
- .unwrap(),
- ),
+ date: DateUtc::from_ymd(2020, 12, 25).unwrap(),
new_budget: 100,
new_period: 1,
},
@@ -156,7 +149,7 @@ mod test {
let result_leftways = calculate_budgets_accrual(&category, &budget_updates);
let result_rightways = calculate_budgets_accrual(&category, &budget_updates_reversed);
- assert_eq!(result_leftways, 24_000);
- assert_eq!(result_rightways, 24_000);
+ assert!(result_leftways.is_err());
+ assert!(result_rightways.is_err());
}
}
diff --git a/backend/core/src/utils/calculate_category_balance.rs b/backend/core/src/utils/calculate_category_balance.rs
index e461cee..296b9de 100644
--- a/backend/core/src/utils/calculate_category_balance.rs
+++ b/backend/core/src/utils/calculate_category_balance.rs
@@ -1,3 +1,4 @@
+use anyhow::Result;
use crate::{
models::{budget_update::BudgetUpdate, category::Category},
utils::{calculate_budgets_accrual, find_by_id_or},
@@ -9,13 +10,18 @@ pub fn calculate_category_balance(
category_transfer_from_sums: &[(i32, Option<i64>)],
category_transfer_to_sums: &[(i32, Option<i64>)],
budget_updates: &[BudgetUpdate],
-) -> i64 {
+) -> Result<i64> {
let transaction_sum = find_by_id_or(transaction_sums, category.id, 0);
let category_transfer_from_sum = find_by_id_or(category_transfer_from_sums, category.id, 0);
let category_transfer_to_sum = find_by_id_or(category_transfer_to_sums, category.id, 0);
- let budget_accruals_sum = calculate_budgets_accrual(category, budget_updates);
-
- transaction_sum + budget_accruals_sum + category_transfer_to_sum - category_transfer_from_sum
+ let budget_accruals_sum = calculate_budgets_accrual(category, budget_updates)?;
+
+ Ok(
+ transaction_sum
+ + budget_accruals_sum
+ + category_transfer_to_sum
+ - category_transfer_from_sum
+ )
}
#[cfg(test)]
@@ -23,7 +29,7 @@ mod test {
use chrono::{Days, Utc};
use crate::{
- models::{budget_update::BudgetUpdate, category::Category, date_time_utc::DateTimeUtc},
+ models::{budget_update::BudgetUpdate, category::Category, date_utc::DateUtc},
utils::calculate_category_balance
};
@@ -36,7 +42,8 @@ mod test {
let result = calculate_category_balance(&category, &[], &[], &[], &[]);
- assert_eq!(result, 0_i64);
+ assert!(result.is_ok());
+ assert_eq!(result.unwrap(), 0_i64);
}
#[test]
@@ -51,7 +58,7 @@ mod test {
let budget_updates = [BudgetUpdate {
id: 0,
category_id: 1,
- date: DateTimeUtc::new(&Utc::now().checked_sub_days(Days::new(120)).unwrap()),
+ date: DateUtc::from(Utc::now().checked_sub_days(Days::new(120)).unwrap()),
new_budget: 77,
new_period: 1,
}];
@@ -64,7 +71,8 @@ mod test {
&budget_updates,
);
- assert_eq!(result, 0_i64);
+ assert!(result.is_ok());
+ assert_eq!(result.unwrap(), 0_i64);
}
#[test]
@@ -86,7 +94,8 @@ mod test {
&budget_updates,
);
- assert_eq!(result, 0_i64);
+ assert!(result.is_ok());
+ assert_eq!(result.unwrap(), 0_i64);
}
#[test]
@@ -108,7 +117,8 @@ mod test {
&budget_updates,
);
- assert_eq!(result, 0_i64);
+ assert!(result.is_ok());
+ assert_eq!(result.unwrap(), 0_i64);
}
#[test]
@@ -123,7 +133,7 @@ mod test {
let budget_updates = [BudgetUpdate {
id: 0,
category_id: 0,
- date: DateTimeUtc::new(&Utc::now().checked_sub_days(Days::new(120)).unwrap()),
+ date: DateUtc::from(&Utc::now().checked_sub_days(Days::new(120)).unwrap()),
new_budget: 77,
new_period: 1,
}];
@@ -137,6 +147,7 @@ mod test {
);
let expected_result = 100 + (-91) + 79 + 77 * 120;
- assert_eq!(result, expected_result);
+ assert!(result.is_ok());
+ assert_eq!(result.unwrap(), expected_result);
}
}