# 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** ```bash # 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: ```sql -- 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** ```bash # 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 ```sql -- 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