diff --git a/fava_client.py b/fava_client.py index e300867..1b426b6 100644 --- a/fava_client.py +++ b/fava_client.py @@ -866,6 +866,9 @@ class FavaClient: """ Get journal entries from Fava (with entry hashes), optionally filtered by date. + Uses Fava's server-side 'time' parameter for efficient date filtering, + avoiding the need to fetch all entries and filter in Python. + Args: days: If provided, only return entries from the last N days. If None, returns all entries (default behavior). @@ -890,59 +893,35 @@ class FavaClient: # Get entries in custom date range custom = await fava.get_journal_entries(start_date="2024-01-01", end_date="2024-01-31") """ + from datetime import datetime, timedelta + try: + # Build query parameters for server-side filtering + params = {} + + # Use date range if both start_date and end_date are provided + if start_date and end_date: + # Fava uses "YYYY-MM-DD - YYYY-MM-DD" format for time ranges + params["time"] = f"{start_date} - {end_date}" + logger.info(f"Querying journal with date range: {start_date} to {end_date}") + + # Fall back to days filter if no date range provided + elif days is not None: + cutoff_date = (datetime.now() - timedelta(days=days)).date() + today = datetime.now().date() + params["time"] = f"{cutoff_date.isoformat()} - {today.isoformat()}" + logger.info(f"Querying journal for last {days} days (from {cutoff_date})") + async with httpx.AsyncClient(timeout=self.timeout) as client: - response = await client.get(f"{self.base_url}/journal") + response = await client.get(f"{self.base_url}/journal", params=params) response.raise_for_status() result = response.json() entries = result.get("data", []) - logger.info(f"Fava /journal returned {len(entries)} entries") - # Filter by date range or days - from datetime import datetime, timedelta - - # Use date range if both start_date and end_date are provided - if start_date and end_date: - try: - filter_start = datetime.strptime(start_date, "%Y-%m-%d").date() - filter_end = datetime.strptime(end_date, "%Y-%m-%d").date() - filtered_entries = [] - for e in entries: - entry_date_str = e.get("date") - if entry_date_str: - try: - entry_date = datetime.strptime(entry_date_str, "%Y-%m-%d").date() - if filter_start <= entry_date <= filter_end: - filtered_entries.append(e) - except (ValueError, TypeError): - # Include entries with invalid dates (shouldn't happen) - filtered_entries.append(e) - logger.info(f"Filtered to {len(filtered_entries)} entries between {start_date} and {end_date}") - entries = filtered_entries - except ValueError as e: - logger.error(f"Invalid date format: {e}") - # Return all entries if date parsing fails - - # Fall back to days filter if no date range provided - elif days is not None: - cutoff_date = (datetime.now() - timedelta(days=days)).date() - filtered_entries = [] - for e in entries: - entry_date_str = e.get("date") - if entry_date_str: - try: - entry_date = datetime.strptime(entry_date_str, "%Y-%m-%d").date() - if entry_date >= cutoff_date: - filtered_entries.append(e) - except (ValueError, TypeError): - # Include entries with invalid dates (shouldn't happen) - filtered_entries.append(e) - logger.info(f"Filtered to {len(filtered_entries)} entries from last {days} days (cutoff: {cutoff_date})") - entries = filtered_entries - - # Log transactions with "Lightning payment" in narration - lightning_entries = [e for e in entries if "Lightning payment" in e.get("narration", "")] - logger.info(f"Found {len(lightning_entries)} Lightning payment entries in journal") + if params: + logger.info(f"Fava /journal returned {len(entries)} entries (filtered)") + else: + logger.info(f"Fava /journal returned {len(entries)} entries (all)") return entries