From 78ebbac9ca4564725b83bcb4f664bd7609a1985f Mon Sep 17 00:00:00 2001 From: andrewlalis Date: Tue, 17 Feb 2026 20:24:19 -0500 Subject: [PATCH] Fixed category balance calculations. --- .../source/transaction/data_impl_sqlite.d | 3 +- web-app/src/api/transaction.ts | 6 +- web-app/src/pages/CategoryPage.vue | 87 +++++-------------- 3 files changed, 29 insertions(+), 67 deletions(-) diff --git a/finnow-api/source/transaction/data_impl_sqlite.d b/finnow-api/source/transaction/data_impl_sqlite.d index 1942bbd..6fb20aa 100644 --- a/finnow-api/source/transaction/data_impl_sqlite.d +++ b/finnow-api/source/transaction/data_impl_sqlite.d @@ -190,7 +190,7 @@ class SqliteTransactionCategoryRepository : TransactionCategoryRepository { stmt.bind(idx++, beforeTimestamp.value.toISOExtString()); }); } - string query = qb.build() ~ " ORDER BY je.currency ASC, je.type ASC"; + string query = qb.build() ~ " GROUP BY je.currency, je.type ORDER BY je.currency ASC, je.type ASC"; Statement stmt = db.prepare(query); qb.applyArgBindings(stmt); ResultRange result = stmt.execute(); @@ -201,7 +201,6 @@ class SqliteTransactionCategoryRepository : TransactionCategoryRepository { Currency currency = Currency.ofCode(row.peek!(string, PeekMode.slice)(0)); string journalEntryType = row.peek!(string, PeekMode.slice)(1); ulong amountSum = row.peek!ulong(2); - TransactionCategoryBalance balance; if (currency.numericCode in balancesGroupedByCurrency) { diff --git a/web-app/src/api/transaction.ts b/web-app/src/api/transaction.ts index cc7b055..6842f9d 100644 --- a/web-app/src/api/transaction.ts +++ b/web-app/src/api/transaction.ts @@ -187,8 +187,10 @@ export class TransactionApiClient extends ApiClient { return super.getJson(this.path + '/categories/' + parentId + '/children') } - getCategoryBalances(id: number): Promise { - return super.getJson(this.path + '/categories/' + id + '/balances') + getCategoryBalances(id: number, includeChildren: boolean): Promise { + return super.getJson( + this.path + '/categories/' + id + '/balances?includeChildren=' + includeChildren, + ) } createCategory(data: CreateCategoryPayload): Promise { diff --git a/web-app/src/pages/CategoryPage.vue b/web-app/src/pages/CategoryPage.vue index 8a55ad2..51692cd 100644 --- a/web-app/src/pages/CategoryPage.vue +++ b/web-app/src/pages/CategoryPage.vue @@ -37,6 +37,7 @@ watch(balancesIncludeSubcategories, async () => { if (!category.value) return balances.value = await new TransactionApiClient(getSelectedProfile(route)).getCategoryBalances( category.value.id, + balancesIncludeSubcategories.value ) }) @@ -49,6 +50,8 @@ async function loadCategory(id: number) { category.value = undefined parentCategory.value = undefined childCategories.value = [] + balances.value = [] + balancesIncludeSubcategories.value = true relatedTransactionsPage.value = defaultPage() try { const api = new TransactionApiClient(getSelectedProfile(route)) @@ -57,7 +60,7 @@ async function loadCategory(id: number) { parentCategory.value = await api.getCategory(category.value.parentId) } childCategories.value = await api.getChildCategories(category.value.id) - balances.value = await api.getCategoryBalances(category.value.id) + balances.value = await api.getCategoryBalances(category.value.id, balancesIncludeSubcategories.value) await fetchPage(1) } catch (err) { console.error(err) @@ -84,32 +87,16 @@ async function fetchPage(pg: number) { }