Overview
The public booking flow is a 3-step funnel designed for non-technical users to quickly reserve a parking spot. It features real-time dynamic pricing, vehicle type detection, and optional additional services.Location:
View:
Controller:
Client Logic:
/booking routeView:
views/booking.ejsController:
controllers/mainController.js:renderBooking()Client Logic:
public/javascripts/public-booking.jsWorkflow: 3-Step Funnel
Step 1: Dates & Service Selection
Customers start by selecting their parking dates and desired service tier.Select Entry/Exit Dates
- Entry Date:
datetime-localinput (e.g., “2024-03-15 09:00”) - Exit Date:
datetime-localinput (e.g., “2024-03-20 18:00”) - Dates can be pre-filled via URL params:
/booking?entrada=2024-03-15T09:00&salida=2024-03-20T18:00
Choose Main Service
Options fetched from
service_catalog_dao.getMainServices(true) (only active services):- Basic Parking: Outdoor, self-park
- Premium Parking: Covered, valet service
- VIP Experience: Climate-controlled, car wash included
Add Optional Extras
Checkbox grid for additional services (from
additional_service table):- Car wash (+€15)
- Tire pressure check (+€5)
- Fuel refill (+€10)
- Interior cleaning (+€20)
- Entry date < Exit date (enforced client-side and server-side)
- Service selection is required
- If no service selected, uses cheapest service for estimation
Step 2: Vehicle & Customer Details
Collect customer information and vehicle details for reservation.Customer Information
Customer Information
- Full Name: Required (pre-filled if logged in:
user.nombre) - Phone: Required (pre-filled:
user.numero) - Email: Optional (pre-filled:
user.email)
customer table. Phone used as unique identifier for walk-in customers.Vehicle Registration
Vehicle Registration
- License Plate: Required, auto-uppercase (e.g., “0000XXX”)
- Vehicle Type: Dropdown (TURISMO, FURGONETA, MOTOCICLETA, etc.)
- Brand: Optional (e.g., “Toyota”)
- Model: Optional (e.g., “Corolla”)
- Color: Optional
customer_dao.getVehiclesByCustomerId()Step 3: Confirmation & Submission
Final review before creating the reservation.Summary Display
Shows all collected data:
- Entry/Exit dates (formatted)
- Customer name & phone
- License plate (uppercase)
- Vehicle description
- Final calculated price
Submission Handler
POST
/api/reservations/publicCreates reservation via reservationDAO.createReservationTransaction():- Find or create customer by phone
- Find or create vehicle by license plate
- Link customer to vehicle
- Create reservation with status
PENDIENTE - Insert additional services
Price Calculation Engine
Dynamic Pricing Algorithm
Implemented inservices/pricingService.js:82-139:
Lookup Base Rate
Find matching rate from Example rates:
service_rate table:- 1-3 days: €15/day
- 4-7 days: €12/day
- 8-15 days: €10/day
Apply Vehicle Multiplier
From
vehicle_type_coefficient table:- TURISMO: 1.0x
- FURGONETA: 1.5x
- MOTOCICLETA: 0.8x
- CAMION: 2.0x
Pricing Cache
All pricing data is cached in RAM on server startup via
PricingService.initCache() to avoid repeated database queries. Cache includes:- Vehicle type coefficients (Map)
- Service rates (Array)
- Additional service prices (Map)
User Experience Features
URL Pre-population
Users can arrive from Dates auto-fill in Step 1
/ with dates already selected:Logged-in User Benefits
- Auto-fill name, email, phone
- First registered vehicle pre-selected
- Faster checkout experience
Visual Validation
Red borders (
.is-invalid) on empty required fields when advancing stepsLoading States
Spinner displays during price calculation API calls
Technical Implementation
Frontend Flow Control
Step Navigation (public-booking.js:126-176):
Backend Transaction Safety
Atomic Reservation Creation (models/reservation-dao.js:239-354):
Code References
| Component | File Path | Key Functions |
|---|---|---|
| Main Controller | controllers/mainController.js | renderBooking() (line 89-127) |
| Public API | routes/api.js | /api/reservations/public endpoint |
| Reservation DAO | models/reservation-dao.js | createReservationTransaction() (line 239-354) |
| Pricing Service | services/pricingService.js | calculateTotalPrice() (line 82-139) |
| Client Logic | public/javascripts/public-booking.js | goToStep(), updateDynamicPrice() |
| View Template | views/booking.ejs | 3-step form structure |
Error Handling
Next Steps
User Profile
Manage reservations after booking
Admin Dashboard
How staff processes bookings
