use anyhow::Result; use schist_models::{budget_drip::BudgetDrip, category::Category}; 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_drips: &[BudgetDrip], ) -> Result { 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_drips)?; Ok( transaction_sum + budget_accruals_sum + category_transfer_to_sum - category_transfer_from_sum ) } #[cfg(test)] mod test { 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 = make_fake_category(0); let result = calculate_category_balance(&category, &[], &[], &[], &[]); assert!(result.is_ok()); assert_eq!(result.unwrap(), 0_i64); } #[test] fn when_data_only_for_another_category_then_returns_zero() { 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_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_drips, ); assert!(result.is_ok()); assert_eq!(result.unwrap(), 0_i64); } #[test] fn when_transaction_sum_is_zero_then_returns_zero() { let category = make_fake_category(0); let transaction_sums = [(0, 0)]; let category_transfer_from_sums = []; let category_transfer_to_sums = []; let budget_drips = []; let result = calculate_category_balance( &category, &transaction_sums, &category_transfer_from_sums, &category_transfer_to_sums, &budget_drips, ); assert!(result.is_ok()); assert_eq!(result.unwrap(), 0_i64); } #[test] fn when_category_transfers_are_zero_then_returns_zero() { 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_drips = []; let result = calculate_category_balance( &category, &transaction_sums, &category_transfer_from_sums, &category_transfer_to_sums, &budget_drips, ); assert!(result.is_ok()); assert_eq!(result.unwrap(), 0_i64); } #[test] fn when_some_data_then_calculates_as_expected() { 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_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_drips, ); let expected_result = 100 + (-91) + 79 + 77 * 5; assert!(result.is_ok()); assert_eq!(result.unwrap(), expected_result); } }