Skip to main content

EP-011: Booking Engine

FieldValue
Epic IDEP-011
TitleBooking Engine
OwnerProduct -- Direct Revenue & Guest Experience
StatusPartial
Last Updated2026-03-05
Target ReleaseR3 (Q2 2026)

1. Business Objective​

Deliver a high-conversion, mobile-first booking engine that enables Indian hotel properties to capture direct reservations, reducing OTA dependency and commission costs (typically 15-25% on MakeMyTrip/Goibibo). The engine must support 14 languages for domestic and Southeast Asian travelers, integrate Razorpay for INR/UPI payments, and embed seamlessly into hotel websites. Target: shift 35%+ of bookings to the direct channel within 12 months of deployment.

2. Audience​

RoleInteraction
Guest (end-user)Searches rooms, compares rates, books, pays, manages reservations
Loyalty MemberViews points, redeems rewards, accesses member-only rates
Revenue ManagerMonitors direct booking performance, manages promo codes
Marketing ManagerEmbeds booking engine on hotel website, tracks conversion funnel
Property ManagerConfigures available inventory, rate plans, restrictions
Super AdminManages multi-property booking engine instances

3. Scope​

3.1 In Scope​

  • Room search with availability calendar (date picker, guest count, room count)
  • Rate plan display with comparison view (Best Available, Advance Purchase, Non-Refundable, Member Rate)
  • Room type gallery with photos, amenities, and floor plan indicators
  • Guest details form with Indian identity support (Aadhaar, PAN, passport)
  • Payment integration via Razorpay (credit/debit card, UPI, net banking, wallet)
  • Booking confirmation page with PDF voucher download
  • 14 language translations (en, hi, ta, te, kn, mr, bn, gu, ml, pa, id, ms, th, vi)
  • Loyalty dashboard (points balance, transaction history, reward catalog, tier status)
  • Manage booking (booking lookup by confirmation number + email/phone, view details, amend dates/room, cancel with policy enforcement)
  • Spa/treatment booking with therapist availability and service catalog
  • Promo code validation with real-time discount calculation
  • Urgency indicators: "Only 3 rooms left", "5 people viewing this room"
  • Social proof: "12 bookings today"
  • Cookie consent banner with GDPR/IT Act compliance
  • Three deployment modes: embeddable widget, iframe, standalone
  • Mobile-responsive design (mobile-first approach)
  • INR currency formatting with GST breakdown display

3.2 Out of Scope​

  • Channel manager integration (OTA rate parity -- covered in EP-006)
  • Group/MICE booking with RFP workflow (covered in EP-007)
  • Travel agent portal / B2B booking (future epic)
  • Multi-currency / forex conversion (phase 2)
  • Flight + hotel bundled packages

4. Current Implementation Status​

ComponentModule / FileStatus
Room search & availability03-hmp-booking-engine/src/pages/Built
Rate plan display + compareSearchResults componentBuilt
Room gallery & amenitiesRoomDetail componentBuilt
Guest details formGuestDetails componentBuilt
Razorpay payment integrationPaymentPage componentBuilt
Booking confirmationConfirmation componentBuilt
14 language i18nsrc/locales/ (14 JSON files)Built
Loyalty dashboardLoyaltyDashboard componentBuilt
Manage booking (lookup)ManageBooking componentBuilt
Manage booking (amend/cancel)ManageBooking componentPartial
Spa bookingSpaBooking componentBuilt
Promo code validationPromoCode componentBuilt
Urgency indicatorsUrgencyBanner componentBuilt
Cookie consentCookieConsent componentPartial
Widget / iframe / standalonesrc/embed/ configurationBuilt
Mock API layersrc/api/mock/Built
Live backend integrationsrc/api/live/Not Started

5. Gap Analysis​

