castle/helper/README.md
padreug 9054b3eb62 Adds Beancount import helper script
Implements a script to import Beancount ledger transactions into the Castle accounting extension.

The script fetches BTC/EUR rates, retrieves accounts from the Castle API, maps users, parses Beancount transactions, converts EUR to sats, and uploads the data to Castle.

Adds error handling, dry-run mode, and detailed logging for improved usability.
Displays equity account status and validates the existence of user equity accounts.
2025-11-08 23:18:42 +01:00

168 lines
4.1 KiB
Markdown

# 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:
```csv
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:
```python
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
```bash
export CASTLE_ADMIN_KEY="your_lnbits_admin_invoice_key"
export LNBITS_URL="http://localhost:5000" # Optional
```
## 📖 Usage
```bash
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:
```beancount
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
```bash
$ 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:
```json
{
"meta": {
"source": "beancount_import",
"imported_at": "2025-11-08T12:00:00",
"btc_eur_rate": 87891.0,
"user_id": "wallet_abc123"
}
}
```
And each line includes:
```json
{
"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.