use anyhow::Result; use schist_models::{Bucket, Drip}; use super::{find_by_id_or, sum_drips_for_bucket}; pub fn calculate_bucket_balance( bucket: &Bucket, transaction_sums: &[(i32, i64)], bucket_transfer_from_sums: &[(i32, i64)], bucket_transfer_to_sums: &[(i32, i64)], budget_drips: &[Drip], ) -> Result { let transaction_sum = find_by_id_or(transaction_sums, bucket.id, 0); let bucket_transfer_from_sum = find_by_id_or(bucket_transfer_from_sums, bucket.id, 0); let bucket_transfer_to_sum = find_by_id_or(bucket_transfer_to_sums, bucket.id, 0); let budget_accruals_sum = sum_drips_for_bucket(bucket, budget_drips)?; Ok(transaction_sum + budget_accruals_sum + bucket_transfer_to_sum - bucket_transfer_from_sum) } #[cfg(test)] mod test { use schist_fakes::{bucket::make_fake_bucket, drip::make_fake_drip_builder}; use super::calculate_bucket_balance; #[test] fn when_no_data_then_returns_zero() { let bucket = make_fake_bucket(0); let result = calculate_bucket_balance(&bucket, &[], &[], &[], &[]); assert!(result.is_ok()); assert_eq!(result.unwrap(), 0_i64); } #[test] fn when_data_only_for_another_bucket_then_returns_zero() { let bucket = make_fake_bucket(0); let transaction_sums = [(1, 100)]; let bucket_transfer_from_sums = [(1, 91)]; let bucket_transfer_to_sums = [(2, 79)]; let budget_drips = [make_fake_drip_builder(0) .amount(100) .bucket_id(1) .build() .unwrap()]; let result = calculate_bucket_balance( &bucket, &transaction_sums, &bucket_transfer_from_sums, &bucket_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 bucket = make_fake_bucket(0); let transaction_sums = [(0, 0)]; let bucket_transfer_from_sums = []; let bucket_transfer_to_sums = []; let budget_drips = []; let result = calculate_bucket_balance( &bucket, &transaction_sums, &bucket_transfer_from_sums, &bucket_transfer_to_sums, &budget_drips, ); assert!(result.is_ok()); assert_eq!(result.unwrap(), 0_i64); } #[test] fn when_bucket_transfers_are_zero_then_returns_zero() { let bucket = make_fake_bucket(0); let transaction_sums = []; let bucket_transfer_from_sums = [(0, 0)]; let bucket_transfer_to_sums = [(0, 0)]; let budget_drips = []; let result = calculate_bucket_balance( &bucket, &transaction_sums, &bucket_transfer_from_sums, &bucket_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 bucket = make_fake_bucket(0); let transaction_sums = [(0, 100)]; let bucket_transfer_from_sums = [(0, 91)]; let bucket_transfer_to_sums = [(0, 79)]; let budget_drips = [ make_fake_drip_builder(0) .amount(77) .bucket_id(0) .build() .unwrap(), make_fake_drip_builder(0) .amount(77) .bucket_id(0) .build() .unwrap(), make_fake_drip_builder(0) .amount(77) .bucket_id(0) .build() .unwrap(), make_fake_drip_builder(0) .amount(77) .bucket_id(0) .build() .unwrap(), make_fake_drip_builder(0) .amount(77) .bucket_id(0) .build() .unwrap(), ]; let result = calculate_bucket_balance( &bucket, &transaction_sums, &bucket_transfer_from_sums, &bucket_transfer_to_sums, &budget_drips, ); let expected_result = 100 + (-91) + 79 + 77 * 5; assert!(result.is_ok()); assert_eq!(result.unwrap(), expected_result); } }