Overview
Viax implements a sophisticated dual-screen pricing system that allows administrators to configure tariffs by vehicle type, time periods, and apply dynamic pricing based on demand.
Pricing is configured per vehicle type with support for peak hours, nighttime, and holiday surcharges.
Pricing Database Schema
The pricing system uses dedicated database tables:
Configuration Table
migrations/007_create_configuracion_precios.sql
CREATE TABLE configuracion_precios (
id INT AUTO_INCREMENT PRIMARY KEY ,
tipo_vehiculo ENUM( 'moto' , 'carro' , 'moto_carga' , 'carro_carga' ) NOT NULL UNIQUE ,
tarifa_base DECIMAL ( 10 , 2 ) NOT NULL DEFAULT 0 ,
costo_por_km DECIMAL ( 10 , 2 ) NOT NULL DEFAULT 0 ,
costo_por_minuto DECIMAL ( 10 , 2 ) NOT NULL DEFAULT 0 ,
tarifa_minima DECIMAL ( 10 , 2 ) NOT NULL DEFAULT 0 ,
recargo_hora_pico DECIMAL ( 5 , 2 ) DEFAULT 0 ,
recargo_nocturno DECIMAL ( 5 , 2 ) DEFAULT 0 ,
recargo_festivo DECIMAL ( 5 , 2 ) DEFAULT 0 ,
descuento_distancia_mayor_15km DECIMAL ( 5 , 2 ) DEFAULT 0 ,
comision_plataforma DECIMAL ( 5 , 2 ) DEFAULT 15 . 00 ,
hora_pico_inicio_manana TIME DEFAULT '07:00:00' ,
hora_pico_fin_manana TIME DEFAULT '09:00:00' ,
hora_pico_inicio_tarde TIME DEFAULT '17:00:00' ,
hora_pico_fin_tarde TIME DEFAULT '19:00:00' ,
hora_nocturna_inicio TIME DEFAULT '22:00:00' ,
hora_nocturna_fin TIME DEFAULT '06:00:00' ,
activo BOOLEAN DEFAULT TRUE,
notas TEXT ,
creado_en TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
actualizado_en TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
Price History Table
CREATE TABLE historial_precios (
id INT AUTO_INCREMENT PRIMARY KEY ,
configuracion_id INT NOT NULL ,
campo_modificado VARCHAR ( 100 ) NOT NULL ,
valor_anterior TEXT ,
valor_nuevo TEXT ,
modificado_por INT ,
fecha_modificacion TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (configuracion_id) REFERENCES configuracion_precios(id),
FOREIGN KEY (modificado_por) REFERENCES usuarios(id)
);
Default Pricing Configuration
Motorcycle
Car
Cargo Motorcycle
Cargo Van
Vehicle Type: motoComponent Value Base Fare $4,000 Per Kilometer $2,000 Per Minute $250 Minimum Fare $6,000 Peak Hour Surcharge 15% Night Surcharge 20% Holiday Surcharge 25% Platform Commission 15%
Vehicle Type: carroComponent Value Base Fare $6,000 Per Kilometer $3,000 Per Minute $400 Minimum Fare $9,000 Peak Hour Surcharge 15% Night Surcharge 20% Holiday Surcharge 25% Platform Commission 15%
Vehicle Type: moto_cargaComponent Value Base Fare $5,000 Per Kilometer $2,500 Per Minute $300 Minimum Fare $7,500 Peak Hour Surcharge 15% Night Surcharge 20% Holiday Surcharge 25% Platform Commission 15%
Vehicle Type: carro_cargaComponent Value Base Fare $8,000 Per Kilometer $3,500 Per Minute $450 Minimum Fare $12,000 Peak Hour Surcharge 15% Night Surcharge 20% Holiday Surcharge 25% Platform Commission 15%
The system uses a comprehensive formula to calculate trip costs:
Subtotal = Base Fare + (Distance × Cost/km) + (Duration × Cost/min)
Discount = If distance ≥ 15km → Subtotal × 10%
Surcharge = Subtotal × (Percentage based on time period)
- Peak hours (7-9am, 5-7pm): +15-20%
- Night (10pm-6am): +20-25%
- Holidays: +25-30%
Total = Subtotal - Discount + Surcharge
Total = MAX(Total, Minimum Fare)
Platform Commission = Total × (Commission %)
Driver Earnings = Total - Platform Commission
Implementation Example
double calculateTripPrice ({
required double distanceKm,
required int durationMinutes,
required String vehicleType,
required DateTime tripTime,
}) {
final config = getPricingConfig (vehicleType);
// Base calculation
double subtotal = config.tarifaBase +
(distanceKm * config.costoPorKm) +
(durationMinutes * config.costoPorMinuto);
// Distance discount
double discount = 0 ;
if (distanceKm >= 15 ) {
discount = subtotal * (config.descuentoDistancia / 100 );
}
// Time-based surcharge
double surcharge = 0 ;
final period = getCurrentPeriod (tripTime, config);
if (period == 'hora_pico' ) {
surcharge = subtotal * (config.recargoHoraPico / 100 );
} else if (period == 'nocturno' ) {
surcharge = subtotal * (config.recargoNocturno / 100 );
} else if ( isHoliday (tripTime)) {
surcharge = subtotal * (config.recargoFestivo / 100 );
}
// Final total
double total = subtotal - discount + surcharge;
total = max (total, config.tarifaMinima);
return total;
}
Time Periods
Peak Hours (Hora Pico)
Morning Peak Default: 7:00 AM - 9:00 AMSurcharge: 15%
Evening Peak Default: 5:00 PM - 7:00 PMSurcharge: 15%
Night Hours (Nocturno)
Time Range: 10:00 PM - 6:00 AM
Surcharge: 20%
Normal Hours
Time Range: All other hours
Surcharge: 0%
Active Prices View
A database view provides quick access to current pricing with period detection:
CREATE VIEW vista_precios_activos AS
SELECT
cp. * ,
CASE
WHEN CURRENT_TIME BETWEEN cp . hora_pico_inicio_manana AND cp . hora_pico_fin_manana THEN 'hora_pico'
WHEN CURRENT_TIME BETWEEN cp . hora_pico_inicio_tarde AND cp . hora_pico_fin_tarde THEN 'hora_pico'
WHEN CURRENT_TIME >= cp . hora_nocturna_inicio OR CURRENT_TIME <= cp . hora_nocturna_fin THEN 'nocturno'
ELSE 'normal'
END AS periodo_actual,
CASE
WHEN CURRENT_TIME BETWEEN cp . hora_pico_inicio_manana AND cp . hora_pico_fin_manana THEN cp . recargo_hora_pico
WHEN CURRENT_TIME BETWEEN cp . hora_pico_inicio_tarde AND cp . hora_pico_fin_tarde THEN cp . recargo_hora_pico
WHEN CURRENT_TIME >= cp . hora_nocturna_inicio OR CURRENT_TIME <= cp . hora_nocturna_fin THEN cp . recargo_nocturno
ELSE 0
END AS recargo_actual
FROM configuracion_precios cp
WHERE cp . activo = TRUE;
Backend API Endpoints
Get Pricing Configuration
backend/pricing/get_config.php
// GET /pricing/get_config.php?tipo_vehiculo=moto
{
"success" : true ,
"data" : {
"tipo_vehiculo" : "moto" ,
"tarifa_base" : 4000.00 ,
"costo_por_km" : 2000.00 ,
"costo_por_minuto" : 250.00 ,
"tarifa_minima" : 6000.00 ,
"recargo_hora_pico" : 15.00 ,
"recargo_nocturno" : 20.00 ,
"recargo_festivo" : 25.00 ,
"periodo_actual" : "hora_pico" ,
"recargo_actual" : 15.00
}
}
Calculate Trip Quote
backend/pricing/calculate_quote.php
// POST /pricing/calculate_quote.php
{
"distancia_km" : 8.5 ,
"duracion_minutos" : 25 ,
"tipo_vehiculo" : "moto"
}
// Response:
{
"success" : true ,
"data" : {
"distancia_km" : 8.5 ,
"duracion_minutos" : 25 ,
"tipo_vehiculo" : "moto" ,
"tarifa_base" : 4000 ,
"precio_distancia" : 17000 ,
"precio_tiempo" : 6250 ,
"subtotal" : 27250 ,
"descuento_distancia" : 0 ,
"recargo_porcentaje" : 15 ,
"recargo_precio" : 4087.5 ,
"total" : 31337.5 ,
"total_formateado" : "$31.338" ,
"periodo_actual" : "hora_pico" ,
"comision_plataforma" : 4700.63 ,
"ganancia_conductor" : 26636.87
}
}
Updating Pricing Configuration
Access Database
Connect to the MySQL database as admin
Update Configuration
UPDATE configuracion_precios
SET costo_por_km = 2200 . 00 ,
notas = 'Ajuste por inflación - Octubre 2025'
WHERE tipo_vehiculo = 'moto' ;
Verify Changes
SELECT * FROM vista_precios_activos
WHERE tipo_vehiculo = 'moto' ;
Check History
Changes are automatically logged in historial_precios
Pricing changes take effect immediately for new trip requests. Active trips use the pricing from when they were created.
Commission Distribution
Platform commission is calculated per trip:
class TripEarnings {
final double tripTotal;
final double platformCommissionPercentage;
double get platformEarnings {
return tripTotal * (platformCommissionPercentage / 100 );
}
double get driverEarnings {
return tripTotal - platformEarnings;
}
double get companyCommission {
// If driver belongs to a company, company may take additional %
final companyRate = driver.company ? .commissionRate ?? 0 ;
return driverEarnings * (companyRate / 100 );
}
double get driverFinalEarnings {
return driverEarnings - companyCommission;
}
}
Example Breakdown
Trip Total: $50,000 COP
Platform Commission (15%): $7,500 COP
Driver Base Earnings: $42,500 COP
Company Commission (10%): $4,250 COP
Driver Final Earnings: $38,250 COP
Distance Discount
Long-distance trips receive automatic discounts:
if (distanceKm >= 15.0 ) {
final discountPercentage = 10.0 ;
discount = subtotal * (discountPercentage / 100 );
}
Trips over 15km automatically receive a 10% discount to encourage long-distance rides.
Holiday Pricing
Implement holiday detection for special rates:
bool isHoliday ( DateTime date) {
final holidays = [
DateTime (date.year, 1 , 1 ), // New Year
DateTime (date.year, 5 , 1 ), // Labor Day
DateTime (date.year, 7 , 20 ), // Independence Day
DateTime (date.year, 8 , 7 ), // Battle of Boyacá
DateTime (date.year, 12 , 25 ), // Christmas
// Add more holidays
];
return holidays. any ((holiday) =>
date.year == holiday.year &&
date.month == holiday.month &&
date.day == holiday.day
);
}
Holiday surcharges can be configured per vehicle type and override other time-based surcharges.
Testing Pricing Configuration
Verify Period Detection
SELECT tipo_vehiculo, periodo_actual, recargo_actual
FROM vista_precios_activos;
Simulate Price Calculation
-- Test pricing for 10km, 20min motorcycle trip
SELECT
tarifa_base + ( 10 * costo_por_km) + ( 20 * costo_por_minuto) AS subtotal,
periodo_actual,
recargo_actual
FROM vista_precios_activos
WHERE tipo_vehiculo = 'moto' ;
Change Time Periods for Testing
UPDATE configuracion_precios
SET hora_pico_inicio_manana = '14:00:00' ,
hora_pico_fin_manana = '16:00:00'
WHERE tipo_vehiculo = 'moto' ;
Price Display to Users
Users see estimated pricing before requesting trips:
Enter Route
User selects origin and destination
Select Vehicle Type
User chooses moto, carro, etc.
View Quote
System calculates and displays:
Base fare
Distance cost
Time cost
Active surcharges
Total estimated price
Confirm Request
User accepts price and requests trip
Future Enhancements
Dynamic Pricing Adjust prices based on real-time demand
Zone-Based Pricing Different rates for different geographic areas
Promotional Codes Discount codes and promotional campaigns
Membership Tiers Discounted rates for premium members
Best Practices
Always test pricing changes with the calculate_quote endpoint before deploying to production.
Use the ‘notas’ field to document why prices were changed and when.
Regularly compare your rates with competitors to stay competitive.
Ensure drivers earn fair wages after platform and company commissions.
Notify drivers and users before implementing significant price changes.
Vehicle Types Manage vehicle categories
Company Management Configure company commissions
Service Areas Define service boundaries