Files
checklist/AUDITORIA_INSPECCIONES.md

12 KiB
Raw Permalink Blame History

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

  1. Modelo de Auditoría

    • Tabla inspection_audit_log que 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
  2. 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)
  3. 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

  1. 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
  2. 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 (✏️🗑️🔄)
  3. 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

  1. Abre el detalle de una inspección completada
  2. Busca la respuesta que quieres modificar
  3. Haz clic en el botón "✏️ Editar" junto a la respuesta
  4. 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
  5. Importante: Escribe el motivo del cambio en el campo "Motivo del cambio"
  6. Haz clic en "Guardar Cambios"
  7. 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

  1. Abre el detalle de cualquier inspección
  2. En el footer, haz clic en "📜 Ver Historial de Cambios"
  3. Se abrirá un modal con la bitácora completa
  4. 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:

  1. Admin abre la inspección
  2. Encuentra la respuesta con estado "Crítico"
  3. Clic en "✏️ Editar"
  4. Cambia Estado a "Advertencia"
  5. En "Motivo del cambio": "Error del mecánico, no era crítico sino advertencia menor"
  6. Guarda cambios
  7. 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:

  1. Admin edita la respuesta
  2. Agrega en "Observación": "Necesita cambio de aceite urgente"
  3. Mantiene el señalamiento activado
  4. Motivo: "Agregando observación faltante para clarity"
  5. 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:

  1. Admin abre inspección
  2. Clic en "📜 Ver Historial de Cambios"
  3. Revisa todos los cambios del mes
  4. Verifica justificaciones
  5. 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

  1. Solo Admins Pueden Editar

    • Los mecánicos NO pueden editar inspecciones completadas
    • Solo usuarios con rol admin tienen acceso
  2. Solo Inspecciones Completadas

    • No se pueden editar inspecciones en estado "draft"
    • El botón de editar solo aparece en inspecciones completadas
  3. Motivo Obligatorio

    • Cada cambio DEBE tener una justificación
    • El campo "Motivo del cambio" es obligatorio
    • No se puede guardar sin completarlo
  4. 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
  5. 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
  6. 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:

  1. Verificar que eres admin: SELECT role FROM users WHERE id = X;
  2. Verificar que la inspección está completada: SELECT status FROM inspections WHERE id = Y;
  3. Verificar que el botón "✏️ Editar" aparece
  4. Revisar consola del navegador para errores

Problema: "Error al guardar cambios"

Solución:

  1. Verificar que completaste el campo "Motivo del cambio"
  2. Verificar token de autenticación válido
  3. Revisar logs del backend para errores específicos
  4. Verificar que la tabla inspection_audit_log existe

Problema: "No veo el historial de cambios"

Solución:

  1. Verificar que eres admin
  2. Verificar que hay cambios registrados: SELECT * FROM inspection_audit_log WHERE inspection_id = X;
  3. Limpiar caché del navegador (Ctrl+Shift+R)
  4. Revisar consola del navegador para errores de API

Problema: "Los puntos no se recalculan correctamente"

Solución:

  1. Verificar la lógica en el backend (main.py, admin_edit_answer)
  2. Revisar que la pregunta tiene points configurados
  3. Verificar logs de auditoría para ver si se registró el cambio de puntos
  4. 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

  1. Trazabilidad Completa: Saber quién cambió qué y cuándo
  2. Auditoría: Cumplimiento de normas de calidad y transparencia
  3. Corrección de Errores: Admins pueden corregir errores sin perder datos
  4. Accountability: Cada cambio requiere justificación documentada
  5. Historial Inmutable: Los registros no se pueden borrar ni modificar
  6. Reportes: Base de datos lista para generar reportes de cambios