#GapImpactEffortPriority
1Connected to mock API -- needs live backend integrationEntire booking flow is non-functional in productionCriticalP0
2Razorpay payment flow not tested end-to-end with real transactionsCannot accept actual payments; money flow unverifiedCriticalP0
3Manage booking (amend/cancel) needs reservation service wiringGuests cannot modify bookings post-confirmationHighP0
4Loyalty points redemption during booking not connectedMembers cannot use points for discounts at checkoutHighP1
5Promo code validation is client-side mockAny promo code is accepted; no server-side validationHighP0
6Cookie consent needs GDPR/IT Act compliant implementationLegal exposure; consent not persisted or auditableMediumP1
7No real-time availability sync (mock returns static data)Overbooking risk once liveCriticalP0
8Urgency indicators use random numbers, not real dataMisleading social proof; potential legal issueMediumP1

6. User Stories Summary​

IDTitlePriorityPointsSprintStatus
US-011-01Room Search & Availability CalendarP081Built
US-011-02Rate Plan Display & ComparisonP081Built
US-011-03Guest Details & Identity CaptureP051Built
US-011-04Razorpay Payment IntegrationP0132Partial
US-011-05Booking Confirmation & VoucherP052Built
US-011-06Live Backend API IntegrationP0213Not Started
US-011-0714-Language InternationalizationP181Built
US-011-08Loyalty Dashboard in Booking EngineP182Built
US-011-09Points Redemption During BookingP184Not Started
US-011-10Manage Booking (Lookup & View)P052Built
US-011-11Manage Booking (Amend & Cancel)P0133Partial
US-011-12Spa & Treatment BookingP283Built
US-011-13Promo Code Server-Side ValidationP053Not Started
US-011-14Real-Time Urgency & Social ProofP154Not Started
US-011-15Cookie Consent (GDPR/IT Act)P154Partial
US-011-16Embeddable Widget & Deployment ModesP182Built

7. Dependencies​

DependencyEpic/ServiceType
Room availability & inventoryEP-004 / property-serviceHard
Rate plans & pricingEP-006 / rate-serviceHard
Reservation creation & managementEP-005 / reservation-serviceHard
Guest profile creationEP-003 / guest-serviceHard
Loyalty points & tier dataEP-010 / crm-serviceHard
Payment processingEP-008 / billing-serviceHard
Notification (confirmation emails)EP-014 / notification-serviceHard
Razorpay merchant accountInfrastructure / FinanceSoft
API Gateway routingEP-001 / api-gatewayHard

8. Acceptance Criteria (Epic-Level)​

  1. A guest can search for rooms, select a rate plan, enter details, pay via Razorpay (UPI/card/net banking), and receive a confirmed booking -- all against the live backend.
  2. The complete booking flow works in all 14 supported languages with correct currency formatting (INR with lakhs notation).
  3. A loyalty member can see their points balance and redeem points as a discount during the booking payment step.
  4. A guest can look up an existing booking by confirmation number + email and amend dates or cancel per the cancellation policy.
  5. Promo codes are validated server-side against the rate-service, with proper error messages for invalid/expired codes.
  6. The booking engine renders correctly on mobile (320px width and above) and achieves Lighthouse performance score > 80.
  7. Urgency indicators reflect real-time data from the property-service (actual remaining inventory, actual concurrent viewers).
  8. Cookie consent is auditable, persisted per session, and compliant with India IT Act 2000 and GDPR for EU visitors.

9. KPIs​

KPITargetMeasurement
Booking conversion rate> 3.5%Completed bookings / unique sessions
Cart abandonment rate< 65%Started checkout / completed checkout
Mobile booking share> 55%Mobile bookings / total bookings
Average booking value (INR)Track and grow +10% QoQTotal revenue / booking count
Page load time (LCP)< 2.5 secondsLighthouse / RUM metrics
Direct channel share> 35% of total bookingsBooking engine / all channels
Language utilization> 20% non-English bookingsNon-English bookings / total
Promo code usage rate8-15% of bookingsPromo bookings / total bookings

10. Detailed User Stories​


US-011-01: Room Search & Availability Calendar​

As a Guest, I want to search for available rooms by selecting check-in/check-out dates, number of guests, and rooms, So that I can find suitable accommodation for my trip.

Priority: P0 | Points: 8 | Sprint: 1 | Status: Built

Implementation Status​

Room search is fully built with a date picker (blocked past dates, max 30-night stays), adult/child selectors, and room count selector. The search results page displays available room types with photos, amenities, and starting price. Currently returns mock data; needs live backend wiring (see US-011-06).

Acceptance Criteria​

