Skip to main content

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​

  1. Platform Overview
  2. Multi-Repo Structure
  3. Developer Experience
  4. Architecture Details Per Repo
  5. Inter-Service Communication
  6. 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?​

PersonaInterfaceKey Actions
Front-desk agentWeb DashboardCheck-in/out, room assignment, folio management, cash drawer
Housekeeping staffMobile AppAccept tasks, mark rooms clean, report maintenance
F&B / Kitchen staffMobile App, KDSTake orders, manage KOTs, close shifts
Revenue managerWeb DashboardSet rate plans, view BAR calendar, approve pricing recommendations
Hotel GM / OwnerWeb Dashboard, Owner PortalView KPIs, night-audit reports, P&L dashboards
GuestBooking Engine, Guest PortalSearch rooms, book, self-check-in, raise requests
Platform admin (SUPER_ADMIN)Admin PortalOnboard 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​

LayerTechnology
Backend servicesNestJS (TypeScript), Prisma ORM, PostgreSQL 16
Event busRedis Streams via @hmp/messaging (its class is named KafkaService for call-site compatibility only; there is no Kafka)
Cache / sessionsRedis 7
Staff dashboardNext.js 16, NextAuth v5, shadcn/ui, Tailwind CSS
Admin portalNext.js 16, NextAuth v5, shadcn/ui
Guest booking engineVite, React, Zustand
Mobile appsReact Native (Expo), Turborepo
KDS / KioskElectron, Vite, React
Forecast sidecarPython, FastAPI, Prophet, scikit-learn
InfrastructureDocker, Terraform (Azure), GitHub Actions / Azure Pipelines
MonitoringPrometheus (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)​

