tmbb

tmbb

Plaintext accounting as DSL for finance

Plaintext accounting is a whole philosophy which tries to get the best of both simple paper ledgers (for maximum flexibility and portability) and the capabilities of modern computers (for maximum error-avoidance). Some interesting software in this category is ledger, hledger (similar to ledger, but implemented in haskell) and beancount (similar to the ones above, implemented in python).

I think all the above programs have some important flaws (ledger is actually not very good, hledger seems to be a bit inplexible with imports and beancount makes it very hard to import transaction data whithout looking at the source and writing custom python scripts). I actually like the flexibility of beancount, but I’ve decided to go a little further and implement a ledger as a DSL on top of Elixir.

The idea is very simple: a ledger is a sequence of elixir function calls (which use the process dictionary for shared mutable state, which is safe because everything runs in order) which build a ledger datastructure in the background. This allows us to have an unambiguous grammar with some goodies such as Elixir sigils.

For example, this very simple ledger which features the opening of accounts, a 3-way transaction and a balance check (the numbers are random, nothing actually checks). The functions in this file only generate the ledger, they don’t actually check anything, that is left for an as of yet unimplemented module.

open ~D[1990-04-25], account("Expenses::Groceries"), currency: "EUR", note: "track all groceries"
open ~D[1990-04-24], account("Expenses::Eating out"), currency: "EUR"
open ~D[1990-04-24], account("Expenses::Going out (other)"), currency: "EUR"

open ~D[2010-04-24], account("Assets::Bank::Checking"), currency: "EUR"
open ~D[1990-04-24], account("Assets::Cash"), currency: "EUR"

open ~D[2010-04-24], account("Income::Salary"), currency: "EUR"
open ~D[2010-04-24], account("Income::Studio rent"), currency: "EUR"

txn ~D[2025-07-09], notes: "account", accounts: %{
  account("Income::Studio rent") => ~A[-800 EUR],
  account("Liabilities::Tax::Tax owed on rent") => ~A[224 EUR],
  account("Assets::Bank::Checking") => ~A[576 EUR]
}

balance ~D[2025-07-09], account("Assets::Bank::CGD::Checking"), ~A[200 EUR]

Has anyone here ever tried something like this?

I think this doens’t attempt to sandbox the elixir execution, so a maliciously constructed ledger could do bad things to your computer. However, I believe, it might be easy to sanbox it if one disallows the use of qualified functions.

Showing Posts 1 to 3

waseigo

waseigo

Double-entry book-keeping is something that I’m interested in. I played around with Tigerbeetle many moons ago and found it impressive, but also overkill for my needs.

At some point I’ll build something using this: GitHub - coinjar/ex_double_entry: An Elixir double-entry library inspired by Ruby's DoubleEntry. Brought to you by CoinJar. · GitHub

It might be useful for you too.

sbuttgereit

sbuttgereit

Sorry, but an accounting nit which admittedly is besides the point of your post. The transaction below…

… looks wrong to me. You’re showing that you’re paying a liability, the amount that you owe someone, without ever having booked an expense for which that liability was incurred. Typically, for an incurred tax liability you’d have two transactions.

When the income is earned and on which the taxes are levied:

txn ~D[2025-07-09], notes: "account", accounts: %{
  account("Income::Studio rent") => ~A[-800 EUR],
  account("Expense::Tax::Taxes on rent") => ~A[224 EUR],
  account("Liabilities::Tax::Taxes owed") => ~A[-224 EUR],
  account("Assets::Bank::Checking") => ~A[800 EUR]
}

Later when the taxes are paid:

txn ~D[2025-08-01], notes: "account", accounts: %{
  account("Liabilities::Tax::Taxes owed") => ~A[224 EUR],
  account("Assets::Bank::Checking") => ~A[-224 EUR]
}

This represents that between earning the income which causes the taxes and the actual payment of the taxes, the money was sitting in your checking account. Naturally, if the taxes are paid straight-away, you’d just book the expense and never go to the liability account at all. There’s more to say about this… but this is a forum for Elixir and not accounting… so I’ve already said too much :slight_smile:. Also, I’m not an accountant, but am forced to play one in my daily work with uncomfortable regularity… so I could be completely wrong!

tmbb

tmbb OP

Thank you for the links, but I think the goal of the projects you’ve linked is very different from my own goal. My own goal is to have the elixir script define a ledger (which is of course further processed by code that checks everything is fine). There is no database because the script is the database.

— All posts loaded —

Where Next? Top

Trending in Discussions Top

AstonJ
As the title says, please share what you’ve been up to with Elixir. Whether that’s been learning it, looking into it, making stuff with i...
2977 94592 917
New
cblavier
Hey there, It’s been more than a year since we started using LiveView as our main UI library and building a whole library of UI componen...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
heathen
Quite interesting article Google brought me. Didn’t find any mentions about it here. What do you think in general? Would you use togethe...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New
axelson
Hi there! :wave: @frigidcode and I (but mostly him) have been running an Elixir Book club, we’re almost done with Designing Elixir Syste...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
georgeguimaraes
Just published claude-code-elixir, a plugin marketplace for Claude Code with Elixir support. These are the plugins I’ve been using for my...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews