feat: Add equity account support to transaction filtering and Beancount import

Improvements to equity account handling across the Castle extension:

  Transaction Categorization (views_api.py):
  - Prioritize equity accounts when enriching transaction entries
  - Use two-pass lookup: first search for equity accounts, then fall back to liability/asset accounts
  - Ensures transactions with Equity:User-<id> accounts are correctly categorized as equity

UI Enhancements (index.html, index.js):
  - Add 'Equity' filter option to Recent Transactions table
  - Display blue "Equity" badge for equity entries (before receivable/payable badges)
  - Add isEquity() helper function to identify equity account entries

Beancount Import (import_beancount.py):
  - Support importing Beancount Equity:<name> accounts
  - Map Beancount "Equity:Pat" to Castle "Equity:User-<id>" accounts
  - Update extract_user_from_user_account() to handle Equity: prefix
  - Improve error messages to include equity account examples
  - Add equity account lookup in get_account_id() with helpful error if equity not enabled

These changes ensure equity accounts (representing user capital contributions) are properly distinguished from payables and receivables throughout the system.
This commit is contained in:
padreug 2025-11-09 21:09:43 +01:00
parent 6f1fa7203b
commit 0b64ffa54f
4 changed files with 74 additions and 11 deletions

View file

@ -318,18 +318,33 @@ async def api_get_user_entries(
enriched_entries = []
for entry in entries:
# Find user_id from entry lines (look for user-specific accounts)
# Prioritize equity accounts, then liability/asset accounts
entry_user_id = None
entry_username = None
entry_account_type = None
equity_account = None
other_user_account = None
# First pass: look for equity and other user accounts
for line in entry.lines:
account = await get_account(line.account_id)
if account and account.user_id:
entry_user_id = account.user_id
entry_account_type = account.account_type.value if hasattr(account.account_type, 'value') else account.account_type
user = await get_user(account.user_id)
entry_username = user.username if user and user.username else account.user_id[:16] + "..."
break
account_type = account.account_type.value if hasattr(account.account_type, 'value') else account.account_type
if account_type == 'equity':
equity_account = (account.user_id, account_type, account)
break # Prioritize equity, stop searching
elif not other_user_account:
other_user_account = (account.user_id, account_type, account)
# Use equity account if found, otherwise use other user account
selected_account = equity_account or other_user_account
if selected_account:
entry_user_id, entry_account_type, account_obj = selected_account
user = await get_user(entry_user_id)
entry_username = user.username if user and user.username else entry_user_id[:16] + "..."
enriched_entries.append({
**entry.dict(),