RepoTypePortPurposeKey Technologies
hmp-api-gatewayBackend3010Request routing, CORS, rate limiting, auth validation, WebSocket proxy, batch API, search aggregationNestJS, Redis, http-proxy-middleware
hmp-auth-serviceBackend3001Authentication (JWT + refresh tokens), MFA (WebAuthn), SSO, tenant CRUD, billing, subscription plans, feature flags, API keysNestJS, Prisma, bcrypt, passport, Razorpay
hmp-admin-portalFrontend3030SUPER_ADMIN platform management: tenant onboarding wizard, subscription management, feature flags, audit logs, billing, analyticsNext.js 16, NextAuth v5, shadcn/ui
hmp-shared-packagesLibrary-5 @hmp/* npm packages (common, messaging, database, api-contracts, ui-kit), dev Docker Compose, CI/CD templatesLerna, TypeScript
hmp-infrastructureDevOps-Docker configs, CI/CD pipeline templates, Terraform modules (Azure), Helm charts, Kubernetes manifests, monitoring dashboards/alerts, DR scripts, load-test configsDocker, Terraform, Helm, k6, Grafana

PMS Team (5 repos)​

RepoTypePortPurposeKey Technologies
hmp-property-serviceBackend3002Properties, room types, rooms, rate plans, cancellation policies, tax config, BAR engine, rate calendar, tenant config, data migration importer, brands, custom fields, edge deploymentNestJS, Prisma
hmp-reservation-serviceBackend3003Reservations, availability, group bookings, promo codes, payments (Razorpay), booking-engine API, guest portal (lookup, pre-check-in, requests, menu)NestJS, Prisma, Razorpay SDK
hmp-frontdesk-serviceBackend3005Check-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-InvoiceNestJS, Prisma
hmp-housekeeping-serviceBackend3006Housekeeping tasks, room status, maintenance requests, lost & found, linen inventory, minibar, inventory management, WebSocket real-time updatesNestJS, Prisma, Socket.IO
hmp-guest-serviceBackend3004Guest profiles, identity documents, addresses, preferences, communications, GDPR/DPDPA consent, DSAR requests, travel agentsNestJS, Prisma

Revenue Team (4 repos)​

RepoTypePortPurposeKey Technologies
hmp-pos-serviceBackend3007F&B outlets, menu management, tables, orders, KOTs, kitchen display, shifts, inventory, recipes, stock movements, WebSocket real-time KDSNestJS, Prisma, Socket.IO
hmp-analytics-serviceBackend3013CQRS 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, RUMNestJS, Prisma
hmp-banquet-serviceBackend3011Venues, event bookings, function sheets, event items, event paymentsNestJS, Prisma
hmp-channel-serviceBackend3009OTA connections (Booking.com, Expedia, MakeMyTrip, Agoda, etc.), room/rate mappings, inventory sync, GDS integration, TDS entriesNestJS, Prisma

Guest Experience Team (6 repos)​

RepoTypePortPurposeKey Technologies
hmp-web-dashboardFrontend3020Staff 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, pilotNext.js 16, NextAuth v5, shadcn/ui, Tailwind CSS
hmp-booking-engineFrontend3040Guest-facing room search, checkout, promo codes, loyalty integration, booking management, language switcher (EN/HI/TH/ID/VI), embeddable web componentVite, React, Zustand
hmp-crm-serviceBackend3012Loyalty programs, tiers, members, points transactions, rewards, campaigns, communication templates, feedback surveys, companies, corporate contracts, partner programs, co-branded cardsNestJS, Prisma
hmp-notification-serviceBackend3008Email (SendGrid), SMS (Twilio), push notifications, notification templates, communication templates, delivery logs, guest preferences, TRAI DND complianceNestJS, Prisma, SendGrid, Twilio
hmp-mobile-appsFrontend-4 React Native apps: housekeeping, F&B, guest, manager. Real-time hooks (useRealtimeTasks, useRealtimeKitchen), swipeable task cards, cleaning timer, modifier sheetReact Native, Expo, Turborepo, Socket.IO
hmp-kds-kioskFrontend-Kitchen Display System (Electron) and Self-Service Kiosk (Electron). Shared component libraryElectron, Vite, React, Vitest

Shared (3 repos)​

RepoTypePortPurposeKey Technologies
hmp-spa-serviceBackend3015Spa treatments, therapists, rooms, appointments, packagesNestJS, Prisma
hmp-docsDocs3050Platform documentation: architecture, requirements (22 epics, 148 stories), API reference, runbooks, review reportsDocusaurus
hmp-platformArchive-Original monorepo (Nx workspace with all 13 backend services + libs). Kept read-only for reference during stabilization periodNestJS, Nx, Prisma

Additional Backend Services (in monorepo, not yet extracted)​

ServicePortPurpose
ai-service3016OTA review ingestion, sentiment analysis, NLQ (natural language queries), multi-language support (Hindi, Tamil, Telugu, Marathi)
integration-service3014Tally accounting integration, integration registry, simulator event bus

Python Sidecar​

RepoPortPurpose
hmp-forecast-sidecar8001Prophet 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)​

PortService
3001auth-service
3002property-service
3003reservation-service
3004guest-service
3005frontdesk-service
3006housekeeping-service
3007pos-service
3008notification-service
3009channel-service
3010api-gateway (all traffic goes through here)
3011banquet-service
3012crm-service
3013analytics-service
3014integration-service
3015spa-service
3016ai-service
3020web-dashboard (Next.js)
3030admin-portal (Next.js)
3040booking-engine (Vite)
3050docs (Docusaurus)
5433-5445PostgreSQL databases (one per service)
6379Redis
8001forecast-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>
ServicePortDatabase
auth5433hmp_auth
property5434hmp_property
reservation5435hmp_reservation
guest5436hmp_guest
frontdesk5437hmp_frontdesk
housekeeping5438hmp_housekeeping
pos5439hmp_pos
analytics5440hmp_analytics
notification5441hmp_notification
channel5442hmp_channel
banquet5443hmp_banquet
crm5444hmp_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​

  1. Pick a ticket from Azure Boards "Sprint Ready" column
  2. Read the story in hmp-docs (docs/requirements/epics/EP-XXX/US-YYY.md)
  3. Create a branch:
    git checkout -b feat/TICKET-123-add-batch-checkin
  4. Code -- follow existing patterns in the service (controller -> service -> Prisma)
  5. Write tests -- unit tests for service methods, e2e tests for API endpoints
  6. Run lint and typecheck:
    npm run lint
    npm run typecheck
  7. Commit using Conventional Commits:
    git commit -m "feat(EP-005): TICKET-123 add batch check-in endpoint"
  8. Push:
    git push origin feat/TICKET-123-add-batch-checkin
  9. 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)
  10. Merge (squash) -- auto-deploys to QA environment
  11. QA verification -- promote to Staging -- promote to Production

Branch Naming​

TypePatternExample
Featurefeat/TICKET-123-short-descriptionfeat/TICKET-123-add-batch-checkin
Bug fixfix/TICKET-456-short-descriptionfix/TICKET-456-login-error
Hotfixhotfix/TICKET-789-short-descriptionhotfix/TICKET-789-critical-fix
Refactorrefactor/TICKET-012-short-descriptionrefactor/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:

PackagePurpose
@hmp/commonDecorators (@CurrentUser, @Roles, @Public), guards, pipes, filters, validators (GSTIN, SAC codes), room status state machine, data retention executor, ESC/POS printer templates
@hmp/messagingKafkaService, EventTopics enum (137 event types), BaseEvent interface, event store service
@hmp/databasePrismaService (extends PrismaClient with $connect/$disconnect lifecycle), multi-tenant query helpers
@hmp/api-contractsShared DTOs, request/response types, API endpoint constants
@hmp/ui-kitShared 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​

  1. Clone hmp-shared-packages
  2. Make changes in packages/<name>/src/
  3. Run tests: cd packages/<name> && npm test
  4. Create PR to hmp-shared-packages (requires 2 reviewers)
  5. On merge, CI auto-publishes a new version to Azure Artifacts
  6. 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
ContainerPortNotes
hmp-backend3010Single container running API gateway + all 13 microservices
hmp-dashboard3020Next.js staff dashboard
hmp-booking3040Vite booking engine
hmp-admin3030Next.js admin portal
hmp-docs3050Docusaurus documentation
hmp-demo-hub8000Landing page linking all services
hmp-postgres5432PostgreSQL 16
hmp-redis6379Redis 7 (cache + sessions)
hmp-redis-session6380Redis 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 /rooms for availability check, GET /room-types for pricing
  • guest-service (API call): GET /guests/:id for 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/:id for check-in validation
  • guest-service (API call): GET /guests/:id for guest profile and ID documents
  • property-service (API call): GET /rooms/:id for room details
  • housekeeping-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 /rooms for 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/charges to 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-plans for mapping reference
  • reservation-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/:id for 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/:id for member profile
  • notification-service (event): campaign.batch.send for 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:

ConsumerEvents ConsumedMaterialized View Updated
ReservationConsumerreservation.created, .modified, .cancelled, .checked_in, .checked_out, .no_showmv_daily_occupancy, mv_adr_revpar, mv_revenue_by_source
FolioConsumerfolio.charge.posted, folio.payment.received, folio.settledmv_revenue_by_source, mv_guest_spend
POSConsumerpos.order.created, pos.order.closedmv_pos_revenue, mv_revenue_by_source
HousekeepingConsumerhousekeeping.task.completed, .task.inspectedmv_housekeeping_kpi
ChannelConsumerchannel.booking.received, channel.sync.completed, channel.parity.alertmv_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:

AppAudienceKey Features
housekeepingHK staffTask list, swipe-to-accept, cleaning timer, photo upload, room status
fnbKitchen/service staffOrder queue, KOT management, table status, modifier selection
guestHotel guestsDigital key, service requests, in-room dining, spa booking
managerDuty managersReal-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:

AppPurpose
kdsKitchen Display System -- shows KOTs on screen, auto-advance, priority sorting, bump-bar support
kioskSelf-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:

DomainEvent CountKey Events
Reservation7created, modified, cancelled, checked_in, checked_out, no_show
Room3status.changed, assigned, unassigned
Group4created, updated, confirmed, cancelled
Guest5created, updated, merged, preferences.applied
Folio5charge.posted, payment.received, settled, transferred, split
POS5order.created, order.closed, kot.generated, kot.ready, inventory.low_stock
Housekeeping7task.created, task.completed, task.assigned, task.inspected, inventory.movement, minibar.consumed, room.inspected
Channel9booking.received, sync.completed, parity.alert, availability.pushed, rates.pushed, restrictions.pushed, booking.cancelled, sync.retry, sync.failed
Notification3send, sent, failed
Rate Plan3created, updated, deleted
Banquet3event.created, event.confirmed, event.cancelled
Loyalty4points.earned, points.redeemed, tier.changed, points.expired
Campaign3launched, completed, batch.send
Spa7appointment.created, confirmed, started, completed, cancelled, no_show, charge.created
Analytics2night.audit.started, night.audit.completed
Other17feedback, 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 ViewWhat It ShowsSource Events
mv_daily_occupancyRooms sold, available, OOO by datereservation.created, .cancelled, .checked_in, .checked_out
mv_revenue_by_sourceRevenue broken down by source (direct, OTA, walk-in) per dayfolio.charge.posted, folio.payment.received, pos.order.closed
mv_guest_spendPer-guest lifetime value, average spend, stay countfolio.settled, pos.order.closed
mv_channel_performanceBookings, revenue, commission per OTA per daychannel.booking.received, channel.sync.completed
mv_housekeeping_kpiAverage clean time, tasks completed, inspection pass rate per dayhousekeeping.task.completed, housekeeping.task.inspected
mv_pos_revenueOrders, revenue, average order value per outlet per daypos.order.created, pos.order.closed
mv_adr_revparADR, RevPAR, TRevPAR, GOPPAR per dayDerived from mv_daily_occupancy + mv_revenue_by_source

How it works:

  1. Domain service performs a write (e.g., reservation-service creates a reservation)
  2. Domain service publishes an event to Redis Streams (e.g., reservation.created)
  3. Analytics-service consumer picks up the event
  4. Consumer updates the relevant materialized view(s) via SQL upsert
  5. Dashboard queries the materialized view via analytics API endpoints
  6. Event is also stored in event_store table 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 dev against local Postgres
  • Tests: npm test runs Jest unit tests locally

QA Environment​

  • Trigger: Auto-deploy on PR merge to main branch
  • 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/common MetricsModule with 12 hmp_* 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​

PortServiceTeam
3001auth-servicePlatform
3002property-servicePMS
3003reservation-servicePMS
3004guest-servicePMS
3005frontdesk-servicePMS
3006housekeeping-servicePMS
3007pos-serviceRevenue
3008notification-serviceGuest Experience
3009channel-serviceRevenue
3010api-gatewayPlatform
3011banquet-serviceRevenue
3012crm-serviceGuest Experience
3013analytics-serviceRevenue
3014integration-servicePlatform
3015spa-serviceShared
3016ai-serviceShared
3020web-dashboardGuest Experience
3030admin-portalPlatform
3040booking-engineGuest Experience
3050docsShared
8001forecast-sidecarRevenue

Database Port Map (Local Dev)​

PortDatabaseService
5433hmp_authauth-service
5434hmp_propertyproperty-service
5435hmp_reservationreservation-service
5436hmp_guestguest-service
5437hmp_frontdeskfrontdesk-service
5438hmp_housekeepinghousekeeping-service
5439hmp_pospos-service
5440hmp_analyticsanalytics-service
5441hmp_notificationnotification-service
5442hmp_channelchannel-service
5443hmp_banquetbanquet-service
5444hmp_crmcrm-service

Key npm Packages​

PackageLatest VersionPurpose
@hmp/common1.xDecorators, guards, validators, utilities
@hmp/messaging1.xEvent bus, topics, base event interface
@hmp/database1.xPrismaService, multi-tenant helpers
@hmp/api-contracts1.xShared DTOs and endpoint constants
@hmp/ui-kit1.xShared React components

Demo Credentials​

UserEmailPasswordRole
Adminadmin@hmphotel.comADMIN
Front Deskfrontdesk@hmphotel.comFRONT_DESK
Housekeepinghk@hmphotel.comHOUSEKEEPING
Managermanager@hmphotel.comMANAGER