Overview
The Maintenance module is a complete Computerized Maintenance Management System (CMMS) that handles preventive maintenance routines, work orders, scheduling, and technician management.
This module integrates tightly with Assets, Inventory, and Safety modules for complete operational control.
Key Features
Preventive Maintenance Automated scheduling based on frequency and calendars
Work Orders Complete work order lifecycle from creation to closure
Visual Scheduler Interactive Gantt chart for planning and execution
Mobile Execution Execute work orders from mobile devices
Procedures Step-by-step checklists with validation
Resource Planning Technician assignment and workload balancing
Data Model
Rutina (Routine)
Template for preventive maintenance activities:
class Rutina ( models . Model ):
nombre = models.CharField( max_length = 200 )
descripcion = models.TextField()
# Target
activo = models.ForeignKey( 'activos.Activo' , on_delete = models. CASCADE )
ubicacion = models.ForeignKey( 'activos.Ubicacion' , on_delete = models. SET_NULL )
# Classification
categoria = models.ForeignKey( 'Categoria' , on_delete = models. PROTECT )
frecuencia = models.ForeignKey( 'Frecuencia' , on_delete = models. PROTECT )
# Execution
duracion_estimada = models.DurationField()
procedimiento = models.ForeignKey( 'Procedimiento' , on_delete = models. SET_NULL )
# Status
activo = models.BooleanField( default = True )
OrdenTrabajo (Work Order)
Executable maintenance tasks:
class OrdenTrabajo ( models . Model ):
ESTADOS = [
( 'PENDIENTE' , 'Pendiente' ),
( 'EN_CURSO' , 'En Curso' ),
( 'COMPLETADA' , 'Completada' ),
( 'CANCELADA' , 'Cancelada' ),
]
codigo = models.CharField( max_length = 50 , unique = True )
descripcion = models.TextField()
# Source
rutina = models.ForeignKey( 'Rutina' , on_delete = models. SET_NULL )
aviso = models.ForeignKey( 'Aviso' , on_delete = models. SET_NULL )
# Scheduling
fecha_programada = models.DateField()
fecha_inicio = models.DateTimeField( blank = True , null = True )
fecha_fin = models.DateTimeField( blank = True , null = True )
# Assignment
tecnico = models.ForeignKey( 'TecnicoPuesto' , on_delete = models. SET_NULL )
empresa = models.ForeignKey( 'Empresa' , on_delete = models. SET_NULL )
# Status
estado = models.CharField( max_length = 20 , choices = ESTADOS )
Preventive Maintenance
Frequency Configuration
Define maintenance intervals:
Time-Based
Meter-Based
Fixed Dates
Frecuencia.objects.create(
nombre = "Monthly" ,
dias = 30 ,
tipo = "CALENDARIO"
)
Frecuencia.objects.create(
nombre = "Every 1000 hours" ,
valor_medidor = 1000 ,
tipo = "CONTADOR"
)
Frecuencia.objects.create(
nombre = "Annual - January" ,
meses_especificos = [ 1 ],
tipo = "ANUAL"
)
Automatic Work Order Generation
Work orders are generated automatically based on routines:
@shared_task
def generar_ordenes_preventivas ():
"""Generate work orders for active routines"""
from mantenimiento.services import ProgramacionService
# Get active routines
rutinas = Rutina.objects.filter( activo = True )
for rutina in rutinas:
# Check if work order is needed
if ProgramacionService.necesita_orden(rutina):
# Calculate next date
fecha = ProgramacionService.calcular_fecha(rutina)
# Create work order
OrdenTrabajo.objects.create(
rutina = rutina,
descripcion = rutina.nombre,
fecha_programada = fecha,
estado = 'PENDIENTE'
)
Work Order Lifecycle
State Machine
Execution Steps
Start Work Order
Technician starts the work order, logging start time orden.estado = 'EN_CURSO'
orden.fecha_inicio = timezone.now()
orden.save()
Execute Procedure
Follow procedure steps and record results for paso in orden.procedimiento.pasos.all():
ValorPasoOrden.objects.create(
orden = orden,
paso = paso,
valor = technician_input
)
Record Resources
Log hours worked and materials consumed CierreOrdenTrabajo.objects.create(
orden = orden,
horas_hombre = 8.5 ,
materiales_usados = [ ... ]
)
Complete Order
Mark work order as completed orden.estado = 'COMPLETADA'
orden.fecha_fin = timezone.now()
orden.save()
Visual Scheduler
Cronogram View
Interactive calendar for planning maintenance:
def cronograma_view ( request ):
"""Display maintenance schedule"""
mes = request. GET .get( 'mes' , timezone.now().month)
anio = request. GET .get( 'anio' , timezone.now().year)
# Get work orders for period
ordenes = OrdenTrabajo.objects.filter(
fecha_programada__year = anio,
fecha_programada__month = mes
).select_related( 'rutina' , 'tecnico' )
# Group by week
calendario = {}
for orden in ordenes:
semana = orden.fecha_programada.isocalendar()[ 1 ]
if semana not in calendario:
calendario[semana] = []
calendario[semana].append(orden)
return render(request, 'cronograma.html' , {
'calendario' : calendario,
'mes' : mes,
'anio' : anio
})
Drag-and-Drop Rescheduling
Move work orders by dragging in the calendar:
// Update work order date via AJAX
function rescheduleOrder ( orderId , newDate ) {
fetch ( `/mantenimiento/ordenes/ ${ orderId } /reschedule/` , {
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
'X-CSRFToken' : getCookie ( 'csrftoken' )
},
body: JSON . stringify ({ fecha_programada: newDate })
});
}
Procedures and Checklists
Procedimiento (Procedure)
Step-by-step instructions for maintenance tasks:
class Procedimiento ( models . Model ):
nombre = models.CharField( max_length = 200 )
descripcion = models.TextField()
version = models.CharField( max_length = 20 )
class PasoProcedimiento ( models . Model ):
TIPOS = [
( 'CHECK' , 'Checkbox' ),
( 'NUMERIC' , 'Numeric Value' ),
( 'TEXT' , 'Text Input' ),
( 'MEDICION' , 'Measurement' ),
]
procedimiento = models.ForeignKey( 'Procedimiento' , on_delete = models. CASCADE )
numero = models.IntegerField()
descripcion = models.TextField()
tipo_respuesta = models.CharField( max_length = 20 , choices = TIPOS )
# Validation
valor_minimo = models.FloatField( blank = True , null = True )
valor_maximo = models.FloatField( blank = True , null = True )
obligatorio = models.BooleanField( default = True )
Corrective Maintenance
Aviso (Maintenance Notice)
User-reported issues that trigger corrective maintenance:
class Aviso ( models . Model ):
TIPOS = [
( 'M1' , 'Service Request' ),
( 'M2' , 'Breakdown' ),
]
tipo = models.CharField( max_length = 2 , choices = TIPOS )
activo = models.ForeignKey( 'activos.Activo' , on_delete = models. CASCADE )
descripcion = models.TextField()
reportado_por = models.ForeignKey(User, on_delete = models. SET_NULL )
fecha_reporte = models.DateTimeField( auto_now_add = True )
# Classification
falla = models.ForeignKey( 'Falla' , on_delete = models. SET_NULL )
prioridad = models.CharField( max_length = 20 )
Notification System
Automatic notifications when maintenance is needed:
@receiver (post_save, sender = Aviso)
def notify_maintenance_team ( sender , instance , created , ** kwargs ):
if created and instance.prioridad == 'ALTA' :
# Send email to maintenance team
send_mail(
subject = f 'Urgent: { instance.tipo } - { instance.activo } ' ,
message = instance.descripcion,
recipient_list = [ '[email protected] ' ]
)
API Endpoints
Work Orders CRUD operations for work orders
Schedule Update and reschedule maintenance
Routines Manage preventive routines
Mobile Endpoints optimized for mobile
Best Practices
Routine Naming : Use descriptive names like “Monthly Generator Inspection” instead of generic codes
Calendar Restrictions : Configure holidays and shutdowns to avoid scheduling conflicts
Workload Balancing : Monitor technician assignments to prevent overload
Assets Equipment being maintained
Inventory Materials for maintenance
Safety Work permits and JSA