EP-012A: KPI Dashboard & Revenue Intelligence
Parent Epic: EP-012 Analytics, Reporting & Night Audit Split Note: EP-012 has been split into sub-epics EP-012A, EP-012B, EP-012C, EP-012D, EP-012E. This file covers the real-time KPI dashboard, RevPAR analysis, revenue benchmarking, and demand forecasting.
| Field | Value |
|---|---|
| Epic ID | EP-012A |
| Epic Name | KPI Dashboard & Revenue Intelligence |
| Parent Epic | EP-012 Analytics, Reporting & Night Audit |
| Owner | Product — Revenue Intelligence |
| Created | 2026-03-27 |
| Last Updated | 2026-03-27 |
| Status | Partial |
| Target Release | R3 (Q2 2026) |
1. Business Objective
Give General Managers, Revenue Managers, and Owners a real-time, actionable intelligence layer that replaces the daily morning Excel spreadsheet. A hotel that can see RevPAR trending down 3% at 14:00 can still adjust rates and recover tonight's revenue. A Revenue Manager who sees that corporate bookings are tracking 20% below forecast can call the account manager. The KPI dashboard should be the first screen every manager opens every morning and the last screen they check every night.
2. Audience
| Role | Interaction |
|---|---|
| General Manager | Daily operational KPIs: occupancy, ADR, RevPAR, in-house count |
| Revenue Manager | RevPAR analysis, pace vs. forecast, channel mix, BAR recommendation review |
| Owner / Investor | High-level financial summary, month-over-month trend, compset gap |
| Chain Admin | Multi-property KPI comparison across the portfolio |
3. Scope
3.1 In Scope
- Real-time KPIs: occupancy rate (%), ADR (INR), RevPAR (INR), TRevPAR (INR), GOPPAR (INR), in-house guest count
- Today's operational counts: arrivals, departures, no-shows, walk-ins, cancellations
- Revenue MTD and YTD with trend sparklines
- Occupancy pacing: current vs. same-time-last-year (STLY) and budget
- RevPAR analysis: 7-day rolling, 30-day rolling, year-over-year
- Demand forecasting: 7-day, 30-day, 90-day occupancy and revenue projections (Prophet model via forecast sidecar)
- Competitive set (compset) analysis: benchmark RevPAR, occupancy against configurable competitors
- KPI catalog and configuration: tenant admin selects which KPIs to show and in what order
- Real-time update via Kafka event consumers (dashboard refreshes within 30 seconds of event)
- Multi-property portfolio view (chain hotels)
- Mobile-responsive dashboard for GM review on phone
3.2 Out of Scope
- Financial P&L and balance sheet (EP-012B)
- GST compliance reports (EP-012C)
- Custom report builder (EP-012D)
- Operational analytics (housekeeping KPIs, channel analytics) — EP-012E
- Full ERP integration (EP-020)
4. Current Implementation Status
4.1 Backend — analytics-service
| Controller / Endpoint | Status | Notes |
|---|---|---|
GET /dashboard/kpis | Built | Occupancy, ADR, RevPAR, TRevPAR, in-house, arrivals/departures |
GET /dashboard/revenue-mtd | Built | MTD and YTD revenue totals |
GET /dashboard/pacing | Built | Occupancy pacing vs. STLY |
GET /revpar/analysis | Built | 7/30-day rolling RevPAR |
GET /forecast/occupancy | Partial | Prophet model via sidecar; placeholder values without training |
GET /forecast/revenue | Partial | GradientBoosting pricing sidecar; not trained on real data |
GET /compset/analysis | Partial | Benchmarking UI built; compset data requires manual entry |
GET /kpi-catalog | Not Started | Tenant-configurable KPI catalog |
PATCH /kpi-catalog/order | Not Started | Drag-and-drop KPI ordering |
| KPI Kafka event consumers | Built | reservation.checkedIn, reservation.checkedOut → Redis TTL |
4.2 Dashboard — 02-hmp-web-dashboard
| Component | Status | Notes |
|---|---|---|
| KPI Cards (occupancy, ADR…) | Built | Real-time cards with trend indicators |
| Revenue MTD chart | Built | Bar chart with YTD overlay |
| Pacing chart (vs. STLY) | Built | Line chart with forecast overlay |
| RevPAR trend chart | Built | 30-day rolling with period selector |
| Compset analysis panel | Partial | Manual data entry; no automated feed |
| Forecast chart (7/30/90 day) | Partial | UI built; sidecar returns placeholder values |
| Multi-property portfolio view | Partial | Chain view exists; per-property drill-down partial |
5. Gap Analysis
| # | Gap | Impact | Effort | Priority |
|---|---|---|---|---|
| 1 | Demand forecasting models not trained on real reservation data | Medium | XL | P2 |
| 2 | Compset data requires manual entry (no API integration) | Medium | L | P2 |
| 3 | KPI catalog configuration (tenant-defined KPI order) missing | Low | M | P3 |
| 4 | GOPPAR requires total F&B and ancillary revenue aggregation | Medium | M | P2 |
| 5 | Multi-property portfolio KPI aggregation incomplete | Medium | M | P2 |
6. User Stories
| Story ID | Title | Priority | Points | Sprint | Status |
|---|---|---|---|---|---|
| US-012-01 | Real-Time KPI Dashboard | P0 | 8 | 1 | Built |
| US-012-17 | Demand Forecasting (7/30/90 day) | P2 | 13 | 5 | Partial |
| US-012-18 | Competitive Set Analysis | P2 | 8 | 6 | Partial |
| US-012A-01 | RevPAR & ADR Trend Analysis | P1 | 8 | 3 | Built |
| US-012A-02 | Occupancy Pacing vs. STLY | P1 | 5 | 3 | Built |
| US-012A-03 | KPI Catalog & Configuration | P3 | 5 | 6 | Not Started |
| US-012A-04 | Multi-Property Portfolio KPI View | P2 | 8 | 5 | Partial |
| US-012A-05 | GOPPAR Calculation | P2 | 5 | 5 | Not Started |
7. Detailed User Stories
US-012-01: Real-Time KPI Dashboard
As a General Manager, I want to see a real-time dashboard with today's key metrics, So that I can make informed operational decisions throughout the day.
Priority: P0 | Points: 8 | Sprint: 1 | Status: Built
Implementation Status
Real-time KPI dashboard is fully built. Displays: occupancy rate (%), ADR (INR), RevPAR (INR), TRevPAR (INR), rooms sold, rooms available, in-house guest count, today's arrivals, today's departures, revenue MTD. Data cached in Redis (TTL 30s) and refreshed via Kafka consumers. Dashboard auto-refreshes every 30 seconds.
Acceptance Criteria
Scenario: View today's operational KPIs
Given I am logged in as General Manager for "Hotel Sunrise, Jaipur"
When I open the Analytics Dashboard
Then I see today's metrics: Occupancy, ADR, RevPAR, In-House Count, Arrivals, Departures, Revenue MTD
And revenue is formatted in Indian lakh notation (e.g., ₹48,75,000)
And data was last refreshed within 30 seconds
Scenario: KPIs update in real-time on new check-in
Given the dashboard shows occupancy at 78%
When a front desk agent checks in a guest (Kafka event "reservation.checkedIn")
Then within 30 seconds the dashboard updates occupancy to 78.75%
And in-house guest count increments accordingly
Scenario: Tenant isolation on KPI dashboard
Given I manage "Hotel Sunrise, Jaipur" (tenant A)
When I view the dashboard
Then I see only data for my property
And data from "Hotel Moonlight, Mumbai" (tenant B) is never visible
US-012-17: Demand Forecasting
As a Revenue Manager, I want to see 7-day, 30-day, and 90-day occupancy and revenue forecasts, So that I can proactively adjust rates and inventory before demand peaks or troughs.
Priority: P2 | Points: 13 | Sprint: 5 | Status: Partial
Implementation Status
GET /forecast/occupancy and GET /forecast/revenue call the Python forecast sidecar at 05-hmp-forecast-sidecar/ (Phase 4 deliverable). Sidecar uses Prophet for demand and GradientBoosting for pricing. Indian holiday calendar (172 entries, 2024-2028) is included. However, models return placeholder predictions until trained on real historical reservation data.
Acceptance Criteria
Scenario: View 30-day occupancy forecast
Given the property has at least 180 days of historical reservation data
When the Revenue Manager opens the 30-day forecast
Then the chart shows predicted occupancy per day with confidence bands
And Indian public holidays are highlighted (e.g., Holi, Diwali, Republic Day)
And accuracy metric "MAPE (last 30 days): 12.3%" is displayed
Scenario: Forecast with Indian festival surge
Given the forecast period includes Diwali weekend
When the Revenue Manager views the 7-day forecast
Then Diwali dates show elevated predicted occupancy (>90%)
And the system suggests increasing BAR rates by the configured festival multiplier
US-012A-04: Multi-Property Portfolio KPI View
As a Chain Owner, I want to see a side-by-side KPI comparison for all my properties, So that I can identify which properties are outperforming and which need attention.
Priority: P2 | Points: 8 | Sprint: 5 | Status: Partial
Implementation Notes
GET /chain/kpis— aggregates KPIs across all properties in the chain (EP-018 dependency)- Columns: property name, occupancy, ADR, RevPAR, rooms sold, revenue MTD
- Sortable and filterable by region, property type
- Drill-down: clicking a property opens its individual KPI dashboard
Acceptance Criteria
Scenario: Portfolio view across 5 properties
Given chain "Sunrise Hotels" has 5 properties
When the Chain Owner opens the portfolio dashboard
Then each property row shows: Occupancy, ADR, RevPAR, Revenue MTD
And the best-performing property (highest RevPAR) is highlighted in green
And the lowest-performing is highlighted in amber
Scenario: Drill down into a property
When owner clicks "Sunrise Goa" row
Then the full KPI dashboard for Sunrise Goa opens with property-specific data
8. Dependencies
| Dependency | Type | Epic / Service | Status |
|---|---|---|---|
| Reservation data (check-in/out events) | Upstream | EP-003 / reservation | Available |
| Property config (rooms, rate plans) | Upstream | EP-002 / property | Available |
| Night audit (business date close) | Peer | EP-005C / frontdesk | Available |
| Forecast sidecar (Python FastAPI) | Internal | 05-hmp-forecast-sidecar/ | Partial |
| Chain management (multi-property KPIs) | Peer | EP-018 / property | Partial |
| Auth / RBAC (role-based KPI access) | Upstream | EP-001 / auth | Available |
| Kafka (real-time event consumers) | Infra | Docker / Kafka | Available |
| Redis (KPI cache, TTL 30s) | Infra | Docker / Redis | Available |
9. Acceptance Criteria (Sub-Epic Level)
- AC-EP-012A-01: Dashboard KPIs (occupancy, ADR, RevPAR) update within 30 seconds of a reservation event via Kafka consumer.
- AC-EP-012A-02: Revenue is displayed in Indian lakh notation (₹48,75,000) and all dates in IST.
- AC-EP-012A-03: Demand forecasting provides 7/30/90-day projections with MAPE < 15% on properties with ≥ 180 days of history.
- AC-EP-012A-04: Compset analysis benchmarks the property's RevPAR against configured competitors with weekly trend comparison.
- AC-EP-012A-05: Multi-property portfolio view shows all properties in a single table with drill-down capability.
- AC-EP-012A-06: All KPI data respects tenant isolation — cross-tenant data leakage produces a 403 error.
10. Technical Notes
- Analytics controller:
01-hmp-backend/apps/analytics-service/src/dashboard/dashboard.controller.ts - KPI Kafka consumers:
01-hmp-backend/apps/analytics-service/src/consumers/— event-driven cache invalidation - Redis KPI cache key pattern:
kpi:{tenantId}:{propertyId}:{date}with 30s TTL - Forecast sidecar:
05-hmp-forecast-sidecar/main.py— FastAPI,GET /forecast/occupancy,GET /forecast/pricing; expects historical CSV from analytics-service - MetricsModule:
01-hmp-backend/libs/common/src/lib/metrics/—hmp_occupancy_rate,hmp_adr_inr,hmp_revpar_inrPrometheus gauges exposed at/metrics - Compset data is stored in
competitor_ratestable (Prisma model); currently requires manual entry; future phase: automated STR feed