Counting corporate beans

LWN.net needs you! Without subscribers, LWN would simply not exist. Please consider signing up for a subscription and helping to keep LWN publishing

Some things simply take time. When your editor restarted the search for a free accounting system, he had truly hoped to be done by now. But life gets busy, and accounting systems are remarkably prone to falling off the list of things one wants to deal with in any given day. On the other hand, accounting can return to that list quickly whenever LWN's proprietary accounting software does something particularly obnoxious. This turns out to be one of those times, so your editor set out to determine whether beancount could do the job.

Beancount was already covered here almost exactly one year ago, but that review was focused on personal finances; company accounting has a different set of requirements. That article is worth reviewing, though, as the material covered there will (mostly) not be repeated here. Here, instead, the emphasis will be on what a simple business needs.

At the top of the list is the ability to import data into the system and to get it back out again. An ongoing business has a long accounting history that needs to be present going forward. Beancount keeps all of its data in a plain-text file with a well-documented format, so both import and export are relatively easy. Building on the the tools written to extract data from QuickBooks, your editor was able to write a script to import the accounting database into beancount over the course of an hour or two.

File formats

There are a couple of things worth noting about the format of the beancount file, though. A typical transaction entry looks like this:

2019-04-01 txn "Faithful reader" "Subscription, professional hacker, 12 months" Assets:Paypal 71.97 USD Income:SubscriptionIncome -75.60 USD Expenses:PayPalExpense 3.63 USD

The first line provides the date and overall descriptive information; the following lines describe the various components of the transactions. These lines are called "postings" in beancount; many other systems will call them "splits" instead. By whatever name, they describe the movement of funds from one account to another; the amounts in the postings must add up to zero. This format has all of the basic information, but there are some shortcomings too.

For example, there is no way in the base format to note whether a transaction has been reconciled or not. Reconciliation is a crucial feature in an accounting system; it's how you know that your view of a specific account matches that of the financial institution on the other side. Beancount provides the ability to "assert" the balance in an account on any given date; it will then verify that the assertion is true. But that falls apart when there is a time lag between when a transaction is initiated and when it shows up in the account; outstanding checks are one example, but there are many others. Lack of proper reconciliation is a nearly fatal flaw in its own right for this particular use case.

One could of course add this feature. Beancount provides the ability to attach "metadata" to transactions, so one can add a flag that looks like this:

2019-04-01 txn "Faithful reader" "Subscription, professional hacker, 12 months" reconciled: "no" Assets:Paypal 71.97 USD Income:SubscriptionIncome -75.60 USD Expenses:PayPalExpense 3.63 USD

Then one could write the tools to support the reconciliation pass. Other missing data, such as check or transaction numbers, could be supported in the same way. It would all work, but the whole purpose was to not have to actually write the accounting system.

There's another interesting question here: how does beancount distinguish the metadata line above from the splits? It turns out that it's all done with case: account names must start with a capital letter, while metadata "keys" must be entirely lower case. Currencies ("USD" above) must be all upper case. Rules of this nature strike your editor as being somewhat fragile and unobvious; they could also restrict the project's ability to extend the transaction format in the future.

It is also worth noting that beancount explicitly ignores any lines in the file that it doesn't recognize. The apparent purpose of this feature is to allow other types of markup in the file; the ability to manage it with the Emacs Org mode is said to be especially gratifying. But this behavior can also make it easy for mistakes to pass unnoticed. Similar behavior in cron has led to security vulnerabilities in the past. Your editor would feel much better knowing that a corrupted beancount file would not escape notice.

Doing accounting

Since beancount is primarily a command-line application, there are no fancy user interfaces for dealing with accounting data. There is an Emacs mode that can help with the creation of transactions; it can perform helpful tasks like name completion. Much of the rest is expected to be done with scripts; there are a number of tools for importing transactions from various sources and a plugin mechanism to augment the processing of those transactions.

Many of the features that one would expect from an accounting system are absent from beancount. There is no ability to generate and track invoices, for example. The same can be said for bills. Indeed, beancount doesn't really have a concept of "accounts receivable" and "accounts payable" built into it. Again, one could add that with a bit of work, but that would be more work to do.

Another significant missing feature is the ability to detect and merge duplicate transactions. The failure to store transaction numbers makes things worse here. The beancount documentation talks about how, with balance assertions in place, duplicates will generate errors that can then be fixed up by hand. That may be tolerable in a personal-finance system; it will lead to significant grumpiness in a business accounting system that has to handle far more transactions.

There is a rudimentary set of reports built into beancount; they look the way one expects a balance sheet or a profit-and-loss statement to look, but there is a lack of flexibility. For example, it is pretty normal to want to restrict a report to a given period of time. The command-line tools appear to lack that capability entirely; the bean-web and fava web-based tools can only select a full year at a time. Fava can generate a basic line plot, but otherwise there is no ability to create plots at all. No pie charts for beancount users; your editor can live with that just fine, but others may feel differently. Beancount also provides a way to perform SQL-like queries on the database, which can be useful for extracting certain kinds of data.

It is worth noting that beancount is generally quick at generating reports, despite reading data from a large text file. Indeed, it is rather quicker than QuickBooks, which is faint praise but still a good thing. Still, it seems clear that the plain-text file will slow things down at some point; indeed, the beancount maintainer recently said that he's beginning to find things a bit too slow.

There is no concept of customers or vendors, so if one needs to store related information (addresses, payment terms, tax ID numbers, etc.) that information must be kept elsewhere.

One feature that isn't useful for LWN but which might be for others is the ability to track "held values" for commodities. Its primary purpose appears to be to ease the calculation of capital gains on investment transactions (investment tracking seems to be one of the main use cases for beancount's developers), but it could be put to use in any situation where one needs to track a price change between the purchase and the sale of a commodity.

Another important task is providing data to the accountant for tax filings and such. Ideally, that data would be in a form that can be read directly into their (proprietary) tax software, but that feature appears to only be available in proprietary systems. Lacking that, it would still be nice to not have to print a pile of data and hand-carry it over to get one's taxes done. Beancount has the ability to "bake" the data into a set of HTML pages that can then be placed somewhere where the accountant can see them. It is, essentially, a static site generator for accounting data.

There is, alas, no ability to generate government-mandated forms from the accounting data — a common failing in free accounting systems. Beancount also lacks the ability to print checks. Your editor is aware that you youngsters out there may never have even seen a check, but they still are necessary at times in a business setting.

Community and more

A look at the beancount Mercurial repository shows a project with a steady stream of activity. The maintainer, Martin Blais, dominates the list with far more commits than anybody else, but he is also far from the only contributor to the project. If Blais were to abruptly conclude that he'd counted enough beans for a lifetime and leave the project, there is a good chance that somebody else would step up to keep things going. That, needless to say, is a good feature for a project that a company may come to depend upon.

There is a mailing list (tragically hosted on Google Groups) as well, with a fair amount of traffic. The beancount community seems to be both engaged and helpful.

Your editor has concluded that beancount is not the solution for LWN's accounting problem. Lest the criticisms in this article seem harsh, though, it is worth pointing one thing out: this was always an attempt to use beancount for a task that is somewhat beyond what it was created for. Most of the "shortcomings" listed here are a result of that mismatch. Beancount is clearly a useful tool in many settings; for those with simpler needs it may provide all that is required, and it is easily extended for those who need to do so.

Meanwhile, the search for a QuickBooks replacement goes on, hopefully with renewed momentum. Stay tuned... sooner or later a conclusion will be reached and we'll be able to close the books on proprietary accounting systems forever.

