Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 

README.md

CSV Importer Example

This example demonstrates how to programmatically build Beancount transactions from CSV bank statement data using the ast builder functions.

Overview

The importer reads a CSV file containing bank transactions and converts each row into a properly formatted Beancount transaction. It showcases:

  • Using encoding/csv from Go's standard library to parse CSV files
  • Building AST nodes with the functional options pattern (ast.NewTransaction, ast.NewPosting)
  • Automatic expense categorization based on payee names
  • Error handling for invalid dates and amounts
  • Formatting transactions with the formatter package

CSV Format

The input CSV file should have the following columns:

Date,Payee,Amount
2024-01-15,Whole Foods Market,-125.43
2024-02-01,Acme Corp Payroll,3500.00
  • Date: YYYY-MM-DD format
  • Payee: Transaction description
  • Amount: Positive for income, negative for expenses

Usage

Run the importer with a CSV file:

go run main.go transactions.csv

This will output Beancount transactions to stdout:

; Imported from transactions.csv
; Generated by csv_importer example

2024-01-15 * "Whole Foods Market"
  Expenses:Groceries  125.43 USD
  Assets:Checking

2024-02-01 * "Acme Corp Payroll"
  Assets:Checking  3500.00 USD
  Income:Salary

You can redirect the output to a file:

go run main.go transactions.csv > imported.beancount

Customization

Adding Expense Categories

Edit the categorizeExpense() function to add custom categorization rules:

case strings.Contains(payeeLower, "amazon"),
     strings.Contains(payeeLower, "ebay"):
    return "Expenses:Shopping"

Changing the Default Account

Modify the checkingAccount variable in recordToTransaction():

checkingAccount, _ := ast.NewAccount("Assets:BankOfAmerica:Checking")

Adding Metadata or Tags

Use additional builder options when creating transactions:

txn := ast.NewTransaction(date, record.Payee,
    ast.WithFlag("*"),
    ast.WithTags("imported", "needs-review"),
    ast.WithPostings(postings...),
)

What This Demonstrates

This example shows the key features of the ast builder API:

  1. Validated constructors: ast.NewDate() and ast.NewAccount() return errors for invalid input
  2. Functional options: ast.NewTransaction() and ast.NewPosting() use the options pattern for flexibility
  3. Builder composition: Postings are built separately and passed to transactions
  4. Formatting: The formatter package outputs clean, aligned Beancount syntax

Next Steps

For more complex scenarios, you might want to:

  • Add support for costs and prices (for investment accounts)
  • Handle multiple currencies
  • Parse additional CSV columns (category, tags, account overrides)
  • Implement interactive categorization prompts
  • Store categorization rules in a configuration file