This set of sample files shows how to organize timetracking and billing with tools like ledgercli and hledger.
The ledger file file includes a timelog. The ledger file also includes transactions to issue a bill with the timelog entries and receive a payment against the bill.
The timelog is separate to make interaction with time tracking tools.
For example, timeclock.el
can generate such a file, usually in
~/.timelog
. In my case, I use org-mode's clocking work time
system to "punch" in and out of different tasks. I then use
John Wiegley's org2tc script to export the clock entry to the
timeclock
format. (Also note that I have
made a few improvements to org2tc that you might be interested
in.)
The resulting ledger balance looks like this:
$ ledger -f ledger.lgr bal
10€ assets:cash
1.00h income:client
--------------------
1.00h
10€
You see we have 10€
in cash, which is about right. However, the
ledger is unbalanced: there's a 10€
and a 1h
that are not matched. That is
because the time entries are "virtual" and so entered only against one
account. To ignore time entries, use the --real
(-R
) flag:
$ ledger -f ledger.lgr bal -B -R
10€ assets:cash
-10€ income:client
--------------------
0
Now our ledger is properly balanced. The downside is that we don't see
the 1h
that still has to be billed. Also notice how we need to
convert the units with --basis
(-B
) otherwise it will show up like
this, which is expected given the different units:
$ ledger -f ledger.lgr bal -R
10€ assets:cash
-10.00h income:client
--------------------
-10.00h
10€
To issue new bills, we will look at those unbalanced virtual entries. They allow you to notice there is another hour of client work to bill. You can issue a bill against that extra hour to complete your billing with an entry like:
2016/01/28 bill
income:client -1h @ 1€
assets:receivables
Then you see something like this:
$ ledger -f ledger.lgr bal
11€ assets
10€ cash
1€ receivables
--------------------
11€
Congratulations, you billed all your hours! It is still
unbalanced, but you can fix that with -R
, as we did before:
$ ledger -f ledger.lgr bal -B -R
11€ assets
10€ cash
1€ receivables
-11€ income:client
--------------------
0
Notice how this shows a 1€ unpaid bill that we are waiting a payment for, which is expected because we only issued the bill and not the payment.
The is the part I am stuck at. I have tried to make a
shell script to generate a bill, but I can't figure
out how to extract the hourly rate. I'd also love to get the details
of the affected punches, but I don't think there's a way to map
transactions like this in ledger. I could extract only the uncleared
punches, set the invoice then clear them, but this would be
overwritten at the next run of org2tc
.
I have even tried to set a commodity price, inspired by adams rate example:
P 2016/01/28 00:00:00 h 1€
But that didn't seem to actually work: the price doesn't apply. But I am not very familiar with this part of ledger.
I have also tried using the Python API but failed to go very far: i could not extract cost there either.
I want to print invoices. More todos above and in the shell script.
The ledger file fails to load in hledger:
$ hledger -f ledger.lgr bal
creating default conversion rules file /home/anarcat/src/ledger-timetracking/ledger.lgr.rules, edit this file for better results
hledger: "/home/anarcat/src/ledger-timetracking/ledger.lgr" (line 1, column 1):
unexpected 'a'
expecting journal transaction or directive or end of input
1$
It first chokes on the apply account
directive from ledger (this was
fixed in commit a2b989d). But even using the regular hledger
include fails:
$ hledger -f hledger.lgr bal
using conversion rules file /home/anarcat/src/ledger-timetracking/hledger.lgr.rules
hledger: "/home/anarcat/src/ledger-timetracking/hledger.lgr" (line 2, column 1) in included file "timelog":
"/home/anarcat/src/ledger-timetracking/timelog" (line 1, column 1):
unexpected 'i'
expecting journal transaction or directive or end of input
1$
This was filed as issue #320 in hledger.
I may be able to feed the timetracking data directly in the
hledger.lgr
file, but
that's rather painful: i'd like to keep that messy file separate from
the main accounting.
The way transactions are imported, above, makes time entries show up
as unbalanced. It's confusing and annoying - there should be a way to
balance them with the right account, maybe the income
account.
But then that would mean the income
account would empty when we
bill, which is not correct: it should be debited with the size of the
bill, so that we have the running expenses showing up in balance
reports.
So in fact, unbalanced entries may be exactly the point of this.
There's this strange error that happens when doing a monthly registry report:
$ ledger -f ledger.lgr reg -p monthly
Error: 'equity' cannot accept virtual and non-virtual postings to the same account
This is not a problem when doing a daily report, as the invoice is (deliberately) sent the day after the time entries:
$ ledger -f ledger.lgr reg -p daily
70-Jan-01 - 70-Jan-01 (income:client) 9.99h 9.99h
70-Jan-02 - 70-Jan-02 assets:cash 10€ 9.99h
10€
equity:volunteer 59.5m 10.98h
10€
income:client -10.99h -30s
10€
How can I work around that issue?
If I understand this right, such an assertion should check that, at the given time, the balance on the account is a given amount:
1970/01/02 assert we have billed everything
[income:client] = 0s
In the above case, there should be zero seconds to be billed to the client on January 2nd. Unfortunately, this doesn't work: if there are punches after that date, they still count towards that balance:
$ ledger -f ledger.lgr bal
While parsing file "/home/anarcat/src/ledger-timetracking/ledger.lgr", line 19:
While balancing transaction from "/home/anarcat/src/ledger-timetracking/ledger.lgr", lines 18-19:
> 1970/01/02 assert we have billed everything
> [income:client] = 0s
Unbalanced remainder is:
-3600s
Amount to balance against:
0
Error: Transaction does not balance
Whereas the punch was after the given date:
i 1970-02-01 12:00:00 client client:test4 1h
o 1970-02-01 13:00:00
A month later!