From 0421c75354c4e72340ec07bcf59cf43898b0292c Mon Sep 17 00:00:00 2001 From: Nicolas Auler Date: Wed, 11 Dec 2024 22:54:16 -0300 Subject: [PATCH] feat: added new categories to transactions --- ...0521ff2b3865b28c063ff317e6d6caf82d005.json | 16 +++++-- ...35bf41fbd392c26633d012b741340df6d8cd7.json | 32 +++++++++---- ...712cf71c6ce960427b3f074fef315255be7f8.json | 16 +++++-- ...ddcb23f779e6be43c91114cd9d033336b2f1.json} | 20 +++++--- ...b997e8e55d73db7af45519acc176364feb4d4.json | 16 +++++-- .../20241212002523_more-categories.down.sql | 20 ++++++++ .../20241212002523_more-categories.up.sql | 26 ++++++++++ src/features/expenses.rs | 11 +++-- src/queries/expenses.rs | 3 +- src/schema.rs | 48 +++++++++++++------ 10 files changed, 156 insertions(+), 52 deletions(-) rename .sqlx/{query-5ef6dfd2c4975355144c235f0aa909fd5b01316daddb314d4e00dca3e11f044a.json => query-9dd2025bdc87c1f068851d68188fddcb23f779e6be43c91114cd9d033336b2f1.json} (78%) create mode 100644 migrations/20241212002523_more-categories.down.sql create mode 100644 migrations/20241212002523_more-categories.up.sql diff --git a/.sqlx/query-0f97cfc9d9961904daa00581e9f0521ff2b3865b28c063ff317e6d6caf82d005.json b/.sqlx/query-0f97cfc9d9961904daa00581e9f0521ff2b3865b28c063ff317e6d6caf82d005.json index 20b30d7..1d86b62 100644 --- a/.sqlx/query-0f97cfc9d9961904daa00581e9f0521ff2b3865b28c063ff317e6d6caf82d005.json +++ b/.sqlx/query-0f97cfc9d9961904daa00581e9f0521ff2b3865b28c063ff317e6d6caf82d005.json @@ -12,12 +12,18 @@ "name": "expense_category", "kind": { "Enum": [ - "food", - "transport", - "health", - "education", + "restaurants", + "shopping", + "services", "entertainment", - "other" + "groceries", + "salary", + "interest Income", + "utilities", + "pharmacy", + "transfer", + "transport", + "others" ] } } diff --git a/.sqlx/query-4c00c0c5726aed16c1fe61772b735bf41fbd392c26633d012b741340df6d8cd7.json b/.sqlx/query-4c00c0c5726aed16c1fe61772b735bf41fbd392c26633d012b741340df6d8cd7.json index 6f05585..9edf373 100644 --- a/.sqlx/query-4c00c0c5726aed16c1fe61772b735bf41fbd392c26633d012b741340df6d8cd7.json +++ b/.sqlx/query-4c00c0c5726aed16c1fe61772b735bf41fbd392c26633d012b741340df6d8cd7.json @@ -26,12 +26,18 @@ "name": "expense_category", "kind": { "Enum": [ - "food", - "transport", - "health", - "education", + "restaurants", + "shopping", + "services", "entertainment", - "other" + "groceries", + "salary", + "interest Income", + "utilities", + "pharmacy", + "transfer", + "transport", + "others" ] } } @@ -62,12 +68,18 @@ "name": "expense_category", "kind": { "Enum": [ - "food", - "transport", - "health", - "education", + "restaurants", + "shopping", + "services", "entertainment", - "other" + "groceries", + "salary", + "interest Income", + "utilities", + "pharmacy", + "transfer", + "transport", + "others" ] } } diff --git a/.sqlx/query-5cc722f72ce0a07b1f67b3cdc78712cf71c6ce960427b3f074fef315255be7f8.json b/.sqlx/query-5cc722f72ce0a07b1f67b3cdc78712cf71c6ce960427b3f074fef315255be7f8.json index 9ca2a79..c3d55ef 100644 --- a/.sqlx/query-5cc722f72ce0a07b1f67b3cdc78712cf71c6ce960427b3f074fef315255be7f8.json +++ b/.sqlx/query-5cc722f72ce0a07b1f67b3cdc78712cf71c6ce960427b3f074fef315255be7f8.json @@ -12,12 +12,18 @@ "name": "expense_category", "kind": { "Enum": [ - "food", - "transport", - "health", - "education", + "restaurants", + "shopping", + "services", "entertainment", - "other" + "groceries", + "salary", + "interest Income", + "utilities", + "pharmacy", + "transfer", + "transport", + "others" ] } } diff --git a/.sqlx/query-5ef6dfd2c4975355144c235f0aa909fd5b01316daddb314d4e00dca3e11f044a.json b/.sqlx/query-9dd2025bdc87c1f068851d68188fddcb23f779e6be43c91114cd9d033336b2f1.json similarity index 78% rename from .sqlx/query-5ef6dfd2c4975355144c235f0aa909fd5b01316daddb314d4e00dca3e11f044a.json rename to .sqlx/query-9dd2025bdc87c1f068851d68188fddcb23f779e6be43c91114cd9d033336b2f1.json index a657fb7..bfbf5a4 100644 --- a/.sqlx/query-5ef6dfd2c4975355144c235f0aa909fd5b01316daddb314d4e00dca3e11f044a.json +++ b/.sqlx/query-9dd2025bdc87c1f068851d68188fddcb23f779e6be43c91114cd9d033336b2f1.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "SELECT id, description, price, category as \"category: ExpenseCategory\", is_essential, date, uuid\n FROM expenses\n WHERE ((date >= $1) OR ($1 IS NULL))\n AND ((date <= $2) OR ($2 IS NULL))\n AND user_id = $3\n and deleted_at is null\n ORDER BY date ASC", + "query": "SELECT id, description, price, category as \"category: ExpenseCategory\", is_essential, date, uuid\n FROM expenses\n WHERE ((date >= $1) OR ($1 IS NULL))\n AND ((date <= $2) OR ($2 IS NULL))\n AND user_id = $3\n and deleted_at is null", "describe": { "columns": [ { @@ -26,12 +26,18 @@ "name": "expense_category", "kind": { "Enum": [ - "food", - "transport", - "health", - "education", + "restaurants", + "shopping", + "services", "entertainment", - "other" + "groceries", + "salary", + "interest Income", + "utilities", + "pharmacy", + "transfer", + "transport", + "others" ] } } @@ -70,5 +76,5 @@ false ] }, - "hash": "5ef6dfd2c4975355144c235f0aa909fd5b01316daddb314d4e00dca3e11f044a" + "hash": "9dd2025bdc87c1f068851d68188fddcb23f779e6be43c91114cd9d033336b2f1" } diff --git a/.sqlx/query-ac8c51d1316f7120d56b03c8881b997e8e55d73db7af45519acc176364feb4d4.json b/.sqlx/query-ac8c51d1316f7120d56b03c8881b997e8e55d73db7af45519acc176364feb4d4.json index fa1baae..ac1b924 100644 --- a/.sqlx/query-ac8c51d1316f7120d56b03c8881b997e8e55d73db7af45519acc176364feb4d4.json +++ b/.sqlx/query-ac8c51d1316f7120d56b03c8881b997e8e55d73db7af45519acc176364feb4d4.json @@ -26,12 +26,18 @@ "name": "expense_category", "kind": { "Enum": [ - "food", - "transport", - "health", - "education", + "restaurants", + "shopping", + "services", "entertainment", - "other" + "groceries", + "salary", + "interest Income", + "utilities", + "pharmacy", + "transfer", + "transport", + "others" ] } } diff --git a/migrations/20241212002523_more-categories.down.sql b/migrations/20241212002523_more-categories.down.sql new file mode 100644 index 0000000..7a78e2e --- /dev/null +++ b/migrations/20241212002523_more-categories.down.sql @@ -0,0 +1,20 @@ +BEGIN; + +ALTER TYPE expense_category RENAME TO expense_category_old; + +CREATE TYPE expense_category AS ENUM ( + 'food', + 'transport', + 'health', + 'education', + 'entertainment', + 'other' +); + +ALTER TABLE expenses + ALTER COLUMN category TYPE expense_category + USING category::text::expense_category; + +DROP TYPE expense_category_old; + +COMMIT; diff --git a/migrations/20241212002523_more-categories.up.sql b/migrations/20241212002523_more-categories.up.sql new file mode 100644 index 0000000..de51b07 --- /dev/null +++ b/migrations/20241212002523_more-categories.up.sql @@ -0,0 +1,26 @@ +BEGIN; + +ALTER TYPE expense_category RENAME TO expense_category_old; + +CREATE TYPE expense_category AS ENUM ( + 'restaurants', + 'shopping', + 'services', + 'entertainment', + 'groceries', + 'salary', + 'interest Income', + 'utilities', + 'pharmacy', + 'transfer', + 'transport', + 'others' +); + +ALTER TABLE expenses + ALTER COLUMN category TYPE expense_category + USING category::text::expense_category; + +DROP TYPE expense_category_old; + +COMMIT; diff --git a/src/features/expenses.rs b/src/features/expenses.rs index 93b7853..2513e38 100644 --- a/src/features/expenses.rs +++ b/src/features/expenses.rs @@ -1,6 +1,6 @@ use plotly::{Layout, Plot, Scatter}; use sqlx::PgPool; -use std::collections::BTreeMap; +use std::{cmp::Reverse, collections::BTreeMap}; use time::{Date, OffsetDateTime}; use uuid::Uuid; @@ -35,7 +35,12 @@ pub async fn list_in_period( from: Option, to: Option, ) -> Result, sqlx::Error> { - crate::queries::expenses::list_for_user_in_period(&db_pool, user_id, from, to).await + let mut expenses = + crate::queries::expenses::list_for_user_in_period(&db_pool, user_id, from, to).await?; + + expenses.sort_unstable_by_key(|e| Reverse(e.date)); + + Ok(expenses) } pub async fn find_active_for_user( @@ -199,7 +204,7 @@ mod tests { let create_expense = crate::schema::CreateExpense { description: "test_expense".to_owned(), price: 6.9, - category: crate::schema::ExpenseCategory::Food, + category: crate::schema::ExpenseCategory::Restaurants, is_essential: Some(false), date: now.date(), }; diff --git a/src/queries/expenses.rs b/src/queries/expenses.rs index 6a65df3..6f98e8f 100644 --- a/src/queries/expenses.rs +++ b/src/queries/expenses.rs @@ -62,8 +62,7 @@ pub async fn list_for_user_in_period( WHERE ((date >= $1) OR ($1 IS NULL)) AND ((date <= $2) OR ($2 IS NULL)) AND user_id = $3 - and deleted_at is null - ORDER BY date ASC"#, + and deleted_at is null"#, from, to, user_id diff --git a/src/schema.rs b/src/schema.rs index a3adfb4..7dbf115 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -11,13 +11,19 @@ use time::{macros::format_description, Date}; #[sqlx(type_name = "expense_category", rename_all = "lowercase")] /// `ExpenseCategory` is an enum with the types of expenses. pub enum ExpenseCategory { - Food, - Transport, - Health, - Education, + Restaurants, + Shopping, + Services, Entertainment, + Groceries, + Salary, + InterestIncome, + Utilities, + Pharmacy, + Transfer, + Transport, #[default] - Other, + Others, } impl FromStr for ExpenseCategory { @@ -25,12 +31,18 @@ impl FromStr for ExpenseCategory { fn from_str(str: &str) -> Result { match str { - "Food" => return Ok(Self::Food), - "Transport" => return Ok(Self::Transport), - "Health" => return Ok(Self::Health), - "Education" => return Ok(Self::Education), + "Restaurants" => return Ok(Self::Restaurants), + "Shopping" => return Ok(Self::Shopping), + "Services" => return Ok(Self::Services), "Entertainment" => return Ok(Self::Entertainment), - "Other" => return Ok(Self::Other), + "Groceries" => return Ok(Self::Groceries), + "Salary" => return Ok(Self::Salary), + "InterestIncome" => return Ok(Self::InterestIncome), + "Utilities" => return Ok(Self::Utilities), + "Pharmacy" => return Ok(Self::Pharmacy), + "Transfer" => return Ok(Self::Transfer), + "Transport" => return Ok(Self::Transport), + "Others" => return Ok(Self::Others), _ => return Err(format!("{str} is not a valid expense type")), } } @@ -39,12 +51,18 @@ impl FromStr for ExpenseCategory { impl Display for ExpenseCategory { fn fmt(&self, fmtr: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { - Self::Food => return write!(fmtr, "Food"), - Self::Transport => return write!(fmtr, "Transport"), - Self::Health => return write!(fmtr, "Health"), - Self::Education => return write!(fmtr, "Education"), + Self::Restaurants => return write!(fmtr, "Restaurants"), + Self::Shopping => return write!(fmtr, "Shopping"), + Self::Services => return write!(fmtr, "Services"), Self::Entertainment => return write!(fmtr, "Entertainment"), - Self::Other => return write!(fmtr, "Other"), + Self::Groceries => return write!(fmtr, "Groceries"), + Self::Salary => return write!(fmtr, "Salary"), + Self::InterestIncome => return write!(fmtr, "InterestIncome"), + Self::Utilities => return write!(fmtr, "Utilities"), + Self::Pharmacy => return write!(fmtr, "Pharmacy"), + Self::Transfer => return write!(fmtr, "Transfer"), + Self::Transport => return write!(fmtr, "Transport"), + Self::Others => return write!(fmtr, "Others"), } } }