From 6d5243b03e27310eb7de04894a4c049770976f0c Mon Sep 17 00:00:00 2001 From: padreug Date: Wed, 22 Oct 2025 17:07:58 +0200 Subject: [PATCH] Filters journal entries by user account Updates journal entry retrieval to filter entries based on the user's accounts rather than the user ID. This ensures that users only see journal entries that directly affect their accounts. Also displays fiat amount in journal entries if available in the metadata. --- crud.py | 50 +++++++++++++++++++++++++++++-------- static/js/index.js | 11 ++++++++ templates/castle/index.html | 6 +++++ views_api.py | 4 +-- 4 files changed, 59 insertions(+), 12 deletions(-) diff --git a/crud.py b/crud.py index 74f04d2..cef3171 100644 --- a/crud.py +++ b/crud.py @@ -236,19 +236,49 @@ async def get_all_journal_entries(limit: int = 100) -> list[JournalEntry]: async def get_journal_entries_by_user( user_id: str, limit: int = 100 ) -> list[JournalEntry]: - entries = await db.fetchall( - """ - SELECT * FROM journal_entries - WHERE created_by = :user_id - ORDER BY entry_date DESC, created_at DESC - LIMIT :limit - """, - {"user_id": user_id, "limit": limit}, - JournalEntry, + """Get journal entries that affect the user's accounts""" + # Get all user-specific accounts + user_accounts = await db.fetchall( + "SELECT id FROM accounts WHERE user_id = :user_id", + {"user_id": user_id}, ) - for entry in entries: + if not user_accounts: + return [] + + account_ids = [acc["id"] for acc in user_accounts] + + # Get all journal entries that have lines affecting these accounts + # Build the IN clause with named parameters + placeholders = ','.join([f":account_{i}" for i in range(len(account_ids))]) + params = {f"account_{i}": acc_id for i, acc_id in enumerate(account_ids)} + params["limit"] = limit + + entries_data = await db.fetchall( + f""" + SELECT DISTINCT je.* + FROM journal_entries je + JOIN entry_lines el ON je.id = el.journal_entry_id + WHERE el.account_id IN ({placeholders}) + ORDER BY je.entry_date DESC, je.created_at DESC + LIMIT :limit + """, + params, + ) + + entries = [] + for entry_data in entries_data: + entry = JournalEntry( + id=entry_data["id"], + description=entry_data["description"], + entry_date=entry_data["entry_date"], + created_by=entry_data["created_by"], + created_at=entry_data["created_at"], + reference=entry_data["reference"], + lines=[], + ) entry.lines = await get_entry_lines(entry.id) + entries.append(entry) return entries diff --git a/static/js/index.js b/static/js/index.js index 6876513..ba27c0c 100644 --- a/static/js/index.js +++ b/static/js/index.js @@ -520,6 +520,17 @@ window.app = Vue.createApp({ getTotalAmount(entry) { if (!entry.lines || entry.lines.length === 0) return 0 return entry.lines.reduce((sum, line) => sum + line.debit + line.credit, 0) / 2 + }, + getEntryFiatAmount(entry) { + // Extract fiat amount from metadata if available + if (!entry.lines || entry.lines.length === 0) return null + + for (const line of entry.lines) { + if (line.metadata && line.metadata.fiat_currency && line.metadata.fiat_amount) { + return this.formatFiat(line.metadata.fiat_amount, line.metadata.fiat_currency) + } + } + return null } }, async created() { diff --git a/templates/castle/index.html b/templates/castle/index.html index 0ac63bc..b9b0c50 100644 --- a/templates/castle/index.html +++ b/templates/castle/index.html @@ -204,9 +204,15 @@ {% raw %}{{ formatDate(entry.entry_date) }}{% endraw %} + + Ref: {% raw %}{{ entry.reference }}{% endraw %} + {% raw %}{{ formatSats(getTotalAmount(entry)) }} sats{% endraw %} + + {% raw %}{{ getEntryFiatAmount(entry) }}{% endraw %} + diff --git a/views_api.py b/views_api.py index 83db451..a588639 100644 --- a/views_api.py +++ b/views_api.py @@ -157,8 +157,8 @@ async def api_get_user_entries( wallet: WalletTypeInfo = Depends(require_invoice_key), limit: int = 100, ) -> list[JournalEntry]: - """Get journal entries created by the current user""" - return await get_journal_entries_by_user(wallet.wallet.id, limit) + """Get journal entries that affect the current user's accounts""" + return await get_journal_entries_by_user(wallet.wallet.user, limit) @castle_api_router.get("/api/v1/entries/{entry_id}")