From 51a40e5ed90f78a0be00c820406007f97bc549a2 Mon Sep 17 00:00:00 2001 From: RunasSudo Date: Tue, 27 May 2025 22:20:33 +1000 Subject: [PATCH] Trial balance using libdrcr --- src-tauri/src/lib.rs | 1 + src-tauri/src/libdrcr_bridge.rs | 116 ++++++++++++++--------------- src/main.ts | 4 +- src/pages/TrialBalanceView.vue | 79 -------------------- src/reports/TrialBalanceReport.ts | 25 ------- src/reports/TrialBalanceReport.vue | 60 +++++++++++++++ 6 files changed, 117 insertions(+), 168 deletions(-) delete mode 100644 src/pages/TrialBalanceView.vue delete mode 100644 src/reports/TrialBalanceReport.ts create mode 100644 src/reports/TrialBalanceReport.vue diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 4c57e3e..d8da86e 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -92,6 +92,7 @@ pub fn run() { set_open_filename, libdrcr_bridge::get_balance_sheet, libdrcr_bridge::get_income_statement, + libdrcr_bridge::get_trial_balance, sql::sql_transaction_begin, sql::sql_transaction_execute, sql::sql_transaction_select, diff --git a/src-tauri/src/libdrcr_bridge.rs b/src-tauri/src/libdrcr_bridge.rs index 4ea0a48..a55384f 100644 --- a/src-tauri/src/libdrcr_bridge.rs +++ b/src-tauri/src/libdrcr_bridge.rs @@ -33,10 +33,9 @@ use tokio::sync::Mutex; use crate::AppState; -#[tauri::command] -pub(crate) async fn get_balance_sheet( +async fn get_dynamic_report( state: State<'_, Mutex>, - dates: Vec, + target: ReportingProductId, ) -> Result { let state = state.lock().await; let db_filename = state.db_filename.clone().unwrap(); @@ -51,19 +50,37 @@ pub(crate) async fn get_balance_sheet( register_lookup_fns(&mut context); register_dynamic_builders(&mut context); - // Get balance sheet - let mut date_args = Vec::new(); - for date in dates.iter() { - date_args.push(DateArgs { - date: NaiveDate::parse_from_str(date, "%Y-%m-%d").unwrap(), - }) - } + // Get dynamic report let targets = vec![ ReportingProductId { name: "CalculateIncomeTax", kind: ReportingProductKind::Transactions, args: Box::new(VoidArgs {}), }, + target.clone(), + ]; + let products = generate_report(targets, Arc::new(context)).await.unwrap(); + let result = products.get_or_err(&target).unwrap(); + + let dynamic_report = result.downcast_ref::().unwrap().to_json(); + + Ok(dynamic_report) +} + +#[tauri::command] +pub(crate) async fn get_balance_sheet( + state: State<'_, Mutex>, + dates: Vec, +) -> Result { + let mut date_args = Vec::new(); + for date in dates.iter() { + date_args.push(DateArgs { + date: NaiveDate::parse_from_str(date, "%Y-%m-%d").expect("Invalid date"), + }) + } + + get_dynamic_report( + state, ReportingProductId { name: "BalanceSheet", kind: ReportingProductKind::Generic, @@ -71,21 +88,8 @@ pub(crate) async fn get_balance_sheet( dates: date_args.clone(), }), }, - ]; - - // Run report - let products = generate_report(targets, Arc::new(context)).await.unwrap(); - let result = products - .get_or_err(&ReportingProductId { - name: "BalanceSheet", - kind: ReportingProductKind::Generic, - args: Box::new(MultipleDateArgs { dates: date_args }), - }) - .unwrap(); - - let balance_sheet = result.downcast_ref::().unwrap().to_json(); - - Ok(balance_sheet) + ) + .await } #[tauri::command] @@ -93,33 +97,16 @@ pub(crate) async fn get_income_statement( state: State<'_, Mutex>, dates: Vec<(String, String)>, ) -> Result { - let state = state.lock().await; - let db_filename = state.db_filename.clone().unwrap(); - - // Connect to database - let db_connection = - DbConnection::new(format!("sqlite:{}", db_filename.as_str()).as_str()).await; - - // Initialise ReportingContext - let eofy_date = db_connection.metadata().eofy_date; - let mut context = ReportingContext::new(db_connection, eofy_date, "$".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(), + date_start: NaiveDate::parse_from_str(date_start, "%Y-%m-%d").expect("Invalid date"), + date_end: NaiveDate::parse_from_str(date_end, "%Y-%m-%d").expect("Invalid date"), }) } - let targets = vec![ - ReportingProductId { - name: "CalculateIncomeTax", - kind: ReportingProductKind::Transactions, - args: Box::new(VoidArgs {}), - }, + + get_dynamic_report( + state, ReportingProductId { name: "IncomeStatement", kind: ReportingProductKind::Generic, @@ -127,19 +114,24 @@ pub(crate) async fn get_income_statement( dates: date_args.clone(), }), }, - ]; - - // Run report - let products = generate_report(targets, Arc::new(context)).await.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 +} + +#[tauri::command] +pub(crate) async fn get_trial_balance( + state: State<'_, Mutex>, + date: String, +) -> Result { + let date = NaiveDate::parse_from_str(&date, "%Y-%m-%d").expect("Invalid date"); + + get_dynamic_report( + state, + ReportingProductId { + name: "TrialBalance", + kind: ReportingProductKind::Generic, + args: Box::new(DateArgs { date }), + }, + ) + .await } diff --git a/src/main.ts b/src/main.ts index 8397aaf..1e64a3f 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,6 +1,6 @@ /* 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 @@ -43,7 +43,7 @@ async function initApp() { { path: '/statement-lines', name: 'statement-lines', component: () => import('./pages/StatementLinesView.vue') }, { path: '/statement-lines/import', name: 'import-statement', component: () => import('./pages/ImportStatementView.vue') }, { path: '/transactions/:account', name: 'transactions', component: () => import('./pages/TransactionsView.vue') }, - { path: '/trial-balance', name: 'trial-balance', component: () => import('./pages/TrialBalanceView.vue') }, + { path: '/trial-balance', name: 'trial-balance', component: () => import('./reports/TrialBalanceReport.vue') }, ]; const router = createRouter({ history: createWebHistory(), diff --git a/src/pages/TrialBalanceView.vue b/src/pages/TrialBalanceView.vue deleted file mode 100644 index a29d1f5..0000000 --- a/src/pages/TrialBalanceView.vue +++ /dev/null @@ -1,79 +0,0 @@ - - - - - diff --git a/src/reports/TrialBalanceReport.ts b/src/reports/TrialBalanceReport.ts deleted file mode 100644 index 56196c1..0000000 --- a/src/reports/TrialBalanceReport.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - DrCr: Web-based double-entry bookkeeping framework - Copyright (C) 2022–2024 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 . -*/ - -import { DrcrReport } from './base.ts'; - -export default class TrialBalanceReport implements DrcrReport { - constructor( - public balances: Map - ) {} -} diff --git a/src/reports/TrialBalanceReport.vue b/src/reports/TrialBalanceReport.vue new file mode 100644 index 0000000..bc98e05 --- /dev/null +++ b/src/reports/TrialBalanceReport.vue @@ -0,0 +1,60 @@ + + + + +