V2.0 Delta from V1.0
What changed from V1.0 "Villas Complete" to V2.0 "Events Complete" Timeline: Month 13-18 (6 months after V1.0 launch) Last Updated: 2025-10-25
Executive Summary
V2.0 adds a complete Events & Experiences product line alongside the villa rental platform. This enables event organizers to list activities/experiences, guests to book them (standalone or as packages with villas), and property managers to create villa + event bundles for enhanced revenue.
What V1.0 Had:
- Complete villa booking platform (guests book villas directly)
- Payment processing and dynamic pricing
- Multi-channel distribution (Hostaway, Airbnb, VRBO)
- Owner portal and financial management
- Guest communication and operational tools
What V2.0 Adds:
- Event creation and management (tours, activities, workshops, experiences)
- Ticketing system with capacity tracking
- Event discovery and search
- Villa + event package bundles
- Multi-day and recurring event support
- Event organizer portal and analytics
- Attendee management and check-in system
Domain Changes
NEW Domain: Events & Experiences
Full domain added in V2.0 - manages event lifecycle from creation through ticketing and attendee tracking.
Key Entities Added:
- EventDefinition - Template for events (e.g., "Beach Yoga Class")
- EventOccurrence - Specific instance of event at date/time
- TicketType - Pricing tiers (General, VIP, Early Bird)
- Ticket - Individual sold tickets with QR codes
- Attendee - Person attending event (may or may not be registered User)
- WaitlistEntry - Queue for sold-out events
- EventPackage - Bundles villas + events or multiple events
- EventPackageItem - Links events/villas to packages
See domains/14-events-experiences/events-experiences_specification.md for complete specification.
Enhanced Domain: Bookings
V1.0 Scope:
- Villa-only bookings
- Quote → Hold → Booking workflow
- Guest checkout and payment
- Booking modifications and cancellations
V2.0 Enhancements:
- Package bookings - Single booking can include villa + multiple events
- Event-only bookings - Guests can book events without villa stays
- Unified itinerary - Combined villa and event schedule
- Package discount application - Discounted pricing for bundles
- Coordinated cancellation - Cancel entire package or individual components
Schema Changes:
-- Added to bookings table
ALTER TABLE bookings ADD COLUMN event_package_id UUID REFERENCES event_packages(id);
ALTER TABLE bookings ADD COLUMN booking_type VARCHAR DEFAULT 'villa'; -- villa | event | package
-- Link bookings to multiple tickets
CREATE TABLE booking_tickets (
  booking_id UUID REFERENCES bookings(id),
  ticket_id UUID REFERENCES tickets(id),
  PRIMARY KEY (booking_id, ticket_id)
);
Enhanced Domain: Pricing & Revenue
V1.0 Scope:
- Dynamic villa pricing (seasonal, LOS, lead-time)
- Tax calculation (Avalara integration)
- Revenue splits (owner/manager/platform)
V2.0 Enhancements:
- Tiered event pricing - Multiple ticket types per event
- Early bird pricing - Time-based discounts (valid_from/valid_until)
- Group discounts - Quantity-based pricing (min_quantity, max_quantity)
- Package discounts - Percentage off total when buying bundle
- Event organizer revenue splits - Configurable payout percentages
New Revenue Actors:
- Event organizers (receive payouts for ticket sales)
- Combined revenue for villa + event packages
Enhanced Domain: Availability & Calendars
V1.0 Scope:
- Villa availability tracking
- Cross-channel sync (prevent double-bookings)
- Blocking rules for maintenance/owner use
V2.0 Enhancements:
- Event occurrence scheduling - Time-slot inventory for events
- Venue capacity management - Track seats sold vs. max capacity
- Integrated calendar view - Show both villa bookings AND event occurrences
- Conflict detection - Prevent overlapping events at same venue
- Real-time capacity updates - Atomic seat tracking to prevent overselling
Schema Changes:
-- Event occurrences reference calendar system
CREATE INDEX idx_event_occurrences_time ON event_occurrences(start_at, end_at);
-- Venue conflict prevention
CREATE UNIQUE INDEX idx_no_venue_overlap ON event_occurrences(venue_space_id, start_at, end_at)
  WHERE venue_space_id IS NOT NULL AND status NOT IN ('canceled', 'completed');
