diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs
index e120918..4c57e3e 100644
--- a/src-tauri/src/lib.rs
+++ b/src-tauri/src/lib.rs
@@ -1,17 +1,17 @@
/*
DrCr: Web-based double-entry bookkeeping framework
- Copyright (C) 2022–2024 Lee Yingtong Li (RunasSudo)
-
+ Copyright (C) 2022-2025 Lee Yingtong Li (RunasSudo)
+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
-
+
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
@@ -33,20 +33,26 @@ struct AppState {
// Filename state
#[tauri::command]
-async fn get_open_filename(state: State<'_, Mutex>) -> Result, tauri_plugin_sql::Error> {
+async fn get_open_filename(
+ state: State<'_, Mutex>,
+) -> Result, tauri_plugin_sql::Error> {
let state = state.lock().await;
Ok(state.db_filename.clone())
}
#[tauri::command]
-async fn set_open_filename(state: State<'_, Mutex>, app: AppHandle, filename: Option) -> Result<(), tauri_plugin_sql::Error> {
+async fn set_open_filename(
+ state: State<'_, Mutex>,
+ app: AppHandle,
+ filename: Option,
+) -> Result<(), tauri_plugin_sql::Error> {
let mut state = state.lock().await;
state.db_filename = filename.clone();
-
+
// Persist in store
let store = app.store("store.json").expect("Error opening store");
store.set("db_filename", filename);
-
+
Ok(())
}
@@ -66,15 +72,15 @@ pub fn run() {
} else {
None
}
- },
- _ => panic!("Unexpected db_filename in store")
+ }
+ _ => panic!("Unexpected db_filename in store"),
};
-
+
app.manage(Mutex::new(AppState {
db_filename: db_filename,
sql_transactions: Vec::new(),
}));
-
+
Ok(())
})
.plugin(tauri_plugin_dialog::init())
@@ -82,9 +88,15 @@ pub fn run() {
.plugin(tauri_plugin_sql::Builder::new().build())
.plugin(tauri_plugin_store::Builder::new().build())
.invoke_handler(tauri::generate_handler![
- get_open_filename, set_open_filename,
+ get_open_filename,
+ set_open_filename,
libdrcr_bridge::get_balance_sheet,
- sql::sql_transaction_begin, sql::sql_transaction_execute, sql::sql_transaction_select, sql::sql_transaction_rollback, sql::sql_transaction_commit
+ libdrcr_bridge::get_income_statement,
+ sql::sql_transaction_begin,
+ sql::sql_transaction_execute,
+ sql::sql_transaction_select,
+ sql::sql_transaction_rollback,
+ sql::sql_transaction_commit
])
.run(tauri::generate_context!())
.expect("Error while running tauri application");
diff --git a/src-tauri/src/libdrcr_bridge.rs b/src-tauri/src/libdrcr_bridge.rs
index 1541ae2..ead5a20 100644
--- a/src-tauri/src/libdrcr_bridge.rs
+++ b/src-tauri/src/libdrcr_bridge.rs
@@ -23,8 +23,8 @@ use libdrcr::reporting::dynamic_report::DynamicReport;
use libdrcr::reporting::generate_report;
use libdrcr::reporting::steps::register_lookup_fns;
use libdrcr::reporting::types::{
- DateArgs, MultipleDateArgs, ReportingContext, ReportingProductId, ReportingProductKind,
- VoidArgs,
+ DateArgs, DateStartDateEndArgs, MultipleDateArgs, MultipleDateStartDateEndArgs,
+ ReportingContext, ReportingProductId, ReportingProductKind, VoidArgs,
};
use tauri::State;
use tokio::sync::Mutex;
@@ -94,3 +94,67 @@ pub(crate) async fn get_balance_sheet(
.await
.unwrap()
}
+
+#[tauri::command]
+pub(crate) async fn get_income_statement(
+ state: State<'_, Mutex>,
+ eofy_date: String,
+ dates: Vec<(String, String)>,
+) -> Result {
+ let state = state.lock().await;
+ let db_filename = state.db_filename.clone().unwrap();
+
+ spawn_blocking(move || {
+ // Connect to database
+ let db_connection =
+ DbConnection::connect(format!("sqlite:{}", db_filename.as_str()).as_str());
+
+ // Initialise ReportingContext
+ let mut context = ReportingContext::new(
+ db_connection,
+ NaiveDate::parse_from_str(eofy_date.as_str(), "%Y-%m-%d").unwrap(),
+ "$".to_string(),
+ );
+ register_lookup_fns(&mut context);
+ register_dynamic_builders(&mut context);
+
+ // Get income statement
+ let mut date_args = Vec::new();
+ for (date_start, date_end) in dates.iter() {
+ date_args.push(DateStartDateEndArgs {
+ date_start: NaiveDate::parse_from_str(date_start, "%Y-%m-%d").unwrap(),
+ date_end: NaiveDate::parse_from_str(date_end, "%Y-%m-%d").unwrap(),
+ })
+ }
+ let targets = vec![
+ ReportingProductId {
+ name: "CalculateIncomeTax",
+ kind: ReportingProductKind::Transactions,
+ args: Box::new(VoidArgs {}),
+ },
+ ReportingProductId {
+ name: "IncomeStatement",
+ kind: ReportingProductKind::Generic,
+ args: Box::new(MultipleDateStartDateEndArgs {
+ dates: date_args.clone(),
+ }),
+ },
+ ];
+
+ // Run report
+ let products = generate_report(targets, &context).unwrap();
+ let result = products
+ .get_or_err(&ReportingProductId {
+ name: "IncomeStatement",
+ kind: ReportingProductKind::Generic,
+ args: Box::new(MultipleDateStartDateEndArgs { dates: date_args }),
+ })
+ .unwrap();
+
+ let income_statement = result.downcast_ref::().unwrap().to_json();
+
+ Ok(income_statement)
+ })
+ .await
+ .unwrap()
+}
diff --git a/src/reports/IncomeStatementReport.vue b/src/reports/IncomeStatementReport.vue
index e363ff7..9482490 100644
--- a/src/reports/IncomeStatementReport.vue
+++ b/src/reports/IncomeStatementReport.vue
@@ -1,6 +1,6 @@
-
-
-
-
-
+
-
+