diff options
| author | Joe Carstairs <me@joeac.net> | 2024-11-24 15:45:04 +0000 |
|---|---|---|
| committer | Joe Carstairs <me@joeac.net> | 2024-11-24 15:56:01 +0000 |
| commit | 1f5dcf9762a83d5972c0c8dbad22732505bf621c (patch) | |
| tree | 5a1f5edd993733d48016ce2a8a8691b8f446858a /rust/schist_queries/src/utils | |
| parent | 022795ffcaaa0d904c9f911d8a059885c2254278 (diff) | |
Swaps budget updates for budget drips
Diffstat (limited to 'rust/schist_queries/src/utils')
| -rw-r--r-- | rust/schist_queries/src/utils/calculate_budgets_accrual.rs | 150 | ||||
| -rw-r--r-- | rust/schist_queries/src/utils/calculate_category_balance.rs | 74 | ||||
| -rw-r--r-- | rust/schist_queries/src/utils/mod.rs | 3 |
3 files changed, 63 insertions, 164 deletions
diff --git a/rust/schist_queries/src/utils/calculate_budgets_accrual.rs b/rust/schist_queries/src/utils/calculate_budgets_accrual.rs index 1d4ed02..ca82953 100644 --- a/rust/schist_queries/src/utils/calculate_budgets_accrual.rs +++ b/rust/schist_queries/src/utils/calculate_budgets_accrual.rs @@ -1,156 +1,72 @@ use anyhow::Result; use schist_models::{ - budget_update::BudgetUpdate, category::Category, date_utc::DateUtc, + budget_drip::BudgetDrip, + category::Category, }; -use schist_traits::nowlike::Nowlike; -pub fn calculate_budgets_accrual(category: &Category, budget_updates: &[BudgetUpdate]) -> Result<i64> { - let mut budget_updates = budget_updates +pub fn calculate_budgets_accrual(category: &Category, budget_drips: &[BudgetDrip]) -> Result<i64> { + Ok(budget_drips .iter() - .filter(|bu| bu.category_id == category.id) - .collect::<Vec<&BudgetUpdate>>(); - budget_updates.sort_by_key(|bu| bu.date.clone()); - budget_updates.reverse(); - - let mut budgets_accrual = 0.0_f64; - 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 { - 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(); - } - - Ok(budgets_accrual.floor() as i64) + .filter(|bd| bd.category_id == category.id) + .map(|bd| Into::<i64>::into(bd.quantity)) + .sum() + ) } #[cfg(test)] mod test { - use chrono::{Days, Utc}; - use schist_models::{budget_update::BudgetUpdate, category::Category, date_utc::DateUtc}; - use schist_traits::nowlike::Nowlike; + use schist_fakes::{budget_drip::make_fake_budget_drip_builder, category::make_fake_category}; use super::calculate_budgets_accrual; #[test] - fn when_no_budget_updates_then_return_zero() { - let category = Category { - id: 0, - name: String::from("Groceries"), - }; - let budget_updates = []; + fn when_no_budget_drips_then_return_zero() { + let category = make_fake_category(0); + let budget_drips = []; - let result = calculate_budgets_accrual(&category, &budget_updates); + let result = calculate_budgets_accrual(&category, &budget_drips); assert!(result.is_ok()); assert_eq!(result.unwrap(), 0_i64); } #[test] - fn when_one_budget_update_for_another_category_then_return_zero() { - let category = Category { - id: 0, - name: String::from("Groceries"), - }; - let budget_updates = [BudgetUpdate { - id: 0, - category_id: 1, - date: DateUtc::now(), - new_budget: 100, - new_period: 1, - }]; + fn when_one_budget_drip_for_another_category_then_return_zero() { + let category = make_fake_category(0); + let budget_drips = [ + make_fake_budget_drip_builder(0).quantity(100).category_id(1).build().unwrap(), + ]; - let result = calculate_budgets_accrual(&category, &budget_updates); + let result = calculate_budgets_accrual(&category, &budget_drips); assert!(result.is_ok()); assert_eq!(result.unwrap(), 0_i64); } #[test] - fn when_one_budget_update_then_return_quantity_times_days_in_past() { - let category = Category { - id: 0, - name: String::from("Groceries"), - }; - let budget_updates = [BudgetUpdate { - id: 0, - category_id: 0, - 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!(result.is_ok()); - assert_eq!(result.unwrap(), 12_000); - } - - #[test] - fn when_two_budget_updates_then_calculates_as_expected() { - let category = Category { - id: 0, - name: String::from("Groceries"), - }; - let budget_updates = [ - BudgetUpdate { - id: 0, - category_id: 0, - 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: DateUtc::from(&Utc::now().checked_sub_days(Days::new(120)).unwrap()), - new_budget: 100, - new_period: 1, - }, + fn when_one_budget_drip_then_return_quantity() { + let category = make_fake_category(0); + let budget_drips = [ + make_fake_budget_drip_builder(0).quantity(100).category_id(0).build().unwrap(), ]; - let result = calculate_budgets_accrual(&category, &budget_updates); + let result = calculate_budgets_accrual(&category, &budget_drips); assert!(result.is_ok()); - assert_eq!(result.unwrap(), 18_000); + assert_eq!(result.unwrap(), 100); } #[test] - fn when_two_budget_updates_on_same_day_then_returns_err() { - let category = Category { - id: 0, - name: String::from("Groceries"), - }; - let budget_updates = [ - BudgetUpdate { - id: 0, - category_id: 0, - date: DateUtc::from_ymd(2020, 12, 25).unwrap(), - new_budget: 200, - new_period: 1, - }, - BudgetUpdate { - id: 0, - category_id: 0, - date: DateUtc::from_ymd(2020, 12, 25).unwrap(), - new_budget: 100, - new_period: 1, - }, + fn when_two_budget_drips_then_return_sum() { + let category = make_fake_category(0); + let budget_drips = [ + make_fake_budget_drip_builder(0).quantity(100).category_id(0).build().unwrap(), + make_fake_budget_drip_builder(1).quantity(120).category_id(0).build().unwrap(), ]; - let mut budget_updates_reversed = budget_updates.clone(); - budget_updates_reversed.reverse(); - let result_leftways = calculate_budgets_accrual(&category, &budget_updates); - let result_rightways = calculate_budgets_accrual(&category, &budget_updates_reversed); + let result = calculate_budgets_accrual(&category, &budget_drips); - assert!(result_leftways.is_err()); - assert!(result_rightways.is_err()); + assert!(result.is_ok()); + assert_eq!(result.unwrap(), 220); } } diff --git a/rust/schist_queries/src/utils/calculate_category_balance.rs b/rust/schist_queries/src/utils/calculate_category_balance.rs index acb56fb..73e80cd 100644 --- a/rust/schist_queries/src/utils/calculate_category_balance.rs +++ b/rust/schist_queries/src/utils/calculate_category_balance.rs @@ -1,19 +1,19 @@ use anyhow::Result; -use schist_models::{budget_update::BudgetUpdate, category::Category}; +use schist_models::{budget_drip::BudgetDrip, category::Category}; -use super::{calculate_budgets_accrual::calculate_budgets_accrual, find_by_id_or::find_by_id_or}; +use super::{calculate_budgets_accrual, find_by_id_or}; pub fn calculate_category_balance( category: &Category, transaction_sums: &[(i32, i64)], category_transfer_from_sums: &[(i32, i64)], category_transfer_to_sums: &[(i32, i64)], - budget_updates: &[BudgetUpdate], + budget_drips: &[BudgetDrip], ) -> 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)?; + let budget_accruals_sum = calculate_budgets_accrual(category, budget_drips)?; Ok( transaction_sum @@ -25,17 +25,13 @@ pub fn calculate_category_balance( #[cfg(test)] mod test { - use chrono::{Days, Utc}; - use schist_models::{budget_update::BudgetUpdate, category::Category, date_utc::DateUtc}; + use schist_fakes::{budget_drip::make_fake_budget_drip_builder, category::make_fake_category}; use super::calculate_category_balance; #[test] fn when_no_data_then_returns_zero() { - let category = Category { - id: 0, - name: String::new(), - }; + let category = make_fake_category(0); let result = calculate_category_balance(&category, &[], &[], &[], &[]); @@ -45,27 +41,20 @@ mod test { #[test] fn when_data_only_for_another_category_then_returns_zero() { - let category = Category { - id: 0, - name: String::new(), - }; + let category = make_fake_category(0); let transaction_sums = [(1, 100)]; let category_transfer_from_sums = [(1, 91)]; let category_transfer_to_sums = [(2, 79)]; - let budget_updates = [BudgetUpdate { - id: 0, - category_id: 1, - date: DateUtc::from(Utc::now().checked_sub_days(Days::new(120)).unwrap()), - new_budget: 77, - new_period: 1, - }]; + let budget_drips = [ + make_fake_budget_drip_builder(0).quantity(100).category_id(1).build().unwrap(), + ]; let result = calculate_category_balance( &category, &transaction_sums, &category_transfer_from_sums, &category_transfer_to_sums, - &budget_updates, + &budget_drips, ); assert!(result.is_ok()); @@ -74,21 +63,18 @@ mod test { #[test] fn when_transaction_sum_is_zero_then_returns_zero() { - let category = Category { - id: 0, - name: String::new(), - }; + let category = make_fake_category(0); let transaction_sums = [(0, 0)]; let category_transfer_from_sums = []; let category_transfer_to_sums = []; - let budget_updates = []; + let budget_drips = []; let result = calculate_category_balance( &category, &transaction_sums, &category_transfer_from_sums, &category_transfer_to_sums, - &budget_updates, + &budget_drips, ); assert!(result.is_ok()); @@ -97,21 +83,18 @@ mod test { #[test] fn when_category_transfers_are_zero_then_returns_zero() { - let category = Category { - id: 0, - name: String::new(), - }; + let category = make_fake_category(0); let transaction_sums = []; let category_transfer_from_sums = [(0, 0)]; let category_transfer_to_sums = [(0, 0)]; - let budget_updates = []; + let budget_drips = []; let result = calculate_category_balance( &category, &transaction_sums, &category_transfer_from_sums, &category_transfer_to_sums, - &budget_updates, + &budget_drips, ); assert!(result.is_ok()); @@ -120,30 +103,27 @@ mod test { #[test] fn when_some_data_then_calculates_as_expected() { - let category = Category { - id: 0, - name: String::new(), - }; + let category = make_fake_category(0); let transaction_sums = [(0, 100)]; let category_transfer_from_sums = [(0, 91)]; let category_transfer_to_sums = [(0, 79)]; - let budget_updates = [BudgetUpdate { - id: 0, - category_id: 0, - date: DateUtc::from(&Utc::now().checked_sub_days(Days::new(120)).unwrap()), - new_budget: 77, - new_period: 1, - }]; + let budget_drips = [ + make_fake_budget_drip_builder(0).quantity(77).category_id(0).build().unwrap(), + make_fake_budget_drip_builder(0).quantity(77).category_id(0).build().unwrap(), + make_fake_budget_drip_builder(0).quantity(77).category_id(0).build().unwrap(), + make_fake_budget_drip_builder(0).quantity(77).category_id(0).build().unwrap(), + make_fake_budget_drip_builder(0).quantity(77).category_id(0).build().unwrap(), + ]; let result = calculate_category_balance( &category, &transaction_sums, &category_transfer_from_sums, &category_transfer_to_sums, - &budget_updates, + &budget_drips, ); - let expected_result = 100 + (-91) + 79 + 77 * 120; + let expected_result = 100 + (-91) + 79 + 77 * 5; assert!(result.is_ok()); assert_eq!(result.unwrap(), expected_result); } diff --git a/rust/schist_queries/src/utils/mod.rs b/rust/schist_queries/src/utils/mod.rs index 6949ce5..f2653d8 100644 --- a/rust/schist_queries/src/utils/mod.rs +++ b/rust/schist_queries/src/utils/mod.rs @@ -2,4 +2,7 @@ mod calculate_budgets_accrual; mod calculate_category_balance; mod find_by_id_or; +use calculate_budgets_accrual::calculate_budgets_accrual; + pub use calculate_category_balance::calculate_category_balance; +pub use find_by_id_or::find_by_id_or; |
