feat(transactions): add input and output types for transaction management

- Introduced `CreateTransactionInput`, `BulkCreateTransactionInput`, `UpdateTransactionInput`, and `TransactionFilter` structs for handling transaction creation and updates.
- Added `BulkDeleteInput` and `BulkDeleteResult` structs for bulk deletion of transactions.
- Created `TransactionStatistics` struct to encapsulate transaction statistics data.
- Established a new module for transaction types in `mod.rs`.
- Implemented `TransactionWithTags` struct in outputs for returning transactions with associated tags.
- Updated `AppState` to include a transaction service, ensuring it is initialized and accessible.
This commit is contained in:
2026-02-25 10:57:48 +00:00
parent 30eb0b71cc
commit bfbb771cbf
8 changed files with 1652 additions and 0 deletions

View File

@@ -74,6 +74,14 @@ pub fn run() {
commands::accounts::delete_account,
commands::accounts::get_account_balance,
commands::accounts::recalculate_account_balance,
// Transaction commands
commands::transactions::create_transaction,
commands::transactions::get_transactions,
commands::transactions::get_transaction,
commands::transactions::update_transaction,
commands::transactions::delete_transaction,
commands::transactions::get_transactions_needing_review,
commands::transactions::confirm_transaction,
// Exchange rate commands
commands::exchange_rate::get_exchange_rate,
commands::exchange_rate::get_supported_currencies,

View File

@@ -8,6 +8,7 @@ pub mod accounts;
pub mod balance_calculator;
pub mod exchange_rate;
pub mod settings;
pub mod transactions;
#[async_trait::async_trait]
pub trait ServiceTrait: Send + Sync {
@@ -21,6 +22,7 @@ pub struct ServiceFactory;
pub struct ServiceFactoryResult {
pub account_service: Arc<dyn accounts::service::AccountService>,
pub transaction_service: Arc<dyn transactions::service::TransactionService>,
pub settings_service: Arc<dyn settings::service::SettingsService>,
pub exchange_rate_service: Arc<dyn exchange_rate::service::ExchangeRateService>,
}
@@ -28,6 +30,7 @@ pub struct ServiceFactoryResult {
impl ServiceFactory {
pub async fn create_services(db: DatabaseConnection) -> ServiceFactoryResult {
let account_service = Arc::new(accounts::service::AccountServiceImpl::new(db.clone()));
let transaction_service = Arc::new(transactions::service::TransactionServiceImpl::new(db.clone()));
let settings_service = Arc::new(settings::service::SettingsServiceImpl::new(db.clone()));
let exchange_rate_service = Arc::new(
exchange_rate::service::ExchangeRateServiceImpl::new(
@@ -38,6 +41,7 @@ impl ServiceFactory {
);
ServiceFactoryResult {
account_service,
transaction_service,
exchange_rate_service,
settings_service,
}

View File

@@ -0,0 +1,2 @@
pub mod service;
pub mod types;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,80 @@
use serde::Deserialize;
use crate::services::balance_calculator::service::TransactionType;
#[derive(Debug, Deserialize)]
pub struct CreateTransactionInput {
pub account_id: String,
pub transaction_type: TransactionType,
pub gross_amount: String,
pub tax_amount: Option<String>,
pub net_amount: String,
pub currency: String,
pub description: String,
pub merchant: Option<String>,
pub notes: Option<String>,
pub receipt_paths: Option<Vec<String>>,
pub transaction_date: String,
pub tag_ids: Vec<String>,
}
#[derive(Debug, Deserialize)]
pub struct BulkCreateTransactionInput {
pub transactions: Vec<CreateTransactionInput>,
}
#[derive(Debug, Deserialize, Default)]
pub struct UpdateTransactionInput {
pub gross_amount: Option<String>,
pub tax_amount: Option<String>,
pub net_amount: Option<String>,
pub description: Option<String>,
pub merchant: Option<String>,
pub notes: Option<String>,
pub transaction_date: Option<String>,
pub receipt_paths: Option<Vec<String>>,
pub tag_ids: Option<Vec<String>>,
}
#[derive(Debug, Deserialize, Default)]
pub struct TransactionFilter {
pub account_id: Option<String>,
pub transaction_type: Option<TransactionType>,
pub start_date: Option<String>,
pub end_date: Option<String>,
pub needs_review: Option<bool>,
pub is_auto_inserted: Option<bool>,
pub search_query: Option<String>,
pub sort_by: Option<String>,
pub sort_order: Option<String>,
pub limit: Option<u64>,
pub offset: Option<u64>,
/// Filter by tag IDs (optional)
pub tag_ids: Option<Vec<String>>,
/// If true, transaction must have ALL specified tags. If false, ANY tag matches.
pub match_all_tags: Option<bool>,
}
#[derive(Debug, Deserialize)]
pub struct BulkDeleteInput {
pub ids: Vec<String>,
}
#[derive(Debug)]
pub struct BulkDeleteResult {
pub deleted_count: usize,
pub failed_ids: Vec<String>,
}
#[derive(Debug, serde::Serialize)]
pub struct TransactionStatistics {
pub total_income: String,
pub total_expense: String,
pub total_transfer_in: String,
pub total_transfer_out: String,
pub net_flow: String,
pub count_income: i64,
pub count_expense: i64,
pub count_transfer: i64,
pub total_count: i64,
}

View File

@@ -0,0 +1,2 @@
pub mod inputs;
pub mod outputs;

View File

@@ -0,0 +1,15 @@
use serde::Serialize;
use crate::db::entities::transactions;
#[derive(Debug, Serialize)]
pub struct TransactionWithTags {
pub transaction: transactions::Model,
pub tags: Vec<String>,
}
#[derive(Debug, Serialize)]
pub struct BulkDeleteResult {
pub deleted_count: usize,
pub failed_ids: Vec<String>,
}

View File

@@ -5,11 +5,13 @@ use crate::{
services::{
ServiceFactoryResult, ServiceTrait, accounts::service::AccountService,
exchange_rate::service::ExchangeRateService, settings::service::SettingsService,
transactions::service::TransactionService,
},
};
pub struct AppState {
db: DbService,
account_service: Arc<dyn AccountService>,
transaction_service: Arc<dyn TransactionService>,
settings_service: Arc<dyn SettingsService>,
exchange_rate_service: Arc<dyn ExchangeRateService>,
}
@@ -20,6 +22,7 @@ impl AppState {
Self {
db,
account_service: services.account_service,
transaction_service: services.transaction_service,
settings_service: services.settings_service,
exchange_rate_service: services.exchange_rate_service,
}
@@ -34,6 +37,11 @@ impl AppState {
&self.account_service
}
/// Get the transaction service
pub fn transaction_service(&self) -> &Arc<dyn TransactionService> {
&self.transaction_service
}
/// Get the settings service
pub fn settings_service(&self) -> &Arc<dyn SettingsService> {
&self.settings_service
@@ -49,6 +57,7 @@ impl AppState {
self.settings_service.on_app_start().await?;
self.exchange_rate_service.on_app_start().await?;
self.account_service.on_app_start().await?;
self.transaction_service.on_app_start().await?;
Ok(())
}
}