diff --git a/src-tauri/src/services/accounts/category.rs b/src-tauri/src/services/accounts/category.rs index 3411aad..18bb544 100644 --- a/src-tauri/src/services/accounts/category.rs +++ b/src-tauri/src/services/accounts/category.rs @@ -1,13 +1,16 @@ +// TODO: validation for all dto use crate::db::{ + Db, entities::account_category::{ ActiveModel as AccountCategoryActiveModel, Entity as AccountCategoryEntity, }, - Db, }; +use migration::OnConflict; use sea_orm::{ - ActiveModelTrait, ActiveValue::Set, ColumnTrait, ConnectionTrait, DatabaseConnection, - DatabaseTransaction, EntityTrait, IntoActiveModel, ModelTrait, PaginatorTrait, QueryFilter, + ActiveModelTrait, ActiveValue::Set, ColumnTrait, DatabaseConnection, EntityTrait, + IntoActiveModel, ModelTrait, PaginatorTrait, QueryFilter, }; +use serde::{Deserialize, Serialize}; pub struct AccountCategory { pub id: i64, @@ -18,17 +21,23 @@ pub struct AccountCategory { pub updated_at: String, } +#[derive(Debug, Clone, Serialize, Deserialize)] pub enum AccountType { - Asset, // Positive balance, e.g. Checking, Savings + #[serde(rename = "Asset")] + Asset, // Positive balance, e.g. Checking, Savings + #[serde(rename = "Liability")] Liability, // Negative balance, e.g. Credit Card - Unknown, // Fallback for unknown types + #[serde(other, rename = "Unknown")] + Unknown, // Fallback for unknown types } +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct CreateAccountCategoryRequest { pub name: String, pub account_type: AccountType, } +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct UpdateAccountCategoryRequest { pub name: Option, pub account_type: Option, @@ -129,9 +138,20 @@ impl AccountCategoryService for AccountCategoryServiceImpl { let new_category = AccountCategoryActiveModel { name: Set(create_request.name), account_type: Set(create_request.account_type.to_string()), + created_at: Set(chrono::Utc::now().to_rfc3339()), + updated_at: Set(chrono::Utc::now().to_rfc3339()), ..Default::default() }; - let res = new_category.insert(tx).await.map_err(|e| e.to_string())?; + let res = AccountCategoryEntity::insert(new_category) + .on_conflict( + // force update to ensure a record is returned + OnConflict::column(crate::db::entities::account_category::Column::Name) + .update_column(crate::db::entities::account_category::Column::Name) + .to_owned(), + ) + .exec_with_returning(tx) + .await + .map_err(|e| e.to_string())?; Ok(res.id) } @@ -187,6 +207,7 @@ impl AccountCategoryService for AccountCategoryServiceImpl { if let Some(account_type) = update_request.account_type { category.account_type = Set(account_type.to_string()); } + category.updated_at = Set(chrono::Utc::now().to_rfc3339()); category.update(tx).await.map_err(|e| e.to_string())?; Ok(()) } else { diff --git a/src-tauri/src/services/accounts/mod.rs b/src-tauri/src/services/accounts/mod.rs index ac102e5..15cb159 100644 --- a/src-tauri/src/services/accounts/mod.rs +++ b/src-tauri/src/services/accounts/mod.rs @@ -1,3 +1,4 @@ +// TODO: validation for all dto use std::sync::Arc; use crate::{ @@ -17,9 +18,11 @@ use crate::{ use sea_orm::{ ActiveModelTrait, ActiveValue::Set, DatabaseConnection, EntityTrait, TransactionTrait, }; +use serde::{Deserialize, Serialize}; pub mod category; +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct Account { pub id: i64, pub name: String, @@ -43,11 +46,13 @@ impl From<(AccountModel, AccountCategoryModel)> for Account { } } +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct CreateAccountRequest { pub name: String, pub category: CreateAccountCategoryRequest, } +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct UpdateAccountRequest { pub name: Option, pub category: Option, @@ -125,8 +130,8 @@ impl AccountsService for AccountsServiceImpl { let new_account = AccountEntity::insert(AccountActiveModel { name: Set(create_request.name), - created_at: Set(chrono::Utc::now().to_string()), - updated_at: Set(chrono::Utc::now().to_string()), + created_at: Set(chrono::Utc::now().to_rfc3339()), + updated_at: Set(chrono::Utc::now().to_rfc3339()), account_category_id: Set(category_id), ..Default::default() }) @@ -162,7 +167,7 @@ impl AccountsService for AccountsServiceImpl { .update_category_with_tx(id, category_request, &(&tx).into()) .await?; } - active_model.updated_at = Set(chrono::Utc::now().to_string()); + active_model.updated_at = Set(chrono::Utc::now().to_rfc3339()); // active_model.update(&tx).await.map_err(|e| e.to_string())?; let res = tx.commit().await.map_err(|e| e.to_string());