Scenario: Search for rooms with valid dates
Given I am on the booking engine home page for "Hotel Taj Residency"
When I select check-in "2026-04-10", check-out "2026-04-13", 2 adults, 1 child, 1 room
Then the search results page displays available room types for those dates
And each room type shows name, photo, amenity icons, and starting price in INR (e.g., "4,500/night + taxes")
And the total stay duration "3 Nights" is displayed

Scenario: No availability for selected dates
Given the hotel is fully booked for 2026-12-31 (New Year's Eve)
When I search for check-in 2026-12-31, check-out 2027-01-01
Then the results page shows "No rooms available for selected dates"
And suggests alternative dates with availability (nearest available dates)

Scenario: Restrict invalid date selections
Given today is 2026-03-05
When I attempt to select check-in date 2026-03-01 (past date)
Then the date is disabled and not selectable
And check-out date must be at least 1 day after check-in

US-011-02: Rate Plan Display & Comparison​

As a Guest, I want to compare different rate plans for a room type, So that I can choose the best value option for my stay.

Priority: P0 | Points: 8 | Sprint: 1 | Status: Built

Implementation Status​

Rate plan comparison view is built. Displays up to 4 rate plans per room type: Best Available Rate (BAR), Advance Purchase (pay now, save 15%), Non-Refundable (save 20%), and Member Rate (loyalty members only). Each plan shows base rate, tax breakdown (GST at 12% for rooms 1000-7499 INR, 18% for 7500+ INR), cancellation policy summary, and inclusions. Currently using mock rate data.

Acceptance Criteria​

Scenario: Compare rate plans for a Deluxe Room
Given I search for a Deluxe Room for 2 nights
When the results load
Then I see rate plans displayed as cards:
| Plan | Rate/Night | GST (18%) | Total (2N) | Cancellation |
| Best Available | 8,000 INR | 1,440 INR | 18,880 INR | Free until 24h before |
| Advance Purchase | 6,800 INR | 1,224 INR | 16,048 INR | Non-refundable |
| Member Rate | 7,200 INR | 1,296 INR | 16,992 INR | Free until 48h before |
And the Member Rate shows a lock icon with "Login to access" for non-members

Scenario: GST rate selection based on room tariff
Given a Standard Room has a tariff of 5,000 INR per night (below 7,500 INR threshold)
When the rate plan is displayed
Then GST is calculated at 12% (600 INR per night)
And the tax line shows "GST @12%: 600 INR"

Scenario: Highlight best value plan
Given multiple rate plans are displayed
When the Advance Purchase rate offers the lowest total
Then it is highlighted with a "Best Value" badge
And the savings compared to BAR are shown (e.g., "Save 2,832 INR")

US-011-03: Guest Details & Identity Capture​

As a Guest, I want to enter my personal details and identity information during booking, So that the hotel can prepare for my arrival and comply with Indian regulations.

Priority: P0 | Points: 5 | Sprint: 1 | Status: Built

Implementation Status​

Guest details form captures: full name, email, phone (+91 validation), address, identity document type (Aadhaar, PAN, Passport, Driving License), document number, special requests, and estimated arrival time. Form validation is implemented client-side. GST details (GSTIN, company name, company address) are optional for business travelers claiming input tax credit.

Acceptance Criteria​

Scenario: Complete guest details for domestic traveler
Given I have selected a room and rate plan
When I fill in: Name "Arjun Reddy", Email "arjun@email.com", Phone "+91-9876543210", ID Type "Aadhaar", ID Number "1234-5678-9012"
Then all fields pass validation
And the Aadhaar number is formatted as "XXXX-XXXX-9012" (masked for display)
And I can proceed to the payment step

Scenario: Capture GST details for business booking
Given a guest selects "Business Travel" purpose
When they enter GSTIN "29ABCDE1234F1Z5" and company name "TechCorp India Pvt Ltd"
Then the GSTIN is validated against the standard format (15 characters, state code prefix)
And the invoice will be generated with GST input credit details
And the company address auto-populates from GSTIN lookup if available

Scenario: Validate Indian phone number
Given the booking engine is configured for an Indian property
When a guest enters phone number "9876543210" (without country code)
Then the system auto-prepends "+91" and validates the 10-digit format
And rejects numbers not starting with 6, 7, 8, or 9

US-011-04: Razorpay Payment Integration​

As a Guest, I want to pay for my booking using UPI, credit/debit card, or net banking via Razorpay, So that I can complete my reservation using my preferred Indian payment method.

Priority: P0 | Points: 13 | Sprint: 2 | Status: Partial

Implementation Status​

Razorpay checkout is integrated using Razorpay.js SDK. The payment modal renders with booking amount, and the Razorpay order ID is generated on the client side. However, the server-side order creation (via billing-service -> Razorpay Orders API) is using mock responses. Payment verification (signature validation) is not tested against Razorpay's live/test environment. Webhook handler for payment status updates is scaffolded but untested.

Acceptance Criteria​

Scenario: Pay via UPI
Given I am on the payment page with booking total 18,880 INR
When I select "UPI" as payment method and enter UPI ID "arjun@okicici"
Then a Razorpay order is created via the billing-service (POST /api/payments/create-order)
And the Razorpay payment modal opens with amount "18,880.00"
And upon successful payment, the server verifies the Razorpay signature
And the booking status changes to "Confirmed" and confirmation page loads

Scenario: Handle payment failure
Given I attempt to pay 18,880 INR via credit card
When the card is declined by the issuing bank
Then the Razorpay modal shows the bank's decline reason
And the booking remains in "Pending Payment" status for 15 minutes
And I can retry with a different payment method without re-entering guest details

Scenario: Razorpay webhook reconciliation
Given a payment was initiated but the browser closed before confirmation
When Razorpay sends a "payment.captured" webhook to the billing-service
Then the payment is reconciled with the pending booking
And the booking status is updated to "Confirmed"
And a confirmation email is sent to the guest

US-011-05: Booking Confirmation & Voucher​

As a Guest, I want to receive a booking confirmation with all details and a downloadable voucher, So that I have a record of my reservation.

Priority: P0 | Points: 5 | Sprint: 2 | Status: Built

Implementation Status​

Confirmation page is fully built. Displays booking ID, hotel name, room type, check-in/check-out dates, guest name, total amount with GST breakdown, and payment reference. A "Download Voucher" button generates a PDF with hotel branding. The confirmation email is triggered (via mock notification service). QR code for mobile check-in is generated on the voucher.

Acceptance Criteria​

Scenario: Display booking confirmation
Given I completed payment for a booking
When the confirmation page loads
Then I see:
| Field | Value |
| Booking ID | BK-20260410-0042 |
| Hotel | Hotel Taj Residency, Mumbai |
| Room Type | Deluxe King |
| Check-in | 10 Apr 2026, 14:00 |
| Check-out | 13 Apr 2026, 11:00 |
| Total Amount | 18,880 INR (incl. GST) |
| Payment Status | Paid via UPI |
And a QR code is displayed for mobile check-in

Scenario: Download PDF voucher
Given I am on the confirmation page
When I click "Download Voucher"
Then a PDF file "HotelTajResidency-BK-20260410-0042.pdf" downloads
And the PDF includes hotel logo, booking details, GST breakdown, cancellation policy, and QR code
And the GST breakdown shows CGST and SGST (or IGST for inter-state) separately

Scenario: Confirmation email sent
Given the booking is confirmed
When the "booking.confirmed" Kafka event fires
Then the notification-service sends a confirmation email to the guest
And the email contains the same details as the confirmation page
And the PDF voucher is attached to the email

US-011-06: Live Backend API Integration​

As a Development Team, I want to replace all mock API calls with live backend service integration, So that the booking engine operates against real hotel inventory, rates, and reservations.

Priority: P0 | Points: 21 | Sprint: 3 | Status: Not Started

Implementation Status​

Not started. The booking engine currently uses a mock API layer (src/api/mock/) that returns hardcoded responses for all endpoints. The live API client (src/api/live/) needs to be implemented to call the API Gateway, which proxies to property-service, rate-service, reservation-service, billing-service, guest-service, and crm-service.

Acceptance Criteria​

Scenario: Room search calls property-service via API Gateway
Given the booking engine is configured with API Gateway URL "https://api.hotel.com"
And the tenant ID is set in the booking engine configuration
When a guest searches for rooms for 2026-04-10 to 2026-04-13
Then the engine calls GET /api/properties/{propertyId}/availability?checkIn=2026-04-10&checkOut=2026-04-13&adults=2&children=1
And the response contains real room availability from the property-service
And the UI renders actual available room types with live pricing

Scenario: Booking creation calls reservation-service
Given the guest has filled details and completed payment
When the "Confirm Booking" action fires
Then the engine calls POST /api/reservations with guest details, room type, dates, and payment reference
And the reservation-service creates the reservation and returns a confirmation number
And inventory is decremented in real-time

Scenario: Graceful degradation on API failure
Given the API Gateway returns HTTP 503 (service unavailable)
When the guest is on the search results page
Then a user-friendly error message is shown: "We're experiencing technical difficulties. Please try again shortly."
And the booking engine does not display stale mock data
And the error is logged with correlation ID for debugging

US-011-07: 14-Language Internationalization​

As a Guest who speaks a regional Indian or Southeast Asian language, I want to use the booking engine in my preferred language, So that I can understand all information and complete my booking confidently.

Priority: P1 | Points: 8 | Sprint: 1 | Status: Built

Implementation Status​

Full i18n implementation using react-i18next. All 14 language JSON files are maintained in src/locales/. Language switcher component in the header. Language preference is persisted in localStorage and sent as Accept-Language header to the API. RTL support is not needed for supported languages. Date and number formatting respects locale (e.g., Hindi uses Devanagari numerals optionally).

Acceptance Criteria​

Scenario: Switch language to Hindi
Given I am on the booking engine in English
When I click the language selector and choose "Hindi"
Then all UI labels, button texts, and static content render in Hindi (Devanagari script)
And the URL updates to include locale parameter "?lang=hi"
And currency remains "INR" with amount in standard numerals

Scenario: Tamil booking flow end-to-end
Given I set the language to Tamil ("ta")
When I complete the entire booking flow from search to confirmation
Then all pages render in Tamil including form labels, error messages, and confirmation text
And the PDF voucher generates with Tamil text for guest-facing fields
And the confirmation email is sent in Tamil

Scenario: Fallback for missing translations
Given a new feature was added with English strings but Telugu translations are pending
When a Telugu-speaking user encounters the untranslated string
Then the English fallback is displayed for that specific string
And all other Telugu translations continue to display correctly

US-011-08: Loyalty Dashboard in Booking Engine​

As a Loyalty Member, I want to view my loyalty status, points balance, and transaction history within the booking engine, So that I can track my rewards without calling the hotel.

Priority: P1 | Points: 8 | Sprint: 2 | Status: Built

Implementation Status​

Loyalty dashboard is fully built with: tier badge and progress bar (e.g., "Gold -- 2,400 points to Platinum"), points balance, transaction history (earned, redeemed, expired), reward catalog browser, and membership QR code. Authentication is via JWT token from the auth-service. Currently displays mock loyalty data.

Acceptance Criteria​

Scenario: View loyalty dashboard
Given I am logged in as loyalty member "HMP-LY-00042" (Gold tier, 12,500 points)
When I navigate to the loyalty dashboard
Then I see:
| Element | Value |
| Tier Badge | Gold (with gold-colored icon) |
| Points Balance | 12,500 points |
| Tier Progress | "2,500 points to Platinum" with bar at 83% |
| Next Expiry | "1,200 points expire on 2026-06-15" |
And the transaction history shows last 20 transactions with date, type, points, and description

Scenario: Browse reward catalog
Given I am on the loyalty dashboard
When I click "Rewards Catalog"
Then I see available rewards grouped by category (Room, F&B, Spa, Experiences)
And each reward shows name, points cost, description, and "Redeem" button
And rewards I cannot afford (insufficient points) show points needed with dimmed "Redeem" button

Scenario: Unauthenticated access
Given I am not logged in
When I navigate to the loyalty dashboard URL
Then I am redirected to the login page
And after login, I am returned to the loyalty dashboard

US-011-09: Points Redemption During Booking​

As a Loyalty Member, I want to apply my loyalty points as a discount during the booking payment step, So that I receive immediate value from my accumulated points.

Priority: P1 | Points: 8 | Sprint: 4 | Status: Not Started

Implementation Status​

Not implemented. The payment page has a placeholder "Apply Points" section in the UI, but it is not connected to the crm-service loyalty API. Points balance retrieval, redemption rate calculation, and points deduction on booking confirmation are all pending.

Acceptance Criteria​

Scenario: Apply points as discount during checkout
Given I am a Gold member with 10,000 points and the redemption rate is 500 points = 1,000 INR
And my booking total is 18,880 INR
When I click "Apply Points" and choose to redeem 5,000 points (= 10,000 INR discount)
Then the payment summary updates:
| Line Item | Amount |
| Room Charges | 16,000 INR |
| GST @18% | 2,880 INR |
| Loyalty Redemption | -10,000 INR |
| Amount to Pay | 8,880 INR |
And the Razorpay payment modal opens for 8,880 INR

Scenario: Partial points redemption
Given I have 3,000 points and maximum redemption is 50% of booking value
And booking total is 18,880 INR (50% = 9,440 INR)
When I move the points slider to maximum
Then the slider caps at 3,000 points (= 6,000 INR, which is under the 50% cap)
And remaining balance of 12,880 INR must be paid via Razorpay

Scenario: Points deducted only on confirmed payment
Given I applied 5,000 points for a 10,000 INR discount
When the Razorpay payment for the remaining amount fails
Then points are NOT deducted from my balance
And I can retry payment or remove the points redemption

US-011-10: Manage Booking (Lookup & View)​

As a Guest, I want to look up my existing booking using confirmation number and email, So that I can review my reservation details.

Priority: P0 | Points: 5 | Sprint: 2 | Status: Built

Implementation Status​

Booking lookup is fully built. Guest enters confirmation number (e.g., "BK-20260410-0042") and registered email. The system retrieves and displays full booking details: dates, room type, guest name, amount paid, payment method, booking status, cancellation policy, and hotel contact information. Currently using mock API.

Acceptance Criteria​

Scenario: Look up a confirmed booking
Given I have booking "BK-20260410-0042" with email "arjun@email.com"
When I enter these on the Manage Booking page and click "Find Booking"
Then the booking details page loads showing all reservation information
And I see action buttons: "Modify Booking", "Cancel Booking", "Download Voucher"

Scenario: Booking not found
Given I enter confirmation number "BK-INVALID-001" with email "wrong@email.com"
When I click "Find Booking"
Then the system displays "No booking found. Please check your confirmation number and email address."
And after 3 failed attempts, a CAPTCHA is presented to prevent brute-force lookup

Scenario: View cancelled booking
Given booking "BK-20260410-0042" was previously cancelled
When I look it up
Then the booking details show status "Cancelled" with cancellation date
And refund details are displayed (amount, refund reference, expected settlement date)
And "Modify Booking" and "Cancel Booking" buttons are disabled

US-011-11: Manage Booking (Amend & Cancel)​

As a Guest, I want to modify my booking dates/room type or cancel my booking per the hotel's policy, So that I have flexibility to change my travel plans.

Priority: P0 | Points: 13 | Sprint: 3 | Status: Partial

Implementation Status​

The UI for amend and cancel flows is partially built. The cancel button triggers a confirmation modal showing the cancellation policy and refund amount. The amend flow allows date changes and displays rate differences. However, neither flow is connected to the reservation-service backend. Cancel does not trigger Razorpay refund. Amend does not check live availability or process differential payment.

Acceptance Criteria​

Scenario: Cancel a booking within free cancellation window
Given booking "BK-20260410-0042" has policy "Free cancellation until 24 hours before check-in"
And check-in is 2026-04-10 14:00 IST and current time is 2026-04-08 10:00 IST
When I click "Cancel Booking" and confirm
Then the reservation-service updates the booking status to "Cancelled"
And a full refund of 18,880 INR is initiated via Razorpay Refunds API
And I receive a cancellation confirmation email with refund reference number
And the room inventory is released back to available pool

Scenario: Cancel after free cancellation window
Given the same booking but current time is 2026-04-09 16:00 IST (within 24 hours of check-in)
When I click "Cancel Booking"
Then the modal shows: "Cancellation charge: 1 night (9,440 INR). Refund amount: 9,440 INR"
And I must explicitly acknowledge the charge before confirming
And upon confirmation, partial refund is processed for 9,440 INR

Scenario: Amend booking dates with rate difference
Given booking is for 2026-04-10 to 2026-04-13 (3 nights, 18,880 INR)
When I change check-out to 2026-04-15 (5 nights) and the rate is unchanged at 8,000/night + GST
Then the system shows: "Additional amount due: 18,880 INR for 2 extra nights"
And I am redirected to Razorpay to pay the difference
And after payment, the reservation is updated with new dates

US-011-12: Spa & Treatment Booking​

As a Guest, I want to book spa treatments and wellness services during the booking flow or from the booking engine, So that I can plan my wellness experience in advance.

Priority: P2 | Points: 8 | Sprint: 3 | Status: Built

Implementation Status​

Spa booking module is fully built. Displays treatment catalog with categories (Ayurvedic, Western, Beauty, Fitness), therapist availability calendar, duration, pricing in INR, and description. Guest can select date, time slot, and preferred therapist gender. Currently using mock spa service data.

Acceptance Criteria​

Scenario: Book an Ayurvedic massage
Given I am booking a stay at a resort with a spa
When I navigate to "Spa & Wellness" and select "Abhyanga Massage - 60 min" at 3,500 INR
And I choose date 2026-04-11 at 10:00 AM with preference "Female therapist"
Then the time slot availability is checked against the spa schedule
And the spa booking is added to my reservation with total updated
And the confirmation shows spa appointment details alongside room booking

Scenario: Spa time slot unavailable
Given the 10:00 AM slot on 2026-04-11 is fully booked
When I select this time slot
Then the system shows "This time slot is unavailable" and suggests nearby alternatives: 11:00 AM, 2:00 PM, 3:00 PM
And I can select an alternative slot

Scenario: Cancel spa booking independently
Given I have a room booking with an attached spa appointment
When I cancel only the spa appointment (not the room)
Then the spa booking is cancelled with full refund (if > 4 hours before appointment)
And the room booking remains unchanged
And the spa time slot is released for other guests

US-011-13: Promo Code Server-Side Validation​

As a Guest, I want to apply a promo code and see the validated discount, So that I can trust the discount is legitimate and will be honored.

Priority: P0 | Points: 5 | Sprint: 3 | Status: Not Started

Implementation Status​

Not started. The current promo code field accepts any input and applies a hardcoded 10% discount on the client side. Server-side validation against the rate-service (which stores promo code definitions with validity dates, usage limits, minimum booking value, applicable room types, and discount type/amount) is not implemented.

Acceptance Criteria​

Scenario: Apply a valid promo code
Given promo code "MONSOON25" offers 25% off on Deluxe rooms, valid until 2026-09-30, minimum booking 10,000 INR
And my Deluxe Room booking total is 18,880 INR
When I enter "MONSOON25" and click "Apply"
Then the system calls POST /api/rates/promo/validate with code, booking details, and tenant ID
And the discount of 4,000 INR (25% of 16,000 INR room charge, pre-GST) is applied
And the updated total shows 14,880 INR (including recalculated GST)

Scenario: Apply an expired promo code
Given promo code "DIWALI25" expired on 2025-11-15
When I enter "DIWALI25" and click "Apply"
Then the server returns "Promo code has expired"
And no discount is applied
And the input field shows a red error message

Scenario: Promo code usage limit exceeded
Given promo code "FLASH50" has a limit of 100 uses and 100 bookings have already used it
When I enter "FLASH50"
Then the server returns "This promo code has reached its maximum usage limit"
And no discount is applied

US-011-14: Real-Time Urgency & Social Proof​

As a Guest, I want to see real-time indicators about room scarcity and booking activity, So that I can make timely booking decisions.

Priority: P1 | Points: 5 | Sprint: 4 | Status: Not Started

Implementation Status​

Not started on the data side. UI components exist for urgency banners ("Only 3 rooms left!") and social proof counters ("5 people viewing this room"), but they currently display random numbers generated client-side. Real data requires WebSocket or polling integration with property-service for inventory counts and a session tracking mechanism for concurrent viewers.

Acceptance Criteria​

Scenario: Display real room scarcity
Given the property-service reports 2 Deluxe Rooms remaining for 2026-04-10
When the search results load for that date
Then the Deluxe Room card shows a red banner: "Only 2 rooms left!"
And the banner only appears when remaining inventory is <= 5

Scenario: Show concurrent viewers
Given 8 unique sessions are currently viewing the Suite room type for 2026-04-10
When I view the Suite room listing
Then I see "8 people are viewing this room" with a pulsing indicator
And the count updates every 30 seconds via WebSocket

Scenario: Do not show misleading indicators
Given the property has 50 Standard Rooms and 45 are available
When I view the Standard Room listing
Then no scarcity banner is shown (threshold not met)
And no fabricated urgency is displayed

As a Guest visiting from any jurisdiction, I want to control my cookie preferences, So that my privacy is respected in compliance with GDPR and India's IT Act 2000.

Priority: P1 | Points: 5 | Sprint: 4 | Status: Partial

Implementation Status​

A basic cookie consent banner is built that shows on first visit with "Accept All" and "Reject All" buttons. However, granular consent categories (Essential, Analytics, Marketing) are not implemented. Consent is stored in localStorage but not persisted server-side for audit. Third-party scripts (Razorpay, analytics) load regardless of consent choice.

Acceptance Criteria​

Scenario: Granular cookie consent
Given a first-time visitor lands on the booking engine
When the cookie consent banner appears
Then I see categories: Essential (always on, greyed out), Analytics (toggle), Marketing (toggle)
And I can selectively enable/disable Analytics and Marketing cookies
And clicking "Save Preferences" persists my choices and dismisses the banner

Scenario: Consent controls third-party scripts
Given I rejected "Analytics" cookies
When the page loads
Then Google Analytics / tracking scripts are NOT loaded
And only essential cookies (session, language preference, CSRF) are set
And Razorpay scripts load only when I reach the payment step (essential for transaction)

Scenario: Consent is auditable
Given I accepted "Analytics" but rejected "Marketing" cookies on 2026-03-05
When the consent record is stored
Then the server receives: { guestSessionId, consentDate, essential: true, analytics: true, marketing: false, ipCountry: "IN" }
And this record is retained for 3 years per GDPR requirements

US-011-16: Embeddable Widget & Deployment Modes​

As a Hotel Marketing Manager, I want to embed the booking engine on my hotel's website as a widget, iframe, or standalone page, So that guests can book directly without leaving our website.

Priority: P1 | Points: 8 | Sprint: 2 | Status: Built

Implementation Status​

Three deployment modes are fully built. Widget mode provides a floating "Book Now" button that expands into a compact booking form. Iframe mode generates an embeddable <iframe> tag with configurable dimensions and property ID. Standalone mode runs as a full-page application at a dedicated URL. Configuration is managed via src/embed/config.ts with property-specific theming (colors, logo, fonts).

Acceptance Criteria​

Scenario: Embed as widget on hotel website
Given the hotel website includes the widget script: <script src="https://book.hmphotel.com/widget.js" data-property="prop-001" data-theme="dark"></script>
When the hotel homepage loads
Then a floating "Book Now" button appears in the bottom-right corner
And clicking it opens a compact booking form overlay with the hotel's theme colors
And the form submits to the booking engine without navigating away from the hotel site

Scenario: Iframe embedding with custom dimensions
Given the hotel marketing page includes <iframe src="https://book.hmphotel.com/embed?property=prop-001&lang=hi" width="100%" height="700"></iframe>
When the page loads
Then the booking engine renders within the iframe in Hindi
And the iframe communicates booking completion to the parent page via postMessage
And cross-origin policies are respected with proper CSP headers

Scenario: Standalone mode with custom domain
Given the booking engine is deployed at "https://book.tajresidency.com"
When a guest navigates to this URL
Then the full booking engine loads with Hotel Taj Residency branding
And all pages (search, results, details, payment, confirmation) are accessible
And the URL structure supports deep linking (e.g., /search?checkIn=2026-04-10)