EP-004: Guest Management
Business Objective
Guest data is the most valuable asset in hospitality after the physical property. A 360-degree guest profile enables personalized service (remembering a returning guest's pillow preference), targeted marketing (birthday offers), and revenue optimization (understanding lifetime guest value). In the Indian regulatory context, hotels must handle Aadhaar data under DPDP Act 2023 compliance, manage foreign guest C-Form submissions to FRRO, and support GDPR for international guests. Guest deduplication prevents fragmented profiles that degrade service quality. This epic ensures that every guest interaction across reservations, front desk, F&B, and spa contributes to a unified guest record.
Audience
- Primary: Front Desk Agent (guest registration, ID capture), Reservations Agent (guest lookup, profile creation)
- Secondary: CRM Manager (guest segmentation, campaigns), Manager (VIP handling, spend analysis)
- Tertiary: Compliance Officer (GDPR/DPDP requests), Guest (data portability rights)
Scope
In Scope
- Guest profile CRUD (title, name, email, phone, DOB, anniversary, gender, nationality, language, guest type)
- 360-degree guest view (profile + stay history + spend + preferences + communications)
- Identity document management (6 types: Passport, Aadhaar, Driving License, Voter ID, PAN Card, National ID) with verification status, issue/expiry dates, document URL
- Guest addresses (home, work, billing -- multiple per guest with primary flag)
- Preference management across 5 categories (ROOM, FOOD, SERVICE, COMMUNICATION, ACCESSIBILITY) with key-value pairs, bulk update, common preference catalog
- VIP level classification (0=None, 1=VIP, 2=VVIP, 3=Celebrity)
- Guest search with filters (name, email, phone, property, fuzzy matching)
- Guest profile merge/deduplication (merge duplicate profiles into primary, reassign linked records)
- Stay history and spend tracking (totalStays, totalNights, totalRevenue, lastStayDate on guest record)
- Communication log (email, SMS, WhatsApp, push -- with status tracking: sent, delivered, opened, clicked)
- Guest type segmentation (INDIVIDUAL, CORPORATE, TRAVEL_AGENT, GOVERNMENT, AIRLINE_CREW)
- Company/corporate guest linking (companyId FK)
- Loyalty member linking (loyaltyMemberId FK)
- GDPR Article 17: Right to Erasure (anonymize PII)
- GDPR Article 20: Right to Data Portability (export all guest data as JSON)
- DPDP Act 2023 compliance: Data principal rights requests (create, list, get, update status), DPA template generation
- Consent management: Record grant/revoke consent actions, view consent history per guest
- Document upload via S3 pre-signed URLs for ID scans
- Guest alerts (important notes shown to staff at check-in)
Out of Scope
- Loyalty program management (point accrual, redemption, tiers) -- covered in EP-011
- Marketing campaigns and segmentation -- covered in EP-011
- Guest-facing mobile app self-service -- covered in EP-010
Current Implementation Status
- Backend (guest-service): Fully built.
GuestsControllerwith CRUD, search, merge, 360 view, history, identity management, address management.PreferencesControllerwith CRUD, bulk update, category filtering, common preference catalog.GdprControllerwith erasure and export.DpdpControllerwith request workflow (create, list, get, update status, DPA template).ConsentControllerwith record and history.UploadsControllerwith S3 pre-signed URL generation. All write operations have@Auditdecorator. - Dashboard: CRM > Guests page with 360-degree view, search, guest list. Guest detail page with tabs: Profile, Stays, Preferences, Identity Documents, Communications.
- Prisma Models: Guest (with totalStays/totalNights/totalRevenue/lastStayDate), GuestIdentity (6 ID types), GuestAddress (4 address types), GuestPreference (5 categories), GuestCommunication (4 channels with full status tracking).
Gap Analysis
- Guest Document Upload -- Encryption at Rest:
UploadsControllergenerates S3 pre-signed URLs andGuestIdentity.documentUrlstores the path. However, S3 bucket encryption configuration (SSE-S3 or SSE-KMS) is not verified. Aadhaar scans require AES-256 encryption at rest per UIDAI guidelines. Impact: High -- compliance risk. - Automated Dedup Suggestions:
POST /guests/mergeexists for manual merge (operator selects primary and secondary profiles). No automated duplicate detection (fuzzy matching on name + phone + email to surface probable duplicates). Impact: Medium -- hotels with 10,000+ guest records will accumulate duplicates over time. - Communication Log Aggregation:
GuestCommunicationmodel exists with full status tracking. However, communications from different services (notification-service emails, WhatsApp messages, POS receipts) are not aggregated into this model. The 360 view's communications tab may be incomplete. Impact: Medium -- CRM managers can't see the full communication picture. - Guest Spend Analysis Dashboard: Guest model tracks totalRevenue and totalStays. However, a breakdown by department (room revenue vs. F&B vs. spa vs. minibar) is not available. Revenue manager needs this for identifying high-value guests. Impact: Medium.
- Aadhaar Masking: When displaying Aadhaar numbers in the UI or exports, only the last 4 digits should be visible (UIDAI regulation). This masking is not enforced at the API level. Impact: High -- compliance risk for Indian properties.
- Guest Photo: No guest photo field on the profile. Some luxury hotels photograph guests at check-in for recognition. Impact: Low -- not a priority for most segments.
User Stories
| Story ID | Title | Priority | Points | Status | Sprint |
|---|---|---|---|---|---|
| US-004-001 | Guest Profile CRUD | P0 | 5 | Built | 2 |
| US-004-002 | Guest Search (Name, Phone, Email) | P0 | 5 | Built | 2 |
| US-004-003 | 360-Degree Guest View | P0 | 8 | Built | 3 |
| US-004-004 | Identity Document Management | P0 | 5 | Built | 3 |
| US-004-005 | Guest Preference Management | P0 | 5 | Built | 3 |
| US-004-006 | VIP Level Classification | P0 | 2 | Built | 2 |
| US-004-007 | Guest Address Management | P1 | 3 | Built | 3 |
| US-004-008 | Guest Profile Merge (Deduplication) | P1 | 8 | Built | 4 |
| US-004-009 | Guest Stay History & Spend Tracking | P1 | 5 | Built | 4 |
| US-004-010 | GDPR Right to Erasure | P1 | 5 | Built | 5 |
| US-004-011 | GDPR Data Portability Export | P1 | 3 | Built | 5 |
| US-004-012 | DPDP Act Compliance (Data Principal Requests) | P1 | 8 | Built | 5 |
| US-004-013 | Consent Management | P1 | 5 | Built | 5 |
| US-004-014 | Automated Duplicate Detection & Suggestions | P2 | 8 | Not Started | 10 |
| US-004-015 | Guest Spend Analysis by Department | P2 | 5 | Not Started | 10 |
| US-004-016 | Aadhaar Number Masking & Encryption Verification | P2 | 5 | Partial | 8 |
Dependencies
- EP-001 (Auth): Guest operations require authenticated users with appropriate roles (FRONT_DESK, RESERVATIONS for create/update; ADMIN for merge/GDPR).
- EP-002 (Property): Guests are scoped to properties (propertyId FK).
- EP-003 (Reservation): Reservations link to guest profiles. Guest history depends on reservation data.
- EP-005 (Front Desk): Check-in captures ID documents and updates guest profile.
- EP-011 (CRM & Loyalty): Loyalty member linking, campaigns depend on guest profiles.
Acceptance Criteria (Epic Level)
- Guest profiles can be created with Indian-specific fields (Aadhaar, PAN, GSTIN for corporate guests)
- 360-degree view aggregates profile, stays, spend, preferences, communications in one endpoint
- 6 identity document types can be stored with verification status and document URL
- Preferences across 5 categories can be set, updated, and retrieved per guest
- Duplicate profiles can be merged with all linked records (reservations, folios) reassigned
- GDPR erasure anonymizes all PII fields irreversibly
- GDPR export returns complete guest data in portable JSON format
- DPDP requests are tracked through a workflow (submitted -> in-progress -> completed)
- Consent grant/revoke actions are logged with timestamps for audit
KPIs / Success Metrics
- Guest profile completeness: > 80% have email + phone + at least 1 ID document
- Duplicate rate: < 2% of total guest records (after automated dedup)
- GDPR/DPDP request response time: < 72 hours (regulatory requirement: 30 days)
- Guest search latency: < 300ms for fuzzy name search across 50,000 records
- 360-view load time: < 1 second for complete guest profile aggregation
- VIP identification at check-in: 100% (VIP flag visible on arrivals board)
Detailed User Stories
US-004-001: Guest Profile CRUD
As a front desk agent, I want to create and update guest profiles with complete demographic information, So that the hotel has accurate guest records for personalized service and regulatory compliance.
Priority: P0 | Points: 5 | Sprint: 2 | Status: Built
Implementation Status
- Backend:
GuestsController--POST /guests(SUPER_ADMIN, ADMIN, MANAGER, FRONT_DESK, RESERVATIONS),GET /properties/:propertyId/guests(paginated),GET /guests/:id,PUT /guests/:id,DELETE /guests/:id(SUPER_ADMIN, ADMIN, MANAGER -- soft delete).@Auditon all write operations. Guest model: title, firstName, lastName, email (unique per property), phone (indexed), secondaryPhone, dateOfBirth, anniversary, gender, nationality, language, vipLevel, guestType, companyId, loyaltyMemberId, notes, alerts, marketingConsent, dataConsent. - Frontend: Guest form with all fields, auto-save on tab-out.
Acceptance Criteria
Scenario: Create a guest profile during reservation
Given the reservations agent is creating a booking and the guest is new
When they create a guest with title "Mr", firstName "Vikram", lastName "Reddy",
email "vikram.reddy@email.com", phone "+91-9876543210", nationality "Indian",
language "en", guestType INDIVIDUAL, marketingConsent true
Then the guest profile is created with a UUID
And totalStays, totalNights, totalRevenue are initialized to 0
And the guest can be linked to the reservation
Scenario: Update guest profile with anniversary date
Given guest "Vikram Reddy" already exists
When the front desk agent adds anniversary date "2018-02-14"
Then the profile is updated and the change is audit-logged
And the CRM can trigger an anniversary greeting on February 14
Scenario: Prevent duplicate email within same property
Given guest "vikram.reddy@email.com" exists for the property
When another agent attempts to create a guest with the same email for the same property
Then the system returns 409 with message "A guest with this email already exists"
And suggests the existing profile for linking
US-004-002: Guest Search (Name, Phone, Email)
As a front desk agent, I want to search for guests by name, phone number, or email, So that I can quickly find returning guests without creating duplicates.
Priority: P0 | Points: 5 | Sprint: 2 | Status: Built
Implementation Status
- Backend:
POST /guests/searchwithSearchGuestsDto. Supports: name (fuzzy, searches firstName + lastName), email (exact or partial), phone (exact or partial), property filter. Pagination. Database indexes on[propertyId, phone]and[propertyId, lastName, firstName]. - Frontend: Search-as-you-type field in reservation form and guest list page.
Acceptance Criteria
Scenario: Search by partial phone number
Given 3 guests have phone numbers starting with "+91-98765"
When the agent searches with phone "98765"
Then 3 matching guests are returned with name, email, phone, VIP level, last stay date
And results are ordered by last stay date (most recent first)
Scenario: Fuzzy search by guest name
Given a guest "Vikram Reddy" exists
When the agent searches "vikram" or "reddy" or "vikram reddy"
Then the guest profile is found in all three search variations
And the search handles case-insensitive matching
Scenario: Search across property for chain-level lookup
Given the agent has MANAGER role with access to multiple properties
When they search without propertyId filter
Then guests from all accessible properties are returned
And the property name is included in results for disambiguation
US-004-003: 360-Degree Guest View
As a front desk agent or CRM manager, I want to see a comprehensive 360-degree view of a guest including their stay history, total spend, preferences, and communications, So that I can provide personalized service and understand the guest's value to the hotel.
Priority: P0 | Points: 8 | Sprint: 3 | Status: Built
Implementation Status
- Backend:
GET /guests/:id/360returns aggregated data: profile (all fields), identities (all documents), addresses, preferences (all categories), stay history (past reservations with room types, dates, amounts), communications (recent interactions), loyalty membership details, total spend breakdown. - Frontend: Guest detail page with tabbed interface showing all 360-view sections.
Acceptance Criteria
Scenario: View 360-degree profile for a returning VIP guest
Given guest "Priya Kapoor" has VIP level 2 (VVIP), 12 stays, INR 4,50,000 lifetime spend
When the front desk agent opens the 360 view for this guest
Then the view displays:
- Profile: name, contact, VIP badge (VVIP), nationality, language
- Stay Summary: 12 stays, 28 total nights, INR 4,50,000 revenue, last stay Dec 2025
- Preferences: Room (high floor, king bed, extra pillows), Food (vegetarian, no onion),
Service (late checkout preferred), Accessibility (none)
- Recent Stays: last 5 reservations with dates, room type, rate, and satisfaction score
- Communications: last 10 messages (confirmation emails, feedback requests)
- Loyalty: Gold tier member, 15,000 points balance
Scenario: 360 view loads within 1 second
Given the guest has 20+ stay records and 50+ communication entries
When the agent opens the 360 view
Then all data loads within 1 second (API response < 800ms)
And lazy loading is used for communication history beyond the first 10 entries
US-004-004: Identity Document Management
As a front desk agent during check-in, I want to record guest identity documents (Aadhaar, Passport, PAN, etc.) with verification status, So that the hotel meets regulatory requirements for guest identification and foreign guest reporting.
Priority: P0 | Points: 5 | Sprint: 3 | Status: Built
Implementation Status
- Backend:
POST /guests/:id/identitieswithAddIdentityDto(idType, idNumber, issueDate, expiryDate, issueCountry, documentUrl, isVerified, isPrimary). Roles: SUPER_ADMIN, ADMIN, MANAGER, FRONT_DESK.@Auditlogged. 6 ID types: PASSPORT, AADHAAR, DRIVING_LICENSE, VOTER_ID, PAN_CARD, NATIONAL_ID. - Frontend: Identity documents tab on guest profile with add/edit forms, document scan upload.
Acceptance Criteria
Scenario: Record Aadhaar during check-in for Indian guest
Given an Indian guest is checking in without an existing ID on file
When the front desk agent adds identity: type AADHAAR, number "XXXX XXXX 1234",
isPrimary true, isVerified true
Then the identity record is created and linked to the guest
And the Aadhaar number is stored (but should be masked in display as "XXXX XXXX 1234")
And the identity appears in the guest's 360 view
Scenario: Record Passport for foreign guest with expiry tracking
Given a foreign guest presents their passport
When the agent adds identity: type PASSPORT, number "A12345678",
issueCountry "United Kingdom", issueDate "2020-05-15", expiryDate "2030-05-14",
isVerified true, isPrimary true
Then the passport details are stored with expiry date for C-Form compliance
And the guest is flagged as a foreign national for FRRO reporting
Scenario: Upload ID scan document
Given the agent wants to upload a scanned copy of the Aadhaar card
When they request a pre-signed URL via POST /uploads/presigned-url
with fileName "aadhaar-scan.jpg", contentType "image/jpeg", folder "guest-documents"
Then a pre-signed S3 URL is returned for direct browser upload
And after upload, the documentUrl is saved on the GuestIdentity record
US-004-005: Guest Preference Management
As a front desk agent or concierge, I want to record and retrieve guest preferences across 5 categories, So that returning guests receive personalized service without having to repeat their requests.
Priority: P0 | Points: 5 | Sprint: 3 | Status: Built
Implementation Status
- Backend:
PreferencesController--GET /guests/:guestId/preferences(all),GET /guests/:guestId/preferences/:category(by category),POST /guests/:guestId/preferences(create/update single),PUT /guests/:guestId/preferences(bulk update),DELETE /guests/:guestId/preferences/:category/:key. 5 categories: ROOM, FOOD, SERVICE, COMMUNICATION, ACCESSIBILITY.GET /preferences/commonreturns catalog of common preference keys and suggested values. - Frontend: Preferences tab on guest detail page with category tabs and key-value editor.
Acceptance Criteria
Scenario: Record room and food preferences for a VIP guest
Given guest "Priya Kapoor" is checking in and mentions preferences
When the agent records:
- ROOM: pillow_type = "Memory Foam", floor_preference = "High Floor", bed_type = "King"
- FOOD: dietary = "Vegetarian", allergies = "Tree Nuts", favorite_drink = "Masala Chai"
- SERVICE: newspaper = "Times of India", wake_up_call = "6:30 AM"
Then 8 preference records are created (or updated if they existed)
And the preferences are visible on the 360-degree view and check-in screen
Scenario: Bulk update preferences
Given the guest has 5 existing preferences
When the agent bulk updates all preferences with 3 modified values
Then the modified preferences are updated and unmentioned preferences are preserved
And each change is audit-logged
Scenario: Retrieve common preference catalog
Given the hotel wants to standardize preference capture
When the agent calls GET /preferences/common
Then a catalog is returned with suggested keys per category:
- ROOM: pillow_type, floor_preference, bed_type, view_preference, temperature
- FOOD: dietary, allergies, cuisine_preference, favorite_drink
- SERVICE: newspaper, wake_up_call, housekeeping_time, turndown_service
- COMMUNICATION: preferred_channel, language
- ACCESSIBILITY: wheelchair, hearing_aid, visual_assistance
US-004-006: VIP Level Classification
As a hotel manager, I want to assign VIP levels to guests (None, VIP, VVIP, Celebrity), So that the front desk and housekeeping provide appropriate attention to high-value guests.
Priority: P0 | Points: 2 | Sprint: 2 | Status: Built
Implementation Status
- Backend:
Guest.vipLevelfield: 0 (None), 1 (VIP), 2 (VVIP), 3 (Celebrity). Updated via PUT /guests/:id. - Frontend: VIP badge on guest cards in arrivals board, check-in screen, guest list.
Acceptance Criteria
Scenario: Set VIP level for a high-value corporate guest
Given guest "Rajesh Malhotra" has 20+ stays and INR 8,00,000 lifetime spend
When the manager sets vipLevel to 2 (VVIP)
Then the guest profile shows a VVIP badge
And arrivals board highlights VVIP arrivals with a gold indicator
And housekeeping receives automatic VIP room preparation instructions
Scenario: VIP alert shown at check-in
Given guest "Rajesh Malhotra" with VIP level 2 and alert "Prefers room 502, complimentary fruit basket"
When the front desk agent opens the check-in screen for this guest
Then the VIP badge and alert text are prominently displayed
And the agent is reminded to arrange the fruit basket before room assignment
US-004-007: Guest Address Management
As a front desk agent, I want to store multiple addresses for a guest (home, work, billing), So that invoices can be addressed correctly and marketing mail reaches the guest.
Priority: P1 | Points: 3 | Sprint: 3 | Status: Built
Implementation Status
- Backend:
POST /guests/:id/addresseswithAddAddressDto(addressType: HOME/WORK/BILLING/OTHER, line1, line2, city, state, country, postalCode, isPrimary). Multiple addresses per guest.@Auditlogged. - Frontend: Address section on guest profile with add/edit capability.
Acceptance Criteria
Scenario: Add corporate billing address for GST invoicing
Given a corporate guest needs invoices addressed to their company
When the agent adds address: type BILLING, line1 "TechCorp Pvt Ltd, Tower A",
city "Gurugram", state "Haryana", postalCode "122001", isPrimary true
Then the billing address is stored and used as the default for invoice generation
And the GST invoice includes this address with the company GSTIN
Scenario: Store home address for a regular guest
Given guest "Vikram Reddy" provides his home address
When the agent adds address: type HOME, line1 "42, MG Road", city "Bengaluru",
state "Karnataka", country "India", postalCode "560001"
Then the address is stored and available for correspondence
US-004-008: Guest Profile Merge (Deduplication)
As a hotel manager, I want to merge duplicate guest profiles into a single primary profile, So that the guest's complete history and preferences are consolidated and service quality improves.
Priority: P1 | Points: 8 | Sprint: 4 | Status: Built
Implementation Status
- Backend:
POST /guests/mergewithMergeGuestsDto(primaryGuestId, secondaryGuestIds array). Reassigns all linked records (reservations, identities, addresses, preferences, communications) from secondary profiles to primary. Deactivates secondary profiles.@Auditlogged. Roles: SUPER_ADMIN, ADMIN, MANAGER. - Gap: No automated duplicate detection. Merge is manual -- operator must identify duplicates and select primary.
Acceptance Criteria
Scenario: Merge two profiles for the same guest
Given "Vikram Reddy" has two profiles:
- Profile A: created during phone booking (email + phone, 3 stays)
- Profile B: created during walk-in (phone only, 2 stays)
When the manager merges Profile B into Profile A (primary)
Then Profile A now shows 5 total stays with combined revenue
And Profile B's reservations are reassigned to Profile A
And Profile B's identity documents and preferences are merged into Profile A
And Profile B is deactivated (soft-deleted)
Scenario: Merge preserves the most complete data
Given Profile A has email but no DOB, Profile B has DOB but no email
When merged into Profile A as primary
Then Profile A retains its email and gains the DOB from Profile B
And a merge audit record is created showing which fields came from which profile
US-004-009: Guest Stay History & Spend Tracking
As a CRM manager, I want to view a guest's complete stay history and cumulative spend, So that I can segment guests by value and reward loyal customers.
Priority: P1 | Points: 5 | Sprint: 4 | Status: Built
Implementation Status
- Backend:
GET /guests/:id/historyreturns past reservations with dates, room type, rate, amount. Guest model fields: totalStays, totalNights, totalRevenue, lastStayDate -- updated on check-out. Included in 360 view. - Gap: No department-level spend breakdown (room vs. F&B vs. spa).
Acceptance Criteria
Scenario: View stay history for a returning guest
Given guest "Priya Kapoor" has stayed 12 times over 3 years
When the CRM manager views the guest's stay history
Then 12 stay records are shown with: check-in/out dates, room type, room number,
rate plan, total amount, and source (direct/OTA)
And a summary shows: 12 stays, 28 nights, INR 4,50,000 lifetime revenue
Scenario: Guest spend updates after checkout
Given guest "Vikram Reddy" has totalRevenue INR 1,00,000 and checks out with folio total INR 25,000
When checkout is processed
Then totalRevenue updates to INR 1,25,000
And totalStays increments by 1
And lastStayDate is set to today
US-004-010: GDPR Right to Erasure
As a hotel admin handling a GDPR erasure request, I want to anonymize all personally identifiable information for a guest, So that the hotel complies with GDPR Article 17 (Right to be Forgotten).
Priority: P1 | Points: 5 | Sprint: 5 | Status: Built
Implementation Status
- Backend:
DELETE /gdpr/guests/:id/erasurewithx-tenant-idheader.GdprService.eraseGuestData()anonymizes: firstName -> "REDACTED", lastName -> "REDACTED", email -> null, phone -> "REDACTED", dateOfBirth -> null, all identity documents removed, all addresses removed. Preserves non-PII for financial records (reservation amounts, dates).@Auditlogged. Roles: SUPER_ADMIN, ADMIN. - Frontend: "Erase Guest Data" button on guest profile (with confirmation dialog explaining irreversibility).
Acceptance Criteria
Scenario: Erase guest data per GDPR request
Given a European guest requests data erasure via email
When the admin processes the erasure via DELETE /gdpr/guests/:id/erasure
Then the guest profile is anonymized:
- firstName: "REDACTED", lastName: "REDACTED"
- email, phone, dateOfBirth, anniversary: nullified
- All identity documents: deleted
- All addresses: deleted
- Preferences: deleted
And financial records (reservation amounts, folio transactions) are preserved
And an audit log records who performed the erasure and when
Scenario: Erasure is irreversible
Given a guest's data has been erased
When any user attempts to view the guest profile
Then the profile shows "REDACTED" for all PII fields
And there is no mechanism to restore the original data
US-004-011: GDPR Data Portability Export
As a hotel admin handling a GDPR portability request, I want to export all data held about a guest in a machine-readable format, So that the guest can transfer their data to another provider per GDPR Article 20.
Priority: P1 | Points: 3 | Sprint: 5 | Status: Built
Implementation Status
- Backend:
GET /gdpr/guests/:id/exportreturns comprehensive JSON with: profile, identities, addresses, preferences, stay history (reservations with dates and amounts), communications, loyalty membership. Roles: SUPER_ADMIN, ADMIN.
Acceptance Criteria
Scenario: Export complete guest data
Given guest "Hans Mueller" (German national) requests his data
When the admin calls GET /gdpr/guests/:id/export
Then a JSON document is returned containing:
- Personal details (name, email, phone, DOB, nationality)
- Identity documents (passport details)
- Addresses (home, billing)
- Preferences (all categories)
- Stay history (dates, room types, amounts for all visits)
- Communications (emails sent, dates, subjects)
And the export is delivered to the guest within the 30-day regulatory window
Scenario: Export excludes internal-only fields
Given the guest record has internal notes and VIP level
When the export is generated
Then internalNotes and vipLevel are excluded from the export
And only guest-facing data is included
US-004-012: DPDP Act Compliance (Data Principal Requests)
As a hotel admin in India, I want to process data principal rights requests under the DPDP Act 2023, So that the hotel complies with Indian data protection law for guest data handling.
Priority: P1 | Points: 8 | Sprint: 5 | Status: Built
Implementation Status
- Backend:
DpdpController--POST /dpdp/requests(create request with x-tenant-id),GET /dpdp/requests(list, filter by guestId, ADMIN only),GET /dpdp/requests/:id,PATCH /dpdp/requests/:id/status(workflow advancement, ADMIN only).GET /dpdp/dpa-templategenerates Data Processing Agreement template.CreateDpdpRequestDtoandUpdateDpdpStatusDto. - Frontend: DPDP request management under Settings > Compliance.
Acceptance Criteria
Scenario: Submit a DPDP data access request
Given an Indian guest requests access to their data under DPDP Act Section 11
When the agent submits a DPDP request with type "DATA_ACCESS", guestId, and details
Then a request record is created with status "SUBMITTED"
And the admin dashboard shows the request in the compliance queue
Scenario: Process a DPDP request through workflow
Given a DPDP request is in "SUBMITTED" status
When the admin updates status to "IN_PROGRESS" with notes "Compiling guest data"
Then the status is updated and the change is audit-logged
And when completed, the admin sets status to "COMPLETED" with the response data
And the total processing time is tracked for regulatory compliance
Scenario: Generate Data Processing Agreement template
Given the hotel needs a DPDP-compliant DPA for a third-party data processor
When the admin calls GET /dpdp/dpa-template
Then a DPA template is returned with clauses aligned to DPDP Act 2023
And placeholders for hotel name, processor name, data categories, and retention periods
US-004-013: Consent Management
As a front desk agent, I want to record whether a guest has granted or revoked consent for marketing and data processing, So that the hotel only contacts guests who have opted in, meeting DPDP Act requirements.
Priority: P1 | Points: 5 | Sprint: 5 | Status: Built
Implementation Status
- Backend:
ConsentController--POST /consentwithRecordConsentDto(records grant or revoke action).GET /consent/:guestIdreturns consent history with timestamps. Guest model hasmarketingConsentanddataConsentboolean fields.@Auditlogged. - Frontend: Consent checkboxes on guest registration form and profile page.
Acceptance Criteria
Scenario: Record marketing consent during check-in
Given a guest is checking in and verbally consents to marketing emails
When the agent records consent: type "MARKETING", action "GRANT",
channel "VERBAL", source "CHECK_IN"
Then a consent log entry is created with timestamp
And the guest's marketingConsent field is set to true
And the guest becomes eligible for marketing campaigns
Scenario: Guest revokes data processing consent
Given a guest previously granted data processing consent
When the guest requests consent revocation
Then the agent records: type "DATA_PROCESSING", action "REVOKE"
And the guest's dataConsent field is set to false
And the consent history shows both the original grant and the revocation with dates
US-004-014: Automated Duplicate Detection & Suggestions
As a front desk agent creating a guest profile, I want the system to automatically detect potential duplicates based on name, phone, and email, So that I can link to an existing profile instead of creating a duplicate.
Priority: P2 | Points: 8 | Sprint: 10 | Status: Not Started
Implementation Status
- Backend: Not implemented. No fuzzy matching or phonetic comparison (Soundex/Metaphone) for duplicate detection.
- Frontend: Not implemented. No duplicate warning during guest creation.
Acceptance Criteria
Scenario: Detect potential duplicate during guest creation
Given a guest "Vikram Reddy" with phone "+91-9876543210" exists
When an agent creates a new guest with name "Vikram Reddi" (slight spelling variation)
and phone "+91-9876543210" (exact match)
Then the system shows a warning: "Potential duplicate found: Vikram Reddy (phone match)"
And the agent can choose to link to the existing profile or create a new one
Scenario: Weekly duplicate report for admin review
Given the property has 15,000 guest records
When the automated dedup job runs (weekly batch)
Then a report is generated with probable duplicate pairs scored by confidence:
- High confidence (same phone + similar name): 12 pairs
- Medium confidence (same email, different name): 5 pairs
And the admin can review and merge from the report
US-004-015: Guest Spend Analysis by Department
As a CRM manager, I want to see a guest's spend broken down by department (room, F&B, spa, minibar, laundry), So that I can identify high-value F&B guests for dining loyalty programs or spa promotion targets.
Priority: P2 | Points: 5 | Sprint: 10 | Status: Not Started
Implementation Status
- Backend: Guest.totalRevenue exists as a single aggregate. Folio transactions have transactionCode (Room, FnB, Laundry, etc.) but no API aggregates spend by department per guest.
- Frontend: Not implemented.
Acceptance Criteria
Scenario: View departmental spend breakdown
Given guest "Priya Kapoor" has INR 4,50,000 lifetime spend
When the CRM manager views the spend analysis
Then the breakdown shows:
- Room Revenue: INR 3,20,000 (71%)
- F&B: INR 85,000 (19%)
- Spa: INR 25,000 (6%)
- Minibar: INR 12,000 (3%)
- Laundry: INR 8,000 (2%)
And a trend chart shows spend per department over the last 12 months
US-004-016: Aadhaar Number Masking & Encryption Verification
As a compliance officer, I want Aadhaar numbers to be masked in all displays and API responses (showing only last 4 digits), So that the hotel complies with UIDAI guidelines for Aadhaar data handling.
Priority: P2 | Points: 5 | Sprint: 8 | Status: Partial
Implementation Status
- Backend: Aadhaar numbers are stored in
GuestIdentity.idNumber. No masking applied at the API response level. S3 bucket for document uploads exists but encryption-at-rest (SSE-KMS) not verified. - Gap: API returns full Aadhaar number. No masking middleware for AADHAAR type identities. Encryption verification needed.
Acceptance Criteria
Scenario: Mask Aadhaar in API responses
Given a guest has Aadhaar number "1234 5678 9012" stored
When any API returns this guest's identity documents
Then the Aadhaar number is displayed as "XXXX XXXX 9012" (last 4 digits only)
And only SUPER_ADMIN role can access the full Aadhaar number
Scenario: Verify encryption at rest for document storage
Given guest identity documents (Aadhaar scans) are stored in S3
When the compliance officer audits the storage configuration
Then S3 bucket has SSE-KMS encryption enabled with a managed key
And CloudTrail logs all access to the guest-documents bucket