DoorDash, Uber Eats and SkipTheDishes each send a payout statement. The point of sale knows what was ordered, the bank knows what arrived, and nobody puts the three side by side. This does, order by order, for four weeks of a fictional two-site group, and shows you every row behind every dollar.
The point of sale knows every delivery order, because the tablet writes the app's order number onto the ticket. Each app publishes a payout statement listing the orders it is paying for, what it deducted, and what it is sending. The bank shows what actually landed. Each of those is correct on its own terms, and none of them checks the others. That is the gap money falls into.
Orders to tickets, by the app's order number. An order on a statement with no ticket, or a ticket naming an order no statement carries, is listed, not guessed at.
Statements to themselves. The orders on a statement are added up and compared with the total it prints. The bank pays what the statement says, so a statement that is wrong about its own orders is never caught by looking at the bank.
Statements to deposits, by app, location, amount and a date window. Exact amounts are matched first, everywhere, so a short deposit cannot borrow the one that belongs to the payout next to it. Only then is whatever is left paired up and the difference stated.
Commission kept on refunded orders. When an order is refunded in full, the restaurant gives back the whole price. If the commission on that order stayed deducted, the restaurant has paid for a sale it did not keep. Whether it is recoverable depends on the agreement, which is exactly why each one is listed with its order number, ready to raise.
Payouts that did not arrive. A statement was issued and no matching deposit landed within the normal lag. Payouts still inside the lag are listed separately as in transit, because calling a two day old payout missing would be crying wolf, and a page that cries wolf stops being read.
Deposits short of their statement. The money arrived, but not all of it.
Nowhere here. Every figure is a sum of rows you can see, made by ordinary code, and the same input gives the same page every time. On a real account a model has exactly one job, the same as in the invoice reader: turning a statement that only exists as a PDF into rows. From the rows on, it is arithmetic.
The data is invented, for a fictional group called Harbour & Co, and so are its commission rates. Statements are simplified to subtotal, tax, commission and refunds; real ones also carry marketing fees, tax on fees and tips, which reconcile the same way with more columns. The matching rules, the tolerances and the arithmetic are the real thing.
With one question: when did someone last tick a delivery app's payout against the bank, deposit by deposit? If the honest answer is "when the total looked off", the small ones have been going through for a while. That is usually a twenty minute conversation.
Yuriy Romanyuk, in Vancouver. I ran restaurant operations before I built software for them, which is why this checks three sources against each other instead of drawing a chart of one.