Files
pagasis/backend/ESTADISTICAS_README.md

283 lines
10 KiB
Markdown

# Sistema de Estadísticas de Asistencia
## Cambios Implementados
### 1. Actualización Automática de Estadísticas
Se implementó un sistema de señales (signals) que **actualiza automáticamente** las estadísticas de asistencia cuando:
- **Se elimina un evento**: Todas las estadísticas de todos los estudiantes se recalculan automáticamente
- **Se crea un nuevo evento**: Todas las estadísticas se actualizan para reflejar el nuevo total de eventos
- **Se elimina una asistencia**: Solo se actualizan las estadísticas del estudiante afectado
**Archivos modificados:**
- `backend/attendance/signals.py` (nuevo)
- `backend/attendance/apps.py` (modificado para registrar señales)
- `backend/attendance/__init__.py` (modificado)
### 2. Prevención de Importación Inconsistente
El admin de Django para **AttendanceStats** ahora:
-**Solo permite EXPORTAR** estadísticas (no importar)
- ✅ Los campos `total_events`, `attended_events` y `attendance_percentage` **siempre se calculan automáticamente**
- ✅ No es posible importar valores manualmente que causen inconsistencias
**Archivos modificados:**
- `backend/attendance/admin.py` - Cambiado de `ImportExportMixin` a `ExportMixin`
### 3. Comando de Recálculo Manual
Se puede ejecutar manualmente el recálculo de estadísticas con:
```bash
docker exec pagina-de-asistencia-mac-backend-1 python manage.py recalculate_stats
```
Este comando:
- ✅ Recalcula las estadísticas de **TODOS** los estudiantes
- ✅ Crea estadísticas para estudiantes que no las tienen
- ✅ Garantiza que **todos los estudiantes tengan el mismo total_events**
**Cuándo usarlo:**
- Después de importar asistencias históricas
- Si sospechas que hay inconsistencias en las estadísticas
- Después de eliminar eventos manualmente desde la BD
## Garantías del Sistema
### ✅ Total de Eventos Consistente
**TODOS los estudiantes siempre tendrán el mismo valor en `total_events`**, que representa el número total de "bloques de horario" de eventos activos en el sistema.
### ✅ Actualización Automática
No es necesario recalcular manualmente las estadísticas en operaciones normales:
- Eliminar un evento → Estadísticas se actualizan automáticamente
- Agregar asistencias → Estadísticas se actualizan automáticamente
- Eliminar asistencias → Estadísticas se actualizan automáticamente
### ✅ Importación Segura y Optimizada
Al importar asistencias desde Excel:
- ✅ Se pueden importar estudiantes y eventos asistidos
- ✅ Las estadísticas se actualizan **automáticamente al finalizar** la importación
-**Optimización de rendimiento**: Las estadísticas se actualizan en batch (una vez por estudiante afectado, no una vez por asistencia)
-**NO** se pueden importar valores de `total_events` directamente (son calculados automáticamente)
**Ejemplo de optimización:**
```
Importando 1000 asistencias de 50 estudiantes diferentes:
- ❌ Sin optimización: 1000 actualizaciones de estadísticas
- ✅ Con optimización: 50 actualizaciones (una por estudiante)
```
**Proceso de importación:**
1. Se importan todas las asistencias
2. Se registra qué estudiantes fueron afectados
3. Al finalizar, se actualizan las estadísticas solo de los estudiantes afectados
4. Mensaje de confirmación: `[IMPORTACIÓN] ✓ Estadísticas actualizadas para X estudiante(s)`
## Verificación
Para verificar que todas las estadísticas son consistentes:
```bash
docker exec pagina-de-asistencia-mac-backend-1 python -c "
import os
import django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mac_attendance.settings.local')
django.setup()
from attendance.models import AttendanceStats
stats = AttendanceStats.objects.all()
total_events_values = stats.values_list('total_events', flat=True).distinct()
print(f'Valores únicos de total_events: {list(total_events_values)}')
if len(total_events_values) == 1:
print('✓ CORRECTO: Todos tienen el mismo total')
else:
print('✗ ERROR: Hay inconsistencias')
"
```
## Importación de Asistencias desde Excel
### Paso a Paso
1. **Preparar archivo Excel** con las siguientes columnas:
**⚠️ IMPORTANTE: NO incluir columna 'id' - se genera automáticamente**
- `account_number`: Matrícula del estudiante (8 dígitos) **[REQUERIDO]**
- `student_name`: Nombre del estudiante (opcional, solo informativo)
- `event_title`: Título exacto del evento (debe existir en la BD) **[REQUERIDO]**
- `timestamp`: Fecha y hora de registro (opcional)
- Formatos aceptados:
- `DD/MM/YYYY HH:MM` (ej: 24/10/2025 11:44)
- `DD/MM/YYYY HH:MM:SS` (ej: 24/10/2025 11:44:00)
- `YYYY-MM-DD HH:MM:SS` (ej: 2025-10-24 11:44:00)
- `YYYY-MM-DD HH:MM` (ej: 2025-10-24 11:44)
- `registered_by_account`: Matrícula del asistente (opcional, default: 11111111)
- `registration_method`: manual o barcode (opcional, default: manual)
- `notes`: Notas adicionales (opcional)
- `is_valid`: True o False (opcional, default: True)
2. **Ir al Django Admin** → Asistencias → IMPORTAR
3. **Seleccionar el archivo Excel**
4. **Vista previa**: Revisar que los datos se vean correctos
5. **Confirmar importación**
6. **Verificar mensaje**:
```
[IMPORTACIÓN] Actualizando estadísticas de X estudiante(s) afectado(s)...
[IMPORTACIÓN] ✓ Estadísticas actualizadas para X estudiante(s)
```
### Ejemplo de Excel
**✅ CORRECTO (sin columna 'id'):**
```
account_number | student_name | event_title | timestamp
42502372 | Aramburo Chang | App Kachi México y su cultura | 24/10/2025 18:30
31720256 | Arenas Juarez | App Kachi México y su cultura | 24/10/2025 18:30
42610156 | Barraza Casta. | De principiante a protector... | 24/10/2025 19:30
```
**❌ INCORRECTO (con columna 'id'):**
```
id | account_number | student_name | event_title | timestamp
1815 | 42502372 | Aramburo Chang | App Kachi México y su cultura | 24/10/2025 18:30
```
⚠️ NO incluir la columna 'id' - causará errores
### Validaciones Automáticas
Durante la importación se valida:
- ✅ Que el estudiante exista en la BD
- ✅ Que el evento exista en la BD
- ✅ Que no haya duplicados (mismo estudiante + mismo evento)
- ✅ Que no haya eventos simultáneos (estudiante no puede estar en dos eventos a la vez)
Si hay errores, se mostrarán en rojo y las filas con error NO se importarán.
### Después de la Importación
**NO es necesario** ejecutar ningún comando adicional. Las estadísticas se actualizan automáticamente.
Si quieres verificar:
```bash
docker exec pagina-de-asistencia-mac-backend-1 python -c "
from attendance.models import AttendanceStats
stats = AttendanceStats.objects.all()
print(f'Total de estudiantes: {stats.count()}')
print(f'Valores de total_events: {set(stats.values_list(\"total_events\", flat=True))}')
"
```
## Administración desde Django Admin
### Acciones disponibles en AttendanceStats Admin:
1. **📊 Exportar estadísticas seleccionadas**
- Exporta las estadísticas de los estudiantes seleccionados
2. **📊 Exportar estudiantes que cumplen requisito para constancia**
- Exporta solo los estudiantes que tienen el porcentaje mínimo de asistencia
3. **🔄 Actualizar estadísticas seleccionadas**
- Recalcula las estadísticas de los estudiantes seleccionados
- Útil si se modificaron eventos o asistencias
## Notas Técnicas
### Cálculo de Total de Eventos (Bloques de Horario)
El sistema usa **bloques de horario** en lugar de contar eventos individuales:
- Eventos simultáneos en la misma fecha/hora se cuentan como **1 solo bloque**
- El estudiante solo necesita asistir a **uno de los eventos simultáneos** para marcar ese bloque como asistido
- Dos eventos son simultáneos si tienen la **misma fecha, misma hora de inicio y misma hora de fin**
**Ejemplo real del sistema:**
```
21 eventos activos en total:
Bloques con múltiples eventos simultáneos:
- 21/Oct 11:00-12:00: 2 eventos (cuenta como 1 bloque)
• Matemáticas Aplicadas a Medicina...
• Tecnologías IIoT al servicio de la Industria
- 21/Oct 12:00-13:00: 2 eventos (cuenta como 1 bloque)
• La presión fiscal como oportunidad...
• Matemáticas Aplicadas y Computación...
- 23/Oct 11:00-12:00: 2 eventos (cuenta como 1 bloque)
• MAC aplicado en el sector de aseguradoras
• Análisis de Escenas Auditivas
- 23/Oct 12:00-13:00: 2 eventos (cuenta como 1 bloque)
• Investigación en MAC con IA
• Cuando los datos hablan...
Total de bloques = 21 eventos - 8 (que se combinan en 4 pares) + 4 (bloques únicos) = 17 bloques
```
**IMPORTANTE:** Si tienes 21 eventos activos pero 4 pares son simultáneos, el `total_events` será **17**, no 21.
### Logs de las Señales
Las señales imprimen mensajes en la consola del contenedor Docker:
```
[SIGNAL] Evento 'Nombre del Evento' eliminado. Actualizando estadísticas de todos los estudiantes...
[SIGNAL] Se actualizaron las estadísticas de 6359 estudiantes.
```
Para ver los logs:
```bash
docker logs -f pagina-de-asistencia-mac-backend-1
```
## Solución de Problemas
### Problema: "Tengo estudiantes con diferentes total_events"
**Solución:**
```bash
docker exec pagina-de-asistencia-mac-backend-1 python manage.py recalculate_stats
```
### Problema: "Las estadísticas no se actualizan al eliminar un evento"
**Verificar:**
1. Que el contenedor Docker esté corriendo
2. Que no haya errores en los logs: `docker logs pagina-de-asistencia-mac-backend-1`
3. Ejecutar recalculate_stats manualmente si es necesario
### Problema: "Quiero importar estadísticas desde Excel"
**Solución:**
- NO importes estadísticas directamente
- En su lugar, importa solo las **asistencias** (estudiantes + eventos)
- Las estadísticas se calcularán automáticamente
- Luego ejecuta: `python manage.py recalculate_stats` para asegurar consistencia
## Migración de Datos Históricos
Si tienes datos históricos con estadísticas inconsistentes:
1. **Respalda tu base de datos** (por si acaso)
2. Ejecuta el comando de recálculo:
```bash
docker exec pagina-de-asistencia-mac-backend-1 python manage.py recalculate_stats
```
3. Verifica la consistencia con el script de verificación
4. Exporta las estadísticas actualizadas desde el admin
---
**Fecha de implementación:** Octubre 2025
**Versión:** 1.0