Enhanced Domain: Payments & Financials
V1.0 Scope:
- Villa booking payments via Stripe Connect
- Payment capture, refunds, and chargebacks
- Owner payouts and financial reconciliation
V2.0 Enhancements:
- Ticket payment processing - Handle event ticket sales
- Event organizer payouts - Split revenue to organizers
- Package payment handling - Single payment for villa + events
- Partial refunds - Refund event tickets while keeping villa booking
- Multi-payee splits - Revenue to property owner + event organizer(s)
New Payment Flows:
- Standalone event ticket purchase → Pay event organizer
- Package purchase → Split to property owner + event organizers based on components
Enhanced Domain: Content & Media
V1.0 Scope:
- Villa photos and descriptions
- Amenity listings
- Property manager profiles
V2.0 Enhancements:
- Event media galleries - Photos/videos for events
- Event organizer profiles - Bios, photos, credentials
- Package marketing assets - Promotional images for bundles
- Event category taxonomy - tour | activity | class | workshop | dining | wellness | cultural | adventure | entertainment
- Multi-language content - i18n support for event descriptions (future enhancement)
Enhanced Domain: Search & Indexing
V1.0 Scope:
- Villa search by location, dates, amenities
- Price filtering and sorting
- Availability-aware search
V2.0 Enhancements:
- Event discovery - Search events by date, category, location
- Combined search - Find villas + nearby events in one query
- Package search - Search bundled experiences
- Event recommendations - "Suggested events during your stay"
- Capacity-aware filtering - Hide sold-out events (optional)
New Search Indexes:
// Event search index structure
{
  event_definition_id: "uuid",
  name: "Beach Yoga Sunrise Session",
  category: "wellness",
  venue_location: { lat, lng },
  next_occurrence_date: "2025-11-01",
  price_from_cents: 2500,
  organizer_name: "Sarah's Wellness Studio",
  seats_available: 15,
  tags: ["yoga", "beach", "morning", "beginner-friendly"]
}
Enhanced Domain: Analytics & Audit
V1.0 Scope:
- Villa booking metrics and revenue reports
- Property performance analytics
- Owner financial dashboards
V2.0 Enhancements:
- Event performance metrics - Attendance, revenue, sell-through rate
- Ticket sales analytics - Track which ticket types sell best
- Package conversion tracking - Villa-only vs. villa+events booking rates
- Event organizer dashboards - Revenue, attendee demographics
- Cross-domain reports - "Guests who book villas + events spend 40% more"
New Metrics:
- Event sell-through rate (seats_sold / max_capacity)
- Average revenue per event occurrence
- Package attachment rate (% of villa bookings that add events)
- Event organizer performance rankings
- Waitlist conversion rate
Enhanced Domain: Authorization & Access
V1.0 Scope:
- Property manager permissions
- Owner portal access
- Guest user roles
V2.0 Enhancements:
- Event organizer role - New user type with event management permissions
- Granular event permissions - event.create,event.manage,ticket.sell,attendee.view
- Package creator permissions - Require both villa and event access
- Venue access control - Organizers can only book approved venue spaces
New Roles:
-- Event organizer permissions
INSERT INTO permissions (name, description) VALUES
  ('event.create', 'Create new event definitions'),
  ('event.manage', 'Manage events and occurrences'),
  ('event.cancel', 'Cancel events and process refunds'),
  ('ticket.sell', 'Sell tickets and manage attendees'),
  ('ticket.checkin', 'Check in attendees at events'),
  ('attendee.view', 'View attendee details and lists'),
  ('package.create', 'Create villa + event packages');
