feat: update services to include transaction handling and refactor database connection setup
This commit is contained in:
29
Cargo.lock
generated
29
Cargo.lock
generated
@@ -1166,20 +1166,6 @@ dependencies = [
|
|||||||
"windows-sys 0.61.2",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "decimal"
|
|
||||||
version = "2.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5a8ab77e91baeb15034c3be91e87bff4665c9036216148e4996d9a9f5792114d"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags 1.3.2",
|
|
||||||
"cc",
|
|
||||||
"libc",
|
|
||||||
"ord_subset",
|
|
||||||
"rustc-serialize",
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "der"
|
name = "der"
|
||||||
version = "0.7.10"
|
version = "0.7.10"
|
||||||
@@ -3270,12 +3256,6 @@ version = "0.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ord_subset"
|
|
||||||
version = "3.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fdcf5505c0f054ce51fa0fa74142738930a45d5ac1faacae4dd4e2f54afe00fa"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ordered-float"
|
name = "ordered-float"
|
||||||
version = "4.6.0"
|
version = "4.6.0"
|
||||||
@@ -3301,14 +3281,15 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"chrono",
|
"chrono",
|
||||||
"decimal",
|
|
||||||
"migration",
|
"migration",
|
||||||
|
"rust_decimal",
|
||||||
"sea-orm",
|
"sea-orm",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"tauri",
|
"tauri",
|
||||||
"tauri-build",
|
"tauri-build",
|
||||||
"tauri-plugin-opener",
|
"tauri-plugin-opener",
|
||||||
|
"thiserror 2.0.18",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4007,12 +3988,6 @@ version = "2.1.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe"
|
checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustc-serialize"
|
|
||||||
version = "0.3.25"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fe834bc780604f4674073badbad26d7219cadfb4a2275802db12cbae17498401"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc_version"
|
name = "rustc_version"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ name = "otter"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
description = "A Tauri App"
|
description = "A Tauri App"
|
||||||
authors = ["you"]
|
authors = ["you"]
|
||||||
edition = "2021"
|
edition = "2024"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
@@ -23,9 +23,10 @@ tauri-plugin-opener = "2"
|
|||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
async-trait = "0.1.89"
|
async-trait = "0.1.89"
|
||||||
decimal = "2.1.0"
|
rust_decimal = "1.42.0"
|
||||||
|
|
||||||
sea-orm.workspace = true
|
sea-orm.workspace = true
|
||||||
migration = { path = "../crates/migration" }
|
migration = { path = "../crates/migration" }
|
||||||
chrono.workspace = true
|
chrono.workspace = true
|
||||||
|
thiserror = "2.0.18"
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ use tauri::Manager;
|
|||||||
|
|
||||||
use crate::services::create_services;
|
use crate::services::create_services;
|
||||||
|
|
||||||
|
mod commands;
|
||||||
mod db;
|
mod db;
|
||||||
mod services;
|
mod services;
|
||||||
|
|
||||||
@@ -27,8 +28,31 @@ pub fn run() {
|
|||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
.setup(|app| {
|
.setup(|app| {
|
||||||
tauri::async_runtime::block_on(async {
|
tauri::async_runtime::block_on(async {
|
||||||
let mut connect_options =
|
// Get the app's data directory
|
||||||
ConnectOptions::new("sqlite://finance_manager.db".to_string());
|
let app_data_dir = app
|
||||||
|
.path()
|
||||||
|
.app_data_dir()
|
||||||
|
.expect("Failed to get app data directory");
|
||||||
|
|
||||||
|
// Create the directory if it doesn't exist
|
||||||
|
std::fs::create_dir_all(&app_data_dir)
|
||||||
|
.expect("Failed to create app data directory");
|
||||||
|
|
||||||
|
// Construct the database path
|
||||||
|
let db_path = app_data_dir.join("finance_manager.db");
|
||||||
|
|
||||||
|
// Ensure the database file exists
|
||||||
|
if !db_path.exists() {
|
||||||
|
std::fs::File::create(&db_path).expect("Failed to create database file");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the canonical path
|
||||||
|
let canonical_path = db_path
|
||||||
|
.canonicalize()
|
||||||
|
.expect("Failed to get canonical path");
|
||||||
|
let db_url = format!("sqlite://{}", canonical_path.to_string_lossy());
|
||||||
|
|
||||||
|
let mut connect_options = ConnectOptions::new(db_url);
|
||||||
connect_options.after_connect(|conn| {
|
connect_options.after_connect(|conn| {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
// Enable foreign key support for SQLite
|
// Enable foreign key support for SQLite
|
||||||
@@ -50,12 +74,22 @@ pub fn run() {
|
|||||||
migration::Migrator::up(&db, None)
|
migration::Migrator::up(&db, None)
|
||||||
.await
|
.await
|
||||||
.expect("Failed to run migrations");
|
.expect("Failed to run migrations");
|
||||||
app.manage(create_services(db))
|
|
||||||
|
let services = create_services(db);
|
||||||
|
app.manage(services)
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.plugin(tauri_plugin_opener::init())
|
.plugin(tauri_plugin_opener::init())
|
||||||
.invoke_handler(tauri::generate_handler![greet])
|
.invoke_handler(tauri::generate_handler![
|
||||||
|
greet,
|
||||||
|
commands::get_account,
|
||||||
|
commands::get_accounts,
|
||||||
|
commands::create_account,
|
||||||
|
commands::get_transactions_for_account,
|
||||||
|
commands::create_transaction,
|
||||||
|
commands::update_transaction
|
||||||
|
])
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
.expect("error while running tauri application");
|
.expect("error while running tauri application");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,22 +2,65 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use sea_orm::DatabaseConnection;
|
use sea_orm::DatabaseConnection;
|
||||||
|
|
||||||
pub mod accounts;
|
use crate::services::{
|
||||||
|
accounts::{
|
||||||
|
AccountsService, AccountsServiceImpl,
|
||||||
|
category::{AccountCategoryService, AccountCategoryServiceImpl},
|
||||||
|
},
|
||||||
|
transaction::{
|
||||||
|
TransactionService, TransactionServiceImpl,
|
||||||
|
category::{CategoryService, CategoryServiceImpl},
|
||||||
|
tag::{TagService, TagServiceImpl},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
pub struct Services {
|
pub mod accounts;
|
||||||
pub account_category: Arc<dyn accounts::category::AccountCategoryService>,
|
pub mod transaction;
|
||||||
pub accounts: Arc<dyn accounts::AccountsService>,
|
|
||||||
|
pub type AppState = Services<
|
||||||
|
dyn AccountCategoryService,
|
||||||
|
dyn AccountsService,
|
||||||
|
dyn TransactionService,
|
||||||
|
dyn CategoryService,
|
||||||
|
dyn TagService,
|
||||||
|
>;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Services<AC, A, T, TC, TT>
|
||||||
|
where
|
||||||
|
AC: AccountCategoryService + ?Sized,
|
||||||
|
A: AccountsService + ?Sized,
|
||||||
|
T: TransactionService + ?Sized,
|
||||||
|
TC: CategoryService + ?Sized,
|
||||||
|
TT: TagService + ?Sized,
|
||||||
|
{
|
||||||
|
pub account_category: Arc<AC>,
|
||||||
|
pub accounts: Arc<A>,
|
||||||
|
pub transaction: Arc<T>,
|
||||||
|
pub transaction_category: Arc<TC>,
|
||||||
|
pub transaction_tag: Arc<TT>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_services(db: DatabaseConnection) -> Services {
|
pub fn create_services(db: DatabaseConnection) -> AppState {
|
||||||
let account_category_service = Arc::new(accounts::category::AccountCategoryServiceImpl::new(
|
let account_category_service: Arc<dyn AccountCategoryService> =
|
||||||
|
Arc::new(AccountCategoryServiceImpl::new(db.clone()));
|
||||||
|
let account_service: Arc<dyn AccountsService> = Arc::new(AccountsServiceImpl::new(
|
||||||
db.clone(),
|
db.clone(),
|
||||||
|
Arc::new(AccountCategoryServiceImpl::new(db.clone())),
|
||||||
));
|
));
|
||||||
|
let transaction_category_service: Arc<dyn CategoryService> =
|
||||||
|
Arc::new(CategoryServiceImpl::new(db.clone()));
|
||||||
|
let transaction_tag_service: Arc<dyn TagService> = Arc::new(TagServiceImpl::new(db.clone()));
|
||||||
Services {
|
Services {
|
||||||
account_category: account_category_service.clone(),
|
account_category: account_category_service.clone(),
|
||||||
accounts: Arc::new(accounts::AccountsServiceImpl::new(
|
accounts: account_service.clone(),
|
||||||
db,
|
transaction: Arc::new(TransactionServiceImpl::new(
|
||||||
account_category_service,
|
db.clone(),
|
||||||
)),
|
account_service.clone(),
|
||||||
|
transaction_category_service.clone(),
|
||||||
|
transaction_tag_service.clone(),
|
||||||
|
)) as Arc<dyn TransactionService>,
|
||||||
|
transaction_category: transaction_category_service,
|
||||||
|
transaction_tag: transaction_tag_service,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user