Overview
PaparcApp implements a dynamic pricing engine that calculates reservation costs based on:- Service Type (ECO, TRANSFER, MEET)
- Stay Duration (days with tiered pricing)
- Vehicle Type (coefficient multiplier)
- Additional Services (optional add-ons)
Pricing Architecture
PricingService Implementation
Singleton Pattern
The PricingService is implemented as a singleton with static methods and properties:- Pricing data is static and changes infrequently
- Loading from database on every request is inefficient
- Single cache instance shared across all requests
- Initialized once at server startup
Cache Initialization
Loaded during server startup inapp.js:89:
Cache Loading Logic
- Map for O(1) lookup (coefficients, extras)
- Array for rate tiers (requires linear search with conditions)
Pricing Components
1. Vehicle Coefficients
Vehicle type determines the base multiplier for all prices:| vehicle_type | multiplier |
|---|---|
| TURISMO | 1.00 |
| MOTOCICLETA | 0.50 |
| FURGONETA | 1.25 |
| CARAVANA | 2.00 |
| ESPECIAL | 1.50 |
- Motorcycle: 50% discount (takes less space)
- Caravan: 100% premium (takes double space)
- Van: 25% premium (slightly larger)
- Special: 50% premium (luxury/exotic cars)
2. Service Rate Tiers
Pricing varies by service type and stay duration (days):ECO Service (id_main_service = 1)
| min_days | max_days | daily_price |
|---|---|---|
| 1 | 3 | €12.00 |
| 4 | 10 | €8.00 |
| 11 | 15 | €6.00 |
| 16 | 9999 | €5.00 |
TRANSFER Service (id_main_service = 2)
| min_days | max_days | daily_price |
|---|---|---|
| 1 | 3 | €15.00 |
| 4 | 10 | €11.00 |
| 11 | 15 | €9.00 |
| 16 | 9999 | €8.00 |
MEET Service (id_main_service = 3)
| min_days | max_days | daily_price |
|---|---|---|
| 1 | 3 | €18.00 |
| 4 | 10 | €14.00 |
| 11 | 15 | €12.00 |
| 16 | 9999 | €11.00 |
- Longer stays get discounted daily rates
- MEET is the premium service (highest prices)
- ECO is the budget option (lowest prices)
- Discount increases with stay duration (encourages longer bookings)
3. Additional Services
Optional add-ons with fixed prices (not affected by vehicle type or duration):| id | name | category | price |
|---|---|---|---|
| 1 | Basic Wash | CLEANING | €15.00 |
| 2 | Interior Cleaning | CLEANING | €25.00 |
| 3 | Full Wash | CLEANING | €50.00 |
| 4 | Pro Detailing | CLEANING | €100.00 |
| 5 | Refueling | MANAGEMENT | €15.00 |
| 6 | MOT Service | MANAGEMENT | €60.00 |
| 7 | Quick Maintenance | MAINTENANCE | €30.00 |
| 8 | EV Charging | ENERGY | €25.00 |
Price Calculation Algorithm
Main Calculation Function
Calculation Breakdown
Formula:-
Calculate Days
- Convert entry/exit dates to Date objects
- Calculate time difference in milliseconds
- Convert to days (rounding down)
- Add 1 day if remainder exceeds 2-hour grace period
- Ensure minimum of 1 day
-
Find Rate Tier
- Search
cache.ratesarray for matching:id_main_service(ECO=1, TRANSFER=2, MEET=3)min_days <= totalDays <= max_days
- Throw error if no match found
- Search
-
Get Vehicle Coefficient
- Lookup in
cache.coefficientsMap - Throw error if vehicle type not found
- Lookup in
-
Sum Additional Services
- Loop through
id_additional_servicesarray - Lookup each in
cache.extrasMap - Sum all prices (skip if ID not found, with warning)
- Loop through
-
Calculate Total
- Base cost:
daily_price × totalDays × vehicleCoefficient - Add extras:
basePrice + extrasTotal - Round to 2 decimal places
- Base cost:
Courtesy Time Feature
- Entry: 10:00, Exit: 10:00 (exactly 24h) → 1 day
- Entry: 10:00, Exit: 11:00 (25h) → 1 day (within 2h grace)
- Entry: 10:00, Exit: 13:00 (27h) → 2 days (exceeds grace period)
- Entry: 10:00, Exit: 08:00 next day (22h) → 1 day
Pricing Examples
Example 1: Basic Reservation
Scenario:- Service: ECO (id=1)
- Vehicle: TURISMO (coefficient=1.00)
- Duration: 5 days
- Additional Services: None
Example 2: Motorcycle with Add-ons
Scenario:- Service: TRANSFER (id=2)
- Vehicle: MOTOCICLETA (coefficient=0.50)
- Duration: 2 days
- Additional Services: Basic Wash (€15)
Example 3: Long Stay Caravan
Scenario:- Service: MEET (id=3)
- Vehicle: CARAVANA (coefficient=2.00)
- Duration: 12 days
- Additional Services: Full Wash (€50), Refueling (€15)
Example 4: Edge Case - Short Stay
Scenario:- Entry: 2026-03-10 14:00
- Exit: 2026-03-10 20:00 (same day, 6 hours later)
- Service: ECO (id=1)
- Vehicle: TURISMO (coefficient=1.00)
API Endpoint
POST /api/pricing/dynamic
Purpose: Calculate price for a potential reservation (used by booking form) Request:Data Access Layer (DAO)
PricingDAO Methods
Location:models/pricing-dao.js
- Each method handles its own error logging
- Results returned as raw database rows
- DAO exported as singleton instance
- Ordered query for service_rates (sorted by service and days for efficient searching)
Performance Optimizations
1. In-Memory Cache
- No database queries during price calculations
- O(1) lookups for coefficients and extras (Map)
- O(n) search for rate tiers (small array, ~12 items)
2. Singleton Pattern
- Single cache instance shared across requests
- Initialized once at startup
- No repeated data loading
3. Data Structures
- Map for key-value lookups (coefficients, extras)
- Array for rate tiers (needs conditional matching)
4. Lazy Evaluation
- Additional services calculated only if provided
- Early validation (cache initialized check)
Error Handling
Cache Not Initialized
Rate Tier Not Found
Vehicle Coefficient Missing
Additional Service Not Found
- Critical errors (no rate, no coefficient) throw exceptions
- Non-critical errors (missing extra) log warnings and continue
- All errors include descriptive messages with context
Testing Considerations
Unit Test Examples
Integration Test
Summary
The PaparcApp pricing engine is:- Fast: In-memory cache with O(1) lookups
- Flexible: Tiered pricing based on duration
- Fair: 2-hour courtesy period for minor overages
- Transparent: Clear calculation formula
- Maintainable: Centralized pricing logic in singleton service
- Reliable: Comprehensive error handling and validation
- Scalable: No database queries during calculations
