Live data from Hacker News

Accounting for developers part III – building a lending marketplace

moderntreasury.com

11–18 of 18 posts

Re: Accounting for developers part III – building a lending marketplace

#12
post #6

I still don't understand why they encourage double-entry accounting for tech. In my experience entries like: | amount | payer_id | payee_id | | 100 | 1 | 2 | are more than sufficient. He uses Square, Uber, and Airbnb as examples in https://www.moderntreasury.com/journal/accounting-for-develo... but, as far as I can tell, only Square uses double-entry. Double entry accounting was for when people were hand-writing a le…

We’ve built our own in house ledger and also use double entry accounting. When one transaction affects multiple accounts, you need to ensure the books balance, which the premise of double entry accounting.

It’s the standard for a reason. Even when using a software like Quickbooks, errors can come up.

Re: Accounting for developers part III – building a lending marketplace

#13
post #9
post #6

I still don't understand why they encourage double-entry accounting for tech. In my experience entries like: | amount | payer_id | payee_id | | 100 | 1 | 2 | are more than sufficient. He uses Square, Uber, and Airbnb as examples in https://www.moderntreasury.com/journal/accounting-for-develo... but, as far as I can tell, only Square uses double-entry. Double entry accounting was for when people were hand-writing a le…

What happens if you need to split that $100 from payer_id 1 into 2 payer_id 2's? I.e. that $100 is actually: $99 from 1 to 2 and $1(let's say in taxes) to payer_id 3. The easy answer is, make it 2 transaction, $99 to 2 and $1 to 3, but then you can't tell that the $1 in taxes is from the $99 transaction. That leads to headaches when you need to balance your taxes.

This is just the ledger table. In your case you would have a payment event table with one row and a join table that connects that event with all the ledger rows.

That's what Airbnb seems to do: https://medium.com/airbnb-engineering/tracking-the-money-sca...

Re: Accounting for developers part III – building a lending marketplace

#14
post #6

I still don't understand why they encourage double-entry accounting for tech. In my experience entries like: | amount | payer_id | payee_id | | 100 | 1 | 2 | are more than sufficient. He uses Square, Uber, and Airbnb as examples in https://www.moderntreasury.com/journal/accounting-for-develo... but, as far as I can tell, only Square uses double-entry. Double entry accounting was for when people were hand-writing a le…

One good technical reason to prefer double entry and relating to the "it helped avoid mistakes [in hand-writing ledgers]" is that double entry patterns encourage better database transaction discipline and provide helpful debugging clues when database transactions half-finish and accidentally commit rather than rollback. Atomic database transactions with single row inserts of accounting transactions are obviously simp…

Not sure I follow: you're claiming that double entry forces you to write things with better transactions in mind but the only difference between the two is having 1 vs. 2 rows.

Say we have a hotel reservation system, it looks like this in my proposition:

1. Wrap a transaction around rows

2. Add reservation event

3. Add one ledger row for payment

4. Add one ledger row for tax

vs. double entry:

1. Wrap a transaction around rows:

2. Add reservation event

3. Add two ledger rows for payment

4. Add two ledger rows for tax

Re: Accounting for developers part III – building a lending marketplace

#15
post #7
post #6

I still don't understand why they encourage double-entry accounting for tech. In my experience entries like: | amount | payer_id | payee_id | | 100 | 1 | 2 | are more than sufficient. He uses Square, Uber, and Airbnb as examples in https://www.moderntreasury.com/journal/accounting-for-develo... but, as far as I can tell, only Square uses double-entry. Double entry accounting was for when people were hand-writing a le…

Isn't your example double entry? It shows both accounts involved in the transaction and the direction of the transaction.

Double-entry is recording the credits and debits in a column and each account change happens on a row.

So if I change the ledger in my parent comment to double entry it would look like:

| account_id | credit_amount | debit_amount |

| 1 | 0 | 100 |

| 2 | 100 | 0 |

Re: Accounting for developers part III – building a lending marketplace

#16
post #9

