The problem
The business rents cars and sells tours in Japan to Thai customers. Bookings came in over LINE, email and phone and lived in spreadsheets. Staff worked out prices, typed invoices and receipts by hand, and checked payments one by one. Bookings slipped through, and customers called to ask for documents.
From booking to paperwork
One flow from booking to paperwork. A customer books on the website; staff confirm it in the back office; the system creates the quotation, deposit request or invoice from the booking, the customer pays by QR or card through the INET gateway, and the gateway’s callback marks the payment, issues the receipt and voucher as PDFs and emails them. Changing a booking’s status carries through to every document that belongs to it.
I gathered the requirements with the business team and the payment provider, wrote the specs, and built and deployed the API. The back office and the public site call it.
How it is put together
- MongoDB with Mongoose. Documents keep a snapshot of what they were issued with, because a financial document has to stay as it was printed.
- Payments. The callback route accepts only the gateway’s IP addresses and handles a repeated callback without issuing a second receipt. A reconciliation job covers the callbacks that never arrive.
- Customers. Records from bookings and every document type are matched on normalized phone, email, tax ID and name into one profile with its service history.
- Operations. Sentry for errors, an audit log of API calls with sensitive fields masked, and a bot check on the public booking form.
The API started as Next.js route handlers. I moved it to NestJS 11 on Fastify.