376 lines
12 KiB
Markdown
376 lines
12 KiB
Markdown
# 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
|