Double-Entry Accounting Guide for Software Engineers — Part One…

Sergey Radzishevskii

Author
TypeScript

Double-Entry Accounting Guide for Software Engineers — Part One: Why We Need It

I’m not a professional accountant, I’m a software engineer. I don’t pretend that I will reveal any secrets about the double-entry system. Everything is already on the internet. However, for people unfamiliar with accounting, understanding its significance can be challenging. That’s why I’m writing this article for engineers like me, who are likely working on a product, whether it’s a startup or an established business, that requires some financial reporting. You are tasked with building these reports. First and foremost, let’s try to understand why the double-entry system is necessary.

Even those unfamiliar with accounting know the basic principle: all money must be accounted for, and debits must match credits. The double-entry system was invented centuries ago, even before the advent of negative numbers, and it was genuinely revolutionary for its time. But nowadays, as software engineers, we meticulously track all transactions in our applications. We diligently record every event in the system that can in any way affect calculations. We can easily track all money flows. Do we still need a double-entry system?

A Real-Life Scenario: Managing Finances in a Marketplace Application

Let’s consider an example. Imagine a fictional application — Firecnc. It’s a new startup application that allows apartment owners to rent them out to tenants. Firecnc earns a percentage from each booking.

In this scenario, we have two user roles — owners and tenants, and we need to implement the following sequence:

Tenants make reservations and pay Firecnc.

Firecnc holds the money until the booking is completed.

Firecnc transfers money to the apartment owner’s account and retains its percentage.

Apartment owners withdraw money from their Firecnc balance to their bank accounts.

Now, let’s think about the data sources we need to implement this scenario. I simplified details to make it easier to understand.

Booking: To store booking information.

Payment: To track incoming payments from tenants.

Transfer: To track transfers of held funds to owner balance.

Payouts: To track owner withdrawals to their bank accounts.

To calculate an owner’s balance, we need to sum up all transfers to their account and deduct payouts.

SELECT (
SELECT SUM(amount)
FROM transfer t
WHERE user_id = 123
) AS total_transfers_amount -
(
SELECT SUM(amount - stripe_payout_fee)
FROM payout p
WHERE user_id = 123
) AS total_payouts

Preventing Unaccounted Funds

One day, we received a complaint from one of our owners that a tenant had caused damage to the apartment. The booking was for $700. As Firecnc is a new app, the team aims to build trust with owners. The product team asks the engineer to add $100 to the owner’s balance. After some thought, the engineer added a new transfer, referencing the existing booking worth $100. This action increases the owner’s balance by $100, and the issue is resolved while maintaining a reference to the existing booking for tracking purposes.

At the end of the year, management requests financial reports with profit calculations. Here’s where the challenge arises. The money we were supposed to earn differs from what we actually earned. We received $700 but spent $700 + $100. This situation occurred multiple times.

This is precisely the scenario where the double-entry system prevents such discrepancies. With double-entry, you can’t simply add money into the system without specifying its intended purpose.

Of course, one might argue that this doesn’t apply to their application, and they’ve learned the lesson, now tracking such fixes as expenses. However, the main idea here is that the next day, another case like this may arise, leading to unaccounted funds in the system. The double-entry system wouldn’t permit such actions.

Preventing Uncategorized Funds

The team successfully resolved the issue of unaccounted funds, ensuring greater financial transparency and trust among owners. At the end of the following year, the product team asks the engineer to prepare a profit report. After some thought, the engineer prepares an SQL query:

SELECT SUM(amount)
FROM booking_fee
WHERE created_at >= '2023-01-01'
AND created_at < '2024-01-01'

However, upon reviewing the report, the CFO points out a discrepancy. The numbers don’t match what’s in the bank account. The oversight? Forgetting about expenses. A fee of 0.25 cents is applied to every payout.

This is a simplified example, but in a real-life application, you would encounter various sources of income and different types of expenses. The double-entry system, alongside a ledger, allows you to account for and categorize all types of funds. It’s a well-established

Calculate Balances with Ease

As Firecnc gains popularity, the product team seeks to enhance flexibility, particularly for owners. They aim to introduce a subscription system offering various benefits and access to new tools. The Pro subscription, for example, grants owners the ability to obtain insurance coverage in case of unexpected damage events. To facilitate this, we’ve implemented a new table, “damage_insurance_transfer,” to track damage insurance transactions. Now, all owner transactions are meticulously recorded through “owner_transaction.” With the increasing variety of transaction types, including transfers upon booking confirmation, partial refunds for tenant cancellations, funds received through damage insurance, withdrawals, and failed withdrawals, accurately tracking owner balances becomes more crucial than ever.

Table owner_transaction {
id int not null,
amount float not null,
transfer_id int,
refund_id int,
damage_insurance_transfer_id int,
payout_id int,
failed_payout_id int,
}

Simultaneously, calculating funds for other accounts, such as Firecnc’s incomes and expenses, becomes more complex as we account for various transaction scenarios. This is where a ledger, built upon the principles of double-entry accounting, proves invaluable. A well-structured ledger can effortlessly compute balances for any account within your system, whether it’s a system account like current income or expenses or individual client accounts holding available balances.

Summary: Ensuring Financial Accuracy with Double-Entry Accounting

In the world of software engineering, where precision and transparency in financial tracking are paramount, the double-entry accounting system stands as a steadfast guardian against discrepancies and unaccounted funds.

The lesson is clear: double-entry accounting guarantees that every cent in your system must have a purpose and a place. It provides the foundation for constructing essential financial reports, such as the Profit and Loss Statement and the Balance Sheet, with the assurance that no detail is overlooked. These reports are must-haves, especially for startup applications, ensuring financial clarity and accountability.

PS: What’s Next?

In this part, we’ve explored why the double-entry ledger is essential and how it can help us prevent errors in financial tracking. However, we haven’t delved into the mechanics of building one just yet. In the next part, I’ll demonstrate how we can construct a ledger with double-entry principles at its core for the Firecnc application.

In the meantime, I highly recommend reading the article “

Accounting for Computer Scientists

” by Martin Kleppmann. It provides an excellent guide on how double-entry accounting works.

Stay tuned for the upcoming part, where we’ll turn theory into practice and build a functional double-entry ledger.

Partner With Sergey
View Services

More Projects by Sergey