New User Workflows
Workflow 1: Guest Books Villa + Event Package
V1.0 Experience:
- Search for villas by location and dates
- Select villa and book
- Complete payment
- Receive villa confirmation
V2.0 Enhanced Experience:
- Search for villas by location and dates
- System recommends "Ultimate Relaxation Package" (villa + spa + yoga + dinner)
- Guest selects package and customizes (adds extra yoga session)
- Single checkout for entire package with 15% bundle discount
- Receive unified itinerary with villa details + event tickets
- Get QR codes for each event ticket
- Attend events and check in with QR code scan
New Touchpoints:
- Package discovery and recommendations
- Event ticket generation and delivery
- Unified itinerary PDF
- Event check-in experience
Workflow 2: Event Organizer Creates Recurring Event
V1.0: Not applicable - events don't exist
V2.0 New Workflow:
- Event organizer creates account (or property manager adds organizer)
- Create EventDefinition: "Beach Yoga Sunrise Session"
- Category: wellness
- Duration: 60 minutes
- Capacity: 20 people
- Event type: recurring (every Tuesday + Thursday, 7am-8am)
 
- Define TicketTypes:
- General Admission: $25
- Early Bird (30 days advance): $20
- 5-class Pack: $100 ($20/class)
 
- System auto-generates EventOccurrences for next 90 days
- Set cancellation policy: "Full refund up to 24 hours before"
- Publish event → appears in search results
- Guests discover and book → organizer receives notifications
- After each event: organizer checks in attendees via QR scan
- Weekly payout to organizer's bank account
System Actions:
- Auto-generate recurring occurrences
- Track capacity in real-time (prevent overselling)
- Process payments and revenue splits
- Send event reminders 24 hours before
- Generate attendance reports
Workflow 3: Join Waitlist for Sold-Out Event
V1.0: Not applicable
V2.0 New Workflow:
- Guest attempts to book sold-out sunset cruise
- System offers: "Event sold out. Join waitlist?"
- Guest enters attendee details and quantity (2 tickets)
- Receives email: "You're #3 on the waitlist for Sunset Cruise"
- Another guest cancels 2 tickets → capacity opens
- System auto-notifies waitlist guest: "2 tickets available! Reserve within 24 hours"
- Guest clicks link and completes purchase
- Waitlist entry marked 'converted' → tickets issued
Business Logic:
- FIFO queue management
- 24-hour purchase window after notification
- Auto-advance to next person if expired
- Quantity matching (only notify if enough seats available)
Workflow 4: Property Manager Creates Package
V1.0: Not applicable
V2.0 New Workflow:
- Property manager creates EventPackage: "Ultimate Wellness Retreat"
- Add package items:
- Villa stay (5 nights) at "Oceanview Villa"
- 3x Beach Yoga sessions
- 1x Private chef dinner
- 1x Spa day
 
- Calculate total: $2,500 (sum of individual components)
- Set package discount: 15% off → Final price $2,125
- Define valid dates: Available May 1 - September 30
- Publish package → appears as featured bundle
- Guest books package:
- Creates 1 Booking (villa stay)
- Creates 5 Tickets (3 yoga + 1 dinner + 1 spa)
- Links all via package_id
- Applies discount to total
 
