From 947342e19618471a317bf08ed76ade29e8b709bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elisi=C3=A1rio=20Couto?= Date: Mon, 8 Sep 2025 23:38:14 +0100 Subject: [PATCH] Add hide_missing_ids filter to transaction queries - Add hide_missing_ids parameter to database functions to filter out transactions without internalTransactionId - Update API routes to support the new filter parameter - Update unit tests to include the new parameter - Add opencode.json configuration file --- leggen/database/sqlite.py | 11 +++++++++++ leggend/api/routes/transactions.py | 19 +++++++++++++++++++ leggend/services/database_service.py | 7 ++++++- opencode.json | 7 +++++++ tests/unit/test_api_transactions.py | 1 + tests/unit/test_database_service.py | 7 ++++++- 6 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 opencode.json diff --git a/leggen/database/sqlite.py b/leggen/database/sqlite.py index af31f9c..010d389 100644 --- a/leggen/database/sqlite.py +++ b/leggen/database/sqlite.py @@ -210,6 +210,7 @@ def get_transactions( min_amount=None, max_amount=None, search=None, + hide_missing_ids=True, ): """Get transactions from SQLite database with optional filtering""" from pathlib import Path @@ -249,6 +250,11 @@ def get_transactions( query += " AND description LIKE ?" params.append(f"%{search}%") + if hide_missing_ids: + query += ( + " AND internalTransactionId IS NOT NULL AND internalTransactionId != ''" + ) + # Add ordering and pagination query += " ORDER BY transactionDate DESC" @@ -397,6 +403,11 @@ def get_transaction_count(account_id=None, **filters): query += " AND description LIKE ?" params.append(f"%{filters['search']}%") + if filters.get("hide_missing_ids", True): + query += ( + " AND internalTransactionId IS NOT NULL AND internalTransactionId != ''" + ) + try: cursor.execute(query, params) count = cursor.fetchone()[0] diff --git a/leggend/api/routes/transactions.py b/leggend/api/routes/transactions.py index 37d1b15..799cd23 100644 --- a/leggend/api/routes/transactions.py +++ b/leggend/api/routes/transactions.py @@ -18,6 +18,9 @@ async def get_all_transactions( summary_only: bool = Query( default=True, description="Return transaction summaries only" ), + hide_missing_ids: bool = Query( + default=True, description="Hide transactions without internalTransactionId" + ), date_from: Optional[str] = Query( default=None, description="Filter from date (YYYY-MM-DD)" ), @@ -47,6 +50,18 @@ async def get_all_transactions( min_amount=min_amount, max_amount=max_amount, search=search, + hide_missing_ids=hide_missing_ids, + ) + + # Get total count for pagination info (respecting the same filters) + total_transactions = await database_service.get_transaction_count_from_db( + account_id=account_id, + date_from=date_from, + date_to=date_to, + min_amount=min_amount, + max_amount=max_amount, + search=search, + hide_missing_ids=hide_missing_ids, ) # Get total count for pagination info @@ -111,6 +126,9 @@ async def get_all_transactions( async def get_transaction_stats( days: int = Query(default=30, description="Number of days to include in stats"), account_id: Optional[str] = Query(default=None, description="Filter by account ID"), + hide_missing_ids: bool = Query( + default=True, description="Hide transactions without internalTransactionId" + ), ) -> APIResponse: """Get transaction statistics for the last N days from database""" try: @@ -128,6 +146,7 @@ async def get_transaction_stats( date_from=date_from, date_to=date_to, limit=None, # Get all matching transactions for stats + hide_missing_ids=hide_missing_ids, ) # Calculate stats diff --git a/leggend/services/database_service.py b/leggend/services/database_service.py index 31334b5..5cbc3b2 100644 --- a/leggend/services/database_service.py +++ b/leggend/services/database_service.py @@ -115,6 +115,7 @@ class DatabaseService: min_amount: Optional[float] = None, max_amount: Optional[float] = None, search: Optional[str] = None, + hide_missing_ids: bool = True, ) -> List[Dict[str, Any]]: """Get transactions from SQLite database""" if not self.sqlite_enabled: @@ -131,6 +132,7 @@ class DatabaseService: min_amount=min_amount, max_amount=max_amount, search=search, + hide_missing_ids=hide_missing_ids, ) logger.debug(f"Retrieved {len(transactions)} transactions from database") return transactions @@ -146,6 +148,7 @@ class DatabaseService: min_amount: Optional[float] = None, max_amount: Optional[float] = None, search: Optional[str] = None, + hide_missing_ids: bool = True, ) -> int: """Get total count of transactions from SQLite database""" if not self.sqlite_enabled: @@ -162,7 +165,9 @@ class DatabaseService: # Remove None values filters = {k: v for k, v in filters.items() if v is not None} - count = sqlite_db.get_transaction_count(account_id=account_id, **filters) + count = sqlite_db.get_transaction_count( + account_id=account_id, hide_missing_ids=hide_missing_ids, **filters + ) logger.debug(f"Total transaction count: {count}") return count except Exception as e: diff --git a/opencode.json b/opencode.json new file mode 100644 index 0000000..62cbf03 --- /dev/null +++ b/opencode.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://opencode.ai/config.json", + "permission": { + "edit": "ask", + "bash": "ask" + } +} diff --git a/tests/unit/test_api_transactions.py b/tests/unit/test_api_transactions.py index bb99740..4e9b1db 100644 --- a/tests/unit/test_api_transactions.py +++ b/tests/unit/test_api_transactions.py @@ -166,6 +166,7 @@ class TestTransactionsAPI: min_amount=-50.0, max_amount=0.0, search="Coffee", + hide_missing_ids=True, ) def test_get_transactions_empty_result( diff --git a/tests/unit/test_database_service.py b/tests/unit/test_database_service.py index 1494725..7bf3393 100644 --- a/tests/unit/test_database_service.py +++ b/tests/unit/test_database_service.py @@ -99,6 +99,7 @@ class TestDatabaseService: min_amount=None, max_amount=None, search=None, + hide_missing_ids=True, ) async def test_get_transactions_from_db_with_filters( @@ -129,6 +130,7 @@ class TestDatabaseService: min_amount=-50.0, max_amount=0.0, search="Coffee", + hide_missing_ids=True, ) async def test_get_transactions_from_db_sqlite_disabled(self, database_service): @@ -158,7 +160,9 @@ class TestDatabaseService: ) assert result == 42 - mock_get_count.assert_called_once_with(account_id="test-account-123") + mock_get_count.assert_called_once_with( + account_id="test-account-123", hide_missing_ids=True + ) async def test_get_transaction_count_from_db_with_filters(self, database_service): """Test getting transaction count with filters.""" @@ -178,6 +182,7 @@ class TestDatabaseService: date_from="2025-09-01", min_amount=-100.0, search="Coffee", + hide_missing_ids=True, ) async def test_get_transaction_count_from_db_sqlite_disabled(