Refund approval process: 245 bookings no one could open
A sign-off before refunds only works if someone holds the role to approve it. How to check yours, and what 245 stuck bookings showed us at one hire business.
If you want a refund approval process, where someone checks a booking before money goes out, the first thing to check is whether the people who must approve actually hold the role in your software. In the case below, four payout roles existed and nobody held any of them, so the refund screen was closed to everyone and 245 bookings sat in a queue no one could open. The second check is when the checks run: at the moment a booking joins the queue, or only when someone tries to pay it.
Here is how that looked at one hire business, and what fixing it took.
The owner of a hire business asks for a simple control: operations must sign off a booking before it passes to accounts for its refund. To add it, we read how refunds actually flowed through the system for GOI Car & Taxi, a self-drive and taxi hire business in Goa.
The refund screen listed 245 bookings holding 10,00,000 rupees of customers’ deposits. It showed zero invoices, zero recorded refunds, zero payout requests, and not one booking had ever reached Refund Done. Our first write-up said what that looks like: a pipeline that had never completed once, and ten lakh rupees of customers waiting.
That was wrong, and the owner told us so. Refunds were being paid by the office by hand, outside the system. What we had found was a gap in recording, not stuck money. We corrected the review to say so.
What was actually going on
Four payout roles existed and nobody held any of them. The refunds screen therefore answered “forbidden” to every user on production, which is why no refund row had ever been written. The system was not stuck; it had simply never been used for this.
Behind the locked screen, the queue was the raw list. A booking reached accounts automatically: a driver uploads a drop-off photo, the booking moves to Returned and on to Refund Issue Pending, and nothing else is checked. Real checks existed and were good, but they all fired at the moment of payment, one click at a time, so accounts met each booking’s problems only when trying to pay it. Among the 245: 99 had incomplete audits, 242 had no refund method chosen, and 177 had no bank details, of which 164 had never been asked.
The second finding was a wrong number. 27 fully paid bookings holding a 5,000 deposit displayed negative refunds, such as minus 16,283. The settlement summary set “Previous Dues” to the gross amount due at pickup instead of the unpaid balance, so payments received were never subtracted. The refund line disagreed with the ledger on 31 of 39 queued bookings.
A third was latent. When a payout completed, the code recorded who created it using a fallback user that does not exist. A finished bank transfer would have failed to record and the failure would have been swallowed. It had never fired, because no payout had ever run.
What we changed
The payout role was granted on the owner’s approval, and the refunds screen now opens on production. We read every refusal in the close path out of the code rather than the design. There are six, and three of them are skipped for cancellations, so a cancelled booking can be paid with no validation at all.
Then the owner asked whether closing a booking had been tested end to end. Honestly, no: every test had inserted a finished invoice directly, skipping the gates. We built tests that take real bookings through audits, documents, collection and invoice into each kind of close. On the first run the desk sent an amount of zero, the invoice finalised to 5,000 in the same call, and every real manual close was refused. That is now fixed. We also added the close the owner described for a booking with nothing to refund.
What it did not fix
The release-to-accounts gate, a named checklist that revokes if anything changes, was designed, not built as far as the log records. The wrong Previous Dues figure was traced to its line and written into the list of outstanding fixes; the log does not record it being corrected.
No money has moved through the system either. The bank’s test environment works up to creating and approving a payout, then stops, because the first access token has never been issued from the bank’s developer portal. That is a human onboarding step.
How to check your own refund approval process
An empty table is a fact, not a verdict. Before you call a refund process stuck, work through these.
- Find out whether refunds are being paid somewhere else, by hand or outside the system. We did not ask first, and our review overstated the problem.
- List who holds each role the refund screen depends on. A role with no holders is a screen nobody can open.
- Ask where the checks run: when a booking is listed for refund, or only at the moment someone clicks pay. Checks that fire at payment mean accounts meet each booking’s problems one at a time.
- For any test that said “closing a booking works”, ask whether it ran the real steps or inserted the result by hand.
- Ask whether a cancelled booking skips any of the checks. Here three of the six were skipped.
Where this ends up
Refund checks that run when a booking is listed, not when someone tries to pay it, are what Sazinga Rentals is built around.