[HN Gopher] Accounting for Developers, Part II ___________________________________________________________________ Accounting for Developers, Part II Author : qin Score : 280 points Date : 2022-08-24 14:36 UTC (8 hours ago) (HTM) web link (www.moderntreasury.com) (TXT) w3m dump (www.moderntreasury.com) | racl101 wrote: | This has been so useful and educational! | | Thank you! | icepopo wrote: | Is chart of accounts usually a flat structure, or can it look | more like a tree? I'm thinking of grouping similiar accounts | together to see what's the balance on single ones vs the group. | meekaaku wrote: | Its a tree. Eg: | | Expense | | - Salaries | | - Rent | | -- Warehouses | | -- Retail space | | - Utilities | photochemsyn wrote: | > "We hope to publish guides about more complex use cases | (lending, insurance, etc.) in the future." | | That would be appreciated. It'd be nice to see the minimal | complexity needed for something like a local credit union that | managed customer savings and checking accounts, as well as home | and car loans. | | More ambitious would be a central banking app, in particular how | does double-entry accounting work when a central bank (i.e. the | Fed) is doing 'quantitative easing' and using their helicopter | money to buy up Treasury bonds and mortgage-backed securities in | order to keep major banks and government solvent? What's the | private bank's balance sheet look like when they use the central | bank money for stock buy-backs instead of for increasing | commercial lending? | | For example, the Fed says it's unloading the mortgage-backed | securities it bought up in 2008-2009. That's got to be some | convoluted accounting: | | https://www.marketplace.org/2022/06/02/why-the-federal-reser... | kojim wrote: | That's a cool idea. Any other deep-dive guides on | fintech/payments that would be helpful for readers here? We're | always looking for new topics to write about. | janci wrote: | The website is so fast I did not notice it redrawed when I | clicked Part I. I'm impressed. | RicoElectrico wrote: | It's Javascript URL manipulation trickery, there's an event | listener attached to that link. | cyral wrote: | It's running on NextJS which pre-loads the content of each link | in the viewport unless you tell it not to, so it's loading a | .json file containing the article content immediately, making | the page transition instant when and if you click it. | jasonbarone wrote: | Oh that's so great to hear, thank you! We use Next.js and | content is statically generated. | pkrumins wrote: | Here's my approach to accounting: If $moneyIn > | $moneyOut: Print("hells yeah") Else: | Print("oh shit") | PopAlongKid wrote: | Over a sufficiently long time period, net profit equals cash in | minus cash out. | chris-orgmenta wrote: | Ha. But a pedantic take at face value: | | This doesn't work on a low level, such as: If you're looking at | an account you want to balance to 0, e.g. a suspense account, | prepayment account, etc. | | Also doesn't work with practical application, such as: Catering | for a profitability target e.g. ($in / $out) > 1.1 | hum3hum3 wrote: | I did like Charles Dickens who has Mr Micawber say 'Annual | income 20 pounds, annual expenditure 19 [pounds] 19 [shillings] | and six [pence], result happiness. Annual income 20 pounds, | annual expenditure 20 pounds ought and six, result misery.' | 3pm wrote: | A quote from a related blog post: "Eventually I figured it out: | basic accounting is just graph theory. Accounts = Nodes, | Transactions = Edges" | | https://martin.kleppmann.com/2011/03/07/accounting-for-compu... | | Also probably worth checking out Martin Fowler's writing on | accounting. | | https://martinfowler.com/apsupp/accounting.pdf | | https://www.amazon.com/Analysis-Patterns-Reusable-Object-pap... | contingencies wrote: | Klepmann is correct but practically you don't control external | accounts thus cannot authoritatively determine if they either | exist, have ceased to exit, or the contents of their ledgers. | Thus, a large number of transactions will always have hanging | references. This ultimately dictates the need for a "settlement | state", which should be modeled as a state machine with careful | transitions. Reversible transactions, fees, taxes and discounts | then come in to play, some of which may be shared between | parties, some of which are not calculable before the fact. | | Fowler's approach is amusing in that, in classic UML style, he | models things which are optional in an authoritative way as if | they are requirements, thus muddying the waters even further. | While his adjustment implementations are interesting as a basis | for feature comparison, there's a lot to be said for | simplicity, and this effectively requires throwing out what the | bean-counters are used to and reconsidering the need from | scratch. The default correction is another transaction, and | this requires no special implementation. | | New systems recommendation: | | (1) For account identification, use IIBAN which provides IBAN- | compatible account identification and checksums and is an open | system @ https://github.com/globalcitizen/iiban | | (2) For all accounting, use UTC. | | (3) For transaction identification, use UTC second of | origination (UTCSO) + account of interest (AOI; eg. IIBAN) + | intra-second transaction identifier (ISTI). | | Free thoughts on forward-looking accounting systems @ | https://raw.githubusercontent.com/globalcitizen/ifex-protoco... | hum3hum3 wrote: | Thank you. Those are some interesting references. I do like | your reference of state machines at the edges of the | accounting model. Definitely the case in payments systems. I | don't like how Modern Ledger goes straight to credits and | debits whereas Klepmann has a graduated approach. I have been | thinking about writing a bit more about this. | nirav72 wrote: | Wish there was similar guide explaining the basics of cooperate | accounting for developers. As a dev that has to occasionally work | on integrating web apps with our erp system, I still get lost | when the erp guys or biz people talk about various accounting | processes. | rudasn wrote: | Don't waste this opportunity to ask people around you and learn | more stuff. | | Personally I think that's the main reason for working on any | project, let alone being your full time job. | keeptrying wrote: | Love the simplicity of their system but don't like the price tag. | | Anyone know of cheaper alternatives to ModernTreasury.com ? | | Funtionality needed: ledger + integration with payments. | eatonphil wrote: | TigerBeetle is an open source ledger database you might be | interested in. | | Not sure about payments integration though. | | https://github.com/coilhq/tigerbeetle | keeptrying wrote: | Thanks! | travisG23 wrote: | Mentioned this above but I'm a co-founder of Proper Finance | https://www.properfinance.io where are building integrated | ledgering and reconciliation software for fintech companies. We | are happy to help where we can - the team were early engineers | at Marqeta where we built the ledger, as well as reconciliation | and financial controls. Shoot me a note - | travis@properfinance.io | superzamp wrote: | Don't want to hijack the thread here but we're building an | open-source platform that includes ledgers and a scripting DSL | for money movements at Formance, with payments connectors in | beta and coming up for recon - always keen to chat | | https://docs.formance.com | deshp wrote: | I'm on the growth team at Modern Treasury. Using our Ledgers | and Payments products together could definitely help here. | Ledgers is actually free to get started. The startup plan | includes 5000 transactions a month and is free forever and the | enterprise plan has volume-based pricing. We'd love to chat | more about your use case and pricing. Feel free to drop a note | - pranav@moderntreasury.com. | [deleted] | pwpw wrote: | As a CPA and software developer, I've been wondering if I should | build my own product out, but there seems to be a number of | options available in the ledger space. However, I'm surprised | there isn't more of an overlap in software engineering and | accounting. There's a bit of overlap in the fields that scratch | the same itch. Although the theory behind accounting is a lot | more interesting than most of the work in my experience. | macintux wrote: | I've often thought that had I been born into a world without | computers I'd have been an accountant. | | On high school career day I attended a talk by an accountant, | and unfortunately he lived up to the stereotype. One of the | most (superficially, anyway) boring people I've ever met. | mamcx wrote: | Making a ledger is step 0 at building ERP-like apps so many of | us don't see it as big deal (until the complexities of it | arise!). | | Also it could be very local-dependent. | | Here in Colombia how we approach it is different to how I see | people in USA do it. | | What I don't know is how make it both easy, universal, | practical and pluggable. | | If for example is a out-of-band solution (aka: a micro-service) | will be a total NO for many of potential users.. | memset wrote: | I'm actually the founder is a startup trying to bridge the gap | between Eng and finance. I'd love to hear your perspective on | what a good solution would look like! | taylorhou wrote: | would love to connect as we're evaluating ledgers for rental | properties. there are a gazillion management softwares with | "accounting" ledgers but they were always an after thought. | we're interested in building the defacto single source of truth | ledger for real estate. taylor at apmhelp.com | Naga wrote: | I'm also a CPA and develop software now (there are dozens of | us!). I think part of this is that the perception among devs is | that accounting is too complicated, and therefore can be | radically simplified in software, which can be true, but | largely doesn't meet real world scenarios. The problem is that | accounting is generally complicated because business is | complicated. I've seen software that throws away the ability to | add more than 2 line items to a transaction. I've also seen | software that goes too far the other way and automates every | step of a process (okay great, how can we show the auditors now | that this works?). It's a pretty classic misunderstanding of | the domain, where most CPAs don't speak software, so there's a | severe lack of communication (which probably makes CPAs who do | understand software very valuable!). | | The other factor is that while accounting software as a whole | sucks, but at least for larger businesses, its probably better | to tell the auditors that you use quickbooks, versus some | custom in house software. From a risk management perspective, | that's a much easier value proposition for the | board/management. | mason55 wrote: | > _The problem is that accounting is generally complicated | because business is complicated._ | | This is it. From a high level, accounting lends itself very | well to software. You have accounts, money, and transactions, | and it appears that the challenge is moving money between | accounts and then adding everything up. Perfect domain for | software, that's all stuff computers are very good at. | | It's only once you start digging in with real companies that | you realize the math is the easy part. The hard parts are the | opposite of things that computers are good at - e.g. "given | this change in rules that takes effect next year and is | written in plain English, how do we account for this | transaction?" Or "when an exception occurs, we need to define | a process for how a human can handle it after month close." | | The parts that are fun for a developer (look at the cool | stuff the computer can do!) are not the parts that are | valuable to a user; the valuable parts are super tedious and | boring. | pwpw wrote: | That's great insight. When I was at big 4, I helped look over | in house software and translate it for auditors to gain | reasonable assurance that the software was correctly | implementing accounting processes. | | A buddy of mine is working on a YC-funded company | (https://www.keeper.app/) that's designed around assisting | the lives of bookkeepers using quickbooks. I think it's a | great angle because I agree with you that quickbooks is the | most logical option for an average company. Where software | could really be improved in my eyes is SAP. Boy does their | software make me want to hurl... But they have such a strong | hold in the industry. | | This is a bit tangential, but my biggest insight when | conducting walkthroughs with the client's accountants was | that there is so much valuable knowledge that is internalized | in singular individuals. I'd have an accountant show me their | month end close process with links between 5 Excel | worksheets. Totally illogical flow and only that person | understood how to follow the process from start to finish. | There would be situations like randomly multiplying a line | item by 32 because of some piece of paper on their desk that | they had written down years ago. These people had been at the | company for 20+ years. I have to think there's a better | system for handling accounting processes like that. Weeding | through a messy code base can be a nightmare, but going | through someone else's accounting worksheets that are crucial | for tying out the financial statements can be nearly | impossible. I suppose eventually the audit team has to decide | what's material, make a judgement call, and move on. | NIL8 wrote: | Could some of these issues you mentioned be helped by | having the ability to make notes in each accounting stage | of a particular customer's file? | travisG23 wrote: | Hey I'm co-founder of Proper Finance | https://www.properfinance.io we're building integrated | ledgering and reconciliation software for fintech companies. | Happy to be helpful where we can - most of the team were early | engineers at Marqeta where we worked on the core ledger, as | well as reconciliation and financial controls - so happy to | provide perspective. shoot me a note - travis@properfinance.io | infogulch wrote: | _Accounting For Developers, Part I_ | 641 points | 7 days ago | | 188 comments | https://news.ycombinator.com/item?id=32495724 | perlgeek wrote: | Does anybody know a good SQL / DDL schema for a double entry | accounting system? | ruuda wrote: | I would like to know about this as well. I struggled with this | for a while for a prediction market app that I'm building. | Eventually I ended up with [1]. I am somewhat pleased with it, | but it does feel unwieldy to work with. I have some vague hope | that somebody who actually implemented banking software would | know of an obvious and elegant schema. | | The summary of my approach is: | | * A table with accounts. * A table with account balances and an | index on (account id, id), so you can efficiently query the | current balance. * A table with transactions. * A table with | mutations. Mutations have an amount, and reference a credit | account, debit account, and transaction. (So one transaction | can consist of multiple mutations.) * The account balances | table list the post-balance, but also references the mutation | that caused it to be that new value. | | All of these tables are append-only. I later added another | layer, with transactions and subtransactions, but I'm not sure | if this was a good idea. | | [1]: | https://github.com/ruuda/hanson/blob/351e8e9bc5c96a9c1dc76fd... | perlgeek wrote: | Thanks! | | If I understood your explanation and schema correctly, a | mutation itself is balanced, and if you have a transaction | that involves three accounts, that would be split up into two | balanced mutations, right? | | The advantage I see with this design is that a mutation (and | thus a transaction) is always balanced (you store the amount | only once, and credit account and a debit account). | | The disadvantages seem to be that the transaction itself | doesn't explicitly list the total changes to an account | explicitly, and that for each account you have to join the | mutations twice (once for the credit side, once for the debit | side) to get to re-calculate the current amount. | | Storing both the current balance in the account means you | cannot have concurrent updates to one account, so you must | rely on row-level locking for consistency. (Which sounds a | bit like a potential bottleneck, if you have something like a | company-wide Cash account that is involved in lots of | transactions, as in the ModernTreasury blog post). | | Does that seem like a fair summary to you? Are there other | trade-offs you have noticed? | ruuda wrote: | Yes, that's a fair summary. | | Performance is not something I'm worried about for my app, | maybe a few dozen people would use it at the same time, and | I run everything at serializable isolation level anyway. | But I can imagine that for processing real-world payment | volumes, at some point you need to sacrifice the balanced- | by-construction property for performance. | | One issue I noticed is that there is some freedom in the | representation of transfers. You can pick a canonical | representation by demanding that the amount is positive, | but then you have to make a case distinction everywhere in | code. Often the code becomes much simpler if negative | amounts are allowed. But it does make the credit/debit more | confusing, and it goes against the observation in part 1 of | the series, that accounting systems rarely work with | negative numbers. I wonder why though. | yobbo wrote: | > ... if you have a transaction that involves three | accounts, that would be split up into two balanced | mutations, right? | | Three or more "mutations", but these might be grouped | together in whatever way you want. For this purpose, the | meaning of "account" is up to you define. You might call | them "accounting objects" representing subscriptions, | contracts, invoices, and so on. | | Account balances (per transaction) can only be calculated | sequentially in the order of transactions, which becomes a | bottle neck at some rate of transactions. | vineyardmike wrote: | GnuCash has a SQL backend, so perhaps you can pick it apart (or | use it as-is as a library?). | | https://wiki.gnucash.org/wiki/SQL | meekaaku wrote: | The heart of double entry accounting is extremely simple. | Forget about asset/liability/expense. Money always flows from | one account to another. What goes out from account_1 must go | into another account(s). Typical tables: | | accounts (id, name) | | transaction (id, date) /* some call it journal */ | | transaction_line (id, transaction_id[fk], account_id[fk], | amount) | | I use -ve amount for credit, +ve for debit. That way when you | do SUM(trascation_line.amount) it would come to 0. | | This also cleanly maps to database transaction too where all | transaction_line rows and transaction row should be atomic. | | If you want multi-currency support, instead of amount column, | it needs to be currency_code, currency_rate, | amount_in_currency, amount_in_basecurrency ( i know we don't | need this all, but sometimes you want to record the amount as | entered, eg EURO 52.10 u want to record as entered even if your | base currency is USD) | meekaaku wrote: | To build a chart of accounts, you can have a parent column in | accounts table. Account balances is just: | | SELECT account.name, SUM(amount) balance | | FROM account ac | | INNER JOIN transaction_line tl ON tl.account_id = ac.id | | GROUP BY account.name | | You can cache this balance values with a current_balance | column on accounts table | | Once you have that, for any real world transaction, all you | need to figure out is what are the accounts to debit/credit, | ie classification. That is a higher level thing and is the | business logic of an accounting application. | ruuda wrote: | This looks nice, but it doesn't enforce in the schema that | all transaction lines sum to zero. Is that a problem in | practice? Or is it one of those things where if you get it | wrong, you tend to notice immediately because everything | breaks (as opposed to silently creating or destroying | currency that goes unnoticed for a long time)? | perlgeek wrote: | I guess you could have a stored procedure that checks for | balanced transactions before inserting (or before | committing, at least), with SECURITY DEFINER, and not give | anybody else permissions to insert or modify the | transaction lines table. | | But yes, that is a downside, and if I were to write such a | thing I'd make sure to have at least two mechanisms to | avoid / detect errors (like, one validation in business | logic and/or stored procedure, plus regular monitoring for | transactions that don't add up to zero). | yobbo wrote: | It is bad practice in terms of software engineering, but | some "real world" apps are implemented like this. They do | verification in the "middleware". | meekaaku wrote: | Its not a problem in practice. There might be a way to | enforce that through database constraints, but in practice, | checking transaction lines sums to 0 in business logic is | not that hard. Having said that, you can run accounting | entry sanity checks on the entire database. As previously | said | | SELECT SUM(amount) /* this should sum to zero */ | | FROM transaction_line | | --- | | Also to identify any non-balancing transaction is easy: | | SELECT tx.id, tx.date, SUM(amount) tx_sum | | FROM transaction tx | | INNER JOIN transaction_line txl ON txl.transaction_id = | tx.id | | GROUP BY tx.id | | HAVING tx_sum != 0 | | --- | | This will identify them even if caused by your business | logic bug, database bug, disk corruption etc. | | This can also be done on the single accounting transaction | just after insert too and can be done within the same | database transaction. | yobbo wrote: | This sort of schema requires a process to verify the sum | before committing, and verification is annoying to achieve | with constraints. Instead, you might consider something like: | | transaction_line (id, transaction_id[fk], dr_account_id[fk], | cr_account_id[fk], amount) | meekaaku wrote: | The problem with this will be when you have 3 accounts | involved on a transaction. Eg, you take a sales receipt | with part bank transfer, part cash. | | Sales Cr $100 | | Cash Dr $30 | | Bank Dr $70 | | Your approach will have: | | Sales Cr $70, Bank Dr $70 | | Sales Cr $30, Cash $30 | | That looks like two sales, which is not really the case. | [deleted] | yobbo wrote: | There exists cases where it is problematic, but your | example is fine. In this case, you would use individual | transaction lines to represent _payments_ , rather than | sales, which is closer to reality. But you can group | transactions in any way you want. | | With sales tax, you would have: | | cr: sales, dr: cash, $100 | | cr: cash, dr: tax, $10 | meekaaku wrote: | The above looks like $70 was taken from cash and | deposited to bank. Thats not whats happening in the real | world. Since cash is fungible, one could ignore that. But | if it was cheque + bank-transfer or something else that | leaves a record, then that wont work. Or when you include | VAT/GST/Sales tax. Or when you pay a loan monthly payment | of $1000 that needs to be split to principal and | interest. etc. | yobbo wrote: | Yes, it is best if transactions correspond to verifiable | events. Complicated situations can be modelled by letting | events be represented by their own "accounts", in a | separate charter. | | In your example, you might let the monthly payment be | represented by its own account, with three transactions | (bank payment, interest, principal). | | The purpose is to make the database constraints enforce | double entry verification. If you don't need this, it can | be made simpler as you suggest. | gen220 wrote: | The experimental directory of `beancount` has some code for | converting beancount data structures into SQL structures [1]. | | You could also take a look at the data structures used by GNU | Ledger (e.g. account [2]) and transcribe them to SQL. A bit | more work, but probably educational. | | [1]: | https://github.com/beancount/beancount/blob/1f180e7176808139... | | [2]: https://github.com/ledger/ledger/blob/master/src/account.h ___________________________________________________________________ (page generated 2022-08-24 23:00 UTC)