Get Upcoming Maintenance
curl -X GET https://api.example.com/api/mantenimiento/proximos \
-H "Authorization: Bearer YOUR_TOKEN"
Endpoint
GET /api/mantenimiento/proximos
Description
This endpoint queries the v_proximo_mantenimiento view which calculates upcoming maintenance requirements based on:
- Active maintenance plans
- Plan conditions (kilometers, days, hours)
- Vehicle current status (last event, current mileage/hours)
The results are ordered by fecha_proximo (next maintenance date) with the most urgent maintenance first.
Response
Returns an array of upcoming maintenance items with vehicle and plan information.
ID of the maintenance plan
ID of the vehicle requiring maintenance
Name of the maintenance plan
Type of maintenance (e.g., “Preventivo”, “Correctivo”)
Calculated next maintenance date (ISO 8601 format: YYYY-MM-DD)
Calculated next maintenance kilometer reading
Calculated next maintenance engine hours
Kilometers remaining until next maintenance
Engine hours remaining until next maintenance
Days remaining until next maintenance
Current status of the maintenance requirement:
"VENCIDO" - Overdue
"PROXIMO" - Coming up soon
"PROGRAMADO" - Scheduled for future
Example Response
[
{
"plan_id": 45,
"vehiculo_id": 123,
"plan_nombre": "Mantenimiento Preventivo 15K",
"tipo_mantenimiento": "Preventivo",
"fecha_proximo": "2026-03-15",
"km_proximo": 30000,
"hr_proximo": 1000,
"km_restante": 500,
"hr_restante": 20,
"dias_restantes": 11,
"estado": "PROXIMO",
"vehiculo": {
"id": 123,
"areas_placas": {
"placa": "ABC123"
}
}
},
{
"plan_id": 46,
"vehiculo_id": 124,
"plan_nombre": "Cambio de Aceite 5K",
"tipo_mantenimiento": "Preventivo",
"fecha_proximo": "2026-03-01",
"km_proximo": 20000,
"km_restante": -200,
"dias_restantes": -3,
"estado": "VENCIDO",
"vehiculo": {
"id": 124,
"areas_placas": {
"placa": "XYZ789"
}
}
},
{
"plan_id": 47,
"vehiculo_id": 125,
"plan_nombre": "Mantenimiento Mayor 50K",
"tipo_mantenimiento": "Preventivo",
"fecha_proximo": "2026-06-15",
"km_proximo": 50000,
"hr_proximo": 2000,
"km_restante": 8500,
"hr_restante": 340,
"dias_restantes": 103,
"estado": "PROGRAMADO",
"vehiculo": {
"id": 125,
"areas_placas": {
"placa": "DEF456"
}
}
}
]
Understanding the Schedule View
The v_proximo_mantenimiento view is a database view that automatically calculates when each vehicle needs maintenance based on:
Calculation Logic
-
Last Event Data: The view looks at the most recent maintenance event for each plan to determine:
- Last maintenance date
- Last odometer reading (km)
- Last engine hours reading
-
Plan Conditions: For each active plan, it evaluates all conditions:
- Time-based: Adds the condition’s day value to the last maintenance date
- Kilometer-based: Adds the condition’s km value to the last odometer reading
- Hour-based: Adds the condition’s hour value to the last engine hours
-
Current Status: Compares the calculated next maintenance values with:
- Current date
- Current vehicle odometer reading
- Current vehicle engine hours
-
State Determination:
VENCIDO (Overdue): Any remaining value (km, hours, or days) is negative
PROXIMO (Coming Soon): Typically within a threshold (e.g., < 500 km, < 50 hours, or < 30 days)
PROGRAMADO (Scheduled): More than the threshold values away
Use Cases
Dashboard Display
Display overdue and upcoming maintenance on a fleet management dashboard:
const response = await fetch('https://api.example.com/api/mantenimiento/proximos', {
headers: { 'Authorization': 'Bearer YOUR_TOKEN' }
});
const schedule = await response.json();
const overdue = schedule.filter(m => m.estado === 'VENCIDO');
const comingSoon = schedule.filter(m => m.estado === 'PROXIMO');
console.log(`${overdue.length} overdue maintenance items`);
console.log(`${comingSoon.length} upcoming maintenance items`);
Vehicle-Specific Schedule
Filter the schedule for a specific vehicle:
const vehicleId = 123;
const vehicleSchedule = schedule.filter(m => m.vehiculo_id === vehicleId);
vehicleSchedule.forEach(item => {
console.log(`${item.plan_nombre}: Due in ${item.dias_restantes} days`);
});
Alert Generation
Generate alerts for critical maintenance:
const critical = schedule.filter(m =>
m.estado === 'VENCIDO' ||
(m.dias_restantes !== null && m.dias_restantes < 7) ||
(m.km_restante !== null && m.km_restante < 200)
);
critical.forEach(item => {
sendAlert({
vehicle: item.vehiculo.areas_placas.placa,
maintenance: item.plan_nombre,
status: item.estado,
urgency: item.estado === 'VENCIDO' ? 'high' : 'medium'
});
});
Best Practices
Regular Polling
Check the upcoming maintenance schedule regularly (e.g., daily) to ensure timely maintenance:
// Check schedule daily
setInterval(async () => {
const schedule = await getUpcomingMaintenance();
updateDashboard(schedule);
checkForAlerts(schedule);
}, 24 * 60 * 60 * 1000); // 24 hours
Update Vehicle Status
Ensure vehicle mileage and engine hours are updated regularly:
// After recording a trip or fuel event
const updateVehicleStatus = async (vehicleId, currentKm, currentHours) => {
await fetch(`/api/vehiculos/${vehicleId}`, {
method: 'PUT',
headers: {
'Authorization': 'Bearer YOUR_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify({
odometro_actual: currentKm,
horometro_actual: currentHours
})
});
};
Record Completed Maintenance
When maintenance is completed, create an event to reset the schedule:
const recordMaintenanceCompletion = async (planId, vehicleId, km, hours) => {
await fetch('/api/mantenimiento/eventos', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify({
plan_id: planId,
vehiculo_id: vehicleId,
fecha: new Date().toISOString().split('T')[0],
km_evento: km,
hr_evento: hours,
descripcion: 'Mantenimiento completado'
})
});
// Refresh the schedule
const updatedSchedule = await getUpcomingMaintenance();
return updatedSchedule;
};
Handle Multiple Conditions
When a plan has multiple conditions (e.g., “every 6 months OR every 10,000 km”), the schedule view will show the earliest trigger:
const interpretSchedule = (item) => {
const triggers = [];
if (item.dias_restantes !== null) {
triggers.push(`${item.dias_restantes} days`);
}
if (item.km_restante !== null) {
triggers.push(`${item.km_restante} km`);
}
if (item.hr_restante !== null) {
triggers.push(`${item.hr_restante} hours`);
}
// Find the most urgent trigger
const mostUrgent = triggers.reduce((min, current) => {
const value = parseInt(current);
return value < min ? value : min;
}, Infinity);
return `Next maintenance due in: ${triggers.join(' or ')}`;
};