Hotel management.
Hotel Management is an internal system that takes a hotel's operations from reservation to checkout without anything falling through the cracks. Front desk staff handle walk-in and online bookings, check guests in and out, log services as they're requested, and generate invoices automatically at the end of each stay. Every role in the hotel — receptionist, cashier, manager — sees and interacts with only what their position requires. Every data change carries a full audit trail with before and after states, so nothing goes unrecorded.
01.Overview
The big pictureHotel-management came out of a very real problem: a 30-room hotel running on Excel and Zalo to take reservations, log check-in / check-out times, tally up ancillary services, and write invoices by hand. Every room change or extra service call meant the receptionist had to remember it, jot it down, then re-enter it into the accounting file at the end of the shift — mistakes weren't the exception, they were routine.
I built hotel-management to wrap the entire lifecycle of a stay into a single flow: from reservation and check-in, through adding services (spa, food and beverage, laundry, transfers), to checkout and invoice generation — nothing entered twice. Granular RBAC ensures front desk staff can't touch the accounting module, and a full audit log records every action with enough detail to trace back anything when needed. This project currently running internally at 1 hotel with ~12 daily users
02.Features
What it does- 01Bookings & lifecycleWalk-in & online · PENDING → CHECKED_OUT
The system accepts reservations through two channels: walk-in at the front desk or from an online source, storing full guest details — name, phone number, national ID — along with the number of adults, children, and any notes. Each booking moves through the lifecycle
PENDING → CONFIRMED → CHECKED_IN → CHECKED_OUT; cancellations transition toCANCELLEDwith a cancellation fee recorded and factored into the final invoice. - 02Realtime room mapStatus by floor · hourly or daily
Each room carries one of four states:
AVAILABLE / OCCUPIED / MAINTENANCE / CLEANING, grouped by floor and room type so front desk staff can see the full picture at a glance. The system supports both rental modes — hourly or nightly — and automatically calculates the charge based on the room type's base rate multiplied by the actual duration of the stay, no manual entry needed. - 03Add-on servicesPer-booking service lines
Throughout the stay, front desk staff can attach additional services to a booking at any time: spa, food and beverage, laundry, transfers. Each service is recorded as a separate
booking_servicesrow, with quantity and unit price locked in at the moment it's added. If the price list changes afterwards, existing rows are unaffected — past invoices always reflect the exact rate at the time the service was incurred. - 04Auto invoicesGenerated on check-out · PDF / Excel
At checkout, the system automatically builds an
invoicefrom all booking data: room charges + total services + tax − discount. The invoice is snapshotted at the moment it's generated — any subsequent changes to room rates or the service price list have no effect on invoices already issued. Front desk staff can print directly at the counter or export to PDF / Excel; both go through a Bull queue so the main flow isn't blocked when multiple invoices are generated simultaneously. - 05RBAC + audit logPer-action permissions · before/after diff
Permissions are controlled down to individual actions: front desk staff only see the rooms and bookings module, while accounting staff are the only ones who can access invoices and reports. Each permission group is scoped by action — create, edit, cancel, refund — not by broad screen access. Every data-mutating operation passes through
AuditInterceptor, automatically saving the before and after state intoaudit_logs— enough to trace who did what, when, and what the data looked like before the change.
03.Tech stack
Tools used| Frontend | Next.js 16 · React 19 · TypeScript · Redux Toolkit · Tailwind 4 · react-hook-form · zod · sonner |
| Backend | NestJS 11 · TypeScript · TypeORM · Passport JWT · class-validator · Socket.IO · Bull |
| Database | MySQL 8 (rooms, bookings, booking_services, invoices, audit_logs JSON) · Redis 7 (cache, queues, socket adapter) |
| Infra | Docker · GitHub Actions · Caddy reverse proxy · VPS (4GB) |
| Observability | In-DB audit logs · Pino · request id middleware |
| Testing | Jest unit (booking lifecycle + RBAC guards) · Supertest e2e (booking → invoice flow) · ~62% coverage |
04.How it works
ArchitectureThe core of hotel-management is the booking lifecycle. Each booking holds a reference to exactly one room and can carry multiple booking_services. When a booking is created, the service checks room availability using a transaction + row lock on the rooms table — preventing double-booking even when two receptionists act on the same room simultaneously. Room state syncs automatically with the booking: CHECKED_IN pushes the room to OCCUPIED, CHECKED_OUT pushes it to CLEANING.
At checkout, a single transaction handles everything: (1) move the booking to CHECKED_OUT, (2) calculate room charges based on actual duration multiplied by the room type rate, (3) sum up booking_services using unit prices snapshotted at the time each service was added, (4) create the invoices record, (5) move the room to CLEANING. Every step is accompanied by a before/after audit record. End-to-end latency from checkout to printed invoice measured on prod: ~180ms.
"Hotel-management currently handles the full operational flow well — reservations, check-in, services, invoicing. Two directions are being developed next: a more complete guest profile with national ID photos attached at check-in — currently the ID number is stored as text only with no image, while in practice many hotels are required to keep document copies when inspections occur. The second direction is webhook integration to receive bookings directly from external platforms — Booking.com, Airbnb, or any OTA — eliminating the need for receptionists to manually re-enter reservations from multiple channels."
A Flutter-based MySQL admin client — saved connections, browse databases → tables → rows, primary-key-safe CRUD, plus a free-form SQL shell; runs on Android, iOS, macOS, Linux and Windows from a single Dart codebase.
CaptchaOCR is a FastAPI micro-service that accepts a 4-digit captcha image in base64 and returns the corresponding integer. The ddddocr pretrained model is loaded once at process startup — every subsequent request is pure inference, with latency in the range of a few tens of milliseconds per image. The service is deployed via PM2 with auto-restart and a hard RAM cap, keeping it stable over long periods without manual oversight.
A NestJS API that auto-logs into ChatGPT via puppeteer-real-browser (Cloudflare anti-bot bypass), supports email OTP, persists the session for route /ask reuse and directly promt promt, and runs an hourly cron that pings Telegram when the session expires. This allows me to send prompts and receive responses directly through the API without needing to open a browser.
ZoomBot is a pool of Chrome bots that automatically join Zoom meetings and wait for remote commands via HTTP API. Each bot runs on its own isolated Chrome instance with its own lock, fully thread-safe — bots don't interfere with each other even when running in parallel. A single API call can instruct any bot to send a chat message, toggle the mic, toggle video, leave the room, or rejoin. When a bot crashes, the system detects it automatically and restarts without any manual intervention. The entire stack is written in Python, Selenium, and Flask — lean enough to run on a standard server without complex infrastructure.
05.Comments
Leave a few wordsNo comments yet.