- Guest receives unified confirmation with full itinerary
Revenue Split:
- Villa owner: $1,500 (5 nights × $300/night - discount)
- Yoga organizer: $60 (3 sessions × $25 - discount)
- Chef: $170 (1 dinner × $200 - discount)
- Spa: $255 (1 spa day × $300 - discount)
- Platform fee: 10% of total
Database Changes
New Tables (8 total)
-- Event Definitions
CREATE TABLE event_definitions (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  org_id UUID NOT NULL REFERENCES organizations(id),
  account_id UUID NOT NULL REFERENCES accounts(id),
  name VARCHAR(255) NOT NULL,
  slug VARCHAR(255) NOT NULL,
  category VARCHAR(50) NOT NULL, -- tour | activity | class | workshop | dining | wellness | cultural | adventure | entertainment | other
  event_type VARCHAR(50) NOT NULL, -- one_time | recurring | multi_day
  duration_minutes INTEGER NOT NULL,
  venue_type VARCHAR(50) NOT NULL, -- on_property | off_property | virtual | mobile
  venue_space_id UUID REFERENCES spaces(id),
  venue_name VARCHAR(255),
  venue_address JSONB,
  organizer_name VARCHAR(255),
  organizer_contact JSONB,
  max_capacity INTEGER,
  min_capacity INTEGER DEFAULT 1,
  status VARCHAR(50) DEFAULT 'draft', -- draft | active | paused | archived
  settings JSONB DEFAULT '{}',
  created_at TIMESTAMPTZ DEFAULT now(),
  updated_at TIMESTAMPTZ DEFAULT now(),
  UNIQUE(org_id, slug)
);
-- Event Occurrences
CREATE TABLE event_occurrences (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  org_id UUID NOT NULL REFERENCES organizations(id),
  account_id UUID NOT NULL REFERENCES accounts(id),
  event_definition_id UUID NOT NULL REFERENCES event_definitions(id),
  occurrence_name VARCHAR(255),
  start_at TIMESTAMPTZ NOT NULL,
  end_at TIMESTAMPTZ NOT NULL,
  timezone VARCHAR(100) NOT NULL,
  capacity_override INTEGER,
  status VARCHAR(50) DEFAULT 'scheduled', -- scheduled | confirmed | in_progress | completed | canceled
  cancellation_reason TEXT,
  canceled_at TIMESTAMPTZ,
  seats_sold INTEGER DEFAULT 0,
  waitlist_count INTEGER DEFAULT 0,
  settings JSONB DEFAULT '{}',
  created_at TIMESTAMPTZ DEFAULT now(),
  updated_at TIMESTAMPTZ DEFAULT now(),
  CHECK (end_at > start_at),
  CHECK (seats_sold >= 0)
);
-- Ticket Types
CREATE TABLE ticket_types (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  org_id UUID NOT NULL REFERENCES organizations(id),
  account_id UUID NOT NULL REFERENCES accounts(id),
  event_definition_id UUID NOT NULL REFERENCES event_definitions(id),
  name VARCHAR(255) NOT NULL,
  description TEXT,
  tier VARCHAR(50) NOT NULL, -- general | vip | early_bird | group | child | senior | student | member
  price_cents INTEGER NOT NULL,
  currency CHAR(3) DEFAULT 'USD',
  quantity_available INTEGER,
  quantity_sold INTEGER DEFAULT 0,
  valid_from TIMESTAMPTZ,
  valid_until TIMESTAMPTZ,
  min_quantity INTEGER DEFAULT 1,
  max_quantity INTEGER DEFAULT 10,
  status VARCHAR(50) DEFAULT 'active', -- active | sold_out | expired | disabled
  settings JSONB DEFAULT '{}',
  created_at TIMESTAMPTZ DEFAULT now(),
  updated_at TIMESTAMPTZ DEFAULT now(),
  CHECK (price_cents >= 0),
  CHECK (quantity_sold <= quantity_available)
);
-- Tickets
CREATE TABLE tickets (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  org_id UUID NOT NULL REFERENCES organizations(id),
  account_id UUID NOT NULL REFERENCES accounts(id),
  event_occurrence_id UUID NOT NULL REFERENCES event_occurrences(id),
  ticket_type_id UUID NOT NULL REFERENCES ticket_types(id),
  attendee_id UUID NOT NULL REFERENCES attendees(id),
  booking_id UUID REFERENCES bookings(id),
  confirmation_code VARCHAR(50) UNIQUE NOT NULL,
  qr_code_data TEXT UNIQUE NOT NULL,
  price_paid_cents INTEGER NOT NULL,
  currency CHAR(3) DEFAULT 'USD',
  status VARCHAR(50) DEFAULT 'reserved', -- reserved | confirmed | checked_in | canceled | refunded
  reserved_at TIMESTAMPTZ DEFAULT now(),
  confirmed_at TIMESTAMPTZ,
  checked_in_at TIMESTAMPTZ,
  canceled_at TIMESTAMPTZ,
  refund_amount_cents INTEGER DEFAULT 0,
  settings JSONB DEFAULT '{}',
  created_at TIMESTAMPTZ DEFAULT now(),
  updated_at TIMESTAMPTZ DEFAULT now()
);
-- Attendees
CREATE TABLE attendees (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  org_id UUID NOT NULL REFERENCES organizations(id),
  user_id UUID REFERENCES users(id),
  email VARCHAR(255) NOT NULL,
  given_name VARCHAR(255) NOT NULL,
  family_name VARCHAR(255),
  phone VARCHAR(50),
  emergency_contact JSONB,
  dietary_restrictions TEXT[],
  accessibility_needs TEXT[],
  notes TEXT,
  created_at TIMESTAMPTZ DEFAULT now(),
  updated_at TIMESTAMPTZ DEFAULT now()
);
-- Waitlist Entries
CREATE TABLE waitlist_entries (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  org_id UUID NOT NULL REFERENCES organizations(id),
  event_occurrence_id UUID NOT NULL REFERENCES event_occurrences(id),
  attendee_id UUID NOT NULL REFERENCES attendees(id),
  position INTEGER NOT NULL,
  quantity_requested INTEGER DEFAULT 1,
  ticket_type_id UUID REFERENCES ticket_types(id),
  status VARCHAR(50) DEFAULT 'waiting', -- waiting | notified | converted | expired | canceled
  notified_at TIMESTAMPTZ,
  expires_at TIMESTAMPTZ,
  converted_ticket_id UUID REFERENCES tickets(id),
  created_at TIMESTAMPTZ DEFAULT now(),
  updated_at TIMESTAMPTZ DEFAULT now(),
  UNIQUE(event_occurrence_id, attendee_id)
);
-- Event Packages
CREATE TABLE event_packages (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  org_id UUID NOT NULL REFERENCES organizations(id),
  account_id UUID NOT NULL REFERENCES accounts(id),
  name VARCHAR(255) NOT NULL,
  slug VARCHAR(255) NOT NULL,
  package_type VARCHAR(50) NOT NULL, -- villa_event | multi_event | experience_bundle
  description TEXT,
  base_price_cents INTEGER,
  currency CHAR(3) DEFAULT 'USD',
  discount_percent DECIMAL(5,2) DEFAULT 0,
  status VARCHAR(50) DEFAULT 'draft', -- draft | active | paused | archived
  valid_from DATE,
  valid_until DATE,
  settings JSONB DEFAULT '{}',
  created_at TIMESTAMPTZ DEFAULT now(),
  updated_at TIMESTAMPTZ DEFAULT now(),
  UNIQUE(org_id, slug)
);
-- Event Package Items
CREATE TABLE event_package_items (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  package_id UUID NOT NULL REFERENCES event_packages(id) ON DELETE CASCADE,
  item_type VARCHAR(50) NOT NULL, -- event | villa
  event_definition_id UUID REFERENCES event_definitions(id),
  space_id UUID REFERENCES spaces(id),
  quantity INTEGER DEFAULT 1,
  is_required BOOLEAN DEFAULT true,
  is_customizable BOOLEAN DEFAULT false,
  position INTEGER DEFAULT 0,
  created_at TIMESTAMPTZ DEFAULT now(),
  updated_at TIMESTAMPTZ DEFAULT now(),
  CHECK (
    (item_type = 'event' AND event_definition_id IS NOT NULL AND space_id IS NULL) OR
    (item_type = 'villa' AND event_definition_id IS NULL AND space_id IS NOT NULL)
  )
);
Modified Tables
-- Add event package reference to bookings
ALTER TABLE bookings ADD COLUMN event_package_id UUID REFERENCES event_packages(id);
ALTER TABLE bookings ADD COLUMN booking_type VARCHAR(50) DEFAULT 'villa'; -- villa | event | package
-- Link tickets to bookings (many-to-many for packages)
CREATE TABLE booking_tickets (
  booking_id UUID NOT NULL REFERENCES bookings(id) ON DELETE CASCADE,
  ticket_id UUID NOT NULL REFERENCES tickets(id) ON DELETE CASCADE,
  created_at TIMESTAMPTZ DEFAULT now(),
  PRIMARY KEY (booking_id, ticket_id)
);
Critical Indexes
-- Event search and filtering
CREATE INDEX idx_event_definitions_org_account ON event_definitions(org_id, account_id);
CREATE INDEX idx_event_definitions_status ON event_definitions(status) WHERE status = 'active';
CREATE INDEX idx_event_definitions_category ON event_definitions(category);
CREATE INDEX idx_event_definitions_slug ON event_definitions(org_id, slug);
-- Occurrence time-based queries
CREATE INDEX idx_event_occurrences_definition ON event_occurrences(event_definition_id);
CREATE INDEX idx_event_occurrences_time ON event_occurrences(start_at, end_at);
CREATE INDEX idx_event_occurrences_status ON event_occurrences(status);
CREATE INDEX idx_event_occurrences_org_time ON event_occurrences(org_id, start_at);
-- Ticket management
CREATE INDEX idx_tickets_occurrence ON tickets(event_occurrence_id);
CREATE INDEX idx_tickets_attendee ON tickets(attendee_id);
CREATE INDEX idx_tickets_booking ON tickets(booking_id) WHERE booking_id IS NOT NULL;
CREATE INDEX idx_tickets_confirmation ON tickets(confirmation_code);
CREATE INDEX idx_tickets_status ON tickets(status);
-- Attendee lookups
CREATE INDEX idx_attendees_email ON attendees(email);
CREATE INDEX idx_attendees_user ON attendees(user_id) WHERE user_id IS NOT NULL;
CREATE INDEX idx_attendees_org ON attendees(org_id);
-- Waitlist processing
CREATE INDEX idx_waitlist_occurrence_position ON waitlist_entries(event_occurrence_id, position);
CREATE INDEX idx_waitlist_attendee ON waitlist_entries(attendee_id);
CREATE INDEX idx_waitlist_status ON waitlist_entries(status) WHERE status IN ('waiting', 'notified');
-- Package queries
CREATE INDEX idx_event_packages_org_account ON event_packages(org_id, account_id);
CREATE INDEX idx_event_packages_status ON event_packages(status) WHERE status = 'active';
CREATE INDEX idx_package_items_package ON event_package_items(package_id);
CREATE INDEX idx_package_items_event ON event_package_items(event_definition_id) WHERE event_definition_id IS NOT NULL;
CREATE INDEX idx_package_items_space ON event_package_items(space_id) WHERE space_id IS NOT NULL;
API Changes
New API Endpoints
Event Management:
POST   /api/v2/events                    - Create event definition
GET    /api/v2/events                    - List events (with filters)
GET    /api/v2/events/:id                - Get event details
PATCH  /api/v2/events/:id                - Update event
DELETE /api/v2/events/:id                - Archive event
POST   /api/v2/events/:id/occurrences    - Schedule occurrence
GET    /api/v2/events/:id/occurrences    - List occurrences
PATCH  /api/v2/occurrences/:id           - Update occurrence
POST   /api/v2/occurrences/:id/cancel    - Cancel occurrence
Ticketing:
POST   /api/v2/events/:id/ticket-types   - Create ticket type
GET    /api/v2/events/:id/ticket-types   - List ticket types
PATCH  /api/v2/ticket-types/:id          - Update pricing/inventory
POST   /api/v2/tickets/purchase           - Buy tickets (creates reservation)
POST   /api/v2/tickets/:id/confirm        - Confirm after payment
POST   /api/v2/tickets/:id/cancel         - Cancel and refund
POST   /api/v2/tickets/:id/checkin        - Check in attendee
GET    /api/v2/tickets/:confirmation      - Retrieve by confirmation code
Waitlist:
POST   /api/v2/occurrences/:id/waitlist  - Join waitlist
GET    /api/v2/waitlist/:id               - Check position
DELETE /api/v2/waitlist/:id               - Leave waitlist
POST   /api/v2/waitlist/:id/notify        - Send availability notification (internal)
Packages:
POST   /api/v2/packages                   - Create package
GET    /api/v2/packages                   - List packages
GET    /api/v2/packages/:id               - Get package details
PATCH  /api/v2/packages/:id               - Update package
POST   /api/v2/packages/:id/book          - Book package (villa + events)
Event Search:
GET    /api/v2/search/events              - Search events
  ?location=lat,lng&radius=25km
  &category=wellness,dining
  &date_from=2025-11-01&date_to=2025-11-07
  &price_max=5000
  &seats_min=2
