Bookings
Bookings represent finalized customer purchases, linking an Offer with a Client and their passengers, plus optional extras (upsells).
Data Model
Section titled “Data Model”Booking├── Offer (the package being booked)├── Client (who is booking)├── Currency (payment currency)├── Passengers (many-to-many via booking_passenger)│ └── is_lead_passenger (pivot field)└── Upsells (optional extras) └── Hotels, Activities, Transfers, Flight UpgradesDatabase Schema
Section titled “Database Schema”Table: bookings
| Column | Type | Description |
|---|---|---|
| id | bigint | Primary key |
| offer_id | bigint | FK to offers (cascade delete) |
| client_id | bigint | FK to clients (cascade delete) |
| booking_reference | varchar(16) | Unique reference (BK-XXXXXXXX) |
| status | varchar | pending / confirmed / cancelled / completed |
| number_of_travelers | smallint | Passenger count (default: 2) |
| total_amount | decimal(10,2) | Booking total (base + extras) |
| base_price | decimal(10,2) | Offer price at booking time (nullable) |
| extras_price | decimal(10,2) | Sum of upsell prices (default: 0) |
| currency_id | bigint | FK to currencies (restrict delete) |
| notes | text | Optional notes |
| booked_at | timestamp | When booking was made |
Indexes:
(status, booked_at)- For status-filtered date queries(client_id, status)- For client booking history
Table: booking_passenger
| Column | Type | Description |
|---|---|---|
| booking_id | bigint | FK to bookings (cascade delete) |
| passenger_id | bigint | FK to passengers (cascade delete) |
| is_lead_passenger | boolean | Lead passenger flag (default: false) |
Constraint: Unique (booking_id, passenger_id)
Table: booking_upsells
Stores selected extras for a booking using a selective FK pattern - only one supplier FK is populated per row (except for flight upgrades which use JSON storage).
| Column | Type | Description |
|---|---|---|
| id | bigint | Primary key |
| booking_id | bigint | FK to bookings (cascade delete) |
| type | varchar(20) | ‘hotel’, ‘activity’, ‘transfer’, ‘flight_upgrade’ |
| supplier_hotel_id | bigint | FK to supplier_hotels (null on delete) |
| supplier_activity_id | bigint | FK to supplier_activities (null on delete) |
| supplier_transfer_id | bigint | FK to supplier_transfers (null on delete) |
| unit_price | decimal(10,2) | Price per unit in EUR at booking time |
| quantity | smallint | Number of units (default: 1) |
| total_price | decimal(10,2) | unit_price × quantity |
| day | smallint | Itinerary day number (nullable) |
| flight_search_params | json | Flight details for upgrades (nullable) |
Selective FK Pattern: The type column determines which FK is populated:
type='hotel'→supplier_hotel_idis set, others nulltype='activity'→supplier_activity_idis set, others nulltype='transfer'→supplier_transfer_idis set, others nulltype='flight_upgrade'→ No FK, usesflight_search_paramsJSON instead
Index: (booking_id, type) - For filtering upsells by type
Status Lifecycle
Section titled “Status Lifecycle”Pending ──┬──► Confirmed ──┬──► Completed │ │ └──► Cancelled ◄─┘Rules:
- Pending can transition to Confirmed or Cancelled
- Confirmed can transition to Completed or Cancelled
- Cancelled and Completed are final states
Source: backend/app/Enums/BookingStatus.php
Booking Reference
Section titled “Booking Reference”Auto-generated on creation with format BK-XXXXXXXX (8 uppercase alphanumeric characters).
// Generation logic in Booking model$reference = 'BK-' . strtoupper(substr(bin2hex(random_bytes(4)), 0, 8));Source: backend/app/Models/Booking.php
Relationships
Section titled “Relationships”$booking->offer; // BelongsTo Offer$booking->client; // BelongsTo Client$booking->currency; // BelongsTo Currency$booking->passengers; // BelongsToMany Passenger (with pivot)$booking->leadPassenger(); // Single Passenger or null$booking->upsells; // HasMany BookingUpsellStatus Methods
Section titled “Status Methods”$booking->canBeCancelled(); // true if status allows$booking->canBeConfirmed(); // true if Pending$booking->canBeCompleted(); // true if ConfirmedFilament Admin
Section titled “Filament Admin”Resource: backend/app/Filament/Resources/Bookings/BookingResource.php
| Page | Description |
|---|---|
| List | View all bookings with filters |
| Create | New booking with offer/client/passenger selection |
| View | Booking details infolist |
| Edit | Status changes only |
Permissions: ViewBooking, CreateBooking, UpdateBooking, DeleteBooking
Creating a Booking
Section titled “Creating a Booking”- Select an active Offer
- Select a Client
- Attach passengers from client’s saved passengers
- Designate one lead passenger
- Select optional extras (hotels, activities, transfers)
- Review pricing (base + extras = total)
Edit Restrictions
Section titled “Edit Restrictions”Only the status field can be modified after creation, following the allowed transitions.
Upsells
Section titled “Upsells”Bookings can include optional extras (upsells) from the tour itinerary. These are fetched and priced by BookingUpsellPriceService.
Upsell Types
Section titled “Upsell Types”| Type | Pricing | Description |
|---|---|---|
| Hotel | Flat per room | Price difference between guaranteed and upgrade hotel |
| Activity | Per person | Unit price × number of travelers |
| Transfer | Flat per trip | Single price for the transfer |
| Flight Upgrade | Per person | Business class upgrade cost × number of travelers |
Flight Upgrade Data
Section titled “Flight Upgrade Data”Flight upgrades store selection data in flight_search_params JSON for later verification:
{ "outbound": { "departure_date": "2026-02-15", "departure_time": "09:10", "arrival_time": "15:15", "departure_airport": "MAD", "arrival_airport": "NBO", "flight_numbers": ["EK123", "EK456"], "airlines": ["EK"], "stops": 1, "stopover_airports": ["DXB"] }, "inbound": { "departure_date": "2026-02-22", "departure_time": "08:00", "arrival_time": "14:30", "departure_airport": "NBO", "arrival_airport": "MAD", "flight_numbers": ["EK789"], "airlines": ["EK"], "stops": 0, "stopover_airports": [] }, "apihubflowid": "4844a05b-3ce2-45b1-b907-1669e574e94c"}This data enables:
- Re-searching to verify flight availability
- Historical reference for flight details
- Tracking via
apihubflowid(Aerticket API Hub flow ID for booking lookup)
Price Calculation
Section titled “Price Calculation”Upsells are sourced from the offer’s tour itinerary:
- Service fetches itinerary days with their optional hotels, activities, transfers
- Prices are calculated using rate periods covering the departure date
- Only upsells with valid rates for the date are shown
Source: backend/app/Services/Checkout/BookingUpsellPriceService.php
BookingUpsell Model
Section titled “BookingUpsell Model”Source: backend/app/Models/BookingUpsell.php
$upsell->booking; // BelongsTo Booking$upsell->hotel; // BelongsTo SupplierHotel (if type=hotel)$upsell->activity; // BelongsTo SupplierActivity (if type=activity)$upsell->transfer; // BelongsTo SupplierTransfer (if type=transfer)$upsell->getItem(); // Returns supplier entity (null for flight_upgrade)$upsell->getName(); // Returns display name or flight summary$upsell->getFlightSummary(); // Returns "MAD → NBO / NBO → MAD" for flightsFlight upgrade display: getName() returns route summary like MAD → NBO / JNB → MAD (supports open-jaw flights where return airport differs).
Checkout Finalization
Section titled “Checkout Finalization”When a customer completes checkout payment, BookingFinalizationService populates the booking:
- Passengers - Created from checkout session’s
traveler_data, attached viabooking_passenger - Upsells - Created from session’s hotel/activity/transfer/flight selections
- Flight Upgrades - If business class selected (
business_extra_price_per_person > 0), stores flight data in JSON - Prices - Updated with
base_price,extras_price,total_amountfrom session
Source: backend/app/Services/Booking/BookingFinalizationService.php
This happens automatically after successful payment in PaymentController::confirm().
Client Analytics
Section titled “Client Analytics”Bookings automatically trigger client.updateBookingAnalytics() on save to keep client statistics current.
Related
Section titled “Related”- Checkout API - Checkout flow and finalization
- Offers - Offer creation and pricing
- Product Relationships - Product entity structure
- Suppliers - Supplier hotels, activities, transfers