Owner: Dev Team | Last Updated: 2026-02-21 | Status: Current
Creating, configuring, and managing Experiences (tours/cruises) in the Booking system.
Experience is the central entity of the Booking system. It is a tour, cruise, or event that a customer can book.
Create → Configure Pricing → Set Availability → Add Media → Activate → Accept Bookings → Cancel (optional)
| Field | Type | Description |
|---|---|---|
name |
string | Tour name |
description |
text | Description |
price |
decimal | Base price |
company_id |
integer | Company association |
| Field | Type | Description |
|---|---|---|
headline |
string | Short description |
location |
string | Venue location |
equipment |
string | Required equipment |
cancellation |
text | Cancellation policy |
content |
json | Additional content |
features |
json | Tour features |
external_id |
string | ID in external system |
Each Experience can have multiple ticket types:
| Field | Description |
|---|---|
name |
Name (Adult, Child, Senior, etc.) |
amount |
Current price |
original_amount |
Original price (for strikethrough display) |
extra |
Additional parameters (JSON) |
For grouping prices, the following are used:
Automatic price adjustment based on rules. See: Dynamic Pricing Guide.
| Field | Description |
|---|---|
repeating |
Recurrence type (daily, weekly, etc.) |
start_date |
Start date |
end_date |
End date |
days |
Days of the week (JSON array) |
| Field | Description |
|---|---|
period_name |
Period name |
periods |
Time slots (JSON array) |
deactivated_periods |
Deactivated slots |
| Field | Description |
|---|---|
total |
Total capacity |
capacity |
Capacity per slot (JSON) |
use_total_capacity |
Use total capacity |
| Field | Description |
|---|---|
age |
Age restrictions |
custom |
Custom groups |
Each Experience can contain multiple images:
| Field | Description |
|---|---|
url |
File path |
order |
Display order |
Image sizes:
Files:
app/Actions/Media/SaveFileAction.php -- file savingapp/Actions/Media/ResizeImageAction.php -- resizingapp/Actions/Media/DeleteFileAction.php -- deletionAssigning staff to an Experience:
// ExperiencePersonnel model
'personnel' => array // Array of user IDs
Additional services for an Experience:
| Field | Description |
|---|---|
name |
Service name |
price |
Price |
type |
Service type |
per_unit |
Price per unit (boolean) |
description |
Description |
An Experience can be linked to multiple locations:
ExperienceLocation -- location linkage with scheduleExperienceLocationPricing -- pricing by locationExperienceLocationsAccessory -- accessories by location| Type | Flag | Description |
|---|---|---|
| Tour | is_gift_card = false |
Water cruise / tour |
| Gift Card | is_gift_card = true |
Gift certificate |
Note: Gift Card is an Experience with the flag
is_gift_card = true. They are stored in the same table but use a separateGiftCardmodel (extendsExperience) with a global scopeGiftCardScope.
Experience data is cached in Redis:
| Cache Key | TTL | Description |
|---|---|---|
xps_available |
Variable | Available experiences |
xps_flow |
Variable | Data for booking flow |
embed_experiences |
Variable | Data for embed widget |
Invalidation: XpCacheForgetAction
Synchronization with external systems:
# Artisan command (daily at 02:00)
php artisan experiences:sync
Files:
app/Console/Commands/SyncExperiencesCommand.phpapp/Services/CompanySyncService.phpapp/Services/CompanyTourSyncService.phpapp/Services/CompanyBikeSyncService.php| File | Purpose |
|---|---|
app/Models/Experience.php |
Experience model |
app/Services/ExperienceService.php |
Business logic |
app/Repositories/ExperienceRepository.php |
Data access |
app/Http/Controllers/Web/ExperienceController.php |
Web controller |
resources/js/pages/experiences/ |
Frontend pages |
| Date | Author | Change |
|---|---|---|
| 2026-02-21 | Documentation Team | Initial creation |
Up: Guides