Dec 6, 2017 - 22 minute read - programming accounting

Accounting For Software Engineers

For my current job, I’ve had to learn how accounting works. In order to learn that, I did the kinds of things you’d expect I might. But one thing I kept finding was that some fairly simple concept seemed to be explained in a way over-complicated way, after I eventually was able to figure it out. I eventually figured out why, and with that, I think that if you’re new to accounting, and a software engineer, I think I can help you out.

The difference between accountants and software engineers, when it comes to accounting systems, is about what we primarily care about. Accountants care about meaning: is the quick ratio in good shape? Is income growing at an expected rate? How do we deal with an upcoming expense? Software engineers care about: will we properly move money around so that the balances are correct given certain latency, concurrency, etc.? Do we have the information required to generate the Income Statement? How do we represent a credit memo?

Once I understood this fundamental difference, it gave me insight into how and why things are described in the accounting world.

The elements of double-entry bookkeeping haven’t changed much in the 523 years since Luca Pacioli published his book that described (among other things) double-entry bookkeeping. That being the case, from a concept perspective, as an engineer, you shouldn’t need to invent anything. If you find yourself doing so, please think again and talk to an accountant. While you may need to deal with your varied mechanisms and invent things becasue the off-the-shelf solution won’t cut it for you, accounting concepts should not need to be invented (at least by you), but the job is merely find the proper ways to apply existing concepts to the problem at hand.

Something I did which gave me much better insight into all of this was to create the books for my personal finances on paper. I used printable paper’s 3 column, letter orientation ledger paper. For the journal, I only used two columns, but for accounts, you’ll want three.

In accounting, there are a few main things from which everything else derives or can be wedged in, in some way:

  • debits/credits
  • the journal
  • the accounts
  • ledgers
  • invoices


The classic description of credits and debits is something like:

A credit increases the value of a liability account, and a debit increases the value of an asset account.


One account will receive a “debit” entry, meaning the amount will be entered on the left side of that account. Another account will receive a “credit” entry, meaning the amount will be entered on the right side of that account.

While these are both accurate, for an engineer, these don’t exactly help clear things up. Wikipedia actually gives a decent, if sloppy, description:

[D]ebits and credits are entries made in account ledgers to record changes in value resulting from business transactions. Generally speaking, the source account for the transaction is credited (that is, an entry is made on the right side of the account’s ledger) and the destination account is debited (that is, an entry is made on the left side).

In short: you __c__redit the account(s) where the money comes from, and debit the account(s) that are the destination(s) of the money.

The Journal

The journal is the set of transactions against the accounts. If you’re working on paper, the journal should be written in ink because it should be write once. My Dad, now since retired, had clients that required that the ledger was posted in indelible fountain pen ink so as to prevent anyone meddling with them. For us engineers, if you’ve worked with log structured storage systems, the journal is the log of the set of accounts.

A transaction in the journal is comprised of at least the following:

  • a transaction number
  • a date
  • a description
  • an unordered set of credit and debit operations against accounts in the general ledger

Since SQLite is easily accessible to just about everybody, I’ll use it for the SQL examples. As engineers, we can think of the set of books as the following database tables. This example is very simplified from what a real accounting system would have, and as engineers, you’d probably make an adjustment or two.

