castle/helper
padreug 0b64ffa54f 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.
2025-11-09 21:09:43 +01:00
..
btc_eur_rates.csv Adds Beancount import helper script 2025-11-08 23:18:42 +01:00
import_beancount.py feat: Add equity account support to transaction filtering and Beancount import 2025-11-09 21:09:43 +01:00
README.md Adds Beancount import helper script 2025-11-08 23:18:42 +01:00

Castle Beancount Import Helper

Import Beancount ledger transactions into Castle accounting extension.

📁 Files

  • import_beancount.py - Main import script
  • btc_eur_rates.csv - Daily BTC/EUR rates (create your own)
  • README.md - This file

🚀 Setup

1. Create BTC/EUR Rates CSV

Create btc_eur_rates.csv in this directory with your actual rates:

date,btc_eur_rate
2025-07-01,86500
2025-07-02,87200
2025-07-03,87450

2. Update User Mappings

Edit import_beancount.py and update the USER_MAPPINGS dictionary:

USER_MAPPINGS = {
    "Pat": "actual_wallet_id_for_pat",
    "Alice": "actual_wallet_id_for_alice",
    "Bob": "actual_wallet_id_for_bob",
}

How to get wallet IDs:

  • Check your LNbits admin panel
  • Or query: curl -X GET http://localhost:5000/api/v1/wallet -H "X-Api-Key: user_invoice_key"

3. Set API Key

export CASTLE_ADMIN_KEY="your_lnbits_admin_invoice_key"
export LNBITS_URL="http://localhost:5000"  # Optional

📖 Usage

cd /path/to/castle/helper

# Test with dry run
python import_beancount.py ledger.beancount --dry-run

# Actually import
python import_beancount.py ledger.beancount

📄 Beancount File Format

Your Beancount transactions must have an Equity:<name> account:

2025-07-06 * "Foix market"
  Expenses:Groceries              69.40 EUR
  Equity:Pat

2025-07-07 * "Gas station"
  Expenses:Transport              45.00 EUR
  Equity:Alice

Requirements:

  • Every transaction must have an Equity:<name> account
  • Account names must match exactly what's in Castle
  • The name after Equity: must be in USER_MAPPINGS

🔄 How It Works

  1. Loads rates from btc_eur_rates.csv
  2. Loads accounts from Castle API automatically
  3. Maps users - Extracts user name from Equity:Name accounts
  4. Parses Beancount transactions
  5. Converts EUR → sats using daily rate
  6. Uploads to Castle with metadata

📊 Example Output

$ python import_beancount.py ledger.beancount
======================================================================
🏰 Beancount to Castle Import Script
======================================================================

📊 Loaded 15 daily rates from btc_eur_rates.csv
   Date range: 2025-07-01 to 2025-07-15

🏦 Loaded 28 accounts from Castle

👥 User ID mappings:
   - Pat → wallet_abc123
   - Alice → wallet_def456
   - Bob → wallet_ghi789

📄 Found 25 potential transactions in ledger.beancount

✅ Transaction 1: 2025-07-06 - Foix market (User: Pat) (Rate: 87,891 EUR/BTC)
✅ Transaction 2: 2025-07-07 - Gas station (User: Alice) (Rate: 88,100 EUR/BTC)
✅ Transaction 3: 2025-07-08 - Restaurant (User: Bob) (Rate: 88,350 EUR/BTC)

======================================================================
📊 Summary: 25 succeeded, 0 failed, 0 skipped
======================================================================

✅ Successfully imported 25 transactions to Castle!

Troubleshooting

"No account found in Castle"

Error: No account found in Castle with name 'Expenses:XYZ'

Solution: Create the account in Castle first with that exact name.

"No user ID mapping found"

Error: No user ID mapping found for 'Pat'

Solution: Add Pat to the USER_MAPPINGS dictionary in the script.

"No BTC/EUR rate found"

Error: No BTC/EUR rate found for 2025-07-15

Solution: Add that date to btc_eur_rates.csv.

"Could not determine user ID"

Error: Could not determine user ID for transaction

Solution: Every transaction needs an Equity:<name> account (e.g., Equity:Pat).

📝 Transaction Metadata

Each imported transaction includes:

{
  "meta": {
    "source": "beancount_import",
    "imported_at": "2025-11-08T12:00:00",
    "btc_eur_rate": 87891.0,
    "user_id": "wallet_abc123"
  }
}

And each line includes:

{
  "metadata": {
    "fiat_currency": "EUR",
    "fiat_amount": "69.400",
    "fiat_rate": 1137.88,
    "btc_rate": 87891.0
  }
}

This preserves the original EUR amount and exchange rate for auditing.