# Changelog Oficial — Admin Edu-Space (UniCABA) Todas las modificaciones notables a este proyecto serán documentadas en este archivo. El formato está basado en [Keep a Changelog](https://keepachangelog.com/es-ES/1.1.0/) y este proyecto se adhiere a [Semantic Versioning](https://semver.org/lang/es/). --- ## [Unreleased] ### Planificado (Fase 6 del Roadmap MVP) - **Despliegue e Infraestructura (Fase 6):** `docker-compose.yml` productivo orquestando Flask (Gunicorn), Node.js BFF (PM2) y PostgreSQL 15, con proxy inverso Nginx, SSL/TLS y compresión. - **Sincronización Continua Moodle (Fase 6):** Automatización de workers persistentes en background para el procesamiento continuo de la cola de Web Services Moodle 4.1. - **Pruebas de Carga y Hardening (Fase 6):** Pruebas de estrés de concurrencia y validación final de producción. --- ## [3.0.0] - 2026-09-23 ### Añadido - **Fase 5 — Integración Auth, Email & Moodle Backend:** - **Épica 1: Panel de Configuración Global (Perfil ADMIN):** - Cifrado simétrico de credenciales y secretos con Fernet (`CryptoService` en `backend/app/services/crypto_service.py`). - Migración y extensión de `SystemSetting` con columnas `category` e `is_encrypted`, junto con métodos polimórficos `get_decrypted_value()` y `get_masked_value()`. - Endpoints REST `/api/v1/admin/settings/*` para administración dinámica de parámetros SMTP, toggles de proveedores SSO, Google OAuth y Web Services de Moodle 4.1. - Nueva vista responsiva `frontend/views/admin/settings/global_config.html` con soporte optimizado para pantallas 720p, 1360x768 y 1080p, y enlace integrado en el menú de navegación lateral. - **Épica 2: Infraestructura Asíncrona y Caché:** - Servicio híbrido de caché `CacheService` con integración Redis y fallback en memoria/TTL. - Modelo `MoodleSyncTask` y procesador asíncrono `MoodleQueueService` con Exponential Backoff y Dead Letter Queue (DLQ). - Métricas en vivo y reintentos manuales individuales y masivos para tareas en DLQ. - **Épica 3: Autenticación Híbrida (SSO & Local):** - Login nativo como fallback con contingencia para cuentas con rol ADMIN. - Integración de Google OAuth 2.0 basada en la arquitectura de AlumnosLS con filtrado estricto por dominios institucionales (`google_allowed_domains`). - Autenticación delegada contra Moodle 4.1 vía `/login/token.php`, mapeo inicial de roles (Admin/Docente/Alumno) y gestión de roles 100% desacoplada en Edu-Space. - **Épica 4: Integración Bidireccional Moodle 4.1:** - Adaptador `MoodleClient` con Web Services de Moodle 4.1 (`core_user_*`, `enrol_manual_*`, `core_enrol_*`, `core_role_*`). - Encolado no bloqueante de sincronización al crear o editar usuarios en Edu-Space. - **Épica 5: Motor de Notificaciones (Email Server):** - Cliente SMTP dinámico en `EmailService` con desencriptación en caliente de contraseñas. - Plantillas HTML transaccionales para asignación de comisiones a profesores, citación a exámenes y pruebas en vivo de conectividad. - **Pruebas y Verificación:** - Suite de integración automatizada `backend/tests/test_phase6_integration.py` con 7 pruebas aprobadas al 100%. Regresión completa de 30 pruebas en verde en los módulos core. --- ## [2.8.0] - 2026-09-23 ### Añadido - **Fase 4 del Roadmap MVP — UI/UX Avanzada para Bedelía & Modo Impersonación:** - **Estadio 4.1 — Grilla Semanal Interactiva (Drag-and-Drop) con Detección de Colisiones:** - Activación de arrastre y edición interactiva en FullCalendar (`editable: true`, `droppable: true`, `eventDurationEditable: true`). - Panel lateral integrado de comisiones sin aula asignada (`unassigned_commissions`) con arrastre fluido hacia la grilla semanal o diaria. - Endpoint REST `POST /api/v1/reservations/drag-update` con validación previa de la matriz integral de conflictos (`ReservationService.check_full_conflicts_matrix`): colisión física de aula, colisión de horario docente y aforo de estudiantes. - Si existe colisión, retorna HTTP 409 (`status: conflict`), revierte automáticamente la posición del evento en la grilla (`info.revert()`) y notifica al usuario con un Toast detallado del motivo del choque. - Si el espacio está disponible, actualiza o crea la reserva en base de datos, asienta la acción en `AuditLog` y muestra confirmación visual de éxito. - **Estadio 4.2 — Modo Impersonación del Superadmin:** - Soporte completo de cabecera `X-Impersonate-User` en el decorador JWT del Backend Flask (`jwt_required`) para administradores. - Endpoints administrativos `POST /api/v1/admin/impersonate` y `POST /api/v1/admin/stop-impersonating` con registro estricto en `AuditLog` bajo las acciones `IMPERSONATE_START` e `IMPERSONATE_END`. - Inyección contextual de impersonación en el Frontend BFF (`authMiddleware` y proxy transparente `/api`) mediante cookies seguras `impersonate_user_id` e `impersonate_user_data`. - Banner de advertencia visual permanente en la barra superior (`base.html`) indicando el usuario y rol impersonado, con botón de salida inmediata hacia la sesión del administrador. - Botón de acceso directo para impersonar (`bi-incognito`) en cada fila de usuario activo en `/admin/users_list`. - **Estadio 4.3 — Acople del Optimizador Genético a Datos y Turnos Reales:** - Algoritmo genético (`ReservationOptimizer`) adaptado a las franjas horarias y turnos institucionales reales de UniCABA (`Mañana` 08:00-12:00, `Tarde` 14:00-18:00, `Vespertino`/`Noche` 18:30-22:30). - Soporte de guardado masivo en base de datos (`POST /api/genetic/apply-optimization` y `apply_optimized_reservations`) con prevención de solapamientos físicos y conversión estricta de fechas ISO. - **Suite de Pruebas Unitarias de Fase 4:** - Archivo `backend/tests/test_phase4_interactive_impersonation.py` con 6 tests unitarios cubriendo los criterios de aceptación: impersonación como docente y estudiante, trazabilidad en auditoría, rechazo de impersonación para usuarios no administradores, finalización de impersonación, drag-update con bloqueo por colisión 409 y drag-update exitoso 200. - Regresión global de 18 tests (Fases 2, 3 y 4) aprobada al 100% (18/18 OK). --- ## [2.7.0] - 2026-09-23 ### Añadido - **Fase 3 del Roadmap MVP — Gestión de Hitos Evaluativos y Libro de Calificaciones (*Gradebook*):** - **Estadio 3.1 — Calendario de Evaluación y Notificaciones Preventivas:** - Modelo relacional `MilestoneGrade` (`milestone_grades`) asociado a estudiantes (`User`) y reservas de tipo hito (`Reservation`). - Servicio `GradebookService.get_student_upcoming_milestones`: consulta inteligente de exámenes parciales, recuperatorios y entregas de TP de las comisiones en las que el alumno está matriculado. - Endpoint REST `GET /api/v1/students/my-upcoming-milestones` con cálculo de días restantes (`days_remaining`). - Cartelera y Widget de Próximos Exámenes en el Dashboard del Alumno (`/dashboard?role=alumno`) con badges dinámicos de cuenta regresiva (*¡Hoy!*, *¡Mañana!*, *Faltan X días*). - **Estadio 3.2 — Libro de Calificaciones (*Gradebook*) y Cierre de Actas:** - Extensiones al modelo `Commission`: campos `grades_closed` (booleano), `grades_closed_at` (timestamp), `grades_closed_by` (ID usuario) y `acta_number` (código oficial de acta). - Servicio académico `GradebookService` (`backend/app/services/gradebook_service.py`): - `get_commission_gradebook`: matriz bidimensional consolidada de alumnos inscriptos y notas por hito evaluativo. - `save_single_grade` y `bulk_save_grades`: registro y actualización de calificaciones con validación estricta de escala (1.0 a 10.0), flag de ausente (`is_absent`) y soporte de retroalimentación pedagógica (`feedback`). - Bloqueo por inmutabilidad: rechazo de modificaciones cuando el acta se encuentra cerrada. - `close_gradebook`: sellado oficial del acta con generación de identificador inmutable (`ACTA-YYYY-Sem-ID`), registro de auditoría en `AuditLog` y congelamiento de calificaciones. - `reopen_gradebook`: reapertura excepcional para Bedelía/Admin con justificación administrativa obligatoria y registro en auditoría. - `get_student_grades`: consolidado para el alumno de todas sus materias cursadas, notas por evaluación, promedio general y condición académica final (*Promocionado*, *Regular*, *Libre*). - Endpoints REST de Calificaciones: - `GET /api/v1/commissions//gradebook`: estructura completa para la matriz del libro de calificaciones. - `PUT /api/v1/commissions//gradebook/grades`: guardado masivo o individual de notas vía JSON. - `POST /api/v1/commissions//gradebook/close`: cierre formal de acta. - `POST /api/v1/commissions//gradebook/reopen`: reapertura justificada de acta. - `GET /api/v1/students/my-grades`: consulta individual de notas y regularidad del estudiante. - Interfaz de Usuario y Vistas Frontend BFF: - Vista `/schedule/gradebook/:id`: matriz interactiva con cálculo de promedio en tiempo real en el DOM, asignación de condición en vivo, autoguardado asíncrono debounced (500ms) con indicador flotante de estado (*Guardando...*, *✓ Todos los cambios guardados*), filtro de búsqueda instantánea por alumno/legajo, modal de cierre formal de acta y modal de reapertura. - Vista `/schedule/my_grades` (`/mis-materias/mis-notas`): portal del estudiante para consultar calificaciones por hito, promedios finales, condición de cursada y actas emitidas, con soporte de impresión de certificado de cursada. - Acceso directo integrado al Libro de Calificaciones en la tarjeta de comisión de `/admin/commission_detail`. - Acceso directo a "Mis Calificaciones" en el launchpad de navegación del alumno en `/dashboard`. - Script de migración de base de datos SQLite `backend/migrate_phase3_fields.py`. - **Suite de Pruebas Unitarias de Fase 3:** - Archivo `backend/tests/test_phase3_gradebook.py` con 6 tests unitarios cubriendo los criterios de aceptación de Fase 3: estructura de matriz, autoguardado de notas, validaciones de rango numérico, cierre formal de acta e inmutabilidad, consulta individual de notas y cuenta regresiva de próximos exámenes. 100% de tests aprobados (12/12 en suite global Fase 2 + Fase 3). --- ## [2.6.1] - 2026-09-23 ### Modificado - **Optimización de Espacio Vertical y Compatibilidad de Pantallas (720p / 1360x768 y 1080p):** - **Navbar Compacta:** Reducción de altura a 46px eliminando desperdicio de espacio superior para maximizar el área visible de trabajo de Bedelía. - **Botón de Toggle de Sidebar:** Reingeniería visual del botón de alternancia del menú lateral con diseño circular limpio, micro-animación en hover y centrado perfecto. - **Soporte Multipantalla:** Media queries CSS especializadas para resoluciones compactas habituales en puestos de trabajo de administración y bedelía argentina (1360x768 / 1366x768) y escalado equilibrado a 1920x1080 Full HD. - **Densidad de Información:** Espaciados y márgenes optimizados para evitar scrolling innecesario en formularios y catálogos de comisiones y aulas. --- ## [2.6.0] - 2026-09-19 ### Añadido - **Fase 2 del Roadmap MVP — Co-docencia, Matriz de Conflictos y Regla Diaria:** - **Estadio 2.1 — Modelo y Gestión Integral de Co-docencia:** - Modelo relacional `CommissionTeacher` (`commission_teachers`) con roles de cátedra (`Titular`, `Adjunto`, `JTP`, `Ayudante`) y flags de docente principal. - Endpoints REST de cátedra: `POST /api/v1/commissions//teachers` y `DELETE /api/v1/commissions//teachers/` con control de duplicados y asignación dinámica. - Integración visual en el detalle de la comisión (`/admin/commission_detail`) con tarjeta interactiva para vincular/desvincular integrantes del equipo docente y badges de rol en la grilla general (`/admin/commissions_list`). - **Estadio 2.2 — Matriz de Conflictos y Validación Integral:** - **Conflicto Físico Estricto:** Bloqueo estricto de superposición horaria en la misma aula física (`ReservationRepository.find_overlapping` & `check_physical_conflicts`). - **Conflicto Docente Inteligente:** Detección de doble reserva simultánea para un mismo profesor (`ReservationRepository.find_teacher_conflicts` & `check_teacher_conflicts`). - **Excepción Justificada por Co-docencia:** Si un docente asignado presenta solapamiento pero la comisión cuenta con co-docentes registrados en `CommissionTeacher`, el motor de conflictos autoriza la reserva validando la cobertura del equipo de cátedra. - **Conflicto de Aforo:** Bloqueo estricto cuando la cantidad de asistentes esperados (`expected_attendees`) excede la capacidad física declarada del aula (`classroom.capacity`). - Endpoint unificado `POST /api/v1/reservations/check-conflicts` para pre-validación asíncrona de conflictos físicos, docentes y de capacidad antes del guardado. - **Estadio 2.3 — Regla de Restricción Diaria del Alumno y Motor de Excepciones:** - Servicio académico `EnrollmentService` (`backend/app/services/enrollment_service.py`) para control de cupos, inscripciones activas y análisis de días de cursada. - **Regla Diaria:** Un alumno no puede matricularse en dos materias regulares programadas para el mismo día de la semana. - **Excepción Automática por Curso Corto:** Indicador `is_short_course` en modelo `Subject`; si una de las asignaturas es un taller, seminario o curso corto, el sistema autoriza automáticamente la cursada simultánea en el mismo día. - **Excepción Expresa de Bedelía:** Parámetros `allow_same_day_exception` y `exception_reason` en el modelo `StudentEnrollment`, permitiendo a Bedelía inscribir alumnos con justificación administrativa expresa (cambio de plan, equivalencias, etc.). - Endpoints de gestión de matrículas por comisión: `GET /api/v1/commissions//enrollments`, `POST /api/v1/commissions//enrollments`, `DELETE /api/v1/commissions//enrollments/` y `PUT /api/v1/commissions//enrollments/`. - Adaptación completa de UI en `/admin/commission_detail` con selector de estudiantes, toggle interactivo de excepción de Bedelía, campo de motivo justificado, y tabla de estudiantes matriculados con badges de excepción. - **Suite de Pruebas Unitarias e Integrales de Reglas de Negocio:** - Archivo `backend/tests/test_phase2_rules.py` con 6 tests completos verificando: bloqueo físico, conflicto de aforo, detección docente con bypass de co-docencia, restricción diaria de cursada, excepción por curso corto y excepción por autorización manual de Bedelía. 100% de tests aprobados. - **Mejoras UI/UX en Dashboard de Bedelía:** - Paneles interactivos para visualizar **Comisiones Sin Reserva de Aula** y **Aulas Disponibles** con soporte de filtrado temporal (Semana/Mes) directamente consumiendo estadísticas en tiempo real del motor backend. - **Fase 1: Auditoría y Seguridad Automatizada:** - **Control de Entorno Dev:** Aislamiento de herramientas de seguridad en `requirements-dev.txt`. - **Automatización Local e Integración Continua:** Correcciones de evaluación en `security_audit.bat` para Windows y actualización de `.gitea/workflows/security-audit.yaml` para asegurar la correcta ejecución del stack de auditoría (Bandit, pip-audit, njsscan y Schemathesis). ## [2.5.0] - 2026-09-19 ### Añadido - **Auditoría y Seguridad Automatizada Completa (Python & Node.js):** - **Python SAST (`bandit`):** Escaneo estático del backend Flask de más de 8.400 líneas. Corrección de vulnerabilidad B310 en `sheets_importer.py` mediante validación estricta de esquema HTTP/HTTPS para prevenir ataques de tipo SSRF. Resultado: 0 fallos detectados. - **Python SCA (`pip-audit`):** Análisis de dependencias con base OSV; detección de 24 CVEs históricas en paquetes desactualizados y actualización completa a versiones seguras (`Flask>=3.1.3`, `Werkzeug>=3.1.8`, `requests>=2.34.2`, `bleach>=6.4.0`, `python-dotenv>=1.2.3`). Resultado: 0 CVEs activas. - **Python DAST / Fuzzing (`schemathesis`):** Especificación OpenAPI 3.0.3 en `backend/app/routes/api/openapi.py` (`/api/v1/openapi.json`). Ejecución de 114 casos de prueba dinámicos con mutación de datos. Detección y corrección de caída 500 por payload de tipo JSON inválido en `/auth/login`. Resultado: 114/114 pruebas aprobadas con 0 errores de servidor. - **Node.js SAST (`njsscan`):** Análisis de patrones de código inseguro en el BFF Express (`frontend/src`). Resultado: 0 hallazgos. - **Node.js SCA (`npm audit`):** Auditoría continua de paquetes npm con 0 vulnerabilidades reportadas. - **Blindaje Activo (`helmet` & `express-rate-limit`):** Incorporación de cabeceras HTTP defensivas (`HSTS`, `nosniff`, `SAMEORIGIN`, `X-Permitted-Cross-Domain-Policies`) y limitadores de tasa ante fuerza bruta en `/auth/login` (30 req / 15 min) y `/api` (180 req / min). - **Script Unificado de Auditoría (`security_audit.bat`):** Ejecutable centralizado para correr los 5 controles en un solo comando. - **Documento Formal de Seguridad (`SECURITY_AUDIT_REPORT.md`):** Reporte ejecutivo de auditoría y controles continuos. --- ## [2.4.0] - 2026-09-19 ### Añadido - **Perfil Extendido de Usuarios y Tipificaciones de Documentos Oficiales (Argentina y Extranjeros):** - Incorporación en el modelo `User` de los campos: `first_name` (Nombre), `last_name` (Apellido), `email` (Email Institucional de acceso), `personal_email` (Email Personal/Particular de contacto), `phone` (Teléfono con código de área), `address` (Domicilio/Dirección), `document_type` (Tipo de documento) y `document_number` (Número de documento validado). - Catálogo formal de reglas de negocio en `backend/app/constants/document_types.py` con tipificaciones oficiales de Argentina y extranjeros (DNI, CUIL, Pasaporte Argentino, Pasaporte Extranjero, DNI Extranjero, Cédula de Identidad PFA, Cédula Mercosur, Libreta Cívica y Libreta de Enrolamiento). - Validaciones de formato, expresiones regulares, y verificación de unicidad de documento por tipo en endpoints `POST /api/v1/users` y `PUT /api/v1/users/`. - Búsqueda dinámica en `/admin/users_list` habilitada para filtrar por número de documento o email personal/institucional además de nombre. - Rediseño del formulario `/admin/users/form` estructurado en secciones: Identidad y Documentación, Contacto y Domicilio (con Teléfono, Email Personal y Dirección), y Cuenta y Rol Institucional (con Email Institucional y Clave), permitiendo al Administrador General gestionar la totalidad de los datos. - Script de migración SQLite `backend/migrate_user_profile_fields.py` para agregar las columnas e inicializar nombres desglosados de los usuarios existentes. - **Co-Docencia y Cátedras Múltiples en Comisiones:** - Creación del modelo relacional `CommissionTeacher` (`commission_teachers`) para asociar múltiples docentes a una misma comisión con roles académicos diferenciados (`Titular`, `Adjunto`, `JTP`, `Ayudante`). - Nuevos endpoints en la API REST: `POST /api/v1/commissions//teachers` y `DELETE /api/v1/commissions//teachers/`, junto con la serialización completa de cátedras en `GET /api/v1/commissions`. - Nueva tarjeta interactiva *"Equipo Docente / Cátedra"* en el detalle de la comisión (`/admin/commission_detail?id=...`) permitiendo agregar y desvincular docentes con sus respectivos roles. - Actualización de la grilla de comisiones (`/admin/commissions_list`) para exhibir a todos los profesores asignados con badges distintivos de rol. - **Eliminación y Gestión Segura de Asignaturas:** - Incorporación de botón y modal interactivo de confirmación de eliminación de asignaturas en `/admin/subjects_list`. - Implementación de regla de negocio de integridad académica: eliminación física si la materia no tiene comisiones asociadas, o desactivación automática si posee historial o cursadas vinculadas. ### Corregido - **Bug Visual en Modificación de Asignaturas (`/admin/subjects_list`):** - Solucionado el problema de modales recortados o cubiertos por el fondo oscuro (`modal-backdrop`), originado por la presencia de 206 modales inline dentro de celdas `` en una tabla con `overflow` (`.table-responsive`). Se refactorizó hacia un único modal global `#modalEditSubject` instanciado fuera de la tabla e inicializado dinámicamente con JavaScript. ### Añadido - **Monitoreo y Percentiles de Asignación de Aulas Físicas (Admin & Bedelía):** - Panel analítico *"Estado y Percentiles de Asignación de Aulas Físicas"* incorporado en los dashboards de Administrador (`/dashboard?role=admin`) y Bedelía (`/dashboard?role=bedelia`). - Cálculo dinámico en tiempo real de **Aulas Asignadas** en número y percentil (**26 aulas · 96.3%**) con enlace directo a cursadas activas. - Cálculo dinámico en tiempo real de **Aulas Sin Asignar / Libres** en número y percentil (**1 aula · 3.7%**) con enlace directo al formulario de asignación de espacios. - Barras de progreso visuales con desglose dual: **Planificación Cuatrimestral** (96.3% asignado vs 3.7% disponible) y **Ocupación Operativa del Día** (aulas con clases hoy vs aulas libres). - Exposición de métricas de asignación y percentiles en el endpoint de la API REST `GET /api/v1/dashboard/stats`. - **Módulo de Cursadas Asignadas y Métricas Reales en Catálogo Presencial (`/classrooms/list_classrooms?view_mode=physical`):** - Incorporación de la sección *"Cursadas Asignadas"* dentro de cada tarjeta de aula física y columna en vista de tabla, detallando asignaturas, comisiones y turnos. - Métricas de ocupación física real por período (Día, Semana, Mes) con porcentajes calculados dinámicamente (6%, 11%, 17%, 22% según la carga horaria del aula). - Botones de acción directa con ID dinámico: **Ficha** (`/classrooms/view_classroom?id=...`), **Horarios en Calendario** (`/schedule/calendar_view?classroom_id=...`) y **Editar**. - Conexión de la tabla *"Próximas Clases y Reservas"* en la ficha individual del aula (`/classrooms/view_classroom`) con las reservas reales del cuatrimestre y enlaces a cada reserva (`/schedule/view_reservation?id=...`). ### Modificado - **Dashboard Docente (`/dashboard?role=docente`):** - Eliminado el botón flotante *"Reservar Aula / Solicitar espacio para clase"* (`/schedule/add_reservation`) a petición de los requerimientos funcionales del cuerpo docente. - Reorganizada la grilla superior a 3 columnas simétricas (`col-md-4`) para las tarjetas de *Mis Clases Hoy*, *Mis Reservas Activas* y *Aulas Virtuales*. ### Corregido - **Fallo Crítico de Renderizado en Nunjucks (`memberLookup` con `.items`):** - Solucionada la incompatibilidad de `nunjucks/src/jinja-compat` que interceptaba la propiedad `.items` convirtiendo `classrooms.items` en una función interna en lugar de un array, lo que impedía dibujar las tarjetas de aulas presenciales en `frontend/views/classrooms/list.html`. - Implementado interceptor en `memberLookup` en `frontend/src/app.js` para preservar arrays intactos. - **Clasificación Errónea de Reservas Físicas como Virtuales (`is_virtual`):** - Corregida la propiedad `@property is_virtual` en `Reservation` (`backend/app/models/reservation.py`) para garantizar que si una reserva tiene aula física asignada (`self.classroom and not self.classroom.is_virtual`), siempre sea clasificada como presencial (`is_virtual = False`), evitando falsos positivos cuando la comisión posee un enlace virtual predeterminado. - **Excepción de SQLAlchemy en Estadísticas de Dashboard:** - Corregido el error de ejecución generado al invocar `.ilike()` sobre la propiedad Python `@property Classroom.room_number` en `backend/app/routes/api/dashboard.py`, migrando la clasificación de aulas presenciales y virtuales a una evaluación robusta en memoria Python (`Classroom.code` y `Classroom.building`). --- ## [2.2.0] - 2026-09-19 ### Añadido - **Herramienta de Purga y Reinicio de Datos Académicos (`reset_academic_data`):** - Script CLI `backend/scripts/reset_academic_data.py` con argumentos de limpieza granular (`--all`, `--reservations`, `--classrooms`, `--careers`, `--yes`). - Endpoint de API `POST /api/v1/admin/reset-academic-data` protegido por JWT (rol `admin`) con registro en `AuditLog`. - Panel interactivo "Zona de Reinicio y Purga Académica" en `/admin/google_sheets_import` con checkboxes independientes para reservas, aulas, comisiones, asignaturas y carreras. - Modal modal de confirmación con advertencias de seguridad para prevenir purgas accidentales. - Preservación íntegra de usuarios del sistema, credenciales de acceso, roles RBAC y registros de auditoría. - **Configuración Global Dinámica de Google Sheets:** - Nuevo modelo `SystemSetting` (`backend/app/models/setting.py`) para almacenamiento persistente clave-valor en base de datos. - Endpoints `GET /api/v1/admin/sheets-config` y `POST /api/v1/admin/sheets-config`. - Normalizador de enlaces en `GoogleSheetsImporter` compatible con URLs compartidas de edición (`/spreadsheets/d/.../edit`) o enlaces publicados (`/pub?output=csv`). - Interfaz web con formulario de edición de URL, botón de guardado en caliente, restauración a URL oficial predeterminada y acceso directo a Google Docs. - **Visualización de Asignaturas Reales:** - Tabla de asignaturas recientemente sincronizadas conectada a la base de datos real en lugar de datos de muestra (*mock*). ### Corregido - **Fallo por Timeout en Google Sheets Academic Sync:** - Solucionado el corte prematuro de conexión en el BFF (`frontend/src/services/apiClient.js`), aumentando el timeout base a 25s y el timeout específico de sincronización a 90s (anteriormente limitado a 5s en operaciones que toman ~6.7s). - Eliminado el enmascaramiento silencioso de errores en el BFF, permitiendo reportar fallos reales o éxitos detallados (+carreras, +aulas, +materias, +comisiones, +reservas). --- ## [2.1.0] - 2026-09-19 ### Añadido - **Ficha Detallada de Reserva (`schedule.view_reservation`):** - Implementación en BFF Node.js de la ruta `/schedule/view_reservation` (soportando parámetros `:id`, `?id=` o selección automática del primer registro). - Vistas y controladores para modificar reservas con selectores en cascada (`/schedule/edit_reservation`). - Endpoints de acción rápida en backend y BFF: `POST /schedule/confirm_reservation` y `POST /schedule/cancel_reservation`. - Actualización de enlaces en `today.html`, `list.html`, `dashboard.html` y `view.html` para navegar directamente con el identificador de la reserva (`?id=...`). - **Creación y Asociación de Comisiones a Asignaturas (`admin/commissions_list`):** - Botón destacado `+ Nueva Comisión` en el encabezado y en el estado vacío de la tabla. - Modal interactivo `#modalAddCommission` con selección obligatoria y clara de la **Asignatura / Materia Asociada** (`