Patterns for Accounting
24 January 2006
This is part of the Further Enterprise Application Architecture development writing that I was doing in the mid 2000’s. Sadly too many other things have claimed my attention since, so I haven’t had time to work on them further, nor do I see much time in the foreseeable future. As such this material is very much in draft form and I won’t be doing any corrections or updates until I’m able to find time to work on it again.
Although I know of no survey that's figured it out, I would believe that a very large proportion of the world's computer systems track money. If nothing else, I guess this means that money is valuable. Indeed it's so valuable that human beings have been obsessed with tracking money for hundreds of years, there's even a rather large profession (Accountancy) dedicated to it. (As a test you can tell if an organization cares more about something than money by comparing how many trackers of the other thing it has compared to accountants.)
One of the most fundamental concepts in accounting is double-entry bookkeeping, developed in medieval times and first documented by Luca Pacioli, an Italian friar, in 1494. Fundamental to this is that you keep track of various pots of money by carefully tracking every movement of money.
The pots of money are Accounts. Each Account has a balance, which is its current value, and a list of Accounting Entrys which represent every change to the Account. The value, or balance, of the Account is derived as the sum of all the Accounting Entrys. A balance can be calculated for now, but in general a balance is over some time period, in which case it sums the value of entries that were posted within that time period.
Although I've listed these as a common group of objects, much of these are optional. I've seen systems use Accounting Entry without Account or Accounting Transaction. Essentially Account acts as a descriptor for classifying Accounting Transactions; so it is possible to use other objects as descriptors. Similarly Accounting Transaction can be dropped if you are less concerned about careful tracking of transfers as Accounting Entrys.
Accounts keep track of the monetary consequences of events, which means they work very well with Event Sourcing. When a Domain Event is processed, it can produce a set of Accounting Transactions. If all Accounting Transactions are produced from processing Domain Events then the Accounting Transactions use Event Sourcing, even if other parts of an application aren't event sourced.
In this kind of situation, Accounting Transactions lend themselves naturally to automatic fixing of errors using Retroactive Event. To do this you need to find the Accounting Transactions that were produced by the erroneous event, determine what Accounting Transactions should have been produced, and then carry out an adjustment to change the erroneous set into the correct set. There are three ways of doing this adjustment.
- Replacement Adjustment deletes the incorrect Accounting Transactions and creates the correct set. It's a simple approach, but it means that you lose history of Accounting Transactions within the accounting framework. (You still can reconstitute it used Parallel Model, but that's not as direct.)
- With Reversal Adjustment you leave the incorrect Accounting Transactions in place, but for each one you post an opposite Accounting Entry to cancel it out. You then post the correct Accounting Transactions to bring things up to the new value. This is pretty straightforward, keeps history, but leads to lots of entries that just cancel each other out.
- Difference Adjustment also leaves the incorrect entries in place, but posts in new entries that represent the difference between the incorrect and correct entries. You can do this by performing one of the other adjustments in a Parallel Model and posting entries that represent the differences between account balances. This keeps history, minimizes the amount of Accounting Transactions, but is more complicated to do.
I've concentrated here on automatic correction using Retroactive Event, but of course you can use these same adjustment approaches to record the results of a manual change.