Implement hybrid approach for balance assertions
Balance assertions now use a hybrid architecture where Beancount is the source of truth for validation, while Castle stores metadata for UI convenience. Backend changes: - Add format_balance() function to beancount_format.py for formatting balance directives - Update POST /api/v1/assertions to write balance directive to Beancount first (via Fava) - Store metadata in Castle DB (created_by, tolerance, notes) for UI features - Validate assertions immediately by querying Fava for actual balance Frontend changes: - Update dialog description to explain Beancount validation - Update button tooltip to clarify balance assertions are written to Beancount - Update empty state message to mention Beancount checkpoints Benefits: - Single source of truth (Beancount ledger file) - Automatic validation by Beancount - Best of both worlds: robust validation + friendly UI See misc-docs/BALANCE-ASSERTIONS-HYBRID-APPROACH.md for full documentation. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
28832d6bfe
commit
a3c3e44e5f
3 changed files with 69 additions and 6 deletions
|
|
@ -104,6 +104,36 @@ def format_transaction(
|
|||
}
|
||||
|
||||
|
||||
def format_balance(
|
||||
date_val: date,
|
||||
account: str,
|
||||
amount: int,
|
||||
currency: str = "SATS"
|
||||
) -> str:
|
||||
"""
|
||||
Format a balance assertion directive for Beancount.
|
||||
|
||||
Balance assertions verify that an account has an expected balance on a specific date.
|
||||
They are checked automatically by Beancount when the file is loaded.
|
||||
|
||||
Args:
|
||||
date_val: Date of the balance assertion
|
||||
account: Account name (e.g., "Assets:Bitcoin:Lightning")
|
||||
amount: Expected balance amount
|
||||
currency: Currency code (default: "SATS")
|
||||
|
||||
Returns:
|
||||
Beancount balance directive as a string
|
||||
|
||||
Example:
|
||||
>>> format_balance(date(2025, 11, 10), "Assets:Bitcoin:Lightning", 1500000, "SATS")
|
||||
'2025-11-10 balance Assets:Bitcoin:Lightning 1500000 SATS'
|
||||
"""
|
||||
date_str = date_val.strftime('%Y-%m-%d')
|
||||
# Two spaces between account and amount (Beancount convention)
|
||||
return f"{date_str} balance {account} {amount} {currency}"
|
||||
|
||||
|
||||
def format_posting_with_cost(
|
||||
account: str,
|
||||
amount_sats: int,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue