Files
admin-edu-space/CHANGELOG.md
T

20 KiB

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 y este proyecto se adhiere a Semantic Versioning.


[Unreleased]

Planificado (Fase 3 del Roadmap MVP)

  • Calendario de Evaluación por Comisión: Programación de parciales, recuperatorios, entregas de trabajos prácticos y exámenes finales con cuenta regresiva.
  • Libro de Calificaciones (Gradebook): Matriz de carga rápida de notas para docentes, consulta pedagógica individual para alumnos y cierre de actas para Bedelía.
  • Grilla Semanal Drag & Drop (Fase 4): Asignación visual interactiva para la oficina de Bedelía.

[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/<id>/teachers y DELETE /api/v1/commissions/<id>/teachers/<user_id> 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/<id>/enrollments, POST /api/v1/commissions/<id>/enrollments, DELETE /api/v1/commissions/<id>/enrollments/<student_id> y PUT /api/v1/commissions/<id>/enrollments/<student_id>.
      • 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.

[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/<id>.
    • 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/<id>/teachers y DELETE /api/v1/commissions/<id>/teachers/<user_id>, 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 <td> 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 (<select name="subject_id" required>), mostrando código oficial, nombre y carrera.
    • Campos completos de cursada: cuatrimestre (1C/2C/Anual), año lectivo, turno, docente a cargo, cupo máximo y días/horarios.
    • Generación y configuración automática de enlace a Google Meet institucional cuando no se ingresa un enlace personalizado.
    • Alerta de confirmación visual (?created=1) al registrar y vincular una comisión exitosamente.
    • Tabla de comisiones actualizada con visualización explícita del código de materia, nombre y badge de carrera.
  • Enriquecimiento de la API REST:
    • Endpoint GET /api/v1/reservations/<id> ampliado con objetos relacionales anidados: classroom (código, edificio, piso, capacidad, descripción, virtualidad), commission (código, código compuesto, materia), user (docente, nombre, apellido, correo), duración en minutos y enlaces virtuales.
    • Endpoint POST /api/v1/admin/commissions con validación estricta de existencia de asignatura y resolución inteligente de unicidad.

[2.0.0] - 2026-09-18

Añadido

  • Reingeniería de Arquitectura Fullstack (Desacople Monolito -> Backend + BFF):
    • Desacople completo del backend Python/Flask como una API REST pura bajo /api/v1/ retornando exclusivamente JSON.
    • Implementación del Frontend BFF en Node.js + Express con renderizado de servidor mediante Nunjucks.
    • Autenticación sin estado (Stateless) basada en tokens JWT firmados con algoritmo HS256.
    • Almacenamiento seguro del token de acceso en cookies del navegador con directivas HttpOnly, SameSite=Lax y Secure.
    • Inyección transparente del token Bearer en peticiones internas mediante cliente Axios centralizado.
  • Dashboards Personalizados por Rol Institucional:
    • Dashboard de Bedelía (/dashboard?role=bedelia): Métricas operativas de campus físico y virtual, cartelera del día y panel de aprobación de solicitudes pendientes.
    • Dashboard de Docente (/dashboard?role=docente): Sesiones del día con botones directos para ingresar a reuniones virtuales (Meet/Teams/Zoom) y formulario de solicitud de aulas.
    • Dashboard de Alumno (/dashboard?role=alumno): Brújula de cursada "¿Dónde curso hoy?" con ubicación por piso/aula o enlace virtual, junto al calendario de exámenes y entregas.
    • Dashboard de Administrador (/dashboard?role=admin): Cockpit institucional de capacidad, usuarios, auditoría RBAC y distribución de comisiones.
    • Selector dinámico de vista previa de roles en el banner superior para administradores.
  • Cartelera del Día Interactiva (/schedule/today_schedule):
    • Grilla estructurada en bloques horarios (07:00 a 21:00 hs) con métricas en tiempo real de ocupación y reservas confirmadas/pendientes.
    • Filtro dinámico para ocultar clases virtuales (hide_virtual=1) y segmentación por pisos o turnos.
  • Seguridad Enterprise (SecurityFilterChain):
    • Pipeline centralizado de cabeceras de blindaje OWASP (nosniff, SAMEORIGIN, X-XSS-Protection, Strict-Transport-Security).
    • Rate limiting dinámico contra ataques de fuerza bruta en endpoints de autenticación.

Corregido

  • Resolución de Colisión de Horarios en Clases Virtuales (Importador de Google Sheets):
    • Corrección de la búsqueda de duplicados en sheets_importer.py que limitaba indebidamente la unicidad a (classroom_id, start_time, end_time).
    • Habilitación de concurrencia ilimitada para el aula virtual (Campus Virtual · VIRTUAL) mediante discriminación por commission_id.
    • El total de reservas registradas aumentó de 363 a 643 (incorporando 280 clases virtuales que eran descartadas por falso conflicto).
    • Generación y guardado automático de enlaces institucionales de Google Meet (https://meet.google.com/edu-{materia}-{comision}).

[1.0.0] - 2026-09-04

Añadido

  • Versión Monolítica Base (legacy_admin-edu-space):
    • Aplicación monolítica en Flask con plantillas Jinja2 y persistencia SQLAlchemy (SQLite / PostgreSQL).
    • Modelado de datos inicial para sedes, aulas físicas, materias, comisiones, usuarios y reservas.
    • Sistema de roles inicial (Admin, Bedelía, Docente, Alumno) basado en sesión tradicional de Flask-Login.
    • Calendario de reservas mensual y semanal con FullCalendar.
    • Prototipo experimental de algoritmo genético para optimización de ocupación áulica.
    • Módulo de sincronización inicial con planillas de Google Sheets.