Preventive Maintenance
Preventive Maintenance
Preventive maintenance helps you avoid unexpected breakdowns by scheduling regular inspections and servicing at fixed time intervals or based on equipment usage. NexusRMS automates the entire process — from creating schedules, to generating tasks, to tracking compliance.
PreventiveMaintenanceSchedule model
Each schedule defines when and how maintenance should occur for a specific piece of equipment. The key fields are:
- equipment_id — The equipment item this schedule applies to.
- schedule_name — A descriptive name (e.g. "Quarterly PAT Test" or "Oil Change Every 500 Hours").
- maintenance_type — The category of work to be performed.
- frequency_type — Either time_based or usage_based.
- interval_value and interval_unit — For time-based schedules, the interval between occurrences. Units: days, weeks, months, years. For usage-based: hours, cycles, km.
- lead_time_days — How many days before the due date the task should be generated, giving your team time to prepare.
- tolerance_days — Grace period after the due date before the task is flagged as overdue.
- usage_trigger — For usage-based schedules, the threshold at which maintenance is due (e.g. every 500 hours).
- current_usage and last_maintenance_usage — Tracks the equipment's current and last-serviced usage values.
- default_assignee_id — The technician automatically assigned to generated tasks.
- estimated_duration_hours and estimated_cost — Planning estimates for each occurrence.
- is_active — Toggle to enable or disable the schedule without deleting it.
- next_due_date and last_performed_date — Calculated automatically based on the interval.
- times_performed — A running count of how many times this maintenance has been completed.
- auto_create_repairs — When enabled, tasks are generated automatically by the daily cron job.
- checklist_template_id — Links a checklist template to be attached to each generated task.
Time-based vs usage-based scheduling
Time-based schedules calculate next_due_date by adding the interval to last_performed_date. For example, a 3-month interval with a last performed date of 1 January sets the next due date to 1 April. The lead_time_days determines when the task is generated in advance.
Usage-based schedules trigger when current_usage reaches or exceeds the usage_trigger threshold. For example, if the trigger is 500 hours and current usage is 498, the task is not yet due. Once usage reaches 500, the task is generated. A 10% overshoot beyond the trigger marks the task as overdue.
MaintenanceTask model
Each generated task represents a single maintenance event. Fields include:
- schedule_id — The parent schedule that generated this task.
- equipment_id — The equipment to service.
- assigned_to — The technician responsible (inherited from default_assignee_id).
- status — One of: pending, in_progress, completed, or skipped.
- due_date — When the task must be completed.
- completed_at — Timestamp of completion.
- notes — Technician notes or skip reason.
- repair_id — If an inspection reveals a fault, the task can be converted to a full repair and linked here.
PreventiveMaintenanceService methods
The service layer handles all business logic:
- createSchedule(data) — Creates a new schedule and calculates the initial next_due_date. If the schedule is immediately due and auto_create_repairs is enabled, the first task is generated straight away.
- updateSchedule(id, data) — Updates a schedule and recalculates next_due_date if the interval changes.
- generateDueTasks() — Called daily via cron. Iterates all active schedules with auto_create_repairs enabled, checks if they are due, and generates tasks. Skips if a task already exists for the same due date.
- generateTaskFromSchedule(schedule) — Creates a single MaintenanceTask from a schedule.
- completeTask(taskId, data) — Marks a task as completed, updates completed_at, and calls markPerformed() on the parent schedule to recalculate the next due date and increment times_performed.
- convertTaskToRepair(taskId, repairData) — Converts a maintenance task to a full repair record when inspection reveals a fault. The repair inherits the equipment and assignee.
- updateEquipmentUsage(equipmentId, usage) — Updates current_usage on all usage-based schedules for the equipment and auto-generates tasks if thresholds are met.
- skipTask(taskId, reason) — Marks a task as skipped with a recorded reason.
- assignTask(taskId, technicianId) — Reassigns a task to a different technician.
Compliance tracking
The calculateComplianceRate() method returns the percentage of tasks completed on time (where completed_at is on or before due_date). It also reports overall completion rate. Use these metrics to demonstrate regulatory compliance and identify areas for improvement.
The getOverdueTaskNotifications() method returns a list of overdue tasks including equipment name, schedule name, days overdue, and assigned technician for alerting.
User interface
The PreventiveMaintenance page displays:
- Statistics cards — Active schedules, tasks due this week, tasks due this month, and completed count.
- Filters — Search by name, filter by frequency type (time_based or usage_based), and toggle to show inactive schedules.
- Data table — Columns for equipment, schedule name, frequency (shown as a chip), next due date (colour-coded: green for upcoming, amber for soon, red for overdue), times performed, active toggle, and an actions menu (edit, delete, generate task, view tasks).
- Create/edit dialogue — A form with the MaintenanceScheduler component covering all schedule fields.
A due maintenance alert banner appears at the top of the page when overdue tasks exist. This banner can be dismissed temporarily using the toggle.
Tips and best practices
- Enable auto_create_repairs on all schedules to ensure tasks are never missed.
- Set lead_time_days to at least 7 so your team has time to prepare parts and schedule technician availability.
- Review compliance rates monthly — a rate below 80% indicates your maintenance programme needs attention.
- Use usage-based schedules for equipment where operating hours vary significantly between rental periods.
Was this article helpful?