
Haazir Billing — GST Billing & Inventory Platform
Multi-Tenant SaaS · POS
Runs a hotel front desk — bookings, the tape chart, folios and check-out — with the bill blocked while money is still owed.
Multi-tenant hotel management: availability and bookings, a month tape chart, check-in/out, per-stay folios with snapshotted tax, food and beverage, housekeeping, expenses and a full reporting suite — Fastify API and Next.js web, one deployment serving many hotels.

Technaut HMS is provisioned per hotel: an account is issued, and the hotel configures its own world inside it — property details, room types and rooms, tax rates, food menu and staff. One deployment, many hotels, hard isolation between them.
The front desk covers availability search, bookings and walk-ins, a month tape chart, check-in/out, room moves, no-shows, cancellation with a reason, and a per-stay timeline read straight from the audit log. Billing is a folio per stay: charges carry snapshotted tax so a later tax-rate change cannot rewrite history, and discounts, voids, split and partial payments, refunds as negative payments and invoices frozen at issue time all hang off it. Check-out is blocked while money is owed — overridable by a manager, and the override is audited.
The three operational areas interlock rather than sitting side by side. Room service posts a single line to the guest's bill in the same transaction as the order, so a drink cannot be served without reaching the folio. Check-out queues the room clean automatically, and finishing it marks the room clean. A high-priority room issue takes the room out of order, which removes it from what can be sold — so housekeeping state feeds availability directly.
Five roles are enforced from one permissions module that is the single source of truth: the UI hides what a role cannot do, and every route checks it independently.
Small and mid-size hotels run the front desk on a booking sheet and the billing on a calculator. Room service reaches the guest's bill only if someone remembers, housekeeping state lives on a whiteboard that availability does not read, and a changed tax rate quietly rewrites what old invoices say.
Traced a single stay from enquiry to invoice and found the failures were all at the seams — order to folio, check-out to cleaning, cleaning to sellable inventory — not inside any one module.
Built the seams into transactions and state rather than into staff habits. Room service posts to the folio in the same transaction as the order; check-out queues the clean and finishing it frees the room; a high-priority issue takes the room out of sale. Charges snapshot their tax so history stays fixed, and check-out is blocked while a balance is owed.
Fastify 5 (TypeScript, ESM) + Prisma 6 over MySQL — owns the database, exposes only REST
Next.js 16 frontend with no database access, proxying /api/* so auth cookies stay first-party
One module per domain under backend/src/modules, with shared rules in lib: permissions, folio, occupancy, availability, reservation-state, reports, audit
Server/client page split — page.tsx (server) beside <name>-client.tsx (client) per route
JWT access token plus hashed rotating refresh token, CSRF double-submit on mutations, sameSite strict cookies, per-route login rate limiting and account lockout
Append-only audit log written inside the same transaction as the change it records
A tax-rate change rewrote the tax on charges that had already been billed, so reprinting an old invoice produced a different number than the guest had paid.
Snapshotted tax onto each charge at the moment it is posted and froze invoices at issue time, so rate changes apply forward only and history is reproducible.
Housekeeping state and sellable inventory were separate, so a dirty or out-of-order room could still be sold and the guest arrived to a room that was not ready.
Made availability read room condition directly — check-out queues the clean, finishing it marks the room clean, and a high-priority issue takes the room out of order and out of what can be sold.
A folio could be closed with money still outstanding, and the loss only surfaced at the month-end reconciliation.
Blocked check-out while a balance is owed, with an explicit manager override that is written to the append-only audit log in the same transaction.
One system runs the desk, the bill, the kitchen and the floor, with occupancy, ADR, RevPAR and revenue-versus-expenses coming out of the same records the staff already touch. Because the frontend has no database access, the REST API is the single contract a Flutter client can later sit beside.