GET    /api/v2/search/packages            - Search villa+event packages
GET    /api/v2/events/:id/recommendations - Get similar events
Organizer Portal:
GET    /api/v2/organizer/events           - My events
GET    /api/v2/organizer/analytics        - Event performance metrics
GET    /api/v2/organizer/attendees        - Attendee lists
GET    /api/v2/organizer/revenue          - Revenue reports
GET    /api/v2/organizer/payouts          - Payout history
Enhanced Endpoints
Bookings:
POST   /api/v1/bookings                   - Enhanced to support event packages
  {
    "booking_type": "package",
    "event_package_id": "uuid",
    "check_in": "2025-11-01",
    "check_out": "2025-11-07",
    "selected_events": [
      {"event_definition_id": "uuid", "occurrence_id": "uuid", "quantity": 2},
      {"event_definition_id": "uuid", "occurrence_id": "uuid", "quantity": 2}
    ]
  }
Search:
GET    /api/v1/search/spaces              - Enhanced with nearby events
  Response now includes:
  {
    "spaces": [...],
    "nearby_events": [...]  // NEW in V2.0
  }
Integration Points
With V1.0 Systems
Payment Processing:
- Event ticket sales use existing Stripe Connect integration
- Revenue splits extended to handle event organizers
- Refund workflows support partial refunds (cancel event, keep villa)
Availability System:
- Event occurrences integrate with calendar blocking
- Real-time capacity tracking prevents overselling
- Shared venue spaces show availability across villas and events
Content Management:
- Event photos/videos use existing media upload system
- Same CDN and image optimization pipelines
- Content moderation applies to event listings
User Authentication:
- Event organizers authenticate via same Google SSO
- Attendees can optionally create user accounts
- Permission model extends to event-specific roles
Search Infrastructure:
- Events indexed in same Elasticsearch cluster
- Combined villa + event queries use unified search API
- Same ranking and relevance algorithms
Analytics Platform:
- Event metrics feed into existing BI dashboards
- Cross-domain reports combine villa and event data
- Same audit logging and GDPR compliance
Migration Strategy
Phase 1: Foundation (Months 13-14)
Week 1-2: Schema Migration
- Create 8 new tables (events, occurrences, tickets, etc.)
- Add indexes and constraints
- Deploy to staging environment
- Run performance tests with simulated data
Week 3-4: Core Event APIs
- Implement EventDefinition CRUD
- EventOccurrence scheduling (one-time and recurring)
- Basic TicketType creation
- Unit tests for all endpoints
Week 5-6: Ticketing System
- Ticket purchase flow (reserve → confirm)
- QR code generation
- Attendee record creation
- Capacity enforcement (atomic locks)
Week 7-8: Integration Testing
- End-to-end event creation and booking
- Payment integration tests
- Load testing (concurrent ticket purchases)
- Beta launch with 5 event organizers
Phase 2: Packages & Discovery (Months 15-16)
Week 1-2: Package System
- EventPackage and EventPackageItem tables
- Package creation API
- Discount calculation logic
- Package booking workflow
Week 3-4: Event Search
- Elasticsearch index for events
- Search API with filters (date, category, location)
- Recommendation engine
- Featured events
Week 5-6: Waitlist Management
- Waitlist entry creation
- Notification system (email + SMS)
- Auto-conversion on availability
- Queue position tracking
Week 7-8: Property Manager Tools
- Package builder UI
- Villa + event bundle creation
- Performance analytics dashboard
- Public launch to all users
Phase 3: Optimization & Scale (Months 17-18)
Week 1-2: Mobile Check-in
- Mobile app for organizers
- QR code scanning
- Offline check-in mode
- Attendee list management
Week 3-4: Advanced Analytics
- Event performance dashboards
- Revenue forecasting
- Organizer leaderboards
- Guest behavior insights
Week 5-6: Multi-language Support
- i18n for event content
- Currency conversion
- Localized search
- Regional event categories
Week 7-8: Scale & Performance
- Database query optimization
- Cache warming for popular events
- CDN for event images
- Load testing (10,000 concurrent users)
Testing Strategy
Unit Tests
- All entity validations (capacity checks, date constraints)
- Business rule enforcement (no double-booking, waitlist FIFO)
- Price calculation logic (discounts, splits)
- QR code generation uniqueness
Integration Tests
- Complete booking flows (event-only, package)
- Payment processing and refunds
- Cross-domain coordination (booking + tickets)
- Search relevance and filtering
Performance Tests
- Concurrent ticket purchases (race conditions)
- 1,000 tickets sold in 60 seconds (capacity locks)
- Search response time <500ms for 10k events
- Package booking with 5+ events <2 seconds
User Acceptance Tests
- Event organizer creates recurring event
- Guest books villa + 3 events as package
- Sold-out event → waitlist → conversion
- Event cancellation → refund processing
- Check-in via QR code scan
Rollout Plan
Beta Phase (Month 13)
- Invite 10 trusted event organizers
- Create 50+ test events
- Internal team books events
- Collect feedback and iterate
Limited Release (Month 14)
- Open to 50 event organizers
- Enable package creation for all property managers
- Monitor system performance
- Fix bugs and UX issues
Public Launch (Month 15)
- Announce Events & Experiences publicly
- Marketing campaign: "Now with Events!"
- Onboard 100+ event organizers
- Featured event promotions
Scale Phase (Months 16-18)
- Target 1,000+ events listed
- 50+ event organizers
- 5,000+ event bookings per month
- 30%+ villa guests also book events
Success Metrics
Business Metrics
- 1,000+ events listed by Month 18
- 50+ active event organizers by Month 18
- 5,000+ event bookings/month by Month 18
- 30%+ villa guests book events (attachment rate)
- 20% increase in average booking value (via packages)
- 15%+ revenue from event tickets by Month 18
Technical Metrics
- 99.9% uptime for event booking system
- <1 second event search response time (p95)
- Zero oversold events (capacity enforcement)
- 99%+ ticket delivery success (QR code generation)
- <500ms ticket purchase completion (p95)
- Real-time capacity updates (<1 second sync)
User Experience Metrics
- 90%+ event organizer satisfaction
- 85%+ guest satisfaction with event bookings
- <2% event cancellation rate (by organizers)
- 80%+ waitlist conversion rate
- 95%+ successful check-ins (QR code scans)
Risks & Mitigation
Risk 1: Capacity Overselling
Scenario: Race condition causes 2 users to buy last ticket simultaneously
Mitigation:
- Database-level row locking on event_occurrences
- Atomic increment/decrement of seats_sold
- Pre-purchase capacity check + post-purchase validation
- Rollback and notify user if oversold detected
Risk 2: Event Organizer Onboarding Friction
Scenario: Organizers find platform too complex, abandon setup
Mitigation:
- Guided onboarding wizard (5 steps to first event)
- Pre-filled templates for common event types
- Video tutorials and documentation
- Dedicated support for first 100 organizers
Risk 3: Package Availability Conflicts
Scenario: Villa available but all events sold out → package can't be booked
Mitigation:
- Real-time availability check before showing package
- "Customize package" option (swap events)
- Suggest alternative dates when package available
- Notify property manager of package failures
Risk 4: Payment Split Errors
Scenario: Revenue incorrectly split between property owner and event organizers
Mitigation:
- Comprehensive split calculation tests
- Audit trail for every split decision
- Reconciliation reports (daily)
- Manual review for packages >$5,000
Risk 5: QR Code Security
Scenario: QR codes leaked, counterfeit tickets
Mitigation:
- Signed QR codes with HMAC
- One-time use enforcement (checked_in_at timestamp)
- Offline check-in uses pre-downloaded attendee list
- Alert on duplicate scan attempts
Future V2.x Enhancements
V2.1: Advanced Ticketing (Months 19-21)
- Multi-session events (courses, workshops)
- Event series and memberships
- Loyalty points for repeat attendees
- Gift vouchers and promotional codes
- Dynamic pricing based on demand
V2.2: Organizer Tools (Months 22-24)
- Advanced revenue analytics
- Attendee communication tools (email broadcasts)
- Automated event reminders (SMS + email)
- Post-event feedback collection
- CRM integration (Mailchimp, HubSpot)
V2.3: Enterprise Features (Months 25-27)
- Corporate event management
- Private event bookings
- Multi-day conference support
- Sponsorship management
- Badge printing integration
Related Documents
- V1.0 Product Specification - What came before V2.0
- V2.0 Product Specification - Full V2.0 vision
- V2.0 Data Model - Complete event schemas
- Events & Experiences Domain Spec - Detailed domain design
- V3.0 Product Specification - What comes next
- Roadmap - Full product timeline
Document Status: Vision Last Updated: 2025-10-25 Version: 1.0 Approvers: Product, Engineering, Operations