12 KiB
Sistema de Auditoría y Edición de Inspecciones
✅ Implementación Completa
Se ha implementado un sistema completo de auditoría que permite a los administradores editar inspecciones completadas y mantener un registro detallado de todos los cambios realizados.
🎯 Características Implementadas
Backend
-
Modelo de Auditoría
- Tabla
inspection_audit_logque registra todos los cambios - Campos: inspection_id, answer_id, user_id, action, entity_type, field_name, old_value, new_value, comment, created_at
- Relaciones con inspections, answers y users
- Tabla
-
Endpoints de Auditoría
GET /api/inspections/{id}/audit-log- Obtener historial de cambios (solo admin)PUT /api/answers/{id}/admin-edit- Editar respuesta con registro automático (solo admin)
-
Registro Automático
- Cada cambio registra: qué se cambió, valor anterior, valor nuevo, quién lo cambió, cuándo y por qué
- Recalcula puntos automáticamente si cambia el status
- Registra múltiples cambios en una sola edición
Frontend
-
Edición de Respuestas (Solo Admin)
- Botón "✏️ Editar" en cada respuesta de inspecciones completadas
- Formulario inline con campos editables:
- Estado (OK, Advertencia, Crítico, N/A)
- Valor de respuesta (según tipo de pregunta)
- Observación
- Marcador de señalamiento
- Motivo del cambio (obligatorio)
- Validación: requiere explicar el motivo del cambio
-
Modal de Historial de Cambios
- Botón "📜 Ver Historial de Cambios" en el footer del modal de inspección
- Lista cronológica de todos los cambios (más reciente primero)
- Para cada cambio muestra:
- Quién lo hizo (nombre del usuario)
- Cuándo (fecha y hora)
- Qué acción realizó
- Qué campo modificó
- Valor anterior vs valor nuevo (visual con colores)
- Motivo del cambio
- Iconos visuales según tipo de acción (➕✏️🗑️🔄)
-
Restricciones de Seguridad
- Solo administradores pueden editar respuestas
- Solo administradores pueden ver el historial
- Solo inspecciones completadas pueden editarse
- Cada cambio requiere justificación obligatoria
📋 Instrucciones de Uso
Para Administradores
1. Editar una Respuesta
- Abre el detalle de una inspección completada
- Busca la respuesta que quieres modificar
- Haz clic en el botón "✏️ Editar" junto a la respuesta
- Modifica los campos necesarios:
- Estado: Cambia entre OK, Advertencia, Crítico o N/A
- Valor de respuesta: Solo si la pregunta no es pass/fail
- Observación: Agrega o modifica comentarios
- Señalado: Marca o desmarca el flag de atención
- Importante: Escribe el motivo del cambio en el campo "Motivo del cambio"
- Haz clic en "Guardar Cambios"
- El sistema:
- Actualiza la respuesta
- Recalcula los puntos automáticamente
- Registra cada cambio en el log de auditoría
- Recarga la inspección con los datos actualizados
Nota: No puedes guardar sin escribir un motivo del cambio.
2. Ver Historial de Cambios
- Abre el detalle de cualquier inspección
- En el footer, haz clic en "📜 Ver Historial de Cambios"
- Se abrirá un modal con la bitácora completa
- Revisa:
- Todos los cambios realizados por administradores
- Orden cronológico (más recientes primero)
- Detalles completos de cada modificación
- Quién, cuándo, qué y por qué
3. Tipos de Cambios Registrados
El sistema registra automáticamente:
- answer_value: Cambio en la respuesta
- status: Cambio en el estado (OK/Advertencia/Crítico/N/A)
- comment: Cambio en las observaciones
- is_flagged: Marcado o desmarcado de señalamiento
- points_earned: Recálculo automático de puntos
Para Mecánicos
- No pueden editar inspecciones completadas
- No pueden ver el historial de cambios
- Solo ven el estado final de las respuestas
🗄️ Migración de Base de Datos
Ejecutar SQL
# Usando psql
psql -U tu_usuario -d tu_database -f migrations/add_inspection_audit_log.sql
# O directamente
psql -U tu_usuario -d tu_database
Luego ejecuta:
-- Crear tabla de auditoría
CREATE TABLE IF NOT EXISTS inspection_audit_log (
id SERIAL PRIMARY KEY,
inspection_id INTEGER NOT NULL REFERENCES inspections(id) ON DELETE CASCADE,
answer_id INTEGER REFERENCES answers(id) ON DELETE CASCADE,
user_id INTEGER NOT NULL REFERENCES users(id),
action VARCHAR(50) NOT NULL,
entity_type VARCHAR(50) NOT NULL,
field_name VARCHAR(100),
old_value TEXT,
new_value TEXT,
comment TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
-- Crear índices
CREATE INDEX idx_audit_log_inspection ON inspection_audit_log(inspection_id);
CREATE INDEX idx_audit_log_answer ON inspection_audit_log(answer_id);
CREATE INDEX idx_audit_log_user ON inspection_audit_log(user_id);
CREATE INDEX idx_audit_log_created_at ON inspection_audit_log(created_at DESC);
Reiniciar Backend
# Si usas Docker
docker-compose restart backend
# Si corres directamente
# Ctrl+C y volver a ejecutar
python -m uvicorn app.main:app --reload
🔍 Ejemplos de Uso
Ejemplo 1: Corregir Estado de Respuesta
Escenario: Un mecánico marcó "Crítico" por error cuando debía ser "Advertencia"
Pasos:
- Admin abre la inspección
- Encuentra la respuesta con estado "Crítico"
- Clic en "✏️ Editar"
- Cambia Estado a "Advertencia"
- En "Motivo del cambio": "Error del mecánico, no era crítico sino advertencia menor"
- Guarda cambios
- El sistema:
- Actualiza el status de "critical" a "warning"
- Recalcula puntos (de 0 a 50% del total)
- Registra: field_name="status", old_value="critical", new_value="warning"
- Registra: field_name="points_earned", old_value="0", new_value="5"
Resultado en Auditoría:
✏️ Juan Pérez (Admin) • 25 de noviembre de 2025, 14:30
Acción: updated en answer (Respuesta #45)
Campo modificado: status
Valor anterior: critical
Valor nuevo: warning
Campo modificado: points_earned
Valor anterior: 0
Valor nuevo: 5
Motivo: Error del mecánico, no era crítico sino advertencia menor
Ejemplo 2: Agregar Observación Faltante
Escenario: El mecánico no dejó observaciones en un item señalado
Pasos:
- Admin edita la respuesta
- Agrega en "Observación": "Necesita cambio de aceite urgente"
- Mantiene el señalamiento activado
- Motivo: "Agregando observación faltante para clarity"
- Guarda
Resultado: Se registra el cambio de observación de vacío a texto.
Ejemplo 3: Revisión de Historial
Escenario: Auditoría mensual de cambios en inspecciones
Pasos:
- Admin abre inspección
- Clic en "📜 Ver Historial de Cambios"
- Revisa todos los cambios del mes
- Verifica justificaciones
- Identifica patrones de errores comunes
📊 Base de Datos
Estructura de inspection_audit_log
| Campo | Tipo | Descripción |
|---|---|---|
| id | SERIAL | ID único del registro |
| inspection_id | INTEGER | ID de la inspección modificada |
| answer_id | INTEGER | ID de la respuesta modificada (nullable) |
| user_id | INTEGER | ID del usuario que hizo el cambio |
| action | VARCHAR(50) | Tipo de acción (created, updated, deleted, status_changed) |
| entity_type | VARCHAR(50) | Tipo de entidad (inspection, answer) |
| field_name | VARCHAR(100) | Nombre del campo modificado |
| old_value | TEXT | Valor anterior |
| new_value | TEXT | Valor nuevo |
| comment | TEXT | Motivo del cambio |
| created_at | TIMESTAMP | Fecha y hora del cambio |
Consultas Útiles
-- Ver todos los cambios de una inspección
SELECT u.full_name, ial.action, ial.field_name, ial.old_value, ial.new_value, ial.comment, ial.created_at
FROM inspection_audit_log ial
JOIN users u ON ial.user_id = u.id
WHERE ial.inspection_id = 123
ORDER BY ial.created_at DESC;
-- Ver cambios realizados por un admin específico
SELECT i.id as inspection_id, i.vehicle_plate, ial.field_name, ial.comment, ial.created_at
FROM inspection_audit_log ial
JOIN inspections i ON ial.inspection_id = i.id
WHERE ial.user_id = 5
ORDER BY ial.created_at DESC;
-- Contar cambios por tipo
SELECT action, COUNT(*) as total
FROM inspection_audit_log
GROUP BY action
ORDER BY total DESC;
-- Ver respuestas más editadas
SELECT answer_id, COUNT(*) as ediciones
FROM inspection_audit_log
WHERE answer_id IS NOT NULL
GROUP BY answer_id
ORDER BY ediciones DESC
LIMIT 10;
-- Cambios en los últimos 7 días
SELECT i.id, i.vehicle_plate, u.full_name, ial.field_name, ial.created_at
FROM inspection_audit_log ial
JOIN inspections i ON ial.inspection_id = i.id
JOIN users u ON ial.user_id = u.id
WHERE ial.created_at >= NOW() - INTERVAL '7 days'
ORDER BY ial.created_at DESC;
⚠️ Notas Importantes
-
Solo Admins Pueden Editar
- Los mecánicos NO pueden editar inspecciones completadas
- Solo usuarios con rol
admintienen acceso
-
Solo Inspecciones Completadas
- No se pueden editar inspecciones en estado "draft"
- El botón de editar solo aparece en inspecciones completadas
-
Motivo Obligatorio
- Cada cambio DEBE tener una justificación
- El campo "Motivo del cambio" es obligatorio
- No se puede guardar sin completarlo
-
Recalculo Automático
- Al cambiar el status, los puntos se recalculan automáticamente
- OK = 100% de puntos
- Warning = 50% de puntos
- Critical/NA = 0% de puntos
-
Registro Completo
- Cada campo modificado genera un registro separado
- Se guarda el valor anterior y el nuevo
- Se registra quién y cuándo hizo el cambio
- No se pueden borrar registros de auditoría
-
Cascada en Borrado
- Si se borra una inspección, se borran sus logs
- Si se borra una respuesta, se borran sus logs
- Los logs del usuario permanecen aunque se borre el usuario
🐛 Troubleshooting
Problema: "No puedo editar una respuesta"
Solución:
- Verificar que eres admin:
SELECT role FROM users WHERE id = X; - Verificar que la inspección está completada:
SELECT status FROM inspections WHERE id = Y; - Verificar que el botón "✏️ Editar" aparece
- Revisar consola del navegador para errores
Problema: "Error al guardar cambios"
Solución:
- Verificar que completaste el campo "Motivo del cambio"
- Verificar token de autenticación válido
- Revisar logs del backend para errores específicos
- Verificar que la tabla
inspection_audit_logexiste
Problema: "No veo el historial de cambios"
Solución:
- Verificar que eres admin
- Verificar que hay cambios registrados:
SELECT * FROM inspection_audit_log WHERE inspection_id = X; - Limpiar caché del navegador (Ctrl+Shift+R)
- Revisar consola del navegador para errores de API
Problema: "Los puntos no se recalculan correctamente"
Solución:
- Verificar la lógica en el backend (main.py, admin_edit_answer)
- Revisar que la pregunta tiene
pointsconfigurados - Verificar logs de auditoría para ver si se registró el cambio de puntos
- Recalcular manualmente si es necesario
🎉 Resumen
✅ Backend: Sistema completo de auditoría con registro automático
✅ Frontend: Edición inline + modal de historial
✅ Base de Datos: Tabla de auditoría con índices optimizados
✅ Seguridad: Solo admins, motivo obligatorio, registro inmutable
✅ Documentación: Completa con ejemplos y troubleshooting
El sistema está listo para usar después de ejecutar la migración SQL y reiniciar el backend.
📈 Beneficios
- Trazabilidad Completa: Saber quién cambió qué y cuándo
- Auditoría: Cumplimiento de normas de calidad y transparencia
- Corrección de Errores: Admins pueden corregir errores sin perder datos
- Accountability: Cada cambio requiere justificación documentada
- Historial Inmutable: Los registros no se pueden borrar ni modificar
- Reportes: Base de datos lista para generar reportes de cambios