CREATE TABLE account (
  name       VARCHAR(255) NOT NULL,
  acct_type  VARCHAR(20) NOT NULL

CREATE TABLE journal (
  txn_id      INTEGER PRIMARY KEY,
  txn_date    DATE NOT NULL,
  description VARCHAR(255) NOT NULL

CREATE TABLE journal_crdr (
  debit      DECIMAL(10,2),
  credit     DECIMAL(10,2),
  FOREIGN KEY(txn_id) REFERENCES journal(txn_id),
  FOREIGN KEY(account_id) REFERENCES account(account_id)

So let’s create some accounts.

-- some accounts
INSERT INTO account (name, acct_type) VALUES
    ('credit card', 'liability'),
    ('income', 'income'),
    ('benefits', 'expense'),
    ('taxes', 'expense'),
    ('A/R:Bill''s computing', 'asset'),
    ('A/P:Power co.', 'liability'),
    ('clothing', 'expense'),
    ('checking account', 'asset'),
    ('expenses', 'expense'),
    ('equity', 'equity');

Now just to make it so things look pretty when we do selects in a bit:

sqlite> .mode column
sqlite> .headers on

When showing debit and credit operations in user interfaces, or on paper, debits are to the left, and credits to the right.

For example, if I buy a shirt for $30 on my credit card, the journal entry might look like this:

INSERT INTO journal (txn_id, txn_date, description) VALUES
   (1, '2017-09-01', 'pay for shirt with credit card');
INSERT INTO journal_crdr (txn_id, account_id, debit, credit) VALUES
   (1, (select account_id from account where name = 'clothing'), 30, NULL),
   (1, (select account_id from account where name = 'credit card'), NULL, 30);

buy shirt entry

There need not be only one debit or credit in a transaction. For example: for when I get a paycheck, it might look like this (if I’m tracking my benefit and taxes):

INSERT INTO journal (txn_id, txn_date, description) VALUES
   (2, '2017-09-02', 'Got paid');
INSERT INTO journal_crdr (txn_id, account_id, debit, credit) VALUES
   (2, (select account_id from account where name = 'benefits'), 150, NULL),
   (2, (select account_id from account where name = 'taxes'), 300, NULL),
   (2, (select account_id from account where name = 'checking account'), 550, NULL),
   (2, (select account_id from account where name = 'income'), NULL, 1000);

got paid entry

Sometimes, no real money really changed hands yet. For example, say I did some work, and cut an invoice (sent the bill) with NET-30 payment terms:

INSERT INTO journal (txn_id, txn_date, description) VALUES
   (3, '2017-09-03', 'Did work for William, PO #910, Invoice #234');
INSERT INTO journal_crdr (txn_id, account_id, debit, credit) VALUES
   (3, (select account_id from account where name = 'A/R:Bill''s computing'), 500, NULL),
   (3, (select account_id from account where name = 'income'), NULL, 500);

did work

Or conversely, I received a bill for services, payable NET-30:

INSERT INTO journal (txn_id, txn_date, description) VALUES
   (4, '2017-09-03', 'Foo power co. Stmt #567');
INSERT INTO journal_crdr (txn_id, account_id, debit, credit) VALUES
   (4, (select account_id from account where name = 'expenses'), 250, NULL),
   (4, (select account_id from account where name = 'A/P:Power co.'), NULL, 250);

got bill

And then I pay the bill:

INSERT INTO journal (txn_id, txn_date, description) VALUES
   (5, '2017-09-10', 'Pay Power co. bill Stmt #567');
INSERT INTO journal_crdr (txn_id, account_id, debit, credit) VALUES
   (5, (select account_id from account where name = 'A/P:Power co.'), 250, NULL),
   (5, (select account_id from account where name = 'checking account'), NULL, 250);

paid bill

Something to note here is that tracking expenses this way allows you to “realize” expenses and income when they occur separately from when you actually pay them, or receive payment for them.

Oops, I realized (pun intended) I never “imported” my initial checking account balance of $1,500.

INSERT INTO journal (txn_id, txn_date, description) VALUES
   (6, '2017-09-11', 'start the books with my checking account balance');
INSERT INTO journal_crdr (txn_id, account_id, debit, credit) VALUES
   (6, (select account_id from account where name = 'checking account'), 1500, NULL),
   (6, (select account_id from account where name = 'equity'), NULL, 1500);

add equity

Now if you’re doing this on paper, I recommend entering the debits and credits onto the individual account pages at the time you make the journal entries. But sometimes, there are valid practical reasons not to, and you’ll need to keep track of which ones have been entered and which ones haven’t. I put a checkmark to the left of the journal entry after I’ve entered it into the account page. You can also do it by backing up by some amount until you find one where the entry id is in the account already, but with the checkmarks on journal entries, it keeps things simpler.

The main rule for a transaction is the sum of debits and credits in the transaction must always match. In essence, this is the law of conservation of money in accounting. Thou shalt not create nor destroy money, it can only be moved.


Accounts are denormalized views of the journal. For accounting purposes you’ll want things separated out like this as each account (and its associated transactions) can be classified by the account type (asset, expense, etc.).

If you’re tracking accounts on paper, you can use the same three column ledger paper that you used for the journal. In the first column, you’ll record the debits from the journal transactions, in the second column, the you’ll record the credits from the journal transactions, and the third you’ll use when you need to find the current balance of the account. You can track the balance for every transaction if you want, but I found I only tended to strike a balance when I reconciled the accounts, or when I actually needed to know the balance for other reasons.

For the checking account, the account sheet might look like this:

checking account

Note that I put the account type at the top of the page, as it makes it simpler when you go to reconcile, so you don’t have to remember/figure out what type of an account a given account is.

From a SQL perspective, the account can be seen as this:

.width 6 40 10 7 7
SELECT j.txn_id, j.description, j.txn_date, crdr.debit, crdr.credit
  FROM journal_crdr crdr, journal j
 WHERE account_id = (SELECT account_id FROM account WHERE name = 'checking account')
   AND j.txn_id = crdr.txn_id;

Would yield

txn_id  description                               txn_date    debit    credit 
------  ----------------------------------------  ----------  -------  -------
2       Got paid                                  2017-09-02  550             
5       Pay Power co. bill Stmt #567              2017-09-10           250    
6       start the books with my checking account  2017-09-11  1500            

To strike the balance, subtract the sum of credits from the sum of debits. If the number is positive, you have a debit balance, and record it in the balance column on the same line as the last entry it includes. If the number is negative, you have a credit balance, and record it in the balance column, surrounded with parentheses, in the balance column on the same line as the last entry it includes. Some examples of credit-normal accounts are things like income, sales, accounts payable, credit accounts. Some examples of debit-normal accounts are things like bank accounts, hard asset accounts, accounts receivable.

In SQL, this would look like this.

       WHEN balance < 0
       THEN '(' || -balance || ')'
       ELSE balance
        END AS balance
  FROM (SELECT sum(debit) - sum(credit) AS balance
          FROM journal_crdr
         WHERE account_id = (
               SELECT account_id
                 FROM account
                WHERE name = 'checking account')) balance;

Accounts, for keeping totals can be thought of as a tree of accounts. For example, we have A/P:Power co. as an account, but it might be in the tree of Accounts Payable. Similarly for Accounts Receivable, retirement accounts, and any time where an aggregate balance of some number of subaccounts is desired. You’ll see this in any reasonable accounting software package (for example, GNUCash, which is free and good can set these up). For our purposes here, we’ll just leave this alone.

Account Types

Different accounts are treated differently for reporting and reconcilliation purposes. The six main account types, and their credit or debit normality are:

  • Assets (debit normal)
  • Liabilities (credit normal)
  • Expenses (debit normal)
  • Income/Revenue (credit normal)
  • Equity (credit normal)
  • Dividend/Disbursement (debit normal)

Don’t worry too much about remembering their normality, as with use, it will become obvious just in the way they are used. All that an account’s normality says is that the vast majority of times, the balance of the account will be a credit balance or a debit balance. It’s not impossible that a given account might not have the appropriate debit or credit state, for example, an A/R account for a customer, which being an asset, is debit normal, might have a credit balance (such as might happen in the case where a customer overpaid a bill), but on the whole, accounts will almost always have the a balance of the type of their normality.

Also a note about the terminology of Dividend/Disbursement: normally, it’s just called dividend, but the reason for including disbursement is that dividend is specific to being a corporation, while there are other forms of companies like sole proprietors, partnerships, and others. For the rest of this, it’ll just be called dividends.

But for each of these account types, what kinds of things are which?

One way to think about what kinds of accounts would be assets are accounts governing things that rational people might sell to other rational people: Bitcoin, cash, gold, financial instruments, houses, cars, pencils, portions of my accounts receivable. Some assets may be things that are hard to really sell – say an installed brick pizza oven, but it still counts. Assets that are hard to liquidate are referred to as fixed assets.

Liabilities are expected payouts or future obligations of the company. Some examples are loans that need to be repaid, an outstanding bill, accounts payable, and customer deposits. Customer deposits sound like they would be an asset, and they are, sort of. Just not to you. Something you discover is that your assets are someone else’s liability and vice versa.

Expenses are what the normal meaning of the word are; things like your telephone or electric bill, salaries and wages, or things you buy that don’t really represent well as assets as they are short lived - like lunch, or stationery.

Equity records the owners’ claims to the assets of the company. These can be things like retained earnings, common stock, capital, etc. If you do books for your own finances, the way you initially “import” your existing stuff onto the books is to credit them from an equity account that belongs to you, and then debit the appropriate asset account, be it current assets like checking, savings, or retirement, fixed assets, tangible assets (like your house or car), etc. even liability account (like your credit card) which would be importing some negative equity.

Income and revenue accounts are what you’d think they’d be; things like your paycheck, or sales, interest income, rent (if you’re the landlord), received dividends, etc.

Dividend accounts are where your company pays out some of its funds to equity holders. It’s important to note that this does not reduce equity, so you shouldn’t pay dividends as debits to the equity accounts – unless it has been specifically requested by the person you’re paying, or some other legal arrangement has been made.

So every account in your books will be one of the above six types.


Periodically, you’ll want to reconcile the books; which means to check that all is at least structurally ok.

There’s a standard equation that should hold, if you did your books correctly:

Assets = Liabilities + Owner's Equity

If you add up the balances of your Asset accounts (which will be debits), they should equal the sum of your Liabilities (which should be credits) with the sum of your Equity (which should also be credits, ok not exactly, we’ll get there in just a second). If you think about this, this is just applying the rule in a journal transaction – the sum of all debits should equal the sum of all credits, just applied across the set of accounts.

Wait, there are only three terms but six account types. What about the others?

Actually, we can three step expand this out a bit:

Equity = Contributed Capital + Retained Earnings

Contributed Capital here fits what we called an equity account earlier. Retained earnings is defined as:

Retained Earnings = Net Income - Dividends


Net Income = Income - Expenses

The full expansion of this looks like:

Assets = Liabilities + (Contributed Capital + (
    (Income - Expenses) - Dividends))

It is important to note that you use the balance of the account relative to its normality when filling these out. If it’s a credit normal account, if the balance is a credit balance, you just put in the balance as a positive number. If the balance is a debit balance, you put it in as a negative number in the equations. The converse is true for debit normal accounts.

If that equation checks out for the full set of your accounts, all is good! If not, then something somewhere needs to be checked out and fixed. Tracking it down can sometimes be a challenge. Back in the day, adding machines were used and had a paper tape. This would allow you to double check that you entered everything correctly. I first did reconcilliation on paper, and then moved to doing it in a spreadsheet which helped track down copying and transcription errors. Once I had balanced my books, in each of the accounts and the journal, I would put a mark in the margin, so when striking a balance the next time, I only had to work from an existing known-good balance.

Something else you can do to verify the state of your books is to add up all the credits and debits across all accounts, and if everything is good, the credits will equal the debits. For some accounts, if you’re doing them on paper, they’ll cross many pages over time, and you don’t want to have to sum them all up every time, so what I’ll do, is write the current sums below the last line on a ledger page for the account after everything has checked out, so that at most, I should have to sum up things since we crossed a page boundary at the last reconcilliation. You could also add a line in the account itself with the current totals in the credits and debits columns, and highlight it or something so you know not to re-add it in, but at least for me, this seemed just enough error prone to avoid.

Ugh, I Messed Something Up!

No worries, accounting systems were designed for humans by humans, and to err is human. Unsurprisingly, accounting has ways of dealing with this.

If you messed up a journal entry because you sent money to the wrong accounts, or the debits/credits don’t equal each other, or whatever, there are a few options to fix things, but something that is definitely not an option is to cross out or edit old entries.

  • If you’ve not put a subsequent entry in the journal after the one with an error in it, you can just add to the last transaction, crediting to fix up a debit and vice versa, or adding a credit/debit line to make the credits equal the debits.

  • You can put in an “undo” transaction which negates the original, putting debits for items that were credits and vice versa, and then create a new one that’s ostensibly correct.

  • You can create a new transaction that just has the things you need to fix in it. For example, say you debited $100 but only credited $80 in the transaction with an error, you can create a new transaction that credits the $20.

Your correction transactions should reference the original, but should be dated with the current date, not the date of the original transaction.

Sidebar on Credit and Debit Terminology

Why all this credit and debit nonsense? Why not just use negative and positive numbers for all this? This is a good question. I can only speculate, but I have a few guesses:

  1. That negative numbers and how to deal with them may not have been widely known when double entry bookkeeping was invented.
  2. Having sales of -$1,000,000 sounds really weird and wrong.
  3. In the days of doing this on paper (probably only as far back as the ’70s probably), treating them differently may just have been simpler.
  4. Having a single column instead of the debit and credit columns could open things up to fraud. It would be very easy to tweak the books by putting either a minus sign before the number, or as accountants deal with negative balances, putting parentheses around it after the fact.

In any case, if you treat credits as negative numbers, and debits as positive numbers, everything works – just make sure you swap signs as necessary when doing the equations for reconcilliation, which means: if it’s a credit normal account, swap the sign of the balance. If you notice in spreadsheet programs, one of the number formatting options is to put negative numbers in parentheses – so this whole credit=negative stuff is not just an invention for this blog post.

So another way to balance your books without the above equation is: add up the balances of all your accounts, treating debit balances as positive, and credit balances as negative. The sum, if your books are correct, is zero. This follows naturally since the account balances are merely derivations of the journal, and the journal, if correct, should have the property that the sum of any transaction should be zero.

If I were to write a real accounting system, rather than the schema as presented above would have it, I would just have an amount column in the journal_crdr table rather than separate debit and credit columns, where a positive amount is a debit and a negative is a credit (or vice versa - just be consistent). This is valid since you never credit or debit a negative value. Strictly speaking, this isn’t true, you can, but you really shouldn’t.

Why then did I use debit and credit terminology up to this point when I could have made things much simpler by just using things like positive and negative numbers from the beginning? Simple. If you’re doing accounting stuff, chances are very good that you’ll be speaking to accountants. If you talk to them in the terms that we as engineers would use and describe things in the way that we think of them, and do not understand their terms, things will get confusing in a hurry. If you talk to them in the terms of accounting rather than those of software engineering, communication gets much easier. Just remember, we use different terminology and mental models because we care about different things than the accountants and bookkeepers do. We care about the mechanics of executing transactions properly, latency, throughput, how to generate reports, and keeping it all correct; they care about what all these numbers mean, and their implications on the financial position and performance of the company. This is their domain, and we are the visitors.


The ledger is the place where accounts are maintained. That is: it’s the collection of the accounts and the journal. When I refer to the general ledger, that is the central accounting record of a company or organization consisting of the accounts that support the value items shown in the major financial statements. You may have subsidiary ledgers that feed into the general ledger so as to make an accounting system and organization scale. They can be split out either by function (sales, payroll, etc.) or by geography, or both, or other criteria to delegate subfunctions of accounting to other groups.

If you have an altogether separate ledger for the same company, weeeelll, you’re probably not operating above board.

Path of a Sale

While in most consumer transactions, this is greatly abbreviated, or there are implied versions of some of these processes, but if you buy something online, or in most business to business transactions, you’ll see all or most of these.

Say you want to buy something from a company. First there’s the order, which is short for purchase order. It’s a document describing what you want to buy, quantities and the prices for those goods and services. The receiver of the purchase order may go to the buyer and renegotiate or adjust the order based upon agreement with the buyer. A purchase order, or PO, has no “books” implications. That is, a PO is not an asset or a liability to be entered into the journal.

Upon shipment of the good or delivery of service (partial or complete), an invoice will be issued from the seller to the buyer. Payment terms are often included. At the point of issuing the invoice, the seller can then create a transaction crediting the value of the shipped/delivered good/service from say, the sales account, and debiting the accounts receivable (A/R) account they have for the buyer. Upon receiving the bill (invoice), the buyer will create a transaction crediting the amount from accounts payable (A/P) for the seller and debiting an appropriate asset or expense account (depending on the good or service purchased). The transactions created by the buyer and seller concerning the invoice will contain a reference to the invoice number. It is important to note that revenue is recognized at the point when the invoice is issued to the buyer. Ideally, the issued date is the same date as sent, as the payment terms clock starts ticking when the invoice is issued. This is also important for financial reporting. There may be multiple invoices as a result of a single PO.

Hopefully, the buyer decides and is able to pay the bill within the appropriate terms. So the buyer creates a transaction to credit an asset account (like a checking account) and debiting A/P with a reference to the invoice # and the transaction which originally moved the money from accounts payable. On the buyer side, when they receive payment on the invoice, they create a transaction crediting A/R for the buyer and debiting an asset account (like a checking account). There may be multiple payments on an invoice, and when the balance of the invoice is paid, the invoice on the buyer side is so marked. Personally, when I did my own books, I put a mark in the accounts receivable entries for that invoice to note that it was all paid so unpaid items would stick out.

Well, things don’t always go smoothly, and buyers don’t always pay. So if you sell the collection of the bill to a bill collector, this needs to be accounted (pun intended) for. So what you do is create a journal entry that credits A/R for the whole amount of the invoice, and debits the amount you get from the bill collector to an asset account, and debits the rest to a realized loss account (that would be an expense type). This is what’s referred to a being written off. If there’s no bill collector and you just write the whole thing off, skip the appropriate part.


There are all sorts of financial reports that you may need. If your books are running correctly, these are all very straightforward to manage.

Final Observations

Anyway, hopefully this will clear some things for engineers who have to think more about mechanics than meaning when it comes to accounting systems.

A good and short book that I got which I found super-helpful was Accounting Made Simple. It’s a quick read and under 100 pages, and will give you more detail regarding the definitions of quick ratio, and the common reports you’ll probably need to be able to produce.

There’s a ton more that I could talk about, like prepaid expenses, details surrounding payment terms, the various different reports, and soooo much more, but hopefully here, I’ve provided you enough basics to understand the stuff you’d encounter learning about those other things.