summaryrefslogtreecommitdiff
path: root/schist_core/schist_queries/src
diff options
context:
space:
mode:
authorJoe Carstairs <me@joeac.net>2025-08-15 16:02:40 +0000
committerjoeac <me@joeac.net>2025-08-15 16:02:40 +0000
commit703496a49315f7b67442abf0e0df3c41d3605d3b (patch)
tree8e92f3842710162f3b26e910eb931950c1049f07 /schist_core/schist_queries/src
parent8d714f760bd0349560d464583a151a04a19de1c9 (diff)
task-012 (#2)
Co-authored-by: Joe Carstairs <jcarstairs@scottlogic.com> Reviewed-on: https://git.joeac.net/joeac/schist/pulls/2 Co-authored-by: Joe Carstairs <me@joeac.net> Co-committed-by: Joe Carstairs <me@joeac.net>
Diffstat (limited to 'schist_core/schist_queries/src')
-rw-r--r--schist_core/schist_queries/src/accounts.rs8
-rw-r--r--schist_core/schist_queries/src/bucket_transfers.rs22
-rw-r--r--schist_core/schist_queries/src/buckets.rs5
-rw-r--r--schist_core/schist_queries/src/budget_drips.rs40
-rw-r--r--schist_core/schist_queries/src/clear.rs8
-rw-r--r--schist_core/schist_queries/src/drips.rs38
-rw-r--r--schist_core/schist_queries/src/lib.rs8
-rw-r--r--schist_core/schist_queries/src/pipes.rs55
-rw-r--r--schist_core/schist_queries/src/transaction_categorisations.rs59
-rw-r--r--schist_core/schist_queries/src/transactions.rs2
-rw-r--r--schist_core/schist_queries/src/utils/calculate_bucket_balance.rs57
-rw-r--r--schist_core/schist_queries/src/utils/calculate_budgets_accrual.rs72
-rw-r--r--schist_core/schist_queries/src/utils/mod.rs4
-rw-r--r--schist_core/schist_queries/src/utils/sum_drips_for_bucket.rs80
14 files changed, 241 insertions, 217 deletions
diff --git a/schist_core/schist_queries/src/accounts.rs b/schist_core/schist_queries/src/accounts.rs
index ead281a..289faf6 100644
--- a/schist_core/schist_queries/src/accounts.rs
+++ b/schist_core/schist_queries/src/accounts.rs
@@ -11,16 +11,14 @@ pub fn delete_all_accounts(connection: &mut SqliteConnection) -> Result<usize> {
}
pub fn get_all_accounts(connection: &mut SqliteConnection) -> Result<Vec<Account>> {
- let all_accounts = accounts_table.select(Account::as_select())
+ let all_accounts = accounts_table
+ .select(Account::as_select())
.load(connection)
.with_context(|| "failed to get all accounts")?;
Ok(all_accounts)
}
-pub fn insert_accounts(
- accounts: &[Account],
- connection: &mut SqliteConnection,
-) -> Result<usize> {
+pub fn insert_accounts(accounts: &[Account], connection: &mut SqliteConnection) -> Result<usize> {
let num_accounts_inserted = diesel::insert_into(accounts_table)
.values(accounts)
.execute(connection)
diff --git a/schist_core/schist_queries/src/bucket_transfers.rs b/schist_core/schist_queries/src/bucket_transfers.rs
index 2145944..923867f 100644
--- a/schist_core/schist_queries/src/bucket_transfers.rs
+++ b/schist_core/schist_queries/src/bucket_transfers.rs
@@ -1,10 +1,9 @@
use anyhow::{Context, Result};
use diesel::{dsl::sum, QueryDsl, RunQueryDsl, SelectableHelper, SqliteConnection};
+use schist_models::bucket_transfer::BucketTransfer;
use schist_schema::schema::bucket_transfers::{
- self as bucket_transfers_schema,
- dsl::bucket_transfers as bucket_transfers_table,
+ self as bucket_transfers_schema, dsl::bucket_transfers as bucket_transfers_table,
};
-use schist_models::bucket_transfer::BucketTransfer;
pub fn delete_all_bucket_transfers(connection: &mut SqliteConnection) -> Result<usize> {
let num_rows_deleted = diesel::delete(bucket_transfers_table)
@@ -50,10 +49,15 @@ pub fn sum_bucket_transfer_quantity_per_from_bucket_id(
.group_by(bucket_transfers_schema::from_bucket_id)
.select((
bucket_transfers_schema::from_bucket_id,
- sum(bucket_transfers_schema::quantity),
+ sum(bucket_transfers_schema::amount),
))
.load::<(i32, Option<i64>)>(connection)
- .map(|result| result.iter().map(|sum| (sum.0, sum.1.unwrap_or(0))).collect())
+ .map(|result| {
+ result
+ .iter()
+ .map(|sum| (sum.0, sum.1.unwrap_or(0)))
+ .collect()
+ })
.with_context(|| "failed to sum bucket transfer quantity per from bucket ID")?;
Ok(sum)
}
@@ -65,10 +69,14 @@ pub fn sum_bucket_transfer_quantity_per_to_bucket_id(
.group_by(bucket_transfers_schema::to_bucket_id)
.select((
bucket_transfers_schema::to_bucket_id,
- sum(bucket_transfers_schema::quantity),
+ sum(bucket_transfers_schema::amount),
))
.load::<(i32, Option<i64>)>(connection)
- .map(|vec| vec.iter().map(|(id, sum)| (*id, sum.unwrap_or(0))).collect())
+ .map(|vec| {
+ vec.iter()
+ .map(|(id, sum)| (*id, sum.unwrap_or(0)))
+ .collect()
+ })
.with_context(|| "failed to sum bucket transfer quantity per to bucket ID")?;
Ok(sum)
}
diff --git a/schist_core/schist_queries/src/buckets.rs b/schist_core/schist_queries/src/buckets.rs
index c7cf213..29270af 100644
--- a/schist_core/schist_queries/src/buckets.rs
+++ b/schist_core/schist_queries/src/buckets.rs
@@ -26,10 +26,7 @@ pub fn get_all_bucket_ids(connection: &mut SqliteConnection) -> Result<Vec<i32>>
Ok(all_bucket_ids)
}
-pub fn insert_buckets(
- buckets: &[Bucket],
- connection: &mut SqliteConnection,
-) -> Result<usize> {
+pub fn insert_buckets(buckets: &[Bucket], connection: &mut SqliteConnection) -> Result<usize> {
let num_buckets_inserted = diesel::insert_into(buckets_table)
.values(buckets)
.execute(connection)
diff --git a/schist_core/schist_queries/src/budget_drips.rs b/schist_core/schist_queries/src/budget_drips.rs
deleted file mode 100644
index b6f9372..0000000
--- a/schist_core/schist_queries/src/budget_drips.rs
+++ /dev/null
@@ -1,40 +0,0 @@
-use anyhow::{Context, Result};
-use diesel::{QueryDsl, RunQueryDsl, SelectableHelper, SqliteConnection};
-use schist_models::budget_drip::BudgetDrip;
-use schist_schema::schema::budget_drips::dsl::budget_drips as budget_drips_table;
-
-pub fn delete_all_budget_drips(connection: &mut SqliteConnection) -> Result<usize> {
- let num_rows_deleted = diesel::delete(budget_drips_table)
- .execute(connection)
- .with_context(|| "failed to delete all budget drips")?;
- Ok(num_rows_deleted)
-}
-
-pub fn get_all_budget_drips(connection: &mut SqliteConnection) -> Result<Vec<BudgetDrip>> {
- let all_budget_drips = budget_drips_table.select(BudgetDrip::as_select())
- .load(connection)
- .with_context(|| "failed to get all budget drips")?;
- Ok(all_budget_drips)
-}
-
-pub fn insert_budget_drips(
- budget_drips: &[BudgetDrip],
- connection: &mut SqliteConnection,
-) -> Result<usize> {
- let num_budget_drips_inserted = diesel::insert_into(budget_drips_table)
- .values(budget_drips)
- .execute(connection)
- .with_context(|| insert_err_msg(budget_drips))?;
- Ok(num_budget_drips_inserted)
-}
-
-fn insert_err_msg(budget_drips: &[BudgetDrip]) -> String {
- format!(
- "failed to insert budget drips: [{}]",
- budget_drips
- .iter()
- .map(|a| a.id.to_string())
- .collect::<Vec<String>>()
- .join(", ")
- )
-}
diff --git a/schist_core/schist_queries/src/clear.rs b/schist_core/schist_queries/src/clear.rs
index 6d2894d..04d22d9 100644
--- a/schist_core/schist_queries/src/clear.rs
+++ b/schist_core/schist_queries/src/clear.rs
@@ -2,15 +2,17 @@ use anyhow::Result;
use diesel::SqliteConnection;
use crate::{
- accounts::delete_all_accounts, budget_drips::delete_all_budget_drips, buckets::delete_all_buckets, bucket_transfers::delete_all_bucket_transfers, transaction_categorisations::delete_all_transaction_categorisations, transactions::delete_all_transactions
+ accounts::delete_all_accounts, bucket_transfers::delete_all_bucket_transfers,
+ buckets::delete_all_buckets, drips::delete_all_drips, pipes::delete_all_pipes,
+ transactions::delete_all_transactions,
};
pub fn clear(connection: &mut SqliteConnection) -> Result<()> {
delete_all_accounts(connection)?;
- delete_all_budget_drips(connection)?;
+ delete_all_drips(connection)?;
delete_all_buckets(connection)?;
delete_all_bucket_transfers(connection)?;
delete_all_transactions(connection)?;
- delete_all_transaction_categorisations(connection)?;
+ delete_all_pipes(connection)?;
Ok(())
}
diff --git a/schist_core/schist_queries/src/drips.rs b/schist_core/schist_queries/src/drips.rs
new file mode 100644
index 0000000..d9e33a8
--- /dev/null
+++ b/schist_core/schist_queries/src/drips.rs
@@ -0,0 +1,38 @@
+use anyhow::{Context, Result};
+use diesel::{QueryDsl, RunQueryDsl, SelectableHelper, SqliteConnection};
+use schist_models::drip::Drip;
+use schist_schema::schema::drips::dsl::drips as drips_table;
+
+pub fn delete_all_drips(connection: &mut SqliteConnection) -> Result<usize> {
+ let num_rows_deleted = diesel::delete(drips_table)
+ .execute(connection)
+ .with_context(|| "failed to delete all drips")?;
+ Ok(num_rows_deleted)
+}
+
+pub fn get_all_drips(connection: &mut SqliteConnection) -> Result<Vec<Drip>> {
+ let all_drips = drips_table
+ .select(Drip::as_select())
+ .load(connection)
+ .with_context(|| "failed to get all drips")?;
+ Ok(all_drips)
+}
+
+pub fn insert_drips(drips: &[Drip], connection: &mut SqliteConnection) -> Result<usize> {
+ let num_drips_inserted = diesel::insert_into(drips_table)
+ .values(drips)
+ .execute(connection)
+ .with_context(|| insert_err_msg(drips))?;
+ Ok(num_drips_inserted)
+}
+
+fn insert_err_msg(drips: &[Drip]) -> String {
+ format!(
+ "failed to insert drips: [{}]",
+ drips
+ .iter()
+ .map(|a| a.id.to_string())
+ .collect::<Vec<String>>()
+ .join(", ")
+ )
+}
diff --git a/schist_core/schist_queries/src/lib.rs b/schist_core/schist_queries/src/lib.rs
index e3e5488..ccd558d 100644
--- a/schist_core/schist_queries/src/lib.rs
+++ b/schist_core/schist_queries/src/lib.rs
@@ -1,10 +1,10 @@
-pub mod accounts;
pub mod account_transfers;
-pub mod budget_drips;
-pub mod buckets;
+pub mod accounts;
pub mod bucket_transfers;
+pub mod buckets;
pub mod clear;
+pub mod drips;
+pub mod pipes;
pub mod transactions;
-pub mod transaction_categorisations;
mod utils;
diff --git a/schist_core/schist_queries/src/pipes.rs b/schist_core/schist_queries/src/pipes.rs
new file mode 100644
index 0000000..188d193
--- /dev/null
+++ b/schist_core/schist_queries/src/pipes.rs
@@ -0,0 +1,55 @@
+use anyhow::{Context, Result};
+use diesel::{dsl::sum, QueryDsl, RunQueryDsl, SelectableHelper, SqliteConnection};
+use schist_models::pipe::Pipe;
+use schist_schema::schema::pipes::{self as pipes_schema, dsl::pipes as pipes_table};
+
+pub fn delete_all_pipes(connection: &mut SqliteConnection) -> Result<usize> {
+ let num_rows_deleted = diesel::delete(pipes_table)
+ .execute(connection)
+ .with_context(|| "failed to delete all pipes")?;
+ Ok(num_rows_deleted)
+}
+
+pub fn get_all_pipes(connection: &mut SqliteConnection) -> Result<Vec<Pipe>> {
+ let all_pipes = pipes_table
+ .select(Pipe::as_select())
+ .load(connection)
+ .with_context(|| "failed to get all pipes")?;
+ Ok(all_pipes)
+}
+
+pub fn insert_pipes(
+ pipes: &[Pipe],
+ connection: &mut SqliteConnection,
+) -> Result<usize> {
+ let num_rows_inserted = diesel::insert_into(pipes_table)
+ .values(pipes)
+ .execute(connection)
+ .with_context(|| insert_err_msg(&pipes))?;
+ Ok(num_rows_inserted)
+}
+
+fn insert_err_msg(pipes: &[Pipe]) -> String {
+ format!(
+ "failed to insert pipes: [{}]",
+ pipes
+ .iter()
+ .map(|tc| tc.id.to_string())
+ .collect::<Vec<String>>()
+ .join(", ")
+ )
+}
+
+pub fn sum_pipes_flow_per_bucket_id(connection: &mut SqliteConnection) -> Result<Vec<(i32, i64)>> {
+ let sum = pipes_table
+ .group_by(pipes_schema::bucket_id)
+ .select((pipes_schema::bucket_id, sum(pipes_schema::amount)))
+ .load::<(i32, Option<i64>)>(connection)
+ .map(|vec| {
+ vec.iter()
+ .map(|(bucket_id, sum)| (*bucket_id, sum.unwrap_or(0)))
+ .collect()
+ })
+ .with_context(|| "failed to sum pipes flow per bucket ID")?;
+ Ok(sum)
+}
diff --git a/schist_core/schist_queries/src/transaction_categorisations.rs b/schist_core/schist_queries/src/transaction_categorisations.rs
deleted file mode 100644
index 95aaf8d..0000000
--- a/schist_core/schist_queries/src/transaction_categorisations.rs
+++ /dev/null
@@ -1,59 +0,0 @@
-use anyhow::{Context, Result};
-use diesel::{dsl::sum, QueryDsl, RunQueryDsl, SelectableHelper, SqliteConnection};
-use schist_models::transaction_categorisation::TransactionCategorisation;
-use schist_schema::schema::transaction_categorisations::{
- self as transaction_categorisations_schema,
- dsl::transaction_categorisations as transaction_categorisations_table,
-};
-
-pub fn delete_all_transaction_categorisations(connection: &mut SqliteConnection) -> Result<usize> {
- let num_rows_deleted = diesel::delete(transaction_categorisations_table)
- .execute(connection)
- .with_context(|| "failed to delete all transaction categorisations")?;
- Ok(num_rows_deleted)
-}
-
-pub fn get_all_transaction_categorisations(connection: &mut SqliteConnection) -> Result<Vec<TransactionCategorisation>> {
- let all_transaction_categorisations = transaction_categorisations_table
- .select(TransactionCategorisation::as_select())
- .load(connection)
- .with_context(|| "failed to get all transaction categorisations")?;
- Ok(all_transaction_categorisations)
-}
-
-pub fn insert_transaction_categorisations(
- transaction_categorisations: &[TransactionCategorisation],
- connection: &mut SqliteConnection,
-) -> Result<usize> {
- let num_rows_inserted = diesel::insert_into(transaction_categorisations_table)
- .values(transaction_categorisations)
- .execute(connection)
- .with_context(|| insert_err_msg(&transaction_categorisations))?;
- Ok(num_rows_inserted)
-}
-
-fn insert_err_msg(transaction_categorisations: &[TransactionCategorisation]) -> String {
- format!(
- "failed to insert transaction categorisations: [{}]",
- transaction_categorisations
- .iter()
- .map(|tc| tc.id.to_string())
- .collect::<Vec<String>>()
- .join(", ")
- )
-}
-
-pub fn sum_transaction_categorisation_quantity_per_bucket_id(
- connection: &mut SqliteConnection,
-) -> Result<Vec<(i32, i64)>> {
- let sum = transaction_categorisations_table
- .group_by(transaction_categorisations_schema::bucket_id)
- .select((
- transaction_categorisations_schema::bucket_id,
- sum(transaction_categorisations_schema::quantity),
- ))
- .load::<(i32, Option<i64>)>(connection)
- .map(|vec| vec.iter().map(|(bucket_id, sum)| (*bucket_id, sum.unwrap_or(0))).collect())
- .with_context(|| "failed to sum transaction categorisation quantity per bucket ID")?;
- Ok(sum)
-}
diff --git a/schist_core/schist_queries/src/transactions.rs b/schist_core/schist_queries/src/transactions.rs
index 5941ebc..3abacfb 100644
--- a/schist_core/schist_queries/src/transactions.rs
+++ b/schist_core/schist_queries/src/transactions.rs
@@ -14,7 +14,7 @@ pub fn get_all_transactions(connection: &mut SqliteConnection) -> Result<Vec<Tra
let all_transactions = transactions_table
.select(Transaction::as_select())
.load(connection)
- .with_context(|| "failed to get all bucket transfers")?;
+ .with_context(|| "failed to get all transactions")?;
Ok(all_transactions)
}
diff --git a/schist_core/schist_queries/src/utils/calculate_bucket_balance.rs b/schist_core/schist_queries/src/utils/calculate_bucket_balance.rs
index 5194084..e238613 100644
--- a/schist_core/schist_queries/src/utils/calculate_bucket_balance.rs
+++ b/schist_core/schist_queries/src/utils/calculate_bucket_balance.rs
@@ -1,31 +1,26 @@
use anyhow::Result;
-use schist_models::{bucket::Bucket, budget_drip::BudgetDrip};
+use schist_models::{bucket::Bucket, drip::Drip};
-use super::{calculate_budgets_accrual, find_by_id_or};
+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: &[BudgetDrip],
+ budget_drips: &[Drip],
) -> Result<i64> {
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 = calculate_budgets_accrual(bucket, budget_drips)?;
-
- Ok(
- transaction_sum
- + budget_accruals_sum
- + bucket_transfer_to_sum
- - bucket_transfer_from_sum
- )
+ 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::{budget_drip::make_fake_budget_drip_builder, bucket::make_fake_bucket};
+ use schist_fakes::{bucket::make_fake_bucket, drip::make_fake_drip_builder};
use super::calculate_bucket_balance;
@@ -45,9 +40,11 @@ mod test {
let transaction_sums = [(1, 100)];
let bucket_transfer_from_sums = [(1, 91)];
let bucket_transfer_to_sums = [(2, 79)];
- let budget_drips = [
- make_fake_budget_drip_builder(0).quantity(100).bucket_id(1).build().unwrap(),
- ];
+ let budget_drips = [make_fake_drip_builder(0)
+ .amount(100)
+ .bucket_id(1)
+ .build()
+ .unwrap()];
let result = calculate_bucket_balance(
&bucket,
@@ -108,11 +105,31 @@ mod test {
let bucket_transfer_from_sums = [(0, 91)];
let bucket_transfer_to_sums = [(0, 79)];
let budget_drips = [
- make_fake_budget_drip_builder(0).quantity(77).bucket_id(0).build().unwrap(),
- make_fake_budget_drip_builder(0).quantity(77).bucket_id(0).build().unwrap(),
- make_fake_budget_drip_builder(0).quantity(77).bucket_id(0).build().unwrap(),
- make_fake_budget_drip_builder(0).quantity(77).bucket_id(0).build().unwrap(),
- make_fake_budget_drip_builder(0).quantity(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(),
+ make_fake_drip_builder(0)
+ .amount(77)
+ .bucket_id(0)
+ .build()
+ .unwrap(),
];
let result = calculate_bucket_balance(
diff --git a/schist_core/schist_queries/src/utils/calculate_budgets_accrual.rs b/schist_core/schist_queries/src/utils/calculate_budgets_accrual.rs
deleted file mode 100644
index cbf7180..0000000
--- a/schist_core/schist_queries/src/utils/calculate_budgets_accrual.rs
+++ /dev/null
@@ -1,72 +0,0 @@
-use anyhow::Result;
-use schist_models::{
- budget_drip::BudgetDrip,
- bucket::Bucket,
-};
-
-pub fn calculate_budgets_accrual(bucket: &Bucket, budget_drips: &[BudgetDrip]) -> Result<i64> {
- Ok(budget_drips
- .iter()
- .filter(|bd| bd.bucket_id == bucket.id)
- .map(|bd| Into::<i64>::into(bd.quantity))
- .sum()
- )
-}
-
-#[cfg(test)]
-mod test {
- use schist_fakes::{budget_drip::make_fake_budget_drip_builder, bucket::make_fake_bucket};
-
- use super::calculate_budgets_accrual;
-
- #[test]
- fn when_no_budget_drips_then_return_zero() {
- let bucket = make_fake_bucket(0);
- let budget_drips = [];
-
- let result = calculate_budgets_accrual(&bucket, &budget_drips);
-
- assert!(result.is_ok());
- assert_eq!(result.unwrap(), 0_i64);
- }
-
- #[test]
- fn when_one_budget_drip_for_another_bucket_then_return_zero() {
- let bucket = make_fake_bucket(0);
- let budget_drips = [
- make_fake_budget_drip_builder(0).quantity(100).bucket_id(1).build().unwrap(),
- ];
-
- let result = calculate_budgets_accrual(&bucket, &budget_drips);
-
- assert!(result.is_ok());
- assert_eq!(result.unwrap(), 0_i64);
- }
-
- #[test]
- fn when_one_budget_drip_then_return_quantity() {
- let bucket = make_fake_bucket(0);
- let budget_drips = [
- make_fake_budget_drip_builder(0).quantity(100).bucket_id(0).build().unwrap(),
- ];
-
- let result = calculate_budgets_accrual(&bucket, &budget_drips);
-
- assert!(result.is_ok());
- assert_eq!(result.unwrap(), 100);
- }
-
- #[test]
- fn when_two_budget_drips_then_return_sum() {
- let bucket = make_fake_bucket(0);
- let budget_drips = [
- make_fake_budget_drip_builder(0).quantity(100).bucket_id(0).build().unwrap(),
- make_fake_budget_drip_builder(1).quantity(120).bucket_id(0).build().unwrap(),
- ];
-
- let result = calculate_budgets_accrual(&bucket, &budget_drips);
-
- assert!(result.is_ok());
- assert_eq!(result.unwrap(), 220);
- }
-}
diff --git a/schist_core/schist_queries/src/utils/mod.rs b/schist_core/schist_queries/src/utils/mod.rs
index c006a9b..6b47b48 100644
--- a/schist_core/schist_queries/src/utils/mod.rs
+++ b/schist_core/schist_queries/src/utils/mod.rs
@@ -1,8 +1,8 @@
-mod calculate_budgets_accrual;
mod calculate_bucket_balance;
mod find_by_id_or;
+mod sum_drips_for_bucket;
-use calculate_budgets_accrual::calculate_budgets_accrual;
+use sum_drips_for_bucket::sum_drips_for_bucket;
pub use calculate_bucket_balance::calculate_bucket_balance;
pub use find_by_id_or::find_by_id_or;
diff --git a/schist_core/schist_queries/src/utils/sum_drips_for_bucket.rs b/schist_core/schist_queries/src/utils/sum_drips_for_bucket.rs
new file mode 100644
index 0000000..76f7988
--- /dev/null
+++ b/schist_core/schist_queries/src/utils/sum_drips_for_bucket.rs
@@ -0,0 +1,80 @@
+use anyhow::Result;
+use schist_models::{bucket::Bucket, drip::Drip};
+
+pub fn sum_drips_for_bucket(bucket: &Bucket, budget_drips: &[Drip]) -> Result<i64> {
+ Ok(budget_drips
+ .iter()
+ .filter(|bd| bd.bucket_id == bucket.id)
+ .map(|bd| Into::<i64>::into(bd.amount))
+ .sum())
+}
+
+#[cfg(test)]
+mod test {
+ use schist_fakes::{bucket::make_fake_bucket, drip::make_fake_drip_builder};
+
+ use super::sum_drips_for_bucket;
+
+ #[test]
+ fn when_no_budget_drips_then_return_zero() {
+ let bucket = make_fake_bucket(0);
+ let budget_drips = [];
+
+ let result = sum_drips_for_bucket(&bucket, &budget_drips);
+
+ assert!(result.is_ok());
+ assert_eq!(result.unwrap(), 0_i64);
+ }
+
+ #[test]
+ fn when_one_budget_drip_for_another_bucket_then_return_zero() {
+ let bucket = make_fake_bucket(0);
+ let budget_drips = [make_fake_drip_builder(0)
+ .amount(100)
+ .bucket_id(1)
+ .build()
+ .unwrap()];
+
+ let result = sum_drips_for_bucket(&bucket, &budget_drips);
+
+ assert!(result.is_ok());
+ assert_eq!(result.unwrap(), 0_i64);
+ }
+
+ #[test]
+ fn when_one_budget_drip_then_return_quantity() {
+ let bucket = make_fake_bucket(0);
+ let budget_drips = [make_fake_drip_builder(0)
+ .amount(100)
+ .bucket_id(0)
+ .build()
+ .unwrap()];
+
+ let result = sum_drips_for_bucket(&bucket, &budget_drips);
+
+ assert!(result.is_ok());
+ assert_eq!(result.unwrap(), 100);
+ }
+
+ #[test]
+ fn when_two_budget_drips_then_return_sum() {
+ let bucket = make_fake_bucket(0);
+ let budget_drips = [
+ make_fake_drip_builder(0)
+ .amount(100)
+ .bucket_id(0)
+ .build()
+ .unwrap(),
+ make_fake_drip_builder(1)
+ .amount(120)
+ .bucket_id(0)
+ .build()
+ .unwrap(),
+ ];
+
+ let result = sum_drips_for_bucket(&bucket, &budget_drips);
+
+ assert!(result.is_ok());
+ assert_eq!(result.unwrap(), 220);
+ }
+}