Files
admin-edu-space/docs/CHANGELOG_VIRTUAL_CLASSES_AND_DASHBOARDS.md
T

101 lines
8.0 KiB
Markdown

# Changelog: Corrección del Importador de Google Sheets, Clases Virtuales y Dashboards por Rol
**Fecha:** 18 de Septiembre de 2026
**Rama:** `testing`
**Autor:** Antigravity AI Assistant
---
## 1. Resumen Ejecutivo
Se investigó y resolvió la causa por la cual el importador de horarios desde Google Sheets no traía la totalidad de las clases virtuales ni se mostraban correctamente en las vistas del sistema (*Cartelera de Hoy*, *Catálogo de Aulas Virtuales*, *Cronograma* y *Dashboards*), tal como ocurría en la versión legacy.
### Causas Raíz Identificadas:
1. **Colisión de Horarios en Aulas Virtuales durante el Sync (`sheets_importer.py`)**:
- En la versión original, al buscar una reserva preexistente (`Reservation.query.filter_by(classroom_id=classroom.id, start_time=dt_start, end_time=dt_end).first()`), todas las clases virtuales apuntaban al mismo espacio (`Campus Virtual · VIRTUAL`).
- Cuando múltiples comisiones de diferentes asignaturas cursaban de manera virtual en la misma franja horaria (por ejemplo, jueves de 17:30 a 21:30 hs donde hay 13 comisiones simultáneas), el importador encontraba la primera reserva creada y descartaba las restantes 12 clases simultáneas actualizando únicamente notas/turno. Esto descartaba más del 75% de las clases virtuales de la planilla.
2. **Ausencia de Enlace Virtual Automático**:
- Las reservas virtuales se generaban sin enlace de videollamada (`virtual_link = None`), impidiendo que los botones de acceso directo ("Unirse a Videollamada / Zoom / Meet") se renderizaran en las vistas.
3. **Serialización Incompleta en la API Backend (`api/v1/reservations`)**:
- El endpoint `/api/v1/reservations` retornaba diccionarios planos sin el objeto anidado `classroom`, omitiendo propiedades críticas como `is_virtual`, `effective_virtual_link`, `subject_name`, `subject_code` y `location_display`.
4. **Falta de Agregación de Salas Virtuales en el BFF Node.js (`classrooms.js`)**:
- En el catálogo de aulas (`/classrooms/list_classrooms?view_mode=virtual`), la plantilla esperaba un arreglo `virtual_rooms` agrupado por comisión con métricas de demanda (`today_count`, `week_count`, `month_count`) y `global_virtual_metrics`. El controlador Node no las generaba, dejando la vista vacía.
5. **Rutas y Vista de Cartelera del Día (`schedule.js` y `app.js`)**:
- `/schedule/today_schedule` no estaba mapeado directamente en el enrutador de Express y su redirección descartaba parámetros de búsqueda (`hide_virtual`, `shift`, `floor`).
- El controlador no calculaba `time_blocks` (horas 7 a 21), provocando que `schedule/today.html` cayera en la condición vacía ("No hay reservas programadas para hoy").
---
## 2. Soluciones Implementadas
### A. Backend Python (`backend/app/services/sheets_importer.py`)
- Se diferenció la comprobación de unicidad para aulas virtuales: al tratarse de espacios con concurrencia ilimitada, la consulta de reserva existente incluye `commission_id=commission.id`.
- Se implementó la generación automática de enlaces de reunión seguros (`https://meet.google.com/edu-{subject_code}-{commission_code}`) para todas las clases y comisiones en modalidad virtual.
- **Resultado del re-sync:** Se procesaron 239 filas de las 6 hojas semanales, añadiendo **280 reservas** que antes colisionaban, alcanzando **388 reservas virtuales activas** en la base de datos con sus respectivos enlaces de videollamada.
### B. Endpoint de Reservas (`backend/app/routes/api/reservations.py`)
- Se enriqueció la serialización de reservas incorporando:
- Objeto anidado `classroom` con `code`, `floor`, `floor_display`, `is_virtual` y `location_display`.
- Objeto `commission` con `code` y `virtual_link`.
- Propiedades computadas `subject_name`, `subject_code`, `effective_virtual_link` e `is_virtual`.
- Se añadieron filtros por query params: `hide_virtual`, `floor`, `shift` y `search`.
### C. Catálogo de Aulas Virtuales (`frontend/src/routes/classrooms.js`)
- Para `view_mode === 'virtual'`, se implementó la agregación de reservas por comisión, calculando:
- `virtual_rooms`: Listado con código de comisión, asignatura, enlace de videollamada, cupo, turno y conteos de sesiones (Hoy, Semana, Mes).
- `global_virtual_metrics`: Contadores globales de clases remotas de hoy, semana, mes y comisiones con entorno virtual activo.
- Asignación de `virtual_classroom_id` para enlaces de gestión.
### D. Cartelera del Día (`frontend/src/routes/schedule.js` y `frontend/src/app.js`)
- Se unificaron las rutas `/today` y `/today_schedule`.
- Se implementó el generador de `time_blocks` para las franjas horarias de 7:00 a 22:00 hs.
- Se implementó soporte completo para el switch "Ocultar Aulas Virtuales" (`hide_virtual=1`), filtros por piso y por turno.
- Se preservan los query params en todas las redirecciones de Express.
### E. Dashboards Personalizados por Rol (`frontend/views/dashboard.html` y `dashboard.js`)
- Habilitación de paneles operativos específicos para **Bedelía**, **Docente / Profesor**, **Alumno / Estudiante** y **Administrador**, con selector dinámico en el banner superior.
---
## 3. Pruebas y Verificación
Se ejecutó la suite de verificación automatizada:
1. **Catálogo de Aulas Virtuales (`/classrooms/list_classrooms?view_mode=virtual`)**:
- Status: `200 OK`.
- Renderiza tarjetas `virtual-room-card` con enlaces a Google Meet y badges "Remoto ∞".
2. **Cartelera del Día (`/schedule/today_schedule`)**:
- Status: `200 OK`.
- Muestra timeline cronológico por horas con clases presenciales y virtuales.
- Botón `hide_virtual=1` filtra instantáneamente las aulas virtuales.
3. **Calendario General (`/schedule/calendar_data`)**:
- 643 eventos en calendario (388 virtuales identificados con `#6366F1` y enlaces activos).
4. **Vistas Principales**:
- 11/11 rutas pasaron con código 200 sin errores de plantilla ni excepciones de servidor.
---
## 4. Acople de `schedule.view_reservation` al BFF Node.js y Gestión de Comisiones
### A. Vista Detallada de Reserva (`schedule.view_reservation`)
- **Backend API (`/api/v1/reservations/<id>`)**:
- Enriquecimiento del payload serializado para incluir objetos relacionales completos: `classroom` (código, edificio, piso, capacidad, descripción, modalidad virtual), `commission` (código, código compuesto, materia, cuatrimestre, año, cupos), `user` (docente, nombre, apellido, email), `duration`, `effective_virtual_link` y `can_be_cancelled`.
- Incorporación de endpoints de acción directa `POST /api/v1/reservations/<id>/confirm` y `POST /api/v1/reservations/<id>/cancel`.
- **Node.js BFF (`frontend/src/routes/schedule.js`)**:
- Implementación de `handleViewReservation` con soporte para `/view_reservation`, `/view_reservation/:id`, `/view/:id`, y `/reservation/:id/view`.
- Implementación de `handleEditReservation` (GET & POST), `handleConfirmReservation` y `handleCancelReservation`.
- Actualización de plantillas (`view.html`, `today.html`, `list.html`, `dashboard.html`) para enlazar directamente las fichas pasando el ID de la reserva.
### B. Creación de Comisiones y Asociación con Materias (`/admin/commissions_list`)
- **Modal y Acción en Interfaz**:
- Incorporación de botón destacado `+ Nueva Comisión` en el encabezado y en el estado vacío de la tabla.
- Implementación de modal interactivo `#modalAddCommission`:
- Selector obligatorio de **Asignatura / Materia Asociada** (`subject_id`), mostrando código, nombre y carrera.
- Campos de código de comisión, cuatrimestre, año lectivo, turno, docente a cargo, cupo máximo y días/horarios.
- Generación y configuración de enlace a aula virtual (Google Meet institucional).
- Alerta de confirmación visual (`?created=1`) al registrar y vincular la comisión exitosamente.
- **Backend API (`POST /api/v1/admin/commissions`)**:
- Validación de existencia de la asignatura vinculada y resolución inteligente de duplicados (`subject_id`, `code`, `semester`, `year`).
- Auto-generación de enlaces seguros de Google Meet en caso de no especificarse enlace personalizado.