From 9350f05d746cdc920e25fb756221bbe3bd848260 Mon Sep 17 00:00:00 2001 From: padreug Date: Sun, 9 Nov 2025 23:26:30 +0100 Subject: [PATCH] Removes voided/flagged entry flags Updates journal entry flags to align with Beancount's limited flag support. Beancount only uses cleared (*) and pending (!) flags. Removes the VOID and FLAGGED flags and recommends using tags instead (e.g., "! + #voided" for voided entries, "! + #review" for flagged entries). Updates the API to reflect this change, removing the ability to directly "reject" an expense entry via the void flag. Instead, instructs users to add the #voided tag in Fava. Updates reconciliation summary to count entries with voided/review tags instead of voided/flagged flags. --- models.py | 13 ++++++++++--- views_api.py | 25 +++++++++++-------------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/models.py b/models.py index 919b722..4386027 100644 --- a/models.py +++ b/models.py @@ -15,11 +15,18 @@ class AccountType(str, Enum): class JournalEntryFlag(str, Enum): - """Transaction status flags (Beancount-style)""" + """Transaction status flags (Beancount-compatible) + + Beancount only supports two user-facing flags: + - * (CLEARED): Completed transactions + - ! (PENDING): Transactions needing attention + + For voided/flagged transactions, use tags instead: + - Voided: Use "!" flag + #voided tag + - Flagged: Use "!" flag + #review tag + """ CLEARED = "*" # Fully reconciled/confirmed PENDING = "!" # Not yet confirmed/awaiting approval - FLAGGED = "#" # Needs review/attention - VOID = "x" # Voided/cancelled entry class Account(BaseModel): diff --git a/views_api.py b/views_api.py index d92201d..f5d81f1 100644 --- a/views_api.py +++ b/views_api.py @@ -1924,19 +1924,14 @@ async def api_reject_expense_entry( detail=f"Entry is not pending (current status: {entry.flag.value})", ) - # Update flag to voided - await db.execute( - """ - UPDATE journal_entries - SET flag = :flag - WHERE id = :id - """, - {"flag": JournalEntryFlag.VOID.value, "id": entry_id} + # Since entries are now in Fava/Beancount, voiding requires editing the Beancount file + # Beancount doesn't have a "void" flag - recommend using ! flag + #voided tag + raise HTTPException( + status_code=HTTPStatus.NOT_IMPLEMENTED, + detail="To reject/void entry, open Fava and either delete the transaction or add the #voided tag. " + "Beancount only supports * (cleared) and ! (pending) flags." ) - # Return updated entry - return await get_journal_entry(entry_id) - # ===== BALANCE ASSERTION ENDPOINTS ===== @@ -2136,11 +2131,13 @@ async def api_get_reconciliation_summary( fava = get_fava_client() all_entries = await fava.query_transactions(limit=1000, include_pending=True) - # Count entries by flag + # Count entries by flag (Beancount only supports * and !) cleared = len([e for e in all_entries if e.get("flag") == "*"]) pending_entries = len([e for e in all_entries if e.get("flag") == "!"]) - flagged = len([e for e in all_entries if e.get("flag") == "#"]) - voided = len([e for e in all_entries if e.get("flag") == "x"]) + + # Count entries with special tags + voided = len([e for e in all_entries if "voided" in e.get("tags", [])]) + flagged = len([e for e in all_entries if "review" in e.get("tags", []) or "flagged" in e.get("tags", [])]) # Get all accounts accounts = await get_all_accounts()