Earlier quoted context omitted.

What happens if you need to split that $100 from payer_id 1 into 2 payer_id 2's? I.e. that $100 is actually: $99 from 1 to 2 and $1(let's say in taxes) to payer_id 3. The easy answer is, make it 2 transaction, $99 to 2 and $1 to 3, but then you can't tell that the $1 in taxes is from the $99 transaction. That leads to headaches when you need to balance your taxes.

This is just the ledger table. In your case you would have a payment event table with one row and a join table that connects that event with all the ledger rows. That's what Airbnb seems to do: https://medium.com/airbnb-engineering/tracking-the-money-sca...

Or just go full double entry and allow multiple accounts per transaction, which is what anyone with an accounting degree would tell you to do.

The bonus of doing it this way, everyone with an accounting degree won't gasp in horror when they understand what it is you did.

The events table in your example is basically the same as a transaction table and dump the transaction_id into the ledger table. The bonus of doing it with a 'transaction_id' is accountants, auditors and the rest won't be confused.

Re: Accounting for developers part III – building a lending marketplace

#17

Earlier quoted context omitted.

One good technical reason to prefer double entry and relating to the "it helped avoid mistakes [in hand-writing ledgers]" is that double entry patterns encourage better database transaction discipline and provide helpful debugging clues when database transactions half-finish and accidentally commit rather than rollback. Atomic database transactions with single row inserts of accounting transactions are obviously simp…

Not sure I follow: you're claiming that double entry forces you to write things with better transactions in mind but the only difference between the two is having 1 vs. 2 rows. Say we have a hotel reservation system, it looks like this in my proposition: 1. Wrap a transaction around rows 2. Add reservation event 3. Add one ledger row for payment 4. Add one ledger row for tax vs. double entry: 1. Wrap a transaction ar…

You can think of double entry as:

1. Create a reservation liability (invoice) [debit the reservation cost]

2. Create a tax liability (tax account)

The preceding may happen asynchronously ahead of the time. The following are generally wrapped in a single database transaction:

3. Credit a user's account for value of (total) payment

(3a. Depending on how deep your double-entry goes, Debit your Payment Processor)

4. Debit the user's account the reservation amount

5. Credit the reservation account the reservation amount (reservation invoice account should sum to 0 now: no assets, nothing liable)

6. Add reservation event for completed invoice

7. Debit the user's account the tax amount

8. Credit the tax account the tax amount (user's account should sum to 0 now: no assets, nothing liable)

It's been a while since I've worked on a system in this mindset, so apologies if I've got subtle things wrong or debit/credit backwards. That's still too easy to do even when you've done it a million times and even when you aren't rusty years later.

It's far more than "just two rows extra" for proper double entry with the right number of "accounts" and a lot more things form "accounts" than you think. Some of those accounts should read 0 after a proper transaction. Those become red flags if a transaction failed in the middle, and debugging tools when that happens (is it an extra credit or an extra debit, the account positive or negative/owed something or owing something, that can be very useful information to have on the failed database transaction).

It seems like a lot of extra steps, but each step should also reflect your domain model in useful ways: don't create new reservations until a reservation invoice has been filled/paid for. Even in cases where you are doing direct sales to a customer and don't think you need "proper" invoices and that the transactions existing in the first place are good enough, it's still sometimes a useful domain model to have that invoice concept and rather than "fire off" events like "Create Reservation" purely on the sales transaction, have a stronger "state model" with an "Invoice Completion" step. It's an abstraction that sometimes gains you some peace of mind that you don't accidentally make a new reservation from an over-payment or a payment intended for a different purpose.

Re: Accounting for developers part III – building a lending marketplace

#18

Having contributed to a project that needed to apply these principles in a previous role, it can’t be understated how important it is to understand these concepts. One thing I found interesting though is that one feature of double entry accounting is creating a paper trail where some lost data can be reconstructed if necessary with redundancies. For example if you lose the physical pages detailing a transaction, you…

You should take a look at SAP's source code
Post reply on HN