HMP Platform Architecture Reference
Last updated: 2026-03-27 | Version 2.0 (Multi-Repo)
This is the definitive reference document for the HMP (Hotel Management Platform) architecture. It covers every repository, service, data flow, and developer workflow. A new engineer joining any team should be able to understand the complete system by reading this document end to end.
Table of Contents
- Platform Overview
- Multi-Repo Structure
- Developer Experience
- Architecture Details Per Repo
- Inter-Service Communication
- Environment Pipeline
1. Platform Overview
What is HMP?
HMP is a cloud-native, multi-tenant hotel management platform built for the Indian hospitality market. It covers the full lifecycle of hotel operations: reservations, front-desk, housekeeping, point-of-sale, banquet management, spa, channel distribution, CRM/loyalty, analytics, and compliance (GST, DPDPA, C-Form, e-Invoice).
Who uses it?
| Persona | Interface | Key Actions |
|---|---|---|
| Front-desk agent | Web Dashboard | Check-in/out, room assignment, folio management, cash drawer |
| Housekeeping staff | Mobile App | Accept tasks, mark rooms clean, report maintenance |
| F&B / Kitchen staff | Mobile App, KDS | Take orders, manage KOTs, close shifts |
| Revenue manager | Web Dashboard | Set rate plans, view BAR calendar, approve pricing recommendations |
| Hotel GM / Owner | Web Dashboard, Owner Portal | View KPIs, night-audit reports, P&L dashboards |
| Guest | Booking Engine, Guest Portal | Search rooms, book, self-check-in, raise requests |
| Platform admin (SUPER_ADMIN) | Admin Portal | Onboard tenants, manage subscriptions, feature flags |
Business Domain
HMP is a SaaS product. Each tenant is a hotel company (may own multiple properties). Each property is a physical hotel with rooms, outlets, venues, and staff. Multi-tenancy is enforced at every layer: database rows carry tenantId, API requests carry x-tenant-id and x-property-id headers, and the API Gateway validates tenant context on every request.
Technology Stack
| Layer | Technology |
|---|---|
| Backend services | NestJS (TypeScript), Prisma ORM, PostgreSQL 16 |
| Event bus | Redis Streams via @hmp/messaging (its class is named KafkaService for call-site compatibility only; there is no Kafka) |
| Cache / sessions | Redis 7 |
| Staff dashboard | Next.js 16, NextAuth v5, shadcn/ui, Tailwind CSS |
| Admin portal | Next.js 16, NextAuth v5, shadcn/ui |
| Guest booking engine | Vite, React, Zustand |
| Mobile apps | React Native (Expo), Turborepo |
| KDS / Kiosk | Electron, Vite, React |
| Forecast sidecar | Python, FastAPI, Prophet, scikit-learn |
| Infrastructure | Docker, Terraform (Azure), GitHub Actions / Azure Pipelines |
| Monitoring | Prometheus (prom-client), Grafana dashboards, custom alert rules |
2. Multi-Repo Structure
The platform is organized into 23 repositories grouped by team ownership. All repos live under the Azure DevOps project KeyNova at https://dev.azure.com/CentraLogicIndia/KeyNova/_git/.
Repository Map
Platform Team (5 repos)
| Repo | Type | Port | Purpose | Key Technologies |
|---|---|---|---|---|
hmp-api-gateway | Backend | 3010 | Request routing, CORS, rate limiting, auth validation, WebSocket proxy, batch API, search aggregation | NestJS, Redis, http-proxy-middleware |
hmp-auth-service | Backend | 3001 | Authentication (JWT + refresh tokens), MFA (WebAuthn), SSO, tenant CRUD, billing, subscription plans, feature flags, API keys | NestJS, Prisma, bcrypt, passport, Razorpay |
hmp-admin-portal | Frontend | 3030 | SUPER_ADMIN platform management: tenant onboarding wizard, subscription management, feature flags, audit logs, billing, analytics | Next.js 16, NextAuth v5, shadcn/ui |
hmp-shared-packages | Library | - | 5 @hmp/* npm packages (common, messaging, database, api-contracts, ui-kit), dev Docker Compose, CI/CD templates | Lerna, TypeScript |
hmp-infrastructure | DevOps | - | Docker configs, CI/CD pipeline templates, Terraform modules (Azure), Helm charts, Kubernetes manifests, monitoring dashboards/alerts, DR scripts, load-test configs | Docker, Terraform, Helm, k6, Grafana |
PMS Team (5 repos)
| Repo | Type | Port | Purpose | Key Technologies |
|---|---|---|---|---|
hmp-property-service | Backend | 3002 | Properties, room types, rooms, rate plans, cancellation policies, tax config, BAR engine, rate calendar, tenant config, data migration importer, brands, custom fields, edge deployment | NestJS, Prisma |
hmp-reservation-service | Backend | 3003 | Reservations, availability, group bookings, promo codes, payments (Razorpay), booking-engine API, guest portal (lookup, pre-check-in, requests, menu) | NestJS, Prisma, Razorpay SDK |
hmp-frontdesk-service | Backend | 3005 | Check-in/out, folios, folio transactions, night audit, room moves, upgrades, service recovery, cash management (drawers, safes, petty cash, bank deposits), company ledger, guest portal (self-check-in/out, concierge), C-Form, compliance, e-Invoice | NestJS, Prisma |
hmp-housekeeping-service | Backend | 3006 | Housekeeping tasks, room status, maintenance requests, lost & found, linen inventory, minibar, inventory management, WebSocket real-time updates | NestJS, Prisma, Socket.IO |
hmp-guest-service | Backend | 3004 | Guest profiles, identity documents, addresses, preferences, communications, GDPR/DPDPA consent, DSAR requests, travel agents | NestJS, Prisma |
Revenue Team (4 repos)
| Repo | Type | Port | Purpose | Key Technologies |
|---|---|---|---|---|
hmp-pos-service | Backend | 3007 | F&B outlets, menu management, tables, orders, KOTs, kitchen display, shifts, inventory, recipes, stock movements, WebSocket real-time KDS | NestJS, Prisma, Socket.IO |
hmp-analytics-service | Backend | 3013 | CQRS event consumers, 7 materialized views, reports, night-audit reports, audit logs, KPI catalog, control center, SOPs, cadences, labor, owner portal, pilot program, activity feed, exceptions, actions, metering, GST filing, pricing recommendations, RUM | NestJS, Prisma |
hmp-banquet-service | Backend | 3011 | Venues, event bookings, function sheets, event items, event payments | NestJS, Prisma |
hmp-channel-service | Backend | 3009 | OTA connections (Booking.com, Expedia, MakeMyTrip, Agoda, etc.), room/rate mappings, inventory sync, GDS integration, TDS entries | NestJS, Prisma |
Guest Experience Team (6 repos)
| Repo | Type | Port | Purpose | Key Technologies |
|---|---|---|---|---|
hmp-web-dashboard | Frontend | 3020 | Staff dashboard: 30+ page groups covering reservations, front-desk, housekeeping, POS, rates, reports, CRM, channel manager, banquet, spa, notifications, settings, night audit, cash management, kiosk, AI, owner portal, pilot | Next.js 16, NextAuth v5, shadcn/ui, Tailwind CSS |
hmp-booking-engine | Frontend | 3040 | Guest-facing room search, checkout, promo codes, loyalty integration, booking management, language switcher (EN/HI/TH/ID/VI), embeddable web component | Vite, React, Zustand |
hmp-crm-service | Backend | 3012 | Loyalty programs, tiers, members, points transactions, rewards, campaigns, communication templates, feedback surveys, companies, corporate contracts, partner programs, co-branded cards | NestJS, Prisma |
hmp-notification-service | Backend | 3008 | Email (SendGrid), SMS (Twilio), push notifications, notification templates, communication templates, delivery logs, guest preferences, TRAI DND compliance | NestJS, Prisma, SendGrid, Twilio |
hmp-mobile-apps | Frontend | - | 4 React Native apps: housekeeping, F&B, guest, manager. Real-time hooks (useRealtimeTasks, useRealtimeKitchen), swipeable task cards, cleaning timer, modifier sheet | React Native, Expo, Turborepo, Socket.IO |
hmp-kds-kiosk | Frontend | - | Kitchen Display System (Electron) and Self-Service Kiosk (Electron). Shared component library | Electron, Vite, React, Vitest |
Shared (3 repos)
| Repo | Type | Port | Purpose | Key Technologies |
|---|---|---|---|---|
hmp-spa-service | Backend | 3015 | Spa treatments, therapists, rooms, appointments, packages | NestJS, Prisma |
hmp-docs | Docs | 3050 | Platform documentation: architecture, requirements (22 epics, 148 stories), API reference, runbooks, review reports | Docusaurus |
hmp-platform | Archive | - | Original monorepo (Nx workspace with all 13 backend services + libs). Kept read-only for reference during stabilization period | NestJS, Nx, Prisma |
Additional Backend Services (in monorepo, not yet extracted)
| Service | Port | Purpose |
|---|---|---|
ai-service | 3016 | OTA review ingestion, sentiment analysis, NLQ (natural language queries), multi-language support (Hindi, Tamil, Telugu, Marathi) |
integration-service | 3014 | Tally accounting integration, integration registry, simulator event bus |
Python Sidecar
| Repo | Port | Purpose |
|---|---|---|
hmp-forecast-sidecar | 8001 | Prophet demand forecasting, GradientBoosting dynamic pricing, Indian holiday calendar (172 entries, 2024-2028) |
3. Developer Experience
3.1 Daily Workflow
Prerequisites
- Node.js 20 LTS
- Docker Desktop (with WSL2 on Windows)
- Git
- VS Code (recommended)
- Access to Azure Artifacts npm registry (for
@hmp/*packages)
Morning Setup (2 minutes)
# 1. Start all infrastructure (one database per service + Redis)
cd hmp-shared-packages
docker compose -f docker/docker-compose.dev.yml up -d
# 2. Wait for databases to be healthy (~30 seconds)
docker compose -f docker/docker-compose.dev.yml ps
# 3. Navigate to your service and start it in dev mode
cd ../hmp-property-service
npm run start:dev
# 4. Open VS Code
code .
Port Map (Local Development)
| Port | Service |
|---|---|
| 3001 | auth-service |
| 3002 | property-service |
| 3003 | reservation-service |
| 3004 | guest-service |
| 3005 | frontdesk-service |
| 3006 | housekeeping-service |
| 3007 | pos-service |
| 3008 | notification-service |
| 3009 | channel-service |
| 3010 | api-gateway (all traffic goes through here) |
| 3011 | banquet-service |
| 3012 | crm-service |
| 3013 | analytics-service |
| 3014 | integration-service |
| 3015 | spa-service |
| 3016 | ai-service |
| 3020 | web-dashboard (Next.js) |
| 3030 | admin-portal (Next.js) |
| 3040 | booking-engine (Vite) |
| 3050 | docs (Docusaurus) |
| 5433-5445 | PostgreSQL databases (one per service) |
| 6379 | Redis |
| 8001 | forecast-sidecar (Python) |
Database Connection Strings
Each service has its own database. Connection strings follow the pattern:
postgresql://hmp:hmp_dev_pass@localhost:<PORT>/hmp_<service>
| Service | Port | Database |
|---|---|---|
| auth | 5433 | hmp_auth |
| property | 5434 | hmp_property |
| reservation | 5435 | hmp_reservation |
| guest | 5436 | hmp_guest |
| frontdesk | 5437 | hmp_frontdesk |
| housekeeping | 5438 | hmp_housekeeping |
| pos | 5439 | hmp_pos |
| analytics | 5440 | hmp_analytics |
| notification | 5441 | hmp_notification |
| channel | 5442 | hmp_channel |
| banquet | 5443 | hmp_banquet |
| crm | 5444 | hmp_crm |
During the Day
# Code changes reflect instantly via NestJS hot-reload
# Test your API directly:
curl http://localhost:3002/api/properties
# Test via the gateway (how the dashboard calls it):
curl http://localhost:3010/api/properties \
-H "Authorization: Bearer <JWT>" \
-H "x-tenant-id: <TENANT_UUID>" \
-H "x-property-id: <PROPERTY_UUID>"
# Run unit tests:
npm test
# Run tests in watch mode:
npm run test:watch
# Run Prisma migrations after schema changes:
npx prisma migrate dev --name describe_the_change
# Dashboard: http://localhost:3020
# Admin portal: http://localhost:3030
# Booking engine: http://localhost:3040
End of Day
# Commit and push if ready
git add -A && git commit -m "feat(EP-005): TICKET-123 add batch check-in"
git push origin feat/TICKET-123-add-batch-checkin
# Optionally stop your service (Ctrl+C in terminal)
# Optionally stop databases (or leave running for next day):
cd ../hmp-shared-packages
docker compose -f docker/docker-compose.dev.yml down
3.2 Creating a Feature
Step-by-Step Process
- Pick a ticket from Azure Boards "Sprint Ready" column
- Read the story in hmp-docs (
docs/requirements/epics/EP-XXX/US-YYY.md) - Create a branch:
git checkout -b feat/TICKET-123-add-batch-checkin - Code -- follow existing patterns in the service (controller -> service -> Prisma)
- Write tests -- unit tests for service methods, e2e tests for API endpoints
- Run lint and typecheck:
npm run lint
npm run typecheck - Commit using Conventional Commits:
git commit -m "feat(EP-005): TICKET-123 add batch check-in endpoint" - Push:
git push origin feat/TICKET-123-add-batch-checkin - Create PR in Azure DevOps:
- Title:
feat(EP-005): TICKET-123 add batch check-in - Link to Azure Boards work item
- CI pipeline runs: lint, typecheck, test, contract validation
- Request 1 reviewer (2 reviewers required for
hmp-shared-packages)
- Title:
- Merge (squash) -- auto-deploys to QA environment
- QA verification -- promote to Staging -- promote to Production
Branch Naming
| Type | Pattern | Example |
|---|---|---|
| Feature | feat/TICKET-123-short-description | feat/TICKET-123-add-batch-checkin |
| Bug fix | fix/TICKET-456-short-description | fix/TICKET-456-login-error |
| Hotfix | hotfix/TICKET-789-short-description | hotfix/TICKET-789-critical-fix |
| Refactor | refactor/TICKET-012-short-description | refactor/TICKET-012-simplify-order |
Commit Messages (Conventional Commits)
feat(EP-005): TICKET-123 add batch check-in endpoint
fix(EP-003): TICKET-456 fix availability calculation off-by-one
refactor(EP-007): TICKET-789 simplify order service validation
docs(EP-023): TICKET-012 update onboarding guide
test(EP-005): TICKET-345 add check-in edge case tests
perf(EP-013): TICKET-678 optimize occupancy query with index
Format: <type>(<scope>): <TICKET-ID> <description>
- type: feat, fix, refactor, docs, test, perf, chore, ci
- scope: Epic ID (EP-001 through EP-022) or module name
- TICKET-ID: Azure Boards work item number
- description: imperative mood, lowercase, no period
3.3 Working with Shared Packages
The hmp-shared-packages repo contains 5 npm packages published to Azure Artifacts:
| Package | Purpose |
|---|---|
@hmp/common | Decorators (@CurrentUser, @Roles, @Public), guards, pipes, filters, validators (GSTIN, SAC codes), room status state machine, data retention executor, ESC/POS printer templates |
@hmp/messaging | KafkaService, EventTopics enum (137 event types), BaseEvent interface, event store service |
@hmp/database | PrismaService (extends PrismaClient with $connect/$disconnect lifecycle), multi-tenant query helpers |
@hmp/api-contracts | Shared DTOs, request/response types, API endpoint constants |
@hmp/ui-kit | Shared React components for dashboard and admin portal (buttons, forms, tables, modals) |
Installing
npm install @hmp/common @hmp/messaging @hmp/database
Importing
import { CurrentUser, Roles, Public, TenantGuard } from '@hmp/common';
import { KafkaService, EventTopics, BaseEvent } from '@hmp/messaging';
import { PrismaService } from '@hmp/database';
Updating When a New Version is Published
npm update @hmp/common
# Test locally to ensure no breaking changes
npm test
# Commit the package-lock.json change
git add package-lock.json
git commit -m "chore: update @hmp/common to v1.2.0"
Contributing to Shared Packages
- Clone
hmp-shared-packages - Make changes in
packages/<name>/src/ - Run tests:
cd packages/<name> && npm test - Create PR to
hmp-shared-packages(requires 2 reviewers) - On merge, CI auto-publishes a new version to Azure Artifacts
- Downstream services update via
npm update
3.4 Running the Full Platform (Docker Demo)
For integration testing or demos, a Docker Compose setup runs all services in containers:
cd docker
docker compose -f docker-compose.demo.yml up -d
| Container | Port | Notes |
|---|---|---|
| hmp-backend | 3010 | Single container running API gateway + all 13 microservices |
| hmp-dashboard | 3020 | Next.js staff dashboard |
| hmp-booking | 3040 | Vite booking engine |
| hmp-admin | 3030 | Next.js admin portal |
| hmp-docs | 3050 | Docusaurus documentation |
| hmp-demo-hub | 8000 | Landing page linking all services |
| hmp-postgres | 5432 | PostgreSQL 16 |
| hmp-redis | 6379 | Redis 7 (cache + sessions) |
| hmp-redis-session | 6380 | Redis 7 (dedicated session store) |
Demo credentials: admin@hmphotel.com / <REDACTED>
Other users: frontdesk@hmphotel.com, hk@hmphotel.com, manager@hmphotel.com (same password).
4. Architecture Details Per Repo
4.1 hmp-api-gateway (Port 3010)
What it does: The single entry point for all client traffic. Every HTTP request from the dashboard, admin portal, booking engine, and mobile apps passes through the gateway. It strips the /api prefix for route matching, identifies the target service via longest-prefix match against 70+ route rules, validates the JWT, injects tenant context headers, and proxies the request to the backend service. It also hosts the integration status API, WebSocket proxy, batch API, and search aggregation endpoints.
Database: None (stateless). Uses Redis for rate-limiting counters and session validation.
API Routes (gateway-level):
ALL /api/* → Proxied to target service based on path prefix matching
GET /health → Gateway health check
GET /integrations/status → Integration registry status page
POST /batch → Batch API (multiple requests in one call)
GET /search → Aggregated search across services
Key Environment Variables:
PORT=3010
REDIS_HOST, REDIS_PORT
AUTH_SERVICE_HOST, AUTH_SERVICE_PORT
PROPERTY_SERVICE_HOST, PROPERTY_SERVICE_PORT
RESERVATION_SERVICE_HOST, RESERVATION_SERVICE_PORT
GUEST_SERVICE_HOST, GUEST_SERVICE_PORT
FRONTDESK_SERVICE_HOST, FRONTDESK_SERVICE_PORT
HOUSEKEEPING_SERVICE_HOST, HOUSEKEEPING_SERVICE_PORT
POS_SERVICE_HOST, POS_SERVICE_PORT
NOTIFICATION_SERVICE_HOST, NOTIFICATION_SERVICE_PORT
CHANNEL_SERVICE_HOST, CHANNEL_SERVICE_PORT
BANQUET_SERVICE_HOST, BANQUET_SERVICE_PORT
CRM_SERVICE_HOST, CRM_SERVICE_PORT
ANALYTICS_SERVICE_HOST, ANALYTICS_SERVICE_PORT
SPA_SERVICE_HOST, SPA_SERVICE_PORT
AI_SERVICE_HOST, AI_SERVICE_PORT
INTEGRATION_SERVICE_HOST, INTEGRATION_SERVICE_PORT
JWT_SECRET
Header Forwarding: The gateway only forwards these headers to backend services: authorization, x-tenant-id, x-property-id, x-request-id, accept, accept-language.
Route Resolution: Longest-prefix match. For example, /api/rooms/status/batch matches housekeeping-service (prefix /rooms/status) rather than property-service (prefix /rooms).
How to run locally:
cd hmp-api-gateway
cp .env.example .env # configure service hosts
npm install
npm run start:dev
4.2 hmp-auth-service (Port 3001)
What it does: Manages authentication and authorization for the entire platform. Handles user login (email/password with bcrypt), JWT issuance (access + refresh tokens), WebAuthn/FIDO2 MFA, tenant creation and lifecycle (signup, suspend, reactivate), subscription billing (Razorpay integration), feature flags, API key management, and audit logging.
Database: hmp_auth (port 5433)
Key Tables:
tenants — id, name, slug, gstin, plan, status, domain, settings
users — id, tenantId, email, passwordHash, role, mfaEnabled
webauthn_credentials — id, userId, credentialId, publicKey
sessions — id, userId, token, expiresAt, ipAddress, userAgent
password_histories — id, userId, passwordHash, changedAt
audit_logs — id, tenantId, userId, action, resource, details, ip
api_keys — id, tenantId, name, keyHash, permissions, expiresAt
tenant_configs — id, tenantId, key, value, category
custom_domains — id, tenantId, domain, verified, sslStatus
subscription_plans — id, name, features, priceMonthly, priceYearly
tenant_subscriptions — id, tenantId, planId, status, currentPeriodEnd
invoices — id, tenantId, amount, status, razorpayInvoiceId
usage_records — id, tenantId, metric, quantity, period
API Endpoints:
POST /api/auth/login → Authenticate, return JWT
POST /api/auth/refresh → Refresh access token
GET /api/auth/me → Current user profile
POST /api/auth/logout → Invalidate session
POST /api/auth/mfa/register → Start WebAuthn registration
POST /api/auth/mfa/verify → Verify WebAuthn assertion
POST /api/tenants/signup → Create tenant + admin user
GET /api/tenants → List tenants (SUPER_ADMIN)
PATCH /api/tenants/:id → Update tenant
POST /api/tenants/:id/suspend → Suspend tenant
POST /api/tenants/:id/reactivate → Reactivate tenant
GET /api/feature-flags → List feature flags for tenant
PUT /api/feature-flags/:key → Toggle feature flag
GET /api/billing/invoices → List invoices
POST /api/billing/subscribe → Create subscription
Events Published:
tenant.created → { tenantId, name, plan }
Events Consumed: None (auth is the source of truth for identity).
Talks to: Redis (session store, rate limiting). No direct calls to other services.
How to run locally:
cd hmp-auth-service
cp .env.example .env
# Set DATABASE_URL=postgresql://hmp:hmp_dev_pass@localhost:5433/hmp_auth
# Set JWT_SECRET, JWT_REFRESH_SECRET, REDIS_HOST, REDIS_PORT
npx prisma migrate deploy
npx prisma db seed
npm run start:dev
4.3 hmp-property-service (Port 3002)
What it does: The master data service for all property configuration. Manages properties, room types, physical rooms, rate plans, rate calendar (BAR engine with Indian festival detection), cancellation policies, tax configuration (GST with SAC codes), brands (chain management), custom fields, tenant-level configuration, and data migration import (Opera, eZee, Hotelogix, IdsNext).
Database: hmp_property (port 5434)
Key Tables:
brands — id, tenantId, name, code, logo
properties — id, tenantId, brandId, name, address, gstin, starRating, timezone
room_types — id, propertyId, name, code, baseOccupancy, maxOccupancy, baseRate
rooms — id, propertyId, roomTypeId, roomNumber, floor, status, isOutOfOrder
room_status_logs — id, roomId, fromStatus, toStatus, changedBy, changedAt
rate_plans — id, propertyId, name, code, type, mealPlan, baseAmount
rate_plan_rates — id, ratePlanId, date, amount, restrictions
cancellation_policies — id, propertyId, name, rules, isDefault
seasons — id, propertyId, name, startDate, endDate, multiplier
tax_configurations — id, propertyId, sacCode, cgstRate, sgstRate, igstRate, threshold
API Endpoints:
GET /api/properties → List properties for tenant
POST /api/properties → Create property
GET /api/properties/:id → Property details
PATCH /api/properties/:id → Update property
GET /api/room-types → List room types
POST /api/room-types → Create room type
GET /api/rooms → List rooms (with filters)
POST /api/rooms → Create room
PATCH /api/rooms/:id → Update room
GET /api/rate-plans → List rate plans
POST /api/rate-plans → Create rate plan
GET /api/rates/calendar → BAR rate calendar (14-day grid)
PUT /api/rates/calendar/bulk → Bulk update rates
GET /api/cancellation-policies → List policies
GET /api/tax → Tax configuration
GET /api/tenant-config → Tenant-level settings
PUT /api/tenant-config/:key → Update tenant setting
GET /api/brands → List brands (chain management)
POST /api/custom-fields → Define custom field
GET /api/edge/status → Edge deployment status
Events Published:
rate_plan.created → { ratePlanId, propertyId, name, baseAmount }
rate_plan.updated → { ratePlanId, changes }
rate_plan.deleted → { ratePlanId, propertyId }
room.status.changed → { roomId, fromStatus, toStatus, changedBy }
Events Consumed: None directly. Property-service is a master data provider.
Talks to: No outbound service calls. Other services call property-service to fetch room/rate data.
4.4 hmp-reservation-service (Port 3003)
What it does: Manages the full reservation lifecycle from creation through check-out. Handles availability calculation, room assignment, group bookings, promo codes, payment processing (Razorpay), and the public booking-engine API. Also serves guest portal endpoints for reservation lookup, pre-check-in, and service requests.
Database: hmp_reservation (port 5435)
Key Tables:
reservations — id, propertyId, guestId, confirmationNumber, status, source, arrivalDate, departureDate, totalAmount, specialRequests
room_reservations — id, reservationId, roomTypeId, roomId, adults, children, checkInDate, checkOutDate
pax_records — id, roomReservationId, guestId, isPrimary
reservation_histories — id, reservationId, action, changes, performedBy, performedAt
groups — id, propertyId, name, code, status, cutoffDate, totalRooms
promo_codes — id, propertyId, code, discountType, discountValue, validFrom, validTo
Data Flow:
[Guest] → [Booking Engine] → [API Gateway :3010] → [Reservation Service :3003]
|
↓
[Dashboard] → [API Gateway] → [Reservation Service] → [reservation.created event]
|
┌─────┴──────────────┐
↓ ↓
[Analytics Service] [Notification Service]
(occupancy views) (confirmation email)
API Endpoints:
GET /api/reservations → List reservations (with filters)
POST /api/reservations → Create reservation
GET /api/reservations/:id → Reservation details
PATCH /api/reservations/:id → Modify reservation
DELETE /api/reservations/:id → Cancel reservation
POST /api/reservations/:id/assign-room → Assign room
GET /api/availability → Check availability for dates
GET /api/groups → List group bookings
POST /api/groups → Create group
POST /api/payments → Process payment (Razorpay)
POST /api/payments/webhook → Razorpay webhook (paise→INR conversion)
GET /api/booking-engine/search → Public: search available rooms
POST /api/booking-engine/reserve → Public: create booking
GET /api/guest-portal/lookup → Guest: find reservation by confirmation number
POST /api/guest-portal/pre-checkin → Guest: submit pre-check-in details
GET /api/guest-portal/requests → Guest: list service requests
GET /api/guest-portal/menu → Guest: view in-room dining menu
Events Published:
reservation.created → { reservationId, guestId, propertyId, dates, amount, source }
reservation.modified → { reservationId, changes }
reservation.cancelled → { reservationId, reason, cancelledBy }
reservation.checked_in → { reservationId, roomId, actualCheckIn }
reservation.checked_out → { reservationId, actualCheckOut, finalAmount }
reservation.no_show → { reservationId, markedAt }
group.created → { groupId, propertyId, name, totalRooms }
group.confirmed → { groupId, confirmedRooms }
Events Consumed:
room.status.changed → Update room availability cache
channel.booking.received → Create reservation from OTA
Talks to:
property-service(API call):GET /roomsfor availability check,GET /room-typesfor pricingguest-service(API call):GET /guests/:idfor guest profile during booking- Redis: availability cache
4.5 hmp-guest-service (Port 3004)
What it does: Central guest profile management. Maintains guest identities (Aadhaar, passport, driving license), addresses, preferences (room, pillow, dietary, etc.), communication history, and privacy compliance (GDPR data subject requests, DPDPA consent management).
Database: hmp_guest (port 5436)
Key Tables:
guests — id, propertyId, firstName, lastName, email, phone, dateOfBirth, nationality, vipLevel, totalStays
guest_identities — id, guestId, type (AADHAAR|PASSPORT|DL), documentNumber, issuingCountry, expiryDate
guest_addresses — id, guestId, type (HOME|OFFICE|BILLING), line1, line2, city, state, postalCode, country
guest_preferences — id, guestId, category, key, value
guest_communications — id, guestId, channel, subject, body, sentAt
guest_communication_preferences — id, guestId, channel, enabled, optOutDate
consent_logs — id, guestId, consentType, granted, timestamp
consent_records — id, guestId, purpose, status, grantedAt, expiresAt
dsar_requests — id, guestId, type (ACCESS|DELETE|PORTABILITY), status, completedAt
dsar_audit_entries — id, dsarRequestId, action, performedBy, details
API Endpoints:
GET /api/guests → List/search guests
POST /api/guests → Create guest profile
GET /api/guests/:id → Guest details (with preferences, identities)
PATCH /api/guests/:id → Update guest
POST /api/guests/merge → Merge duplicate profiles
GET /api/preferences → List preference definitions
GET /api/travel-agents → List travel agent companies
GET /api/gdpr/dsar → List DSAR requests
POST /api/gdpr/dsar → Submit data subject request
GET /api/dpdp/consent/:guestId → Get consent status
POST /api/dpdp/consent → Record consent
Events Published:
guest.created → { guestId, propertyId, email, phone }
guest.updated → { guestId, changes }
guest.merged → { survivorId, mergedIds }
guest.preferences.applied → { guestId, preferences }
Events Consumed: None.
Talks to: No outbound service calls. Other services call guest-service to fetch profiles.
4.6 hmp-frontdesk-service (Port 3005)
What it does: The operational heart of the hotel. Handles check-in (including batch and group check-in), check-out, folio management (charges, payments, transfers, splits), night audit, room moves, upgrades, service recovery (compensation), cash management (drawers, safes, petty cash, bank deposits), company ledger, guest portal self-service (self-check-in/out, concierge), C-Form generation for foreign nationals, compliance reporting, and e-Invoice generation.
Database: hmp_frontdesk (port 5437)
Key Tables:
folios — id, reservationId, guestId, propertyId, status, totalCharges, totalPayments, balance
folio_transactions — id, folioId, type (CHARGE|PAYMENT|ADJUSTMENT), category, amount, description, postedBy
payments — id, folioId, method, amount, reference, razorpayPaymentId, status
e_invoice_jobs — id, folioId, irn, ackNumber, status, signedQr
credit_notes — id, folioId, amount, reason, approvedBy
wake_up_calls — id, reservationId, roomNumber, scheduledTime, status
phone_charges — id, reservationId, roomNumber, duration, amount
key_card_logs — id, reservationId, roomNumber, action, cardNumber, issuedBy
invoice_sequences — id, propertyId, prefix, currentValue, fiscalYear
night_audit_logs — id, propertyId, auditDate, status, startedAt, completedAt, summary
cash_drawers — id, propertyId, name, location, status
cash_drawer_shifts — id, drawerId, userId, openedAt, closedAt, openingBalance, closingBalance
drawer_transactions — id, shiftId, type, amount, reference
property_safes — id, propertyId, name, currentBalance
safe_transactions — id, safeId, type, amount, performedBy
bank_deposits — id, propertyId, amount, depositDate, reference
petty_cash_funds — id, propertyId, balance, limit
petty_cash_disbursements — id, fundId, amount, purpose, approvedBy
petty_cash_replenishments — id, fundId, amount, source
exchange_rate_histories — id, fromCurrency, toCurrency, rate, effectiveDate
Data Flow:
[Dashboard: Check-in] → [API Gateway] → [Frontdesk Service]
|
┌─────────┼──────────────────┐
↓ ↓ ↓
[Reservation [Guest [Housekeeping
Service] Service] Service]
(get booking) (get profile) (auto-create
cleaning task)
API Endpoints:
POST /api/check-in → Check in a reservation
POST /api/check-in/batch → Batch check-in (multiple reservations)
POST /api/check-out → Check out
GET /api/folios → List folios
GET /api/folios/:id → Folio details with transactions
POST /api/folios/:id/charges → Post charge to folio
POST /api/folios/:id/payments → Post payment to folio
POST /api/folios/:id/transfer → Transfer charges between folios
POST /api/folios/:id/split → Split folio
POST /api/night-audit/run → Execute night audit
GET /api/night-audit/status → Night audit status
POST /api/room-move → Move guest to different room
POST /api/upgrades → Upgrade room
POST /api/service-recovery → Create service recovery (compensation)
GET /api/cash-drawers → List cash drawers
POST /api/drawer-shifts/open → Open cash drawer shift
POST /api/drawer-shifts/close → Close and reconcile shift
GET /api/safes → List property safes
POST /api/bank-deposits → Record bank deposit
GET /api/companies → List company accounts
POST /api/companies/:id/charges → Post charge to company ledger
GET /api/guest-portal/self-checkin → Self check-in flow
POST /api/guest-portal/self-checkout → Self check-out
GET /api/guest-portal/concierge → Concierge services
GET /api/frontdesk/cform → List C-Forms
POST /api/frontdesk/cform → Generate C-Form for foreign national
GET /api/compliance/reports → Compliance report status
POST /api/refund-ledger → Process refund
Events Published:
reservation.checked_in → { reservationId, roomId, actualCheckIn }
reservation.checked_out → { reservationId, actualCheckOut, finalAmount }
folio.charge.posted → { folioId, transactionId, category, amount }
folio.payment.received → { folioId, method, amount }
folio.settled → { folioId, totalAmount, settledAt }
folio.transferred → { sourceFolioId, targetFolioId, amount }
night.audit.started → { propertyId, auditDate }
night.audit.completed → { propertyId, auditDate, summary }
Events Consumed:
reservation.created → Create folio for new reservation
pos.order.closed → Auto-post F&B charges to guest folio
spa.charge.created → Auto-post spa charges to guest folio
Talks to:
reservation-service(API call):GET /reservations/:idfor check-in validationguest-service(API call):GET /guests/:idfor guest profile and ID documentsproperty-service(API call):GET /rooms/:idfor room detailshousekeeping-service(event): triggers task creation on check-out
4.7 hmp-housekeeping-service (Port 3006)
What it does: Manages housekeeping operations: task creation and assignment, room status tracking (9-state machine: VACANT_CLEAN, VACANT_DIRTY, OCCUPIED_CLEAN, OCCUPIED_DIRTY, INSPECTED, OUT_OF_ORDER, OUT_OF_SERVICE, PICKUP, TURNDOWN), maintenance requests, lost & found items, linen inventory and movements, minibar consumption, and general inventory. Provides WebSocket real-time updates for the mobile app.
Database: hmp_housekeeping (port 5438)
Key Tables:
housekeeping_tasks — id, propertyId, roomId, type (CHECKOUT|STAYOVER|DEEP_CLEAN|TURNDOWN), status, priority, assignedTo, startedAt, completedAt, inspectedBy
housekeeping_photos — id, taskId, url, type (BEFORE|AFTER|ISSUE)
maintenance_requests — id, propertyId, roomId, category, description, priority, status, assignedTo
linen_inventories — id, propertyId, itemType, quantity, parLevel
linen_movements — id, inventoryId, type (ISSUE|RETURN|DISCARD), quantity, movedBy
minibar_items — id, propertyId, roomId, itemName, quantity, price
lost_found — id, propertyId, roomId, description, foundBy, status, claimedBy
API Endpoints:
GET /api/housekeeping/dashboard → HK dashboard (task counts by status)
GET /api/tasks → List tasks (with filters)
POST /api/tasks → Create task
PATCH /api/tasks/:id → Update task status
POST /api/tasks/:id/assign → Assign task to staff
POST /api/tasks/:id/inspect → Mark task as inspected
GET /api/rooms/status → Room status board
PATCH /api/rooms/status/:roomId → Update room status
GET /api/rooms/discrepancy → Room discrepancy report
GET /api/maintenance → List maintenance requests
POST /api/maintenance → Create maintenance request
GET /api/lost-found → List lost & found items
POST /api/lost-found → Register found item
GET /api/inventory → List inventory items
POST /api/inventory/movement → Record inventory movement
WebSocket Events (Socket.IO, namespace /housekeeping):
Client → Server:
joinProperty(propertyId) → Join property room for updates
joinFloor(floor) → Join floor-specific room
taskAccepted(taskId) → Staff accepts task on mobile
Server → Client:
taskCreated(task) → New task created
taskAssigned(task) → Task assigned to staff
taskUpdated(task) → Task status changed
taskInspected(task) → Task passed/failed inspection
Events Published:
housekeeping.task.created → { taskId, roomId, type, priority }
housekeeping.task.assigned → { taskId, assignedTo }
housekeeping.task.completed → { taskId, completedAt, duration }
housekeeping.task.inspected → { taskId, inspectedBy, passed }
room.status.changed → { roomId, fromStatus, toStatus }
minibar.consumed → { roomId, items, totalAmount }
Events Consumed:
reservation.checked_out → Auto-create checkout cleaning task
reservation.checked_in → Update room status to OCCUPIED_CLEAN
Talks to:
property-service(API call):GET /roomsfor room list and floor data
4.8 hmp-pos-service (Port 3007)
What it does: Full F&B point-of-sale system. Manages outlets (restaurants, bars, room service, pool bar), menus (categories, items, modifiers), table management, orders (dine-in, takeaway, room-charge), KOT (Kitchen Order Ticket) generation and lifecycle, kitchen display, shift management, inventory tracking, recipes, and stock movements. Provides WebSocket real-time updates for KDS.
Database: hmp_pos (port 5439)
Key Tables:
outlets — id, propertyId, name, type (RESTAURANT|BAR|ROOM_SERVICE|POOL_BAR), status
pos_tables — id, outletId, tableNumber, capacity, status, section
menu_categories — id, outletId, name, sortOrder, parentId
menu_items — id, categoryId, name, shortName, code, price, taxRate, isVeg, isAvailable
item_modifier_groups — id, menuItemId, name, required, multiSelect
item_modifiers — id, groupId, name, priceAdjustment
pos_orders — id, outletId, tableId, guestId, reservationId, type, status, subtotal, tax, total
order_items — id, orderId, menuItemId, quantity, unitPrice, modifiers, kotId, status
kots — id, orderId, outletId, kotNumber, status (PENDING|ACCEPTED|PREPARING|READY|SERVED)
pos_shifts — id, outletId, userId, openedAt, closedAt, totalSales
cash_transactions — id, shiftId, type, amount
inventory_items — id, propertyId, name, unit, currentStock, reorderLevel
recipes — id, menuItemId, yieldQuantity
recipe_ingredients — id, recipeId, inventoryItemId, quantity
stock_movements — id, inventoryItemId, type (PURCHASE|USAGE|WASTE|ADJUSTMENT), quantity, reference
API Endpoints:
GET /api/outlets → List outlets
POST /api/outlets → Create outlet
GET /api/outlets/:id/menu → Menu for outlet (categories + items)
GET /api/outlets/:id/menu/search?q= → Search menu items
POST /api/menu/categories → Create category
POST /api/menu/items → Create menu item
GET /api/tables → List tables
PATCH /api/tables/:id → Update table status
POST /api/orders → Create order
GET /api/orders/:id → Order details with items
PATCH /api/orders/:id/items → Add/modify order items
POST /api/orders/:id/close → Close order
GET /api/kitchen/kots → List KOTs for kitchen display
PATCH /api/kitchen/kots/:id → Update KOT status
GET /api/shifts → List shifts
POST /api/shifts/open → Open shift
POST /api/shifts/close → Close shift with reconciliation
WebSocket Events (Socket.IO, namespace /kitchen):
Client → Server:
joinOutlet(outletId) → Join outlet room
joinOrder(orderId) → Join order-specific room
kotAcknowledged(kotId) → Kitchen acknowledges KOT
Server → Client:
kotCreated(kot) → New KOT for kitchen
kotStatusChanged(kot) → KOT status update
orderItemReady(item) → Individual item ready
orderUpdated(order) → Order modified
Events Published:
pos.order.created → { orderId, outletId, guestId, items }
pos.order.closed → { orderId, total, paymentMethod }
pos.kot.generated → { kotId, orderId, items }
pos.kot.ready → { kotId, readyAt }
pos.inventory.low_stock → { itemId, currentStock, reorderLevel }
Events Consumed:
reservation.checked_in → Enable room-charge for guest
reservation.checked_out → Disable room-charge, close open orders
Talks to:
frontdesk-service(API call):POST /folios/:id/chargesto post room charges
4.9 hmp-notification-service (Port 3008)
What it does: Centralized notification delivery across email (SendGrid), SMS (Twilio), and push channels. Manages notification templates (with variable substitution), communication templates, delivery logging, guest notification preferences, and TRAI DND registry compliance for Indian mobile numbers.
Database: hmp_notification (port 5441)
Key Tables:
notification_templates — id, tenantId, name, channel, subject, body, variables
communication_templates — id, tenantId, name, type, content, locale
notification_logs — id, tenantId, templateId, channel, recipient, status, sentAt, deliveredAt, error
notification_preferences — id, tenantId, guestId, channel, enabled
API Endpoints:
GET /api/templates → List notification templates
POST /api/templates → Create template
PATCH /api/templates/:id → Update template
GET /api/notifications → List notification logs
POST /api/notifications/send → Send notification
GET /api/notifications/preferences/:guestId → Guest preferences
PUT /api/notifications/preferences/:guestId → Update preferences
Events Published:
notification.sent → { notificationId, channel, recipient }
notification.failed → { notificationId, error }
Events Consumed:
notification.send → Dispatch email/SMS/push
reservation.created → Send confirmation email
reservation.checked_in → Send welcome message
reservation.checked_out → Send thank-you / feedback request
campaign.batch.send → Batch send campaign messages
spa.appointment.confirmed → Send appointment confirmation
Talks to:
- SendGrid API (outbound HTTP): email delivery
- Twilio API (outbound HTTP): SMS delivery
- TRAI DND registry (outbound HTTP): DND check before SMS
4.10 hmp-channel-service (Port 3009)
What it does: Two-way OTA (Online Travel Agency) channel manager. Manages connections to Booking.com, Expedia, MakeMyTrip, Agoda, Goibibo, and GDS (Amadeus, Sabre). Handles room mapping, rate mapping, availability/rate/restriction push, booking pull, parity monitoring, sync logging, and TDS (Tax Deducted at Source) tracking for OTA commissions.
Database: hmp_channel (port 5442)
Key Tables:
channel_connections — id, propertyId, channelName, credentials, status, lastSyncAt
channel_room_mappings — id, connectionId, roomTypeId, externalRoomTypeId
channel_rate_mappings — id, connectionId, ratePlanId, externalRatePlanId
channel_sync_logs — id, connectionId, direction, type, status, details, syncedAt
gds_property_mappings — id, propertyId, gdsProvider, propertyCode
tds_entries — id, propertyId, channelName, quarter, tdsAmount, certificateNumber
API Endpoints:
GET /api/channels → List channel connections
POST /api/channels → Connect to OTA
PATCH /api/channels/:id → Update connection
DELETE /api/channels/:id → Disconnect OTA
GET /api/channel-mappings/rooms → List room mappings
POST /api/channel-mappings/rooms → Create room mapping
GET /api/channel-mappings/rates → List rate mappings
POST /api/channel-sync/push → Push availability/rates to OTA
GET /api/channel-sync/logs → Sync history
POST /api/channel-sync/pull → Pull bookings from OTA
Events Published:
channel.booking.received → { reservationData, channelName, externalId }
channel.sync.completed → { connectionId, direction, recordCount }
channel.parity.alert → { propertyId, channelName, discrepancy }
channel.availability.pushed → { connectionId, dates, roomTypes }
channel.rates.pushed → { connectionId, dates, ratePlans }
channel.sync.retry → { syncLogId, retryCount }
channel.sync.failed → { syncLogId, error }
Events Consumed:
rate_plan.updated → Trigger rate push to mapped OTAs
room.status.changed → Update availability on OTAs
reservation.created → Reduce availability on OTAs
reservation.cancelled → Increase availability on OTAs
Talks to:
- OTA APIs (outbound HTTP): Booking.com, Expedia, MakeMyTrip, etc.
property-service(API call):GET /room-types,GET /rate-plansfor mapping referencereservation-service(event): sends booking data for reservation creation
4.11 hmp-banquet-service (Port 3011)
What it does: Manages banquet and event operations: venues (ballrooms, meeting rooms, lawns), event bookings, function sheets (detailed event plans), event items (F&B, AV equipment, decor), and event payments.
Database: hmp_banquet (port 5443)
Key Tables:
venues — id, propertyId, name, type, capacity, area, amenities, hourlyRate
event_bookings — id, propertyId, venueId, guestId, groupId, name, type, startDate, endDate, status, totalAmount
event_items — id, eventId, category (FOOD|BEVERAGE|AV|DECOR|OTHER), description, quantity, unitPrice
function_sheets — id, eventId, timeline, setupInstructions, staffAssignments
event_payments — id, eventId, amount, method, paidAt
API Endpoints:
GET /api/venues → List venues
POST /api/venues → Create venue
GET /api/venues/:id/availability → Venue availability calendar
GET /api/events → List event bookings
POST /api/events → Create event booking
GET /api/events/:id → Event details with items
PATCH /api/events/:id → Update event
POST /api/events/:id/items → Add event items
GET /api/events/:id/function-sheet → Function sheet
POST /api/events/:id/payments → Record payment
Events Published:
banquet.event.created → { eventId, venueId, dates, type }
banquet.event.confirmed → { eventId, totalAmount }
banquet.event.cancelled → { eventId, reason }
Events Consumed: None.
Talks to:
guest-service(API call):GET /guests/:idfor event organizer profile
4.12 hmp-crm-service (Port 3012)
What it does: Customer relationship management and loyalty. Manages loyalty programs (points-based with tier progression), campaigns (email/SMS marketing), feedback surveys, corporate accounts (companies, contracts, negotiated rates), partner programs, and co-branded card integration.
Database: hmp_crm (port 5444)
Key Tables:
loyalty_programs — id, tenantId, name, pointsPerCurrencyUnit, redemptionRate
loyalty_tiers — id, programId, name, minPoints, benefits, multiplier
loyalty_members — id, programId, guestId, tierName, totalPoints, lifetimePoints
points_transactions — id, memberId, type (EARN|REDEEM|EXPIRE|ADJUST), points, source
loyalty_rewards — id, programId, name, pointsCost, description
campaigns — id, propertyId, name, channel, status, scheduledAt, sentCount, openRate
communication_templates — id, tenantId, name, channel, content
feedback_surveys — id, propertyId, name, questions, isActive
feedback_responses — id, surveyId, guestId, reservationId, ratings, comments, sentiment
companies — id, tenantId, name, gstin, contactPerson, creditLimit
corporate_contracts — id, companyId, validFrom, validTo, negotiatedRates, terms
loyalty_partners — id, programId, partnerName, conversionRate
co_branded_cards — id, programId, bankName, cardType, benefits
API Endpoints:
GET /api/loyalty/programs → List loyalty programs
POST /api/loyalty/enroll → Enroll guest in program
GET /api/loyalty/members/:id → Member details
POST /api/loyalty/points/earn → Earn points
POST /api/loyalty/points/redeem → Redeem points
GET /api/campaigns → List campaigns
POST /api/campaigns → Create campaign
POST /api/campaigns/:id/launch → Launch campaign
GET /api/feedback/surveys → List surveys
GET /api/feedback/responses → List responses with sentiment
GET /api/revenue/corporate → Corporate revenue report
Events Published:
loyalty.points.earned → { memberId, points, source }
loyalty.points.redeemed → { memberId, points, rewardId }
loyalty.tier.changed → { memberId, oldTier, newTier }
campaign.launched → { campaignId, channel, recipientCount }
campaign.completed → { campaignId, sentCount, failedCount }
feedback.received → { surveyId, guestId, sentiment }
Events Consumed:
reservation.checked_out → Auto-award loyalty points
guest.created → Auto-enroll in default loyalty program (if configured)
Talks to:
guest-service(API call):GET /guests/:idfor member profilenotification-service(event):campaign.batch.sendfor campaign delivery
4.13 hmp-analytics-service (Port 3013)
What it does: The CQRS read-side of the platform. Consumes domain events from all services and builds 7 materialized views for dashboards and reports. Also hosts the night-audit report generation, audit log queries, KPI catalog, control center, SOPs, cadences, labor tracking, owner portal, pilot program management, activity feed, exception management, action tracking, usage metering, GST filing, and pricing recommendation approval workflow.
Database: hmp_analytics (port 5440)
Key Tables:
event_store — id, eventType, tenantId, propertyId, payload, version, createdAt
mv_daily_occupancy — propertyId, date, totalRooms, occupied, available, outOfOrder, occupancyRate
mv_revenue_by_source — propertyId, date, source, roomRevenue, fbRevenue, otherRevenue, totalRevenue
mv_guest_spend — guestId, propertyId, totalSpend, avgSpend, stayCount, lastVisit
mv_channel_performance — propertyId, channelName, date, bookings, revenue, commission, cancellations
mv_housekeeping_kpi — propertyId, date, avgCleanTime, tasksCompleted, inspectionPassRate
mv_pos_revenue — propertyId, outletId, date, orderCount, revenue, avgOrderValue
mv_adr_revpar — propertyId, date, adr, revpar, trevpar, goppar
night_audit_logs — id, propertyId, auditDate, status, data
report_schedules — id, propertyId, reportType, frequency, recipients
consumer_offsets — consumerId, topic, offset, updatedAt
Event Consumers:
| Consumer | Events Consumed | Materialized View Updated |
|---|---|---|
ReservationConsumer | reservation.created, .modified, .cancelled, .checked_in, .checked_out, .no_show | mv_daily_occupancy, mv_adr_revpar, mv_revenue_by_source |
FolioConsumer | folio.charge.posted, folio.payment.received, folio.settled | mv_revenue_by_source, mv_guest_spend |
POSConsumer | pos.order.created, pos.order.closed | mv_pos_revenue, mv_revenue_by_source |
HousekeepingConsumer | housekeeping.task.completed, .task.inspected | mv_housekeeping_kpi |
ChannelConsumer | channel.booking.received, channel.sync.completed, channel.parity.alert | mv_channel_performance |
API Endpoints:
GET /api/analytics/dashboard → KPI summary (occupancy, ADR, RevPAR)
GET /api/analytics/occupancy → Daily occupancy data
GET /api/analytics/revenue → Revenue breakdown by source
GET /api/analytics/channel → Channel performance comparison
GET /api/reports → List available reports
GET /api/reports/:type → Generate report (PDF/CSV)
GET /api/night-audit-reports → Night audit history
GET /api/audit-logs → Query audit trail
GET /api/kpi-catalog → List all KPI definitions
GET /api/control-center → Operations control center
GET /api/sops → Standard operating procedures
GET /api/cadences → Operational cadence definitions
GET /api/labor → Labor metrics
GET /api/owner-portal/dashboard → Owner P&L dashboard
GET /api/pilot/status → Pilot program status
GET /api/activity-feed → Recent activity across property
GET /api/exceptions → Open exceptions
POST /api/exceptions/:id/resolve → Resolve exception
GET /api/actions → Action items
GET /api/metering/usage → Usage metrics for billing
GET /api/gst/summary → GST filing summary
GET /api/recommendations → Pricing recommendations
POST /api/recommendations/:id/accept → Accept recommendation
POST /api/recommendations/:id/reject → Reject recommendation
GET /api/rum/metrics → Real user monitoring data
Events Published:
night.audit.completed → { propertyId, auditDate, summary }
exception.suggested → { propertyId, type, details }
audit.anomaly.detected → { propertyId, anomalyType, details }
rate.recommendation.updated → { propertyId, dates, suggestedRates }
Talks to: No outbound service calls. Reads only from its own materialized views.
4.14 hmp-spa-service (Port 3015)
What it does: Spa and wellness management. Handles treatments, therapist scheduling, spa room allocation, appointment lifecycle (book, confirm, start, complete, cancel, no-show), packages, and charge posting to guest folios.
Database: hmp_spa (port not mapped in dev compose -- typically 5446)
Key Tables:
spa_treatments — id, propertyId, name, duration, price, category, isActive
spa_therapists — id, propertyId, name, specializations, availability
spa_rooms — id, propertyId, name, type, amenities
spa_appointments — id, propertyId, guestId, reservationId, treatmentId, therapistId, roomId, startTime, endTime, status
spa_packages — id, propertyId, name, treatments, price, duration
spa_package_items — id, packageId, treatmentId, order
API Endpoints:
GET /api/spa/treatments → List treatments
GET /api/spa/therapists → List therapists with availability
GET /api/spa/availability → Available slots for date
POST /api/spa/appointments → Book appointment
PATCH /api/spa/appointments/:id → Update appointment status
GET /api/spa/packages → List packages
Events Published:
spa.appointment.created → { appointmentId, guestId, treatmentId, startTime }
spa.appointment.confirmed → { appointmentId }
spa.appointment.completed → { appointmentId, therapistId, duration }
spa.appointment.cancelled → { appointmentId, reason }
spa.charge.created → { guestId, reservationId, amount }
Events Consumed:
reservation.checked_in → Enable spa booking for guest
4.15 hmp-web-dashboard (Port 3020)
What it does: The primary staff interface. A Next.js 16 application with 30+ page groups covering every operational area of the hotel. Uses NextAuth v5 for authentication and shadcn/ui components.
Page Groups (Routes):
/(auth)/login → Staff login page
/(dashboard)/ → Main dashboard (KPIs, activity feed, quick actions)
/(dashboard)/reservations → Reservation list, calendar, tape chart
/(dashboard)/front-desk → Room grid, check-in/out, walk-in
/(dashboard)/guests → Guest profiles, search, merge
/(dashboard)/housekeeping → Task board, room status, maintenance
/(dashboard)/pos → Outlet management, orders, kitchen display
/(dashboard)/rates → Rate plans, BAR calendar, rate management
/(dashboard)/reports → Report generator (occupancy, revenue, etc.)
/(dashboard)/night-audit → Night audit execution and history
/(dashboard)/banquet → Venues, event bookings, function sheets
/(dashboard)/spa → Treatments, appointments, therapist schedule
/(dashboard)/channel-manager → OTA connections, sync status, parity
/(dashboard)/crm → Loyalty programs, campaigns, feedback
/(dashboard)/notifications → Templates, delivery logs
/(dashboard)/cash-management → Cash drawers, safes, petty cash
/(dashboard)/settings → Property config, users, roles, integrations
/(dashboard)/kiosk → Self-service kiosk check-in wizard
/(dashboard)/ai → AI insights, NLQ queries, review sentiment
/(dashboard)/control-center → Operations dashboard, exceptions, actions
/(dashboard)/owner-portal → Owner P&L, investor dashboard
/(dashboard)/pilot → Pilot program management
/(dashboard)/chain → Multi-property comparison, trends
/(dashboard)/marketing → Promo codes, packages
/(dashboard)/marketplace → Integration marketplace
/(dashboard)/partners → Partner management
/(dashboard)/activities → Activity log
API Calls: All API calls go through the gateway at /api/*. The dashboard uses fetch with JWT in Authorization header and tenant/property context in x-tenant-id / x-property-id headers.
State Management: Server Components (RSC) for data fetching where possible. Client-side state via React hooks. NextAuth for auth state. No global state library.
Key Components: Built on shadcn/ui. Custom components include RoomGrid, TapeChart, RateCalendar, FolioView, KitchenDisplay, TaskBoard, CashDrawerPanel.
4.16 hmp-admin-portal (Port 3030)
What it does: Platform administration interface for SUPER_ADMIN users. Manages tenant onboarding, subscription billing, feature flags, platform-wide analytics, support tools, and announcements.
Page Groups (Routes):
/(auth)/login → Admin login
/(admin)/dashboard → Platform KPIs (total tenants, MRR, active properties)
/(admin)/tenants → Tenant list, create, edit, suspend/reactivate
/(admin)/onboarding → Tenant onboarding wizard (company info, property setup, admin user)
/(admin)/subscriptions → Subscription plans, pricing management
/(admin)/billing → Invoice list, payment status
/(admin)/feature-flags → Toggle features per tenant or globally
/(admin)/analytics → Platform-wide analytics
/(admin)/audit-log → Cross-tenant audit trail
/(admin)/support → Support ticket management
/(admin)/announcements → Platform announcements to tenants
4.17 hmp-booking-engine (Port 3040)
What it does: Guest-facing booking widget. Can run standalone or embed as a web component on the hotel's website. Supports room search, date selection, rate comparison, promo codes, loyalty point redemption, checkout with Razorpay payment, booking management, and 5 languages (English, Hindi, Thai, Indonesian, Vietnamese).
Pages:
/search → Room search with date picker, guest count, filters
/checkout → Booking form, guest details, payment (Razorpay)
/manage → Manage existing booking (lookup by confirmation number)
/loyalty → Loyalty point balance and redemption
State Management: Zustand stores for search state, booking flow, and user session.
Embeddable: Can be used as <hmp-booking-engine property-id="..." /> web component on any website.
4.18 hmp-mobile-apps
What it does: Four React Native (Expo) apps sharing a common codebase via Turborepo:
| App | Audience | Key Features |
|---|---|---|
housekeeping | HK staff | Task list, swipe-to-accept, cleaning timer, photo upload, room status |
fnb | Kitchen/service staff | Order queue, KOT management, table status, modifier selection |
guest | Hotel guests | Digital key, service requests, in-room dining, spa booking |
manager | Duty managers | Real-time KPIs, exception alerts, staff overview, approval workflows |
Shared packages (in packages/): API client, auth hooks, real-time hooks, UI components.
4.19 hmp-kds-kiosk
What it does: Two Electron desktop applications:
| App | Purpose |
|---|---|
kds | Kitchen Display System -- shows KOTs on screen, auto-advance, priority sorting, bump-bar support |
kiosk | Self-service kiosk -- 5-step check-in wizard (find booking, verify identity, select room, encode key card, welcome screen) |
Shared components and utilities in packages/shared/.
5. Inter-Service Communication
5.1 Synchronous Communication (HTTP API Calls)
Services call each other directly via HTTP when they need an immediate response. The API gateway is NOT used for service-to-service calls; services call each other directly by hostname and port.
reservation-service → property-service: GET /rooms (availability check)
reservation-service → property-service: GET /room-types (pricing lookup)
reservation-service → guest-service: GET /guests/:id (guest profile)
frontdesk-service → reservation-service: GET /reservations/:id (check-in validation)
frontdesk-service → guest-service: GET /guests/:id (guest profile + ID docs)
frontdesk-service → property-service: GET /rooms/:id (room details)
pos-service → frontdesk-service: POST /folios/:id/charges (room charge posting)
banquet-service → guest-service: GET /guests/:id (event organizer)
crm-service → guest-service: GET /guests/:id (loyalty member profile)
channel-service → property-service: GET /room-types, /rate-plans (mapping reference)
5.2 Asynchronous Communication (Domain Events via Redis Streams)
Events are published to Redis Streams and consumed by interested services. This decouples services and enables the CQRS pattern for analytics.
Event Flow Diagram
┌──────────────────┐ reservation.created ┌────────────────────┐
│ Reservation │ ──────────────────────────→ │ Analytics │
│ Service │ reservation.checked_in │ Service │
│ │ ──────────────────────────→ │ (CQRS consumers) │
└──────────────────┘ └────────────────────┘
│ ↑
│ reservation.created │
↓ │
┌──────────────────┐ folio.charge.posted ┌────────┴───────────┐
│ Notification │ ←─────────────────────────── │ Frontdesk │
│ Service │ reservation.checked_out │ Service │
│ (send emails) │ ←─────────────────────────── │ │
└──────────────────┘ └────────────────────┘
↑
pos.order.closed │
┌──────────────────┐ ─────────────────────────────────────┘
│ POS Service │
│ │ ────→ analytics-service (pos revenue)
└──────────────────┘
┌──────────────────┐ housekeeping.task.completed
│ Housekeeping │ ──────────────────────────→ analytics-service
│ Service │ room.status.changed
│ │ ──────────────────────────→ channel-service (availability update)
└──────────────────┘
┌──────────────────┐ channel.booking.received
│ Channel │ ──────────────────────────→ reservation-service (create booking)
│ Service │ channel.sync.completed
│ │ ──────────────────────────→ analytics-service
└──────────────────┘
┌──────────────────┐ loyalty.points.earned
│ CRM Service │ ──────────────────────────→ analytics-service
│ │ campaign.batch.send
│ │ ──────────────────────────→ notification-service
└──────────────────┘
┌──────────────────┐ spa.charge.created
│ Spa Service │ ──────────────────────────→ frontdesk-service (folio charge)
│ │ spa.appointment.*
│ │ ──────────────────────────→ notification-service
└──────────────────┘
Complete Event Catalog
The @hmp/messaging package defines 137 event types in the EventTopics enum, organized into 16 domain groups:
| Domain | Event Count | Key Events |
|---|---|---|
| Reservation | 7 | created, modified, cancelled, checked_in, checked_out, no_show |
| Room | 3 | status.changed, assigned, unassigned |
| Group | 4 | created, updated, confirmed, cancelled |
| Guest | 5 | created, updated, merged, preferences.applied |
| Folio | 5 | charge.posted, payment.received, settled, transferred, split |
| POS | 5 | order.created, order.closed, kot.generated, kot.ready, inventory.low_stock |
| Housekeeping | 7 | task.created, task.completed, task.assigned, task.inspected, inventory.movement, minibar.consumed, room.inspected |
| Channel | 9 | booking.received, sync.completed, parity.alert, availability.pushed, rates.pushed, restrictions.pushed, booking.cancelled, sync.retry, sync.failed |
| Notification | 3 | send, sent, failed |
| Rate Plan | 3 | created, updated, deleted |
| Banquet | 3 | event.created, event.confirmed, event.cancelled |
| Loyalty | 4 | points.earned, points.redeemed, tier.changed, points.expired |
| Campaign | 3 | launched, completed, batch.send |
| Spa | 7 | appointment.created, confirmed, started, completed, cancelled, no_show, charge.created |
| Analytics | 2 | night.audit.started, night.audit.completed |
| Other | 17 | feedback, waitlist, revenue management, exceptions, actions, audit anomaly, tenant |
BaseEvent Envelope
Every event follows this structure:
interface BaseEvent {
eventId: string; // UUID, unique per event
eventType: EventTopics; // Enum value
timestamp: string; // ISO 8601
tenantId: string; // Tenant UUID
propertyId: string; // Property UUID
correlationId?: string; // For request tracing
userId?: string; // User who triggered the action
}
5.3 CQRS Analytics (Materialized Views)
The analytics-service implements CQRS (Command Query Responsibility Segregation). Write operations happen in domain services. The analytics-service consumes events and maintains 7 pre-computed materialized views for fast dashboard queries.
| Materialized View | What It Shows | Source Events |
|---|---|---|
mv_daily_occupancy | Rooms sold, available, OOO by date | reservation.created, .cancelled, .checked_in, .checked_out |
mv_revenue_by_source | Revenue broken down by source (direct, OTA, walk-in) per day | folio.charge.posted, folio.payment.received, pos.order.closed |
mv_guest_spend | Per-guest lifetime value, average spend, stay count | folio.settled, pos.order.closed |
mv_channel_performance | Bookings, revenue, commission per OTA per day | channel.booking.received, channel.sync.completed |
mv_housekeeping_kpi | Average clean time, tasks completed, inspection pass rate per day | housekeeping.task.completed, housekeeping.task.inspected |
mv_pos_revenue | Orders, revenue, average order value per outlet per day | pos.order.created, pos.order.closed |
mv_adr_revpar | ADR, RevPAR, TRevPAR, GOPPAR per day | Derived from mv_daily_occupancy + mv_revenue_by_source |
How it works:
- Domain service performs a write (e.g., reservation-service creates a reservation)
- Domain service publishes an event to Redis Streams (e.g.,
reservation.created) - Analytics-service consumer picks up the event
- Consumer updates the relevant materialized view(s) via SQL upsert
- Dashboard queries the materialized view via analytics API endpoints
- Event is also stored in
event_storetable for replay capability
Consumer offsets are tracked in the consumer_offsets table to enable at-least-once delivery and replay from a specific point.
6. Environment Pipeline
┌───────────┐ PR Merge ┌───────────┐ Manual Promote ┌───────────┐ Manual Promote ┌───────────┐
│ LOCAL DEV │ ──────────────→ │ QA │ ──────────────────→ │ STAGING │ ──────────────────→ │ PROD │
│ │ │ │ │ │ │ │
│ Docker │ │ Auto- │ │ Manual │ │ Manual │
│ Desktop │ │ deploy │ │ promote │ │ promote │
│ + VS Code │ │ on merge │ │ + Integ. │ │ (2 approv-│
│ hot-reload│ │ Smoke │ │ tests + │ │ als) │
│ │ │ tests │ │ Client │ │ Health │
│ │ │ │ │ demos │ │ check │
└───────────┘ └───────────┘ └───────────┘ └───────────┘
Local Development
- Infrastructure: Docker Compose runs one PostgreSQL per service + shared Redis
- Your service: Runs natively with
npm run start:dev(NestJS hot-reload) - Other services: Either run in Docker or connect to QA environment
- Database migrations:
npx prisma migrate devagainst local Postgres - Tests:
npm testruns Jest unit tests locally
QA Environment
- Trigger: Auto-deploy on PR merge to
mainbranch - Infrastructure: Azure Container Instances (ACI) or AKS dev namespace
- Automated tests: Smoke tests run post-deploy (API health checks, critical path tests)
- Data: Seeded with demo data (same as local Docker demo)
- Access: Internal only (VPN required)
Staging Environment
- Trigger: Manual promote from QA (team lead approval)
- Infrastructure: AKS staging namespace (mirrors production topology)
- Tests: Full integration test suite, Playwright E2E tests, k6 load tests (smoke profile)
- Data: Anonymized copy of production data (refreshed weekly)
- Access: Internal + client demo access
Production Environment
- Trigger: Manual promote from Staging (requires 2 approvals)
- Infrastructure: AKS production namespace with:
- Azure Database for PostgreSQL (Flexible Server) per service
- Azure Cache for Redis (Premium tier, 2 instances)
- Azure Front Door (CDN + WAF)
- Azure Monitor + Grafana dashboards
- Deployment: Rolling update (zero-downtime)
- Post-deploy: Automated health check verification, synthetic monitoring
- Rollback: Automatic on failed health checks (previous image tag)
CI/CD Pipeline (Per Service)
PR Created → Lint → Typecheck → Unit Tests → Contract Check → Build Docker Image
↓
PR Merged → Push Image to ACR → Deploy to QA → Smoke Tests → ✓ Ready for Staging
Pipeline Templates are defined in hmp-infrastructure and referenced by each service's pipeline config. This ensures consistent build/test/deploy across all 23 repos.
Monitoring
- Metrics: Each service exposes
/metrics(Prometheus format) via@hmp/commonMetricsModule with 12hmp_*business metrics - Dashboards: 8 Grafana dashboards (api-gateway, auth, reservation, frontdesk, housekeeping, pos, analytics, notification)
- Alerts: 6 alert rules (auth login spike, reservation errors, check-in latency, night audit failure, POS backlog, KOT latency)
- Routing: 6 team routes (platform, reservations, channel, payments, pos, booking) with inhibition rules
- Runbooks: 16 operational runbooks (one per alert + DR procedures)
- DR: 4 disaster recovery scripts (promote-rds, warm-cache, failback, generate-report) with 6 runbooks
Appendix A: Quick Reference
Service Port Map
| Port | Service | Team |
|---|---|---|
| 3001 | auth-service | Platform |
| 3002 | property-service | PMS |
| 3003 | reservation-service | PMS |
| 3004 | guest-service | PMS |
| 3005 | frontdesk-service | PMS |
| 3006 | housekeeping-service | PMS |
| 3007 | pos-service | Revenue |
| 3008 | notification-service | Guest Experience |
| 3009 | channel-service | Revenue |
| 3010 | api-gateway | Platform |
| 3011 | banquet-service | Revenue |
| 3012 | crm-service | Guest Experience |
| 3013 | analytics-service | Revenue |
| 3014 | integration-service | Platform |
| 3015 | spa-service | Shared |
| 3016 | ai-service | Shared |
| 3020 | web-dashboard | Guest Experience |
| 3030 | admin-portal | Platform |
| 3040 | booking-engine | Guest Experience |
| 3050 | docs | Shared |
| 8001 | forecast-sidecar | Revenue |
Database Port Map (Local Dev)
| Port | Database | Service |
|---|---|---|
| 5433 | hmp_auth | auth-service |
| 5434 | hmp_property | property-service |
| 5435 | hmp_reservation | reservation-service |
| 5436 | hmp_guest | guest-service |
| 5437 | hmp_frontdesk | frontdesk-service |
| 5438 | hmp_housekeeping | housekeeping-service |
| 5439 | hmp_pos | pos-service |
| 5440 | hmp_analytics | analytics-service |
| 5441 | hmp_notification | notification-service |
| 5442 | hmp_channel | channel-service |
| 5443 | hmp_banquet | banquet-service |
| 5444 | hmp_crm | crm-service |
Key npm Packages
| Package | Latest Version | Purpose |
|---|---|---|
@hmp/common | 1.x | Decorators, guards, validators, utilities |
@hmp/messaging | 1.x | Event bus, topics, base event interface |
@hmp/database | 1.x | PrismaService, multi-tenant helpers |
@hmp/api-contracts | 1.x | Shared DTOs and endpoint constants |
@hmp/ui-kit | 1.x | Shared React components |
Demo Credentials
| User | Password | Role | |
|---|---|---|---|
| Admin | admin@hmphotel.com | ADMIN | |
| Front Desk | frontdesk@hmphotel.com | FRONT_DESK | |
| Housekeeping | hk@hmphotel.com | HOUSEKEEPING | |
| Manager | manager@hmphotel.com | MANAGER |