Beancount importers for Chilean banks
Project description
beancount-chile
Beancount importers for Chilean banks using the beangulp framework.
This project provides importers for various Chilean bank account statement formats, enabling automatic import of transactions into Beancount for double-entry bookkeeping.
Supported Banks and Formats
| Bank | Format | Status | File Extension |
|---|---|---|---|
| Banco de Chile | Cartola (Account Statement) | ✅ Supported | .xls, .xlsx, .pdf |
| Banco de Chile | Credit Card Statements (Facturado/No Facturado) | ✅ Supported | .xls, .xlsx |
Installation
Prerequisites
- Python 3.10 or higher
- Beancount 3.x
Install
pip install beancount-chile
Usage
Banco de Chile Importer
The Banco de Chile importer supports XLS/XLSX/PDF account statement files (cartola).
Basic Usage
Create a configuration file (e.g., import_config.py):
from beancount_chile import BancoChileImporter, BancoChileCreditImporter
CONFIG = [
# Checking account
BancoChileImporter(
account_number="00-123-45678-90", # Your account number
account_name="Assets:BancoChile:Checking",
currency="CLP",
),
# Credit card
BancoChileCreditImporter(
card_last_four="1234", # Last 4 digits of your card
account_name="Liabilities:CreditCard:BancoChile",
currency="CLP",
),
]
Import Transactions
Use beangulp to extract transactions:
# Identify which importers can handle your files
bean-extract import_config.py ~/Downloads/
# Extract transactions from a specific file (XLS, XLSX, or PDF)
bean-extract import_config.py ~/Downloads/cartola.xls
bean-extract import_config.py ~/Downloads/cartola.pdf
# Extract and append to your beancount file
bean-extract import_config.py ~/Downloads/cartola.pdf >> accounts.beancount
Note: The importer automatically detects the file format (XLS/XLSX/PDF) and uses the appropriate parser. PDF files are parsed using text extraction, which handles the same transaction types as XLS files.
Example Output
The importer will generate Beancount entries like:
2026-01-01 * "Supermercado Santa Isabel" "Supermercado Santa Isabel"
channel: "Internet"
Assets:BancoChile:Checking -45000 CLP
2026-01-03 * "María González" "Traspaso A:María González"
channel: "Internet"
Assets:BancoChile:Checking -125000 CLP
2026-01-05 balance Assets:BancoChile:Checking 1230000 CLP
Banco de Chile Credit Card Importer
The credit card importer supports both billed (Facturado) and unbilled (No Facturado) statements.
Basic Usage
The credit card importer automatically detects whether a file contains billed or unbilled transactions:
from beancount_chile import BancoChileCreditImporter
CONFIG = [
BancoChileCreditImporter(
card_last_four="1234", # Last 4 digits of your card
account_name="Liabilities:CreditCard:BancoChile",
currency="CLP",
),
]
Example Output
Billed Transactions (Mov_Facturado.xls):
2026-01-08 note Liabilities:CreditCard:BancoChile "Credit Card Statement - FACTURADO (Billed) | Total Billed: $850,000 CLP | Minimum Payment: $42,500 CLP | Due Date: 2026-01-21"
2026-01-02 * "SUPERMERCADO JUMBO" "SUPERMERCADO JUMBO SANTIAGO"
statement_type: "facturado"
category: "Total de Pagos, Compras, Cuotas y Avance"
installments: "01/01"
Liabilities:CreditCard:BancoChile 75000 CLP
Unbilled Transactions (Saldo_y_Mov_No_Facturado.xls):
2026-01-16 note Liabilities:CreditCard:BancoChile "Credit Card Statement - NO FACTURADO (Unbilled) | Available Credit: $6,500,000 CLP | Total Limit: $7,000,000 CLP"
2026-01-16 ! "NETFLIX.COM" "NETFLIX.COM COMPRAS"
statement_type: "no_facturado"
city: "LAS CONDES"
installments: "01/01"
Liabilities:CreditCard:BancoChile 12000 CLP
Note: Billed transactions are marked as cleared (*) while unbilled transactions are marked as pending (!).
Features
- Automatic payee extraction: Extracts payee names from transaction descriptions
- Balance assertions: Adds balance assertions to verify account balances
- Metadata tracking: Preserves channel information (Internet, Sucursal, etc.)
- Deduplication support: Works with beangulp's existing entry detection
- Custom categorization: Optional categorizer function for automatic transaction categorization
Advanced Features
Custom Categorization
Both importers support an optional categorizer parameter that allows you to automatically categorize transactions by providing a custom function. This is more flexible than pattern matching approaches as it gives you full control over the categorization logic.
Categorizer Function Signature
def categorizer(date, payee, narration, amount, metadata):
"""
Categorize a transaction.
Args:
date: Transaction date (datetime.date)
payee: Extracted payee name (str)
narration: Transaction description (str)
amount: Transaction amount (Decimal, negative for debits)
metadata: Dict with transaction-specific metadata
Returns:
str: Account name for categorization, or None to skip
"""
# Your categorization logic here
return "Expenses:Category" or None
Metadata Available
For Checking Account (BancoChileImporter):
channel: Transaction channel (e.g., "Internet", "Sucursal")debit: Debit amount (Decimal or None)credit: Credit amount (Decimal or None)balance: Account balance after transaction (Decimal)
For Credit Card (BancoChileCreditImporter):
statement_type: "facturado" or "no_facturado"installments: Installment info (e.g., "01/12" or None)category: Transaction category for billed statementscity: Transaction city for unbilled statementscard_type: Card information for unbilled statements
Example: Simple Pattern Matching
def my_categorizer(date, payee, narration, amount, metadata):
"""Categorize based on payee name patterns."""
# Internet services
if "Starlink" in payee or "STARLINK" in narration:
return "Expenses:Internet"
# Transportation
if any(keyword in narration.upper() for keyword in ["UBER", "CABIFY", "TAXI"]):
return "Expenses:Transportation"
# Groceries
if any(store in payee.upper() for store in ["JUMBO", "UNIMARC", "SANTA ISABEL"]):
return "Expenses:Groceries"
# Don't categorize this transaction
return None
CONFIG = [
BancoChileImporter(
account_number="00-123-45678-90",
account_name="Assets:BancoChile:Checking",
currency="CLP",
categorizer=my_categorizer,
),
]
Example: Amount-Based Categorization
def amount_based_categorizer(date, payee, narration, amount, metadata):
"""Categorize based on transaction amount."""
# Large debits might be rent or major expenses
if amount < -500000: # More than 500k CLP debit
return "Expenses:Major"
# Credits are income
if amount > 0:
return "Income:Salary"
return None
Example: Metadata-Based Categorization
def metadata_categorizer(date, payee, narration, amount, metadata):
"""Categorize based on transaction metadata."""
# Only categorize online transactions
if metadata.get("channel") == "Internet":
if amount < 0: # Debit
return "Expenses:Online"
# For credit cards, use statement type
if metadata.get("statement_type") == "facturado":
# Already billed transactions
return "Expenses:CreditCard"
return None
Example: Different Categorizers for Different Accounts
def checking_categorizer(date, payee, narration, amount, metadata):
"""Categorizer for checking account."""
if "Starlink" in payee:
return "Expenses:Internet"
return None
def credit_card_categorizer(date, payee, narration, amount, metadata):
"""Categorizer for credit card."""
if "NETFLIX" in payee.upper():
return "Expenses:Streaming"
if metadata.get("city") == "LAS CONDES":
return "Expenses:Shopping"
return None
CONFIG = [
BancoChileImporter(
account_number="00-123-45678-90",
account_name="Assets:BancoChile:Checking",
currency="CLP",
categorizer=checking_categorizer,
),
BancoChileCreditImporter(
card_last_four="1234",
account_name="Liabilities:CreditCard:BancoChile",
currency="CLP",
categorizer=credit_card_categorizer,
),
]
Example Output with Categorizer
When a categorizer is provided and returns an account, transactions will have both postings:
2026-01-01 * "Starlink" "Pago:starlink Starlink"
channel: "Internet"
Assets:BancoChile:Checking -48000 CLP
Expenses:Internet 48000 CLP
2026-01-16 ! "NETFLIX.COM" "NETFLIX.COM COMPRAS"
statement_type: "no_facturado"
city: "LAS CONDES"
installments: "01/01"
Liabilities:CreditCard:BancoChile 12000 CLP
Expenses:Streaming -12000 CLP
Best Practices
- Start Simple: Begin with a few high-frequency patterns and expand over time
- Return None: Always return
Nonefor transactions you don't want to categorize automatically - Case Insensitive: Use
.upper()or.lower()for pattern matching to handle case variations - Test Thoroughly: Review categorized transactions to ensure accuracy
- Use Metadata: Leverage the metadata dict for more precise categorization rules
- Combine Strategies: Mix pattern matching, amount-based, and metadata-based logic as needed
Development
Running Tests
# Activate virtual environment
source venv/bin/activate
# Run all tests
pytest
# Run with coverage
pytest --cov=beancount_chile
# Run specific test file
pytest tests/test_banco_chile.py -v
Code Quality
# Format code with ruff
ruff format .
# Lint code
ruff check .
# Fix auto-fixable issues
ruff check --fix .
Project Structure
beancount-chile/
├── beancount_chile/ # Main package
│ ├── __init__.py
│ ├── banco_chile.py # Checking account importer
│ ├── banco_chile_credit.py # Credit card importer
│ ├── helpers.py # Shared utilities
│ └── extractors/ # File format parsers
│ ├── __init__.py
│ ├── banco_chile_xls.py # Checking account XLS parser
│ ├── banco_chile_pdf.py # Checking account PDF parser
│ └── banco_chile_credit_xls.py # Credit card parser
├── tests/ # Test suite
│ ├── __init__.py
│ ├── test_banco_chile.py # Checking account tests
│ ├── test_banco_chile_credit.py # Credit card tests
│ ├── test_banco_chile_pdf.py # PDF parser tests
│ └── fixtures/ # Test data (anonymized)
│ ├── banco_chile_cartola_sample.xls
│ ├── banco_chile_credit_facturado_sample.xls
│ └── banco_chile_credit_no_facturado_sample.xls
├── pyproject.toml
├── requirements.txt
└── README.md
Contributing
Contributions are welcome! To add support for a new bank:
- Fork the repository
- Create a feature branch
- Add the importer in
beancount_chile/ - Add an extractor in
beancount_chile/extractors/ - Create anonymized test fixtures in
tests/fixtures/ - Write comprehensive tests
- Update this README
- Submit a pull request
Guidelines
- Privacy: Never commit real bank data. All test fixtures must use anonymized data.
- Testing: Every importer must have comprehensive tests.
- Documentation: Update README.md and CLAUDE.md with new features.
- Code Quality: Follow PEP 8 and use ruff for linting.
License
MIT License
Disclaimer
This project is not affiliated with any bank. Use at your own risk. Always verify imported transactions against your bank statements.
Support
For issues, questions, or contributions, please open an issue on GitHub.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file beancount_chile-0.3.1.tar.gz.
File metadata
- Download URL: beancount_chile-0.3.1.tar.gz
- Upload date:
- Size: 27.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
729afb5d233abc6cedc28c981d2b486c153fa4ced79a99eadac6f31d6118a6fc
|
|
| MD5 |
d4a083a39bb1c9f9ec843f632fe82356
|
|
| BLAKE2b-256 |
b0b85b23dd31bd7a896bd53c3056bc368de99720283c50c816fb3a0e2d0887bb
|
Provenance
The following attestation bundles were made for beancount_chile-0.3.1.tar.gz:
Publisher:
publish.yml on mabahamo/beancount-chile
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
beancount_chile-0.3.1.tar.gz -
Subject digest:
729afb5d233abc6cedc28c981d2b486c153fa4ced79a99eadac6f31d6118a6fc - Sigstore transparency entry: 832906946
- Sigstore integration time:
-
Permalink:
mabahamo/beancount-chile@b65079ff423482464fe3448b9fc1bc924ae09cb1 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/mabahamo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b65079ff423482464fe3448b9fc1bc924ae09cb1 -
Trigger Event:
release
-
Statement type:
File details
Details for the file beancount_chile-0.3.1-py3-none-any.whl.
File metadata
- Download URL: beancount_chile-0.3.1-py3-none-any.whl
- Upload date:
- Size: 23.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3e6a980c452d3e8129d3fb28fcc580e978a5b6d82d4f89448063ac2bb1798471
|
|
| MD5 |
eeb1842d348eea18437f3334aa55552f
|
|
| BLAKE2b-256 |
9913cb443f01a35b81573bb0f1beee0c61d86f6839b83b16f9ff5ea259b7872c
|
Provenance
The following attestation bundles were made for beancount_chile-0.3.1-py3-none-any.whl:
Publisher:
publish.yml on mabahamo/beancount-chile
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
beancount_chile-0.3.1-py3-none-any.whl -
Subject digest:
3e6a980c452d3e8129d3fb28fcc580e978a5b6d82d4f89448063ac2bb1798471 - Sigstore transparency entry: 832906950
- Sigstore integration time:
-
Permalink:
mabahamo/beancount-chile@b65079ff423482464fe3448b9fc1bc924ae09cb1 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/mabahamo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b65079ff423482464fe3448b9fc1bc924ae09cb1 -
Trigger Event:
release
-
Statement type: