I first started using ledger the original
plain-text accounting
software in 2017. Since then, I had been pretty happy with my
accounting routine, but grew a little annoyed by the repetitive manual work I
had to do to assign recurring transactions to the right account.
To make things easier, I had a collection of bash scripts to parse and convert
the CSV files from my bank's website
into ledger entries. They were of
course ugly, unreadable piles of sed-grep-regex and did not let met achieve the
automation complexity I longed for.
Dissatisfied with ledger's features, I decided to migrate to hledger. Contrary
to ledger, hledger comes with a
CSV parser one can use to import
and classify recurring transactions automagically.
Having a proper DSL for this makes all the difference: I can easily add new
rules and understand the old ones. In the end, I get a very consistent result,
something my old bash scripts weren't great at.
Here is what my
debit.csv.rules
file looks like. It is used to tell hledger
how CSV data from my debit card should be parsed:
# skip the headings line:
skip 1
# assign fields
fields , , , date, , description, , amount2-in, amount2-out
# assign account where the money comes from
# 99 to get it at the bottom of the transaction
account99 assets:checking
include matchers.rules
As you can see, the rules matching transactions to specific accounts are
imported from another file,
matchers.rules
. I'm doing this since I want to be
able to use the same set of rules for debit and credit and use the cards
interchangeably.
Here's a snippet of my
matchers.rules
file:
# house
if Loyer/bail
account2 expenses:rent
# leisure
if PAYPAL .*STEAM GAMES
account2 expenses:leisure:videogame
if PAYPAL .*BANDCAMP
account2 expenses:leisure:music
Using this ruleset, a transaction looking like this:
"SOME ACCOUNT DESC","111111","EOP","2022/01/03",00002,"Loyer/bail","",521.00,"","","","",""
Would be transformed into:
2022-01-03 Loyer/bail
expenses:rent 521.00
assets:checking
Sadly, hledger's CSV rules won't let you do arithmetics. This can be useful
when you know a certain transaction needs to be split between accounts.
This is where
auto postings come in. They are a way to specify arbitrary
rules when an account is encountered.
Going back to my previous rent example, I split it 50/50 with my SO using this
rule:
= expenses:rent
assets:receivable:rent *0.5
assets:checking
After it is applied, the final transaction looks like this:
2022-01-03 Loyer/bail ; modified:
expenses:rent 521.00
assets:receivable:rent 260.50 ; generated-posting: = expenses:rent
assets:checking
Neat eh? Here is the little bash script I've written to automate all these
steps:
#!/bin/bash
#
# Convert CSV to ledger using hledger
declare -a assets=("credit" "debit")
# Read the array values with space
for i in "$ assets[@] "
do
if test -f "$i.csv"
then
# convert to ledger
LEDGER=$(hledger -f "$i.csv" --rules-file rules/"$i.csv".rules print)
# add auto_postings
LEDGER=$(printf "include rules/auto_postings.ledger\n\n$LEDGER\n" hledger print -f- --auto)
# remove superfluous assets:checking lines
LEDGER=$(printf "$LEDGER" sed '/assets:checking \+; generated.\+/d')
printf "$LEDGER" > "$i.ledger"
else
printf "File $i.csv does not exist\n"
fi
done
Migrating to hledger, I've cut down the time I spend on accounting from 1 hour
per month to about 10 minutes, all while making my workflow much cleaner.
Many thanks to the kind folks on
#hledger @irc.libera.chat
for the help!