From 1056421dd45b7e9af6f63a95026cb069cfa34e29 Mon Sep 17 00:00:00 2001 From: Joe Carstairs Date: Fri, 9 Jan 2026 18:13:36 +0000 Subject: improves balance format/style --- schist_core/schist_models/src/bucket.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'schist_core') diff --git a/schist_core/schist_models/src/bucket.rs b/schist_core/schist_models/src/bucket.rs index a28aa8f..67ed31e 100644 --- a/schist_core/schist_models/src/bucket.rs +++ b/schist_core/schist_models/src/bucket.rs @@ -1,3 +1,5 @@ +use std::ops::Div; + use derive_builder::Builder; use diesel::prelude::*; use serde::{Deserialize, Serialize}; @@ -34,3 +36,14 @@ impl Bucket { .all(|t| t.bucket_id.is_none_or(|id| id != self.id)) } } + +impl Bucket { + pub fn pretty_balance_per_100(&self) -> String { + let abs_balance_per_100 = self.balance.unwrap_or(0).div(100).abs(); + if self.balance.is_none_or(|balance| balance >= 0) { + abs_balance_per_100.to_string() + } else { + format!("({abs_balance_per_100})") + } + } +} -- cgit v1.2.3 From 2809e6a2ef3ea636f3de5873f6c874923b410400 Mon Sep 17 00:00:00 2001 From: Joe Carstairs Date: Thu, 15 Jan 2026 22:35:39 +0000 Subject: renames categories -> buckets, refactors category_transfers -> bucket_transactions --- schist_core/schist_fakes/src/bucket_transaction.rs | 15 ++ schist_core/schist_fakes/src/bucket_transfer.rs | 16 -- schist_core/schist_fakes/src/lib.rs | 2 +- .../2024-08-31-084439_initial_setup/down.sql | 2 +- .../2024-08-31-084439_initial_setup/up.sql | 11 +- schist_core/schist_models/src/bucket.rs | 2 - .../schist_models/src/bucket_transaction.rs | 11 ++ schist_core/schist_models/src/bucket_transfer.rs | 12 -- schist_core/schist_models/src/lib.rs | 4 +- schist_core/schist_models/src/schema.rs | 8 +- schist_core/schist_models/user_data.sqlite | Bin 45056 -> 49152 bytes .../schist_queries/src/bucket_transactions.rs | 65 +++++++ schist_core/schist_queries/src/bucket_transfers.rs | 82 --------- schist_core/schist_queries/src/clear.rs | 6 +- schist_core/schist_queries/src/lib.rs | 2 +- .../schist_queries/tests/bucket_transactions.rs | 160 ++++++++++++++++ schist_core/schist_queries/tests/buckets.rs | 83 +++++++++ .../schist_queries/tests/category_transfers.rs | 201 --------------------- 18 files changed, 350 insertions(+), 332 deletions(-) create mode 100644 schist_core/schist_fakes/src/bucket_transaction.rs delete mode 100644 schist_core/schist_fakes/src/bucket_transfer.rs create mode 100644 schist_core/schist_models/src/bucket_transaction.rs delete mode 100644 schist_core/schist_models/src/bucket_transfer.rs create mode 100644 schist_core/schist_queries/src/bucket_transactions.rs delete mode 100644 schist_core/schist_queries/src/bucket_transfers.rs create mode 100644 schist_core/schist_queries/tests/bucket_transactions.rs create mode 100644 schist_core/schist_queries/tests/buckets.rs delete mode 100644 schist_core/schist_queries/tests/category_transfers.rs (limited to 'schist_core') diff --git a/schist_core/schist_fakes/src/bucket_transaction.rs b/schist_core/schist_fakes/src/bucket_transaction.rs new file mode 100644 index 0000000..3dd0a6f --- /dev/null +++ b/schist_core/schist_fakes/src/bucket_transaction.rs @@ -0,0 +1,15 @@ +use schist_models::{BucketTransaction, BucketTransactionBuilder}; + +pub fn make_fake_bucket_transaction(id: i32) -> BucketTransaction { + make_fake_bucket_transaction_builder(id).build().unwrap() +} + +pub fn make_fake_bucket_transaction_builder(id: i32) -> BucketTransactionBuilder { + let mut builder = BucketTransactionBuilder::default(); + builder + .id(id) + .description(String::from("Fake bucket transaction")) + .amount(0) + .bucket_id(1); + builder +} diff --git a/schist_core/schist_fakes/src/bucket_transfer.rs b/schist_core/schist_fakes/src/bucket_transfer.rs deleted file mode 100644 index 1342ca2..0000000 --- a/schist_core/schist_fakes/src/bucket_transfer.rs +++ /dev/null @@ -1,16 +0,0 @@ -use schist_models::{BucketTransfer, BucketTransferBuilder}; - -pub fn make_fake_bucket_transfer(id: i32) -> BucketTransfer { - make_fake_bucket_transfer_builder(id).build().unwrap() -} - -pub fn make_fake_bucket_transfer_builder(id: i32) -> BucketTransferBuilder { - let mut builder = BucketTransferBuilder::default(); - builder - .id(id) - .description(String::from("Fake bucket transfer")) - .amount(0) - .from_bucket_id(0) - .to_bucket_id(1); - builder -} diff --git a/schist_core/schist_fakes/src/lib.rs b/schist_core/schist_fakes/src/lib.rs index 0e4cbb4..7ac98fa 100644 --- a/schist_core/schist_fakes/src/lib.rs +++ b/schist_core/schist_fakes/src/lib.rs @@ -1,7 +1,7 @@ pub mod account; pub mod account_transfer; pub mod bucket; -pub mod bucket_transfer; +pub mod bucket_transaction; pub mod drip; pub mod pipe; pub mod transaction; diff --git a/schist_core/schist_models/migrations/2024-08-31-084439_initial_setup/down.sql b/schist_core/schist_models/migrations/2024-08-31-084439_initial_setup/down.sql index 3b2c73e..f6ead07 100644 --- a/schist_core/schist_models/migrations/2024-08-31-084439_initial_setup/down.sql +++ b/schist_core/schist_models/migrations/2024-08-31-084439_initial_setup/down.sql @@ -1,7 +1,7 @@ DROP TABLE accounts; DROP TABLE account_transfers; DROP TABLE buckets; -DROP TABLE bucket_transfers; +DROP TABLE bucket_transactions; DROP TABLE drips; DROP TABLE pipes; DROP TABLE transactions; diff --git a/schist_core/schist_models/migrations/2024-08-31-084439_initial_setup/up.sql b/schist_core/schist_models/migrations/2024-08-31-084439_initial_setup/up.sql index b37c626..e645d43 100644 --- a/schist_core/schist_models/migrations/2024-08-31-084439_initial_setup/up.sql +++ b/schist_core/schist_models/migrations/2024-08-31-084439_initial_setup/up.sql @@ -32,17 +32,12 @@ CREATE TABLE buckets( name TEXT NOT NULL ); -CREATE TABLE bucket_transfers( +CREATE TABLE bucket_transactions( id INTEGER NOT NULL PRIMARY KEY, amount INTEGER NOT NULL, + bucket_id INTEGER NOT NULL, description TEXT NOT NULL, - from_bucket_id INTEGER NOT NULL, - to_bucket_id INTEGER NOT NULL, - FOREIGN KEY (from_bucket_id) - REFERENCES buckets (id) - ON UPDATE CASCADE - ON DELETE RESTRICT, - FOREIGN KEY (to_bucket_id) + FOREIGN KEY (bucket_id) REFERENCES buckets (id) ON UPDATE CASCADE ON DELETE RESTRICT diff --git a/schist_core/schist_models/src/bucket.rs b/schist_core/schist_models/src/bucket.rs index 67ed31e..debbab7 100644 --- a/schist_core/schist_models/src/bucket.rs +++ b/schist_core/schist_models/src/bucket.rs @@ -35,9 +35,7 @@ impl Bucket { .iter() .all(|t| t.bucket_id.is_none_or(|id| id != self.id)) } -} -impl Bucket { pub fn pretty_balance_per_100(&self) -> String { let abs_balance_per_100 = self.balance.unwrap_or(0).div(100).abs(); if self.balance.is_none_or(|balance| balance >= 0) { diff --git a/schist_core/schist_models/src/bucket_transaction.rs b/schist_core/schist_models/src/bucket_transaction.rs new file mode 100644 index 0000000..2aeae8a --- /dev/null +++ b/schist_core/schist_models/src/bucket_transaction.rs @@ -0,0 +1,11 @@ +use derive_builder::Builder; +use diesel::prelude::*; + +#[derive(Builder, Queryable, Identifiable, Selectable, Debug, PartialEq, Insertable)] +#[diesel(table_name = crate::schema::bucket_transactions)] +pub struct BucketTransaction { + pub id: i32, + pub amount: i32, + pub bucket_id: i32, + pub description: String, +} diff --git a/schist_core/schist_models/src/bucket_transfer.rs b/schist_core/schist_models/src/bucket_transfer.rs deleted file mode 100644 index 7c3a9d2..0000000 --- a/schist_core/schist_models/src/bucket_transfer.rs +++ /dev/null @@ -1,12 +0,0 @@ -use derive_builder::Builder; -use diesel::prelude::*; - -#[derive(Builder, Queryable, Identifiable, Selectable, Debug, PartialEq, Insertable)] -#[diesel(table_name = crate::schema::bucket_transfers)] -pub struct BucketTransfer { - pub id: i32, - pub amount: i32, - pub description: String, - pub from_bucket_id: i32, - pub to_bucket_id: i32, -} diff --git a/schist_core/schist_models/src/lib.rs b/schist_core/schist_models/src/lib.rs index 3aa4733..2a119cb 100644 --- a/schist_core/schist_models/src/lib.rs +++ b/schist_core/schist_models/src/lib.rs @@ -1,7 +1,7 @@ mod account; mod account_transfer; mod bucket; -mod bucket_transfer; +mod bucket_transaction; mod budget_period_unit; mod date_utc; mod datetime_utc; @@ -15,7 +15,7 @@ pub mod schema; pub use account::Account; pub use account_transfer::{AccountTransfer, AccountTransferBuilder}; pub use bucket::{Bucket, BucketBuilder}; -pub use bucket_transfer::{BucketTransfer, BucketTransferBuilder}; +pub use bucket_transaction::{BucketTransaction, BucketTransactionBuilder}; pub use budget_period_unit::BudgetPeriodUnit; pub use date_utc::DateUtc; pub use datetime_utc::DatetimeUtc; diff --git a/schist_core/schist_models/src/schema.rs b/schist_core/schist_models/src/schema.rs index d16e636..8744696 100644 --- a/schist_core/schist_models/src/schema.rs +++ b/schist_core/schist_models/src/schema.rs @@ -21,12 +21,11 @@ diesel::table! { } diesel::table! { - bucket_transfers (id) { + bucket_transactions (id) { id -> Integer, amount -> Integer, + bucket_id -> Integer, description -> Text, - from_bucket_id -> Integer, - to_bucket_id -> Integer, } } @@ -74,6 +73,7 @@ diesel::table! { } } +diesel::joinable!(bucket_transactions -> buckets (bucket_id)); diesel::joinable!(drips -> buckets (bucket_id)); diesel::joinable!(pipes -> buckets (bucket_id)); diesel::joinable!(transactions -> accounts (account_id)); @@ -81,7 +81,7 @@ diesel::joinable!(transactions -> accounts (account_id)); diesel::allow_tables_to_appear_in_same_query!( account_transfers, accounts, - bucket_transfers, + bucket_transactions, buckets, drips, pipes, diff --git a/schist_core/schist_models/user_data.sqlite b/schist_core/schist_models/user_data.sqlite index 175ce60..81fd25c 100644 Binary files a/schist_core/schist_models/user_data.sqlite and b/schist_core/schist_models/user_data.sqlite differ diff --git a/schist_core/schist_queries/src/bucket_transactions.rs b/schist_core/schist_queries/src/bucket_transactions.rs new file mode 100644 index 0000000..da06341 --- /dev/null +++ b/schist_core/schist_queries/src/bucket_transactions.rs @@ -0,0 +1,65 @@ +use anyhow::{Context, Result}; +use diesel::{dsl::sum, QueryDsl, RunQueryDsl, SelectableHelper, SqliteConnection}; +use schist_models::BucketTransaction; +use schist_schema::schema::bucket_transactions::{ + self as bucket_transactions_schema, dsl::bucket_transactions as bucket_transactions_table, +}; + +pub fn delete_all_bucket_transactions(connection: &mut SqliteConnection) -> Result { + let num_rows_deleted = diesel::delete(bucket_transactions_table) + .execute(connection) + .with_context(|| "failed to delete all bucket transactions")?; + Ok(num_rows_deleted) +} + +pub fn get_all_bucket_transactions( + connection: &mut SqliteConnection, +) -> Result> { + let all_bucket_transactions = bucket_transactions_table + .select(BucketTransaction::as_select()) + .load(connection) + .with_context(|| "failed to get all bucket transactions")?; + Ok(all_bucket_transactions) +} + +pub fn insert_bucket_transactions( + bucket_transactions: &[BucketTransaction], + connection: &mut SqliteConnection, +) -> Result { + let num_rows_inserted = diesel::insert_into(bucket_transactions_table) + .values(bucket_transactions) + .execute(connection) + .with_context(|| insert_err_msg(&bucket_transactions))?; + Ok(num_rows_inserted) +} + +fn insert_err_msg(bucket_transactions: &[BucketTransaction]) -> String { + format!( + "failed to insert bucket transactions: [{}]", + bucket_transactions + .iter() + .map(|ct| ct.id.to_string()) + .collect::>() + .join(", ") + ) +} + +pub fn sum_bucket_transaction_amount_per_bucket_id( + connection: &mut SqliteConnection, +) -> Result> { + let sum = bucket_transactions_table + .group_by(bucket_transactions_schema::bucket_id) + .select(( + bucket_transactions_schema::bucket_id, + sum(bucket_transactions_schema::amount), + )) + .load::<(i32, Option)>(connection) + .map(|result| { + result + .iter() + .map(|sum| (sum.0, sum.1.unwrap_or(0))) + .collect() + }) + .with_context(|| "failed to sum bucket transaction amount per bucket ID")?; + Ok(sum) +} diff --git a/schist_core/schist_queries/src/bucket_transfers.rs b/schist_core/schist_queries/src/bucket_transfers.rs deleted file mode 100644 index 652c8e0..0000000 --- a/schist_core/schist_queries/src/bucket_transfers.rs +++ /dev/null @@ -1,82 +0,0 @@ -use anyhow::{Context, Result}; -use diesel::{dsl::sum, QueryDsl, RunQueryDsl, SelectableHelper, SqliteConnection}; -use schist_models::BucketTransfer; -use schist_schema::schema::bucket_transfers::{ - self as bucket_transfers_schema, dsl::bucket_transfers as bucket_transfers_table, -}; - -pub fn delete_all_bucket_transfers(connection: &mut SqliteConnection) -> Result { - let num_rows_deleted = diesel::delete(bucket_transfers_table) - .execute(connection) - .with_context(|| "failed to delete all bucket transfers")?; - Ok(num_rows_deleted) -} - -pub fn get_all_bucket_transfers(connection: &mut SqliteConnection) -> Result> { - let all_bucket_transfers = bucket_transfers_table - .select(BucketTransfer::as_select()) - .load(connection) - .with_context(|| "failed to get all bucket transfers")?; - Ok(all_bucket_transfers) -} - -pub fn insert_bucket_transfers( - bucket_transfers: &[BucketTransfer], - connection: &mut SqliteConnection, -) -> Result { - let num_rows_inserted = diesel::insert_into(bucket_transfers_table) - .values(bucket_transfers) - .execute(connection) - .with_context(|| insert_err_msg(&bucket_transfers))?; - Ok(num_rows_inserted) -} - -fn insert_err_msg(bucket_transfers: &[BucketTransfer]) -> String { - format!( - "failed to insert bucket transfers: [{}]", - bucket_transfers - .iter() - .map(|ct| ct.id.to_string()) - .collect::>() - .join(", ") - ) -} - -pub fn sum_bucket_transfer_quantity_per_from_bucket_id( - connection: &mut SqliteConnection, -) -> Result> { - let sum = bucket_transfers_table - .group_by(bucket_transfers_schema::from_bucket_id) - .select(( - bucket_transfers_schema::from_bucket_id, - sum(bucket_transfers_schema::amount), - )) - .load::<(i32, Option)>(connection) - .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) -} - -pub fn sum_bucket_transfer_quantity_per_to_bucket_id( - connection: &mut SqliteConnection, -) -> Result> { - let sum = bucket_transfers_table - .group_by(bucket_transfers_schema::to_bucket_id) - .select(( - bucket_transfers_schema::to_bucket_id, - sum(bucket_transfers_schema::amount), - )) - .load::<(i32, Option)>(connection) - .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/clear.rs b/schist_core/schist_queries/src/clear.rs index a5a82f3..845e109 100644 --- a/schist_core/schist_queries/src/clear.rs +++ b/schist_core/schist_queries/src/clear.rs @@ -2,7 +2,9 @@ use anyhow::Result; use diesel::SqliteConnection; use crate::{ - account_transfers::delete_all_account_transfers, 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 + account_transfers::delete_all_account_transfers, accounts::delete_all_accounts, + bucket_transactions::delete_all_bucket_transactions, buckets::delete_all_buckets, + drips::delete_all_drips, pipes::delete_all_pipes, transactions::delete_all_transactions, }; pub fn clear(connection: &mut SqliteConnection) -> Result<()> { @@ -11,7 +13,7 @@ pub fn clear(connection: &mut SqliteConnection) -> Result<()> { delete_all_pipes(connection)?; delete_all_transactions(connection)?; delete_all_accounts(connection)?; - delete_all_bucket_transfers(connection)?; + delete_all_bucket_transactions(connection)?; delete_all_buckets(connection)?; Ok(()) } diff --git a/schist_core/schist_queries/src/lib.rs b/schist_core/schist_queries/src/lib.rs index ccd558d..ee74d6b 100644 --- a/schist_core/schist_queries/src/lib.rs +++ b/schist_core/schist_queries/src/lib.rs @@ -1,6 +1,6 @@ pub mod account_transfers; pub mod accounts; -pub mod bucket_transfers; +pub mod bucket_transactions; pub mod buckets; pub mod clear; pub mod drips; diff --git a/schist_core/schist_queries/tests/bucket_transactions.rs b/schist_core/schist_queries/tests/bucket_transactions.rs new file mode 100644 index 0000000..9c877af --- /dev/null +++ b/schist_core/schist_queries/tests/bucket_transactions.rs @@ -0,0 +1,160 @@ +mod common; + +use common::test_context::TestContext; +use diesel::{Connection, SqliteConnection}; +use schist_fakes::{ + bucket::make_fake_bucket, bucket_transaction::make_fake_bucket_transaction_builder, +}; +use schist_queries as queries; + +#[test] +fn when_insert_bucket_transactions_then_returns_num_bucket_transactions() { + let context = TestContext::new(); + let connection = &mut SqliteConnection::establish(&context.db_url).unwrap(); + let buckets = [make_fake_bucket(0), make_fake_bucket(1)]; + let bucket_transactions = [ + make_fake_bucket_transaction_builder(0) + .bucket_id(0) + .build() + .unwrap(), + make_fake_bucket_transaction_builder(1) + .bucket_id(1) + .build() + .unwrap(), + ]; + let _ = queries::buckets::insert_buckets(&buckets, connection); + + let num_bucket_transactions_inserted = + queries::bucket_transactions::insert_bucket_transactions(&bucket_transactions, connection) + .unwrap(); + + assert_eq!(num_bucket_transactions_inserted, 2); +} + +#[test] +fn given_bucket_transactions_when_get_all_bucket_transactions_then_return_bucket_transactions() { + let context = TestContext::new(); + let connection = &mut SqliteConnection::establish(&context.db_url).unwrap(); + let buckets = [make_fake_bucket(0), make_fake_bucket(1)]; + let bucket_transactions = [ + make_fake_bucket_transaction_builder(0) + .bucket_id(0) + .build() + .unwrap(), + make_fake_bucket_transaction_builder(1) + .bucket_id(1) + .build() + .unwrap(), + ]; + let _ = queries::buckets::insert_buckets(&buckets, connection); + let _ = + queries::bucket_transactions::insert_bucket_transactions(&bucket_transactions, connection) + .unwrap(); + + let bucket_transactions_in_db = + queries::bucket_transactions::get_all_bucket_transactions(connection).unwrap(); + + assert_eq!(bucket_transactions_in_db.len(), bucket_transactions.len()); + for bucket_transaction in &bucket_transactions { + assert!(bucket_transactions_in_db + .iter() + .any(|bucket_transaction_in_db| bucket_transaction_in_db.eq(&bucket_transaction))); + } + for bucket_transaction_in_db in bucket_transactions_in_db { + assert!(bucket_transactions + .iter() + .any(|bucket_transaction| bucket_transaction.eq(&bucket_transaction_in_db))); + } +} + +#[test] +fn given_bucket_transactions_when_delete_all_bucket_transactions_then_return_num_of_bucket_transactions( +) { + let context = TestContext::new(); + let connection = &mut SqliteConnection::establish(&context.db_url).unwrap(); + let buckets = [make_fake_bucket(0), make_fake_bucket(1)]; + let bucket_transactions = [ + make_fake_bucket_transaction_builder(0) + .bucket_id(0) + .build() + .unwrap(), + make_fake_bucket_transaction_builder(1) + .bucket_id(1) + .build() + .unwrap(), + ]; + let _ = queries::buckets::insert_buckets(&buckets, connection); + let _ = + queries::bucket_transactions::insert_bucket_transactions(&bucket_transactions, connection) + .unwrap(); + + let num_bucket_transactions_deleted = + queries::bucket_transactions::delete_all_bucket_transactions(connection).unwrap(); + + assert_eq!(num_bucket_transactions_deleted, bucket_transactions.len()); +} + +#[test] +fn given_deleted_bucket_transactions_when_get_all_bucket_transactions_then_return_empty() { + let context = TestContext::new(); + let connection = &mut SqliteConnection::establish(&context.db_url).unwrap(); + let buckets = [make_fake_bucket(0), make_fake_bucket(1)]; + let bucket_transactions = [ + make_fake_bucket_transaction_builder(0) + .bucket_id(0) + .build() + .unwrap(), + make_fake_bucket_transaction_builder(1) + .bucket_id(1) + .build() + .unwrap(), + ]; + let _ = queries::buckets::insert_buckets(&buckets, connection); + let _ = + queries::bucket_transactions::insert_bucket_transactions(&bucket_transactions, connection) + .unwrap(); + let _ = queries::bucket_transactions::delete_all_bucket_transactions(connection).unwrap(); + + let bucket_transactions_returned = + queries::bucket_transactions::get_all_bucket_transactions(connection).unwrap(); + + assert_eq!(bucket_transactions_returned.len(), 0); +} + +#[test] +fn given_bucket_transactions_when_sum_quantity_per_bucket_id_then_returns_sum_per_bucket_id() { + let context = TestContext::new(); + let connection = &mut SqliteConnection::establish(&context.db_url).unwrap(); + let buckets = [make_fake_bucket(0), make_fake_bucket(1)]; + let bucket_transactions = [ + make_fake_bucket_transaction_builder(0) + .bucket_id(0) + .amount(1) + .build() + .unwrap(), + make_fake_bucket_transaction_builder(1) + .bucket_id(0) + .amount(2) + .build() + .unwrap(), + make_fake_bucket_transaction_builder(2) + .bucket_id(1) + .amount(4) + .build() + .unwrap(), + ]; + let _ = queries::buckets::insert_buckets(&buckets, connection); + let _ = + queries::bucket_transactions::insert_bucket_transactions(&bucket_transactions, connection) + .unwrap(); + + let sums = + queries::bucket_transactions::sum_bucket_transaction_amount_per_bucket_id(connection); + + assert!(sums.is_ok()); + let mut sums = sums.unwrap(); + sums.sort_by_key(|sum| sum.0); + assert_eq!(buckets.len(), sums.len()); + assert_eq!(3, sums[0].1); + assert_eq!(4, sums[1].1); +} diff --git a/schist_core/schist_queries/tests/buckets.rs b/schist_core/schist_queries/tests/buckets.rs new file mode 100644 index 0000000..72dd4c7 --- /dev/null +++ b/schist_core/schist_queries/tests/buckets.rs @@ -0,0 +1,83 @@ +mod common; + +use common::test_context::TestContext; +use diesel::{Connection, SqliteConnection}; +use schist_fakes::bucket::make_fake_bucket; +use schist_models::Bucket; +use schist_queries as queries; + +fn given_buckets(connection: &mut SqliteConnection) -> Vec { + let buckets = vec![make_fake_bucket(0), make_fake_bucket(1)]; + let _ = queries::buckets::insert_buckets(&buckets, connection).unwrap(); + buckets +} + +#[test] +fn when_insert_buckets_then_returns_num_buckets() { + let context = TestContext::new(); + let connection = &mut SqliteConnection::establish(&context.db_url).unwrap(); + let buckets = [make_fake_bucket(0), make_fake_bucket(1)]; + + let num_buckets_inserted = queries::buckets::insert_buckets(&buckets, connection).unwrap(); + + assert_eq!(num_buckets_inserted, 2); +} + +#[test] +fn given_buckets_when_get_all_buckets_then_return_buckets() { + let context = TestContext::new(); + let connection = &mut SqliteConnection::establish(&context.db_url).unwrap(); + let buckets = given_buckets(connection); + + let buckets_in_db = queries::buckets::get_all_buckets(connection).unwrap(); + + assert_eq!(buckets_in_db.len(), buckets.len()); + for bucket in &buckets { + assert!(buckets_in_db + .iter() + .any(|bucket_in_db| bucket_in_db.eq(&bucket))); + } + for bucket_in_db in buckets_in_db { + assert!(buckets.iter().any(|bucket| bucket.eq(&bucket_in_db))); + } +} + +#[test] +fn given_buckets_when_delete_all_buckets_then_return_num_of_buckets() { + let context = TestContext::new(); + let connection = &mut SqliteConnection::establish(&context.db_url).unwrap(); + let buckets = given_buckets(connection); + + let num_buckets_deleted = queries::buckets::delete_all_buckets(connection).unwrap(); + + assert_eq!(num_buckets_deleted, buckets.len()); +} + +#[test] +fn given_deleted_buckets_when_get_all_buckets_then_return_empty() { + let context = TestContext::new(); + let connection = &mut SqliteConnection::establish(&context.db_url).unwrap(); + given_buckets(connection); + let _ = queries::buckets::delete_all_buckets(connection).unwrap(); + + let buckets_returned = queries::buckets::get_all_buckets(connection).unwrap(); + + assert_eq!(buckets_returned.len(), 0); +} + +#[test] +fn given_buckets_when_get_all_ids_then_return_all_ids() { + let context = TestContext::new(); + let connection = &mut SqliteConnection::establish(&context.db_url).unwrap(); + let buckets = given_buckets(connection); + + let ids = queries::buckets::get_all_bucket_ids(connection).unwrap(); + + assert_eq!(buckets.len(), ids.len()); + for bucket in &buckets { + assert!(ids.iter().any(|id| bucket.id == *id)); + } + for id in ids { + assert!(buckets.iter().any(|bucket| bucket.id == id)); + } +} diff --git a/schist_core/schist_queries/tests/category_transfers.rs b/schist_core/schist_queries/tests/category_transfers.rs deleted file mode 100644 index f7c75a7..0000000 --- a/schist_core/schist_queries/tests/category_transfers.rs +++ /dev/null @@ -1,201 +0,0 @@ -mod common; - -use common::test_context::TestContext; -use diesel::{Connection, SqliteConnection}; -use schist_fakes::{bucket::make_fake_bucket, bucket_transfer::make_fake_bucket_transfer_builder}; -use schist_queries as queries; - -#[test] -fn when_insert_bucket_transfers_then_returns_num_bucket_transfers() { - let context = TestContext::new(); - let connection = &mut SqliteConnection::establish(&context.db_url).unwrap(); - let buckets = [make_fake_bucket(0), make_fake_bucket(1)]; - let bucket_transfers = [ - make_fake_bucket_transfer_builder(0) - .from_bucket_id(0) - .to_bucket_id(1) - .build() - .unwrap(), - make_fake_bucket_transfer_builder(1) - .from_bucket_id(0) - .to_bucket_id(1) - .build() - .unwrap(), - ]; - let _ = queries::buckets::insert_buckets(&buckets, connection); - - let num_bucket_transfers_inserted = - queries::bucket_transfers::insert_bucket_transfers(&bucket_transfers, connection).unwrap(); - - assert_eq!(num_bucket_transfers_inserted, 2); -} - -#[test] -fn given_bucket_transfers_when_get_all_bucket_transfers_then_return_bucket_transfers() { - let context = TestContext::new(); - let connection = &mut SqliteConnection::establish(&context.db_url).unwrap(); - let buckets = [make_fake_bucket(0), make_fake_bucket(1)]; - let bucket_transfers = [ - make_fake_bucket_transfer_builder(0) - .from_bucket_id(0) - .to_bucket_id(1) - .build() - .unwrap(), - make_fake_bucket_transfer_builder(1) - .from_bucket_id(0) - .to_bucket_id(1) - .build() - .unwrap(), - ]; - let _ = queries::buckets::insert_buckets(&buckets, connection); - let _ = - queries::bucket_transfers::insert_bucket_transfers(&bucket_transfers, connection).unwrap(); - - let bucket_transfers_in_db = - queries::bucket_transfers::get_all_bucket_transfers(connection).unwrap(); - - assert_eq!(bucket_transfers_in_db.len(), bucket_transfers.len()); - for bucket_transfer in &bucket_transfers { - assert!(bucket_transfers_in_db - .iter() - .any(|bucket_transfer_in_db| bucket_transfer_in_db.eq(&bucket_transfer))); - } - for bucket_transfer_in_db in bucket_transfers_in_db { - assert!(bucket_transfers - .iter() - .any(|bucket_transfer| bucket_transfer.eq(&bucket_transfer_in_db))); - } -} - -#[test] -fn given_bucket_transfers_when_delete_all_bucket_transfers_then_return_num_of_bucket_transfers() { - let context = TestContext::new(); - let connection = &mut SqliteConnection::establish(&context.db_url).unwrap(); - let buckets = [make_fake_bucket(0), make_fake_bucket(1)]; - let bucket_transfers = [ - make_fake_bucket_transfer_builder(0) - .from_bucket_id(0) - .to_bucket_id(1) - .build() - .unwrap(), - make_fake_bucket_transfer_builder(1) - .from_bucket_id(0) - .to_bucket_id(1) - .build() - .unwrap(), - ]; - let _ = queries::buckets::insert_buckets(&buckets, connection); - let _ = - queries::bucket_transfers::insert_bucket_transfers(&bucket_transfers, connection).unwrap(); - - let num_bucket_transfers_deleted = - queries::bucket_transfers::delete_all_bucket_transfers(connection).unwrap(); - - assert_eq!(num_bucket_transfers_deleted, bucket_transfers.len()); -} - -#[test] -fn given_deleted_bucket_transfers_when_get_all_bucket_transfers_then_return_empty() { - let context = TestContext::new(); - let connection = &mut SqliteConnection::establish(&context.db_url).unwrap(); - let buckets = [make_fake_bucket(0), make_fake_bucket(1)]; - let bucket_transfers = [ - make_fake_bucket_transfer_builder(0) - .from_bucket_id(0) - .to_bucket_id(1) - .build() - .unwrap(), - make_fake_bucket_transfer_builder(1) - .from_bucket_id(0) - .to_bucket_id(1) - .build() - .unwrap(), - ]; - let _ = queries::buckets::insert_buckets(&buckets, connection); - let _ = - queries::bucket_transfers::insert_bucket_transfers(&bucket_transfers, connection).unwrap(); - let _ = queries::bucket_transfers::delete_all_bucket_transfers(connection).unwrap(); - - let bucket_transfers_returned = - queries::bucket_transfers::get_all_bucket_transfers(connection).unwrap(); - - assert_eq!(bucket_transfers_returned.len(), 0); -} - -#[test] -fn given_bucket_transfers_when_sum_quantity_per_from_bucket_id_then_returns_sum_per_from_bucket_id() -{ - let context = TestContext::new(); - let connection = &mut SqliteConnection::establish(&context.db_url).unwrap(); - let buckets = [make_fake_bucket(0), make_fake_bucket(1)]; - let bucket_transfers = [ - make_fake_bucket_transfer_builder(0) - .from_bucket_id(0) - .to_bucket_id(1) - .amount(1) - .build() - .unwrap(), - make_fake_bucket_transfer_builder(1) - .from_bucket_id(0) - .to_bucket_id(1) - .amount(2) - .build() - .unwrap(), - make_fake_bucket_transfer_builder(2) - .from_bucket_id(1) - .to_bucket_id(0) - .amount(4) - .build() - .unwrap(), - ]; - let _ = queries::buckets::insert_buckets(&buckets, connection); - let _ = - queries::bucket_transfers::insert_bucket_transfers(&bucket_transfers, connection).unwrap(); - - let sums = - queries::bucket_transfers::sum_bucket_transfer_quantity_per_from_bucket_id(connection); - - assert!(sums.is_ok()); - let mut sums = sums.unwrap(); - sums.sort_by_key(|sum| sum.0); - assert_eq!(buckets.len(), sums.len()); - assert_eq!(3, sums[0].1); - assert_eq!(4, sums[1].1); -} - -#[test] -fn given_bucket_transfers_when_sum_quantity_per_to_bucket_id_then_returns_sum_per_to_bucket_id() { - let context = TestContext::new(); - let connection = &mut SqliteConnection::establish(&context.db_url).unwrap(); - let buckets = [make_fake_bucket(0), make_fake_bucket(1)]; - let bucket_transfers = [ - make_fake_bucket_transfer_builder(0) - .from_bucket_id(0) - .to_bucket_id(1) - .amount(1) - .build() - .unwrap(), - make_fake_bucket_transfer_builder(1) - .from_bucket_id(0) - .to_bucket_id(1) - .amount(2) - .build() - .unwrap(), - make_fake_bucket_transfer_builder(2) - .from_bucket_id(1) - .to_bucket_id(0) - .amount(4) - .build() - .unwrap(), - ]; - let _ = queries::buckets::insert_buckets(&buckets, connection); - let _ = - queries::bucket_transfers::insert_bucket_transfers(&bucket_transfers, connection).unwrap(); - - let sums = queries::bucket_transfers::sum_bucket_transfer_quantity_per_to_bucket_id(connection); - - assert!(sums.is_ok()); - let mut sums = sums.unwrap(); - sums.sort_by_key(|sum| sum.0); - assert_eq!([(0, 4), (1, 3)], sums.as_slice()); -} -- cgit v1.2.3 From 76ba747912a391d235a9c4456e1d813dee9712f3 Mon Sep 17 00:00:00 2001 From: Joe Carstairs Date: Sat, 17 Jan 2026 07:50:42 +0000 Subject: Publicise DateUtc::first_day_in_month and DateUtc::first_day_in_next_month --- schist_core/schist_models/src/date_utc.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'schist_core') diff --git a/schist_core/schist_models/src/date_utc.rs b/schist_core/schist_models/src/date_utc.rs index 18a894b..927644c 100644 --- a/schist_core/schist_models/src/date_utc.rs +++ b/schist_core/schist_models/src/date_utc.rs @@ -105,7 +105,7 @@ impl DateUtc { return true; } - fn first_day_in_next_month(&self) -> Self { + pub fn first_day_in_next_month(&self) -> Self { let month = self.month(); let mut curr_guess: Option> = None; let mut curr_add = 1; @@ -120,7 +120,7 @@ impl DateUtc { }; } - fn first_day_in_month(&self) -> Self { + pub fn first_day_in_month(&self) -> Self { let month = self.month(); let mut prev_guess = self.clone(); let mut curr_guess = self.clone(); -- cgit v1.2.3 From 0971a7a4e847a5ae935c164d8d63c18d803ddc70 Mon Sep 17 00:00:00 2001 From: Joe Carstairs Date: Sat, 17 Jan 2026 08:34:18 +0000 Subject: BucketTransaction has date field --- schist_core/schist_fakes/src/bucket_transaction.rs | 6 +++++- .../migrations/2024-08-31-084439_initial_setup/up.sql | 1 + schist_core/schist_models/src/bucket_transaction.rs | 3 +++ schist_core/schist_models/src/schema.rs | 1 + schist_core/schist_models/user_data.sqlite | Bin 49152 -> 0 bytes 5 files changed, 10 insertions(+), 1 deletion(-) delete mode 100644 schist_core/schist_models/user_data.sqlite (limited to 'schist_core') diff --git a/schist_core/schist_fakes/src/bucket_transaction.rs b/schist_core/schist_fakes/src/bucket_transaction.rs index 3dd0a6f..aecc057 100644 --- a/schist_core/schist_fakes/src/bucket_transaction.rs +++ b/schist_core/schist_fakes/src/bucket_transaction.rs @@ -1,4 +1,7 @@ -use schist_models::{BucketTransaction, BucketTransactionBuilder}; +use schist_models::{ + bucket_transaction::{BucketTransaction, BucketTransactionBuilder}, + date_utc::DateUtc, +}; pub fn make_fake_bucket_transaction(id: i32) -> BucketTransaction { make_fake_bucket_transaction_builder(id).build().unwrap() @@ -10,6 +13,7 @@ pub fn make_fake_bucket_transaction_builder(id: i32) -> BucketTransactionBuilder .id(id) .description(String::from("Fake bucket transaction")) .amount(0) + .date(DateUtc::from_ymd(1970, 1, 1).unwrap()) .bucket_id(1); builder } diff --git a/schist_core/schist_models/migrations/2024-08-31-084439_initial_setup/up.sql b/schist_core/schist_models/migrations/2024-08-31-084439_initial_setup/up.sql index e645d43..da85b33 100644 --- a/schist_core/schist_models/migrations/2024-08-31-084439_initial_setup/up.sql +++ b/schist_core/schist_models/migrations/2024-08-31-084439_initial_setup/up.sql @@ -36,6 +36,7 @@ CREATE TABLE bucket_transactions( id INTEGER NOT NULL PRIMARY KEY, amount INTEGER NOT NULL, bucket_id INTEGER NOT NULL, + date TEXT NOT NULL, description TEXT NOT NULL, FOREIGN KEY (bucket_id) REFERENCES buckets (id) diff --git a/schist_core/schist_models/src/bucket_transaction.rs b/schist_core/schist_models/src/bucket_transaction.rs index 2aeae8a..a956d0b 100644 --- a/schist_core/schist_models/src/bucket_transaction.rs +++ b/schist_core/schist_models/src/bucket_transaction.rs @@ -1,11 +1,14 @@ use derive_builder::Builder; use diesel::prelude::*; +use crate::date_utc::DateUtc; + #[derive(Builder, Queryable, Identifiable, Selectable, Debug, PartialEq, Insertable)] #[diesel(table_name = crate::schema::bucket_transactions)] pub struct BucketTransaction { pub id: i32, pub amount: i32, pub bucket_id: i32, + pub date: DateUtc, pub description: String, } diff --git a/schist_core/schist_models/src/schema.rs b/schist_core/schist_models/src/schema.rs index 8744696..9579e5c 100644 --- a/schist_core/schist_models/src/schema.rs +++ b/schist_core/schist_models/src/schema.rs @@ -25,6 +25,7 @@ diesel::table! { id -> Integer, amount -> Integer, bucket_id -> Integer, + date -> Text, description -> Text, } } diff --git a/schist_core/schist_models/user_data.sqlite b/schist_core/schist_models/user_data.sqlite deleted file mode 100644 index 81fd25c..0000000 Binary files a/schist_core/schist_models/user_data.sqlite and /dev/null differ -- cgit v1.2.3 From 23de65aef4a7feadaafa0d42c2a801d19f6f31da Mon Sep 17 00:00:00 2001 From: Joe Carstairs Date: Sat, 17 Jan 2026 16:48:30 +0000 Subject: Rename quantity -> amount --- schist_core/schist_queries/src/utils/sum_drips_for_bucket.rs | 2 +- schist_core/schist_queries/tests/bucket_transactions.rs | 2 +- schist_core/schist_queries/tests/pipes.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'schist_core') 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 index 20d05a0..27f6036 100644 --- a/schist_core/schist_queries/src/utils/sum_drips_for_bucket.rs +++ b/schist_core/schist_queries/src/utils/sum_drips_for_bucket.rs @@ -42,7 +42,7 @@ mod test { } #[test] - fn when_one_budget_drip_then_return_quantity() { + fn when_one_budget_drip_then_return_amount() { let bucket = make_fake_bucket(0); let budget_drips = [make_fake_drip_builder(0) .amount(100) diff --git a/schist_core/schist_queries/tests/bucket_transactions.rs b/schist_core/schist_queries/tests/bucket_transactions.rs index 9c877af..0b63458 100644 --- a/schist_core/schist_queries/tests/bucket_transactions.rs +++ b/schist_core/schist_queries/tests/bucket_transactions.rs @@ -122,7 +122,7 @@ fn given_deleted_bucket_transactions_when_get_all_bucket_transactions_then_retur } #[test] -fn given_bucket_transactions_when_sum_quantity_per_bucket_id_then_returns_sum_per_bucket_id() { +fn given_bucket_transactions_when_sum_amount_per_bucket_id_then_returns_sum_per_bucket_id() { let context = TestContext::new(); let connection = &mut SqliteConnection::establish(&context.db_url).unwrap(); let buckets = [make_fake_bucket(0), make_fake_bucket(1)]; diff --git a/schist_core/schist_queries/tests/pipes.rs b/schist_core/schist_queries/tests/pipes.rs index 9203aa3..f883fe6 100644 --- a/schist_core/schist_queries/tests/pipes.rs +++ b/schist_core/schist_queries/tests/pipes.rs @@ -115,7 +115,7 @@ fn given_deleted_pipes_when_get_all_pipes_then_return_empty() { } #[test] -fn given_pipes_when_sum_quantity_per_bucket_id_then_returns_sum_quantity_per_bucket_id() { +fn given_pipes_when_sum_amount_per_bucket_id_then_returns_sum_amount_per_bucket_id() { let context = TestContext::new(); let connection = &mut SqliteConnection::establish(&context.db_url).unwrap(); given_accounts(connection); -- cgit v1.2.3 From 11dbd9b38609fe85c2881bbe3588045f445645e5 Mon Sep 17 00:00:00 2001 From: Joe Carstairs Date: Sat, 17 Jan 2026 16:52:10 +0000 Subject: typo --- schist_core/schist_fakes/src/bucket_transaction.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'schist_core') diff --git a/schist_core/schist_fakes/src/bucket_transaction.rs b/schist_core/schist_fakes/src/bucket_transaction.rs index aecc057..45aa39c 100644 --- a/schist_core/schist_fakes/src/bucket_transaction.rs +++ b/schist_core/schist_fakes/src/bucket_transaction.rs @@ -1,7 +1,4 @@ -use schist_models::{ - bucket_transaction::{BucketTransaction, BucketTransactionBuilder}, - date_utc::DateUtc, -}; +use schist_models::{BucketTransaction, BucketTransactionBuilder, DateUtc}; pub fn make_fake_bucket_transaction(id: i32) -> BucketTransaction { make_fake_bucket_transaction_builder(id).build().unwrap() -- cgit v1.2.3 From ac45871306b7a917b199876598c192320ebc8a4f Mon Sep 17 00:00:00 2001 From: Joe Carstairs Date: Sat, 17 Jan 2026 17:11:14 +0000 Subject: remove queries/categories --- schist_core/schist_queries/tests/categories.rs | 83 -------------------------- 1 file changed, 83 deletions(-) delete mode 100644 schist_core/schist_queries/tests/categories.rs (limited to 'schist_core') diff --git a/schist_core/schist_queries/tests/categories.rs b/schist_core/schist_queries/tests/categories.rs deleted file mode 100644 index 72dd4c7..0000000 --- a/schist_core/schist_queries/tests/categories.rs +++ /dev/null @@ -1,83 +0,0 @@ -mod common; - -use common::test_context::TestContext; -use diesel::{Connection, SqliteConnection}; -use schist_fakes::bucket::make_fake_bucket; -use schist_models::Bucket; -use schist_queries as queries; - -fn given_buckets(connection: &mut SqliteConnection) -> Vec { - let buckets = vec![make_fake_bucket(0), make_fake_bucket(1)]; - let _ = queries::buckets::insert_buckets(&buckets, connection).unwrap(); - buckets -} - -#[test] -fn when_insert_buckets_then_returns_num_buckets() { - let context = TestContext::new(); - let connection = &mut SqliteConnection::establish(&context.db_url).unwrap(); - let buckets = [make_fake_bucket(0), make_fake_bucket(1)]; - - let num_buckets_inserted = queries::buckets::insert_buckets(&buckets, connection).unwrap(); - - assert_eq!(num_buckets_inserted, 2); -} - -#[test] -fn given_buckets_when_get_all_buckets_then_return_buckets() { - let context = TestContext::new(); - let connection = &mut SqliteConnection::establish(&context.db_url).unwrap(); - let buckets = given_buckets(connection); - - let buckets_in_db = queries::buckets::get_all_buckets(connection).unwrap(); - - assert_eq!(buckets_in_db.len(), buckets.len()); - for bucket in &buckets { - assert!(buckets_in_db - .iter() - .any(|bucket_in_db| bucket_in_db.eq(&bucket))); - } - for bucket_in_db in buckets_in_db { - assert!(buckets.iter().any(|bucket| bucket.eq(&bucket_in_db))); - } -} - -#[test] -fn given_buckets_when_delete_all_buckets_then_return_num_of_buckets() { - let context = TestContext::new(); - let connection = &mut SqliteConnection::establish(&context.db_url).unwrap(); - let buckets = given_buckets(connection); - - let num_buckets_deleted = queries::buckets::delete_all_buckets(connection).unwrap(); - - assert_eq!(num_buckets_deleted, buckets.len()); -} - -#[test] -fn given_deleted_buckets_when_get_all_buckets_then_return_empty() { - let context = TestContext::new(); - let connection = &mut SqliteConnection::establish(&context.db_url).unwrap(); - given_buckets(connection); - let _ = queries::buckets::delete_all_buckets(connection).unwrap(); - - let buckets_returned = queries::buckets::get_all_buckets(connection).unwrap(); - - assert_eq!(buckets_returned.len(), 0); -} - -#[test] -fn given_buckets_when_get_all_ids_then_return_all_ids() { - let context = TestContext::new(); - let connection = &mut SqliteConnection::establish(&context.db_url).unwrap(); - let buckets = given_buckets(connection); - - let ids = queries::buckets::get_all_bucket_ids(connection).unwrap(); - - assert_eq!(buckets.len(), ids.len()); - for bucket in &buckets { - assert!(ids.iter().any(|id| bucket.id == *id)); - } - for id in ids { - assert!(buckets.iter().any(|bucket| bucket.id == id)); - } -} -- cgit v1.2.3