387 lines
40 KiB
Markdown
387 lines
40 KiB
Markdown
# Resumen de Cambios - Sesión de Desarrollo (Rama `dev`)
|
|
|
|
**Fecha:** 2026-09-02 / 2026-09-03 / 2026-09-04
|
|
**Proyecto:** Admin Edu-Space (Flask + PostgreSQL)
|
|
**Rama:** `dev`
|
|
|
|
---
|
|
|
|
## 1. Auditoría Git y Puesta en Producción
|
|
* **Informe Técnico Completo (`DEPLOYMENT_AUDIT.md`):**
|
|
* Análisis de ramas locales y remotas (`main`, `dev`, `origin/planning`, `origin/commissions`, `origin/spanish`).
|
|
* Manual de despliegue en producción con arquitectura WSGI (Gunicorn), Nginx como proxy inverso, Systemd unit y contenedorización Docker / Docker Compose.
|
|
* **Archivos Base:**
|
|
* Creación de `.env.example` con todas las variables requeridas (PostgreSQL, Flask, Secret Key, Babel).
|
|
* Creación y posterior actualización de `init_db.py` para bootstrap inicial seguro de base de datos, roles RBAC y usuario administrador por defecto (`admin@edu-space.com` / `admin123`).
|
|
|
|
---
|
|
|
|
## 2. Base de Datos y Modelos
|
|
* **Preferencia de Idioma Persistente:**
|
|
* Migración en PostgreSQL agregando la columna `preferred_language VARCHAR(10)` a la tabla `users`.
|
|
* Actualización del modelo `User` en `app/models/user.py` con el campo `preferred_language`.
|
|
* **Preferencia de Tema Visual Persistente:**
|
|
* Migración agregando la columna `theme_preference VARCHAR(10) DEFAULT 'auto' NOT NULL` a la tabla `users`.
|
|
* Soporte en el modelo `User` para valores `'auto'`, `'light'` y `'dark'`.
|
|
* **Control de Acceso Basado en Roles (RBAC):**
|
|
* Migración creando las tablas `roles` y `permissions`, y agregando la clave foránea `role_id` a la tabla `users`.
|
|
* Modelos `Role` y `Permission` en `app/models/role.py`.
|
|
* Métodos `has_permission(module, min_level)` y `can_manage()` en `User`.
|
|
|
|
---
|
|
|
|
## 3. Implementación de Vistas y Plantillas
|
|
* **Perfil de Usuario (`app/templates/auth/profile.html`):**
|
|
* Vista completa con datos del usuario, rol, estado, fecha de registro y reservas recientes.
|
|
* Formulario integral para configurar **Idioma de la interfaz** (*Detectar automáticamente del navegador*, *Español*, *English*) y **Tema visual** (*Automático*, *Modo Claro*, *Modo Oscuro*).
|
|
* **Cambio de Contraseña (`app/templates/auth/change_password.html`):**
|
|
* Formulario seguro para actualización de credenciales.
|
|
* **Manejo de Errores (`app/templates/auth/403.html`):**
|
|
* Pantalla de error 403 Forbidden estilizada e integrada con el sistema de diseño.
|
|
|
|
---
|
|
|
|
## 4. Correcciones de UX, Linter y Bugs de Rutas
|
|
* **Navbar Limpio (`app/templates/base.html`):**
|
|
* Eliminación del bloque duplicado del menú de usuario `System Administrator`.
|
|
* **Corrección de BuildError en Comisiones:**
|
|
* En `app/routes/classrooms.py`, se agregó el alias de ruta `@classrooms_bp.route('/', endpoint='index')` para resolver enlaces a `classrooms.index`.
|
|
* En `app/templates/schedule/commissions.html`, se reemplazó el filtro inválido de Django `truncatewords(20)` por el filtro estándar de Jinja2 `truncate(100)`.
|
|
* **Corrección Visual en `/genetic-optimizer` (`app/templates/genetic_optimizer.html`):**
|
|
* Se agregó el espaciado `pt-5 mt-4` evitando que la barra fija superior se monte sobre el contenido.
|
|
* Rediseño de tarjeta hero con contraste óptimo y reemplazo de iconos faltantes por Bootstrap Icons (`bi bi-...`).
|
|
* **Corrección de Errores del Linter en `schedule/add.html` y `schedule/view.html`:**
|
|
* En `add.html`: Desacople de iteraciones Jinja a `<script type="application/json" id="classroom-data">` y parseo con `JSON.parse()`, eliminando 19 errores sintácticos del editor.
|
|
* En `view.html`: Formateo de la propiedad inline `style` en barras de progreso para cumplir con el validador CSS.
|
|
|
|
---
|
|
|
|
## 5. Rediseño UI/UX, Assets Institucionales y Modo Claro/Oscuro
|
|
* **Exploración e Integración de Assets Gráficos:**
|
|
* Sincronización desde `app/resources` hacia `app/static/img/`:
|
|
* `logo_unicaba.png`: Logo institucional principal para el login.
|
|
* `logo_unicaba_mini.png`: Isotipo oficial para el navbar.
|
|
* `favicon.png`: Favicon vinculado en las plantillas base.
|
|
* `icons/`: Paquete de resoluciones WebApp/PWA.
|
|
* **Sistema de Diseño y Tokens de Color (`app/static/css/theme.css`):**
|
|
* Paleta institucional basada en Magenta/Uva (`#B43E8E`), acentos violetas (`#682CAD` / `#AE7FFF`) y secundarios magentas.
|
|
* Tokens CSS para `:root` (Modo Claro) y `[data-bs-theme="dark"]` (Modo Oscuro).
|
|
* Clases especializadas: `.auth-card`, `.navbar-app`, `.user-avatar-small`, `.theme-toggle-btn`, `.badge-brand`.
|
|
* **Modo Claro / Modo Oscuro Dinámico (`app/static/js/theme-toggle.js`):**
|
|
* Script anti-flickering en `<head>` para evitar parpadeos visuales al cargar la página.
|
|
* Botón toggle interactivo con persistencia en `localStorage`.
|
|
* En Modo Claro: Isotipo del navbar con filtro blanco puro (`brightness(0) invert(1)`) sobre el fondo magenta.
|
|
* Selector de idioma (`#languageDropdown`) con fondo y bordes de alto contraste y tilde de verificación blanca (`bi-check-lg`) visible **únicamente** en el idioma activo sobre gradiente magenta.
|
|
|
|
---
|
|
|
|
## 6. Internacionalización (i18n), Localización y Formateo de Fechas
|
|
* **Detección Inteligente de Subtags Regionales (`get_locale` en `app/__init__.py`):**
|
|
* Extracción del subtag primario (`es` a partir de `es-419`, `es-AR`, `es-ES`), resolviendo el fallo donde Werkzeug saltaba erróneamente a inglés.
|
|
* Configuración institucional: `BABEL_DEFAULT_LOCALE = 'es'` y `LANGUAGES = ['es', 'en']`.
|
|
* **Reglas de Idioma para la Pantalla de Login:**
|
|
* Resuelve según el navegador del visitante o recurre a español por defecto.
|
|
* Inmunidad contra cookies o sesiones residuales de otros usuarios.
|
|
* Flash messages traducidos (`¡Bienvenido de nuevo!`, `Has cerrado sesión correctamente`).
|
|
* **Formateador de Fechas Localizadas en Jinja2:**
|
|
* Registro de `format_date` y `format_datetime` de Flask-Babel.
|
|
* Fechas en español natural en `schedule/today.html` (`Jueves, 3 de septiembre de 2026`), `view.html` y `list.html`.
|
|
* **Traducción Integral de `schedule/add.html`:**
|
|
* Formulario y textos de ayuda 100% traducidos.
|
|
* Caja dinámica de resumen (JavaScript e `i18n-strings`) con cálculo de duración y validación de sobrecupo en español.
|
|
|
|
---
|
|
|
|
## 7. Módulo de Gestión de Accesos (RBAC) con Matriz FortiGate
|
|
* **Modelos y Persistencia:**
|
|
* Módulo `app/models/role.py` con `Role` y `Permission`.
|
|
* Roles iniciales sembrados: `Admin` (total, protegido), `Docente` (reservas y horarios), `Operador` (aulas y reservas), `Consulta` (solo lectura).
|
|
* Vinculación del usuario inicial `admin@edu-space.com` al rol `Admin`.
|
|
* **Matriz de Permisos Estilo FortiGate (`/admin/roles/edit/<id>`):**
|
|
* Tabla interactiva con columnas **Access Control** y **Permissions**.
|
|
* Segmented control por módulo con tres estados: `🚫 None`, `👁️ Read` y `✏️ Read/Write`.
|
|
* Color activo verde esmeralda FortiGate (`#2D9F6F`) con texto e icono en blanco puro.
|
|
* Menú desplegable masivo **Set All ▾** (*Set All to None*, *Set All to Read*, *Set All to Read/Write*).
|
|
* **Módulo de Administración (`app/routes/admin.py`):**
|
|
* `/admin/roles`: Listado de roles, conteo de miembros, visualización de permisos en badges (RW, R, -) y modal de borrado seguro.
|
|
* `/admin/users`: Listado de cuentas con filtros por nombre, rol y estado (Activo/Inactivo), paginación y switch rápido para alternar accesos.
|
|
* `/admin/users/add` y `/admin/users/edit/<id>`: Formularios de alta y edición con asignación de rol y contraseña opcional.
|
|
* **Seguridad y Decoradores (`app/utils/decorators.py`):**
|
|
* `@permission_required(module, min_level)` y `@admin_required`.
|
|
* Pestaña **Management** en el navbar visible exclusivamente para administradores.
|
|
* Botones de acción sensibles en el navbar (*Add Classroom*, *New Reservation*) condicionados a permisos de escritura.
|
|
|
|
---
|
|
|
|
## 8. Sincronización y Actualización de `init_db.py`
|
|
* Migraciones DDL automáticas (`ALTER TABLE ... ADD COLUMN IF NOT EXISTS`) para `preferred_language`, `theme_preference`, `role_id`, y para la tabla `careers` y columna `career_id` en `subjects`.
|
|
* Creación y siembra de roles institucionales y permisos en PostgreSQL.
|
|
* Configuración de salida con codificación UTF-8 segura en Windows para evitar excepciones de `cp1252`.
|
|
|
|
---
|
|
|
|
## 9. Sincronización e Importación de Datos Académicos (Google Sheets)
|
|
* **Modelo `Career` (`app/models/career.py`):**
|
|
* Entidad de carreras universitarias vinculada con `Subject` vía relación uno a muchos.
|
|
* Migración en PostgreSQL de la tabla `careers` y campo `career_id` en `subjects`.
|
|
* **Servicio de Extracción ([app/services/sheets_importer.py](file:///c:/Workspace/admin-edu-space/app/services/sheets_importer.py)):**
|
|
* Integración con la cartelera oficial UniCABA 2026 a través de 6 hojas CSV (`Lunes` a `Sábado`).
|
|
* Normalización inteligente de espacios áulicos físicos (`Aula 402`, `Aula 302`), espacios virtuales (`VIRTUAL`), auditorios y salas de reunión.
|
|
* Extracción y parseo de franjas horarias (`8:00 a 9:00hs`, `17:30 a 21:30hs`).
|
|
* Rutina de **upsert** transaccional e idempotente que previene la duplicación de datos.
|
|
* Generación de reservas/clases en el calendario para poblar instantáneamente las vistas de horario diario y semanal.
|
|
* **Interfaz de Gestión (`/admin/import`):**
|
|
* Vista interactiva con métricas en tiempo real (total de carreras, asignaturas, aulas, comisiones y clases).
|
|
* Botón de ejecución manual de sincronización con indicador visual de progreso (`spinner`).
|
|
* Reporte detallado de resultados y tabla con vista previa de asignaturas y comisiones sincronizadas.
|
|
* **Acceso Rápido en Navbar (`app/templates/base.html`):**
|
|
* Nueva opción **"Import from Google Sheets"** incorporada en el menú desplegable **Management**, restringida a roles con permisos administrativos.
|
|
|
|
---
|
|
|
|
## 10. Correcciones en la Vista de Calendario (FullCalendar) y Códigos de Asignatura
|
|
* **Carga de Eventos y Corrección de Error 500 (`/schedule/calendar-data`):**
|
|
* Se identificó y corrigió el error `AttributeError: 'str' object has no attribute 'value'` provocado por llamadas a `.status.value` sobre campos de estado textuales.
|
|
* Se implementó el TypeDecorator `StatusType` con la clase `StatusString` en `app/models/reservation.py` garantizando compatibilidad total tanto para `.status` como para `.status.value`.
|
|
* Sanitización de fechas ISO 8601 con zona horaria (`Z`, `-03:00`) enviadas por FullCalendar para comparación adecuada con campos `TIMESTAMP WITHOUT TIME ZONE` en PostgreSQL.
|
|
* Anclaje de fecha inicial con `initialDate: '{{ today_date }}'` para posicionar el calendario en la semana activa de cursada 2026.
|
|
* **Corrección del Código de Asignatura (`subject_code`):**
|
|
* Se reemplazó la concatenación de código extendido de comisión (`Commission.get_full_code()` que arrojaba cadenas distorsionadas como `INGA0003-C1-2026-22026`) por el **código de asignatura real** del Sheet (`Subject.code`, ej. `INGA0003`, `ASIG00165`).
|
|
* Propiedades de acceso directo añadidas en `Reservation`: `subject_code`, `subject_name` y `classroom_name`.
|
|
* **Jerarquía Visual y Renderizado de Tarjetas (`calendar.html`):**
|
|
* Implementación del hook `eventContent` en FullCalendar 5 para construir tarjetas personalizadas.
|
|
* **Nombre de la Asignatura** destacado como elemento principal con tipografía grande y en negrita (`font-weight: 700; font-size: 0.88rem`).
|
|
* **Código de Asignatura** y **Aula** mostrados como datos secundarios en badges de alto contraste (código con fondo oscuro translúcido y aula con isotipo y fondo blanco translúcido).
|
|
* Modal interactivo instantáneo al hacer clic en cualquier evento con todos los detalles académicos de la clase y enlace a la ficha completa.
|
|
|
|
---
|
|
|
|
## 11. Filtros por Aula y Materia en el Calendario de Reservas
|
|
* **Barra de Herramientas de Filtros Interactiva (`calendar.html`):**
|
|
* **Filtrar por Aula:** Desplegable dinámico con todas las aulas activas ordenadas por edificio y código (físicas y virtuales). Al seleccionar un aula (ej. `Aula 402`), se eliminan todas las superposiciones visuales mostrando el cronograma limpio de ese espacio.
|
|
* **Filtrar por Materia:** Desplegable ordenado alfabéticamente con formato `[Código] Nombre de la Asignatura`. Permite aislar todas las clases de una asignatura en particular.
|
|
* **Filtrar por Carrera:** Filtro adicional por plan académico/carrera.
|
|
* **Botón Limpiar Filtros:** Restablece instantáneamente todos los controles y refresca la vista.
|
|
* **Insignias de Estado:** Indicador en tiempo real de los filtros aplicados y contador de clases visibles (`X clases visibles`).
|
|
* **Soporte en Backend (`app/routes/schedule.py`):**
|
|
* `calendar_view`: Suministra las listas de `classrooms`, `subjects` y `careers` a la plantilla.
|
|
* `calendar_data`: Procesa `classroom_id`, `subject_id`, `career_id` y `search` aplicando cláusulas `filter()` con `JOIN` en SQLAlchemy.
|
|
* `refetchEvents()` de FullCalendar conectado a los eventos `change` de cada selector para recarga inmediata vía AJAX sin parpadeo de pantalla.
|
|
|
|
---
|
|
|
|
## 12. Módulo de Gestión de Edificios y Corrección de Vistas de Aulas
|
|
* **Corrección de Plantillas de Aulas Faltantes:**
|
|
* Se crearon las plantillas [app/templates/classrooms/edit.html](file:///c:/Workspace/admin-edu-space/app/templates/classrooms/edit.html) y [app/templates/classrooms/view.html](file:///c:/Workspace/admin-edu-space/app/templates/classrooms/view.html), solucionando el error HTTP 500 (`TemplateNotFound: classrooms/edit.html`) y la redirección 302 que ocurría al hacer clic en cualquier aula.
|
|
* La vista de ficha técnica del aula ahora muestra detalles de capacidad, piso, estado, edificio y la tabla interactiva de próximas reservas.
|
|
* **Modelo y Base de Datos de Edificios (`Building`):**
|
|
* Se creó el modelo [app/models/building.py](file:///c:/Workspace/admin-edu-space/app/models/building.py) (`id`, `name`, `code`, `address`, `floors`, `description`, `is_active`, timestamps y relación con `Classroom`).
|
|
* Migración DDL en PostgreSQL (`CREATE TABLE buildings`, `ALTER TABLE classrooms ADD COLUMN building_id`).
|
|
* Actualización de [init_db.py](file:///c:/Workspace/admin-edu-space/init_db.py) y siembra de edificios institucionales iniciales (`Edificio Central` y `Campus Virtual`) con vinculación de las 25 aulas existentes.
|
|
* **Rutas y Gestión Completa (`app/routes/buildings.py`):**
|
|
* `/buildings`: Listado con métricas de infraestructura (total de edificios, aulas activas, capacidad total y plantas/pisos), barra de búsqueda y filtros por estado.
|
|
* `/buildings/<id>`: Vista de detalle con distribución de aulas organizadas visualmente por piso (Planta Baja, Piso 1, Piso 2, etc.), capacidad por sala y acciones directas.
|
|
* `/buildings/add` y `/buildings/<id>/edit`: Formularios con validación WTForms para alta y actualización.
|
|
* `/buildings/<id>/toggle` y `/buildings/<id>/delete`: Control de activación y eliminación protegida (impide borrar edificios que contengan aulas asignadas).
|
|
* **Navegación (`app/templates/base.html`):**
|
|
* Enlace a **Edificios** (`/buildings`) incorporado en el menú **Classrooms** y en el menú administrativo **Management**.
|
|
|
|
---
|
|
|
|
## 13. Mapeo de Campos del Google Sheet y Concepto de Turno (Mañana / Tarde)
|
|
* **Uso de los 5 Campos de la Cartelera Oficial:**
|
|
* **Codigo (`Subject.code` y `Commission.code`):** Almacena el código académico real (`INGA0003`, `ASIG00165`). Se expone como badge monoespaciado en eventos de calendario, comisiones y vistas administrativas.
|
|
* **Asignatura (`Subject.name`):** Título principal de la materia destacado en texto grande y en negrita en FullCalendar y en la cartelera diaria.
|
|
* **Aula (`Classroom.code`, `Classroom.building`, `Classroom.floor`, `Classroom.capacity`):** Normalización de espacios físicos y virtuales vinculados al nuevo modelo `Building`.
|
|
* **Carrera (`Career.name` y `Subject.career_id`):** Entidad de carrera universitaria con relaciones relacionales normalizadas.
|
|
* **Horarios (`Commission.schedule`, `Reservation.start_time`, `Reservation.end_time`):** Rango horario parseado hacia objetos `datetime` nativos para el motor de reservas y el calendario.
|
|
* **Modelado y Captura de Turnos (`TURNO MAÑANA` y `TURNO VESPERTINO`):**
|
|
* Se agregó la columna `shift` en las tablas `commissions` y `reservations` de PostgreSQL y en sus respectivos modelos de SQLAlchemy.
|
|
* El parser de [app/services/sheets_importer.py](file:///c:/Workspace/admin-edu-space/app/services/sheets_importer.py) identifica las filas delimitadoras de bloque (`TURNO MAÑANA` vs `TURNO VESPERTINO / TARDE`) y corrobora la hora de inicio (< 13:00hs = Mañana, $\ge$ 14:00hs = Tarde).
|
|
* Se sincronizaron todas las comisiones y reservas de cursada: 15 comisiones y 48 reservas en `Turno Mañana`; 191 comisiones y 364 reservas en `Turno Tarde / Vespertino`.
|
|
* En el Calendario de Reservas (`/schedule/calendar`) se añadió el selector **Filtrar por Turno** (`Todos`, `Mañana`, `Tarde / Vespertino`), permitiendo a los usuarios aislar las franjas horarias y resolver la alta concentración de clases en el horario vespertino (17:30 a 21:30hs).
|
|
|
|
---
|
|
|
|
## 14. Accesos Directos en Panel, Ocultamiento de Virtuales, Filtro por Piso, Dirección Oficial y Traducción
|
|
* **Tarjetas Estadísticas como Accesos Directos Interactivos ([app/templates/dashboard.html](file:///c:/Workspace/admin-edu-space/app/templates/dashboard.html)):**
|
|
* **Total de Aulas (25):** Redirige a `/classrooms/list` con feedback visual de hover y elevación.
|
|
* **Total de Materias (206):** Redirige a `/schedule/commissions`.
|
|
* **Reservas de Hoy (18):** Redirige a `/schedule/today`.
|
|
* **Esta Semana (103):** Redirige a `/schedule/calendar`.
|
|
* Se añadieron microinteracciones CSS en [app/static/css/style.css](file:///c:/Workspace/admin-edu-space/app/static/css/style.css) (`.dashboard-stat-card`).
|
|
* **Ocultar Aulas Virtuales y Filtro por Piso:**
|
|
* **Calendario ([app/templates/schedule/calendar.html](file:///c:/Workspace/admin-edu-space/app/templates/schedule/calendar.html)):** Switch interactivo *Ocultar Aulas Virtuales* (indica capacidad ilimitada) y selector *Filtrar por Piso* (`Planta Baja`, `Piso 1`, `Piso 2`, `Piso 3`, `Piso 4`). El backend `/schedule/calendar-data` excluye las aulas virtuales o filtra por número de piso.
|
|
* **Cartelera del Día ([app/templates/schedule/today.html](file:///c:/Workspace/admin-edu-space/app/templates/schedule/today.html)):** Barra de filtros completa con soporte para ocultar virtuales, piso y turno.
|
|
* **Listado de Reservas ([app/templates/schedule/list.html](file:///c:/Workspace/admin-edu-space/app/templates/schedule/list.html)):** Endpoint `/schedule/list` totalmente operativo con paginación de 20 registros, preservación de query params y filtros de piso, turno, virtuales, estado y rango de fechas.
|
|
* **Dirección Oficial de la Sede Central:**
|
|
* Se configuró la dirección oficial de la Universidad de la Ciudad de Buenos Aires (UniCABA): **`Tte. Gral. Juan Domingo Perón 802, CABA`** en la base de datos, en [init_db.py](file:///c:/Workspace/admin-edu-space/init_db.py) y en el importador [app/services/sheets_importer.py](file:///c:/Workspace/admin-edu-space/app/services/sheets_importer.py).
|
|
* **Traducción Integral al Español y Catálogo Babel:**
|
|
* Se agregaron traducciones en [translations/es/LC_MESSAGES/messages.po](file:///c:/Workspace/admin-edu-space/translations/es/LC_MESSAGES/messages.po) y se recompiló el binario `.mo` con `pybabel`.
|
|
* Textos traducidos: `Buildings` $\rightarrow$ *Edificios*, `Management` $\rightarrow$ *Gestión*, `Timeline View` $\rightarrow$ *Vista Cronológica*, `Grid View` $\rightarrow$ *Vista en Tabla*, `Active Classrooms` $\rightarrow$ *Aulas Ocupadas*, `All Reservations` $\rightarrow$ *Todas las Reservas*, `AI Room Optimizer` $\rightarrow$ *Optimizador de Aulas*, etc.
|
|
|
|
---
|
|
|
|
## 15. Actualización Integral de Roles RBAC, Capacidad Infinita (∞) y Horarios de Próximas Clases
|
|
* **Actualización de Roles, Grupos de Acceso y Matriz de Permisos ([app/models/role.py](file:///c:/Workspace/admin-edu-space/app/models/role.py), [init_db.py](file:///c:/Workspace/admin-edu-space/init_db.py)):**
|
|
* Se amplió `SYSTEM_MODULES` para cubrir los 8 módulos del sistema:
|
|
1. `classrooms`: **Aulas y Espacios** (físicas, virtuales y capacidades).
|
|
2. `buildings`: **Edificios y Sedes** (Sede Central, Campus Virtual, plantas).
|
|
3. `reservations`: **Reservas de Aulas** (aprobación, confirmación, cancelación).
|
|
4. `schedule`: **Cartelera y Cronograma** (calendario, cartelera del día, comisiones).
|
|
5. `academic`: **Gestión Académica** (carreras, asignaturas, códigos).
|
|
6. `import`: **Sincronización Sheets** (importador Google Sheets).
|
|
7. `optimizer`: **Optimizador IA** (algoritmo genético áulico).
|
|
8. `users`: **Usuarios y Accesos RBAC** (cuentas, roles y matriz).
|
|
* Se actualizaron los perfiles estándar (`Admin`, `Docente`, `Operador`, `Consulta`) en PostgreSQL y en `init_db.py`.
|
|
* Se tradujeron completamente las plantillas [app/templates/admin/roles/list.html](file:///c:/Workspace/admin-edu-space/app/templates/admin/roles/list.html) y [app/templates/admin/roles/edit.html](file:///c:/Workspace/admin-edu-space/app/templates/admin/roles/edit.html) al español.
|
|
* **Soporte de Capacidad Infinita (∞) y Aclaración ([app/forms/classroom.py](file:///c:/Workspace/admin-edu-space/app/forms/classroom.py), [app/templates/classrooms/edit.html](file:///c:/Workspace/admin-edu-space/app/templates/classrooms/edit.html)):**
|
|
* Se actualizó `ClassroomForm.capacity` con validador personalizado que admite el símbolo **`∞`**, `inf`, `0` o cualquier capacidad numérica positiva.
|
|
* Se corrigió la validación de `floor` con `InputRequired` y `NumberRange(min=0)` para aceptar Planta Baja (Piso 0).
|
|
* En la interfaz de edición y alta de aulas se incluyó el botón de acción rápida **`Ilimitada (∞)`** que rellena automáticamente el campo con el símbolo `∞`.
|
|
* Se añadió una leyenda explicativa directa: *"Para aulas virtuales o eventos sin aforo restringido, ingrese ∞ o 0 (Capacidad ilimitada)"*.
|
|
* Se tradujo el botón de guardado a *"Guardar Cambios"* (reemplazando *"Save Changes"*).
|
|
* El aula virtual institucional (`Campus Virtual - VIRTUAL`) se actualizó a capacidad `0` (`∞`), renderizando el badge `∞ Ilimitada` en listados y fichas.
|
|
* **Próximas Clases: Visualización Exclusiva del Horario ([app/templates/dashboard.html](file:///c:/Workspace/admin-edu-space/app/templates/dashboard.html), [app/templates/classrooms/view.html](file:///c:/Workspace/admin-edu-space/app/templates/classrooms/view.html)):**
|
|
* En la tabla de *Próximas Reservas* del panel y en la ficha del aula se cambió la columna a **"Horario"**, removiendo la fecha del calendario y destacando únicamente el rango horario de cursada (ej. `17:30 - 21:30 hs`).
|
|
|
|
---
|
|
|
|
## 16. Desacoplamiento de Hitos Académicos: Catálogo Dinámico de Tipificaciones y Matriz RBAC
|
|
* **Modelos de Datos ([app/models/milestone.py](file:///c:/Workspace/admin-edu-space/app/models/milestone.py), [app/models/__init__.py](file:///c:/Workspace/admin-edu-space/app/models/__init__.py)):**
|
|
* `MilestoneType`: Catálogo dinámico y administrable con `id`, `name`, `code` (slug único), `color` (hexadecimal), `description`, `sort_order` e `is_active`.
|
|
* `AcademicMilestone`: Relacionado mediante clave foránea `milestone_type_id` a `MilestoneType` en lugar de strings estáticos.
|
|
* Sembrado de 12 categorías iniciales predeterminadas (`Parcial 1`, `Parcial 2`, `TP 1`, `TP 2`, `TP 3`, `Recu. P1`, `Recu. P2`, `Recu. TP 1`, `Recu. TP 2`, `Recu. TP 3`, `Final`, `Otro`).
|
|
* **Matriz de Permisos RBAC ([app/models/role.py](file:///c:/Workspace/admin-edu-space/app/models/role.py), [init_db.py](file:///c:/Workspace/admin-edu-space/init_db.py)):**
|
|
* Se agregó el módulo `milestone_types` a `SYSTEM_MODULES` cubriendo los 9 módulos de la plataforma.
|
|
* Niveles asignados: `Admin` (RW), `Docente` (R), `Operador` (RW), `Consulta` (R).
|
|
* **Vistas y ABM en Management ([app/routes/admin.py](file:///c:/Workspace/admin-edu-space/app/routes/admin.py), [app/templates/admin/milestone_types/list.html](file:///c:/Workspace/admin-edu-space/app/templates/admin/milestone_types/list.html)):**
|
|
* Se añadió el ítem de navegación **"Tipificaciones"** al menú desplegable *Management*.
|
|
* Tabla completa con badges de color, slugs, switches interactivos de activación/desactivación y modales para dar de alta y editar tipificaciones.
|
|
* **API y Modal del Docente ([app/routes/main.py](file:///c:/Workspace/admin-edu-space/app/routes/main.py), [example/aulas-unicaba-mvp/...](file:///c:/Workspace/admin-edu-space/example/aulas-unicaba-mvp/src/app/components/evento-modal/evento-modal.component.html)):**
|
|
* Se expuso el endpoint `GET /api/milestone-types` para consumo desacoplado.
|
|
* Se actualizó el modal de eventos académicos (`evento-modal.component.html` y `.ts`) desacoplando las opciones estáticas y cargando dinámicamente el catálogo de tipificaciones activas con fallback automático para funcionamiento offline.
|
|
|
|
---
|
|
|
|
## 17. Rediseño de Calendario Estilo Google Calendar y Corrección Visual en Eliminación de Roles
|
|
* **Manejo de Eventos Simultáneos y Densidad Visual ([app/templates/schedule/calendar.html](file:///c:/Workspace/admin-edu-space/app/templates/schedule/calendar.html)):**
|
|
* Se configuró FullCalendar con `eventMaxStack: 3`, evitando que decenas de reservas concurrentes reduzcan las columnas a franjas milimétricas del 3%.
|
|
* Se habilitó `dayMaxEvents: 3`, `dayMaxEventRows: true` y `moreLinkClick: 'popover'` nativo de Google Calendar con enlaces "+X más".
|
|
* Se fijaron `slotMinTime: "07:00:00"`, `slotMaxTime: "23:00:00"`, `slotDuration: "00:30:00"`, `slotLabelInterval: "01:00:00"` y `nowIndicator: true` con la línea roja indicadora de hora actual.
|
|
* **Diseño de Tarjetas de Evento Píldora (`.gc-event-pill` / `.gc-month-pill`):**
|
|
* Estilo Google Calendar con barra lateral de color (magenta UniCABA `#B43E8E`, ámbar `#F59E0B` para pendientes, índigo `#6366F1` para aulas virtuales).
|
|
* Encabezado compacto con hora de inicio y badge de aula (`bi bi-door-open` o `bi bi-camera-video` con fondo suave para `VIRTUAL`).
|
|
* Tipografía en `0.78rem` con elipsis para evitar desbordes y sombras sutiles.
|
|
* Compatibilidad completa con modo oscuro (`[data-bs-theme="dark"]`).
|
|
* **Modal Flotante Interactivo al Clic (`#eventPreviewModal`):**
|
|
* Reemplazo de la navegación directa por un popover flotante estilizado como Google Calendar.
|
|
* Banner artístico superior con accesos rápidos: editar (✏️), eliminar/cancelar (🗑️) y cerrar (✕).
|
|
* Fila principal con indicador cuadrado de color, título completo, código de materia y badge de estado/turno.
|
|
* Lista con íconos: 🕒 horario y fecha completa, 📍 aula/piso/sede (o enlace directo al Campus Virtual), 👤 carrera/comisión/docente, 📝 hito o notas.
|
|
* Botones de acción inferior: "Ver Ficha Completa" y "Cerrar".
|
|
* **Corrección de Modal de Eliminación de Roles ([app/templates/admin/roles/list.html](file:///c:/Workspace/admin-edu-space/app/templates/admin/roles/list.html)):**
|
|
* Se trasladó el modal de confirmación de eliminación `#deleteRoleModal` fuera de la celda `<td>` y de la tabla `<table>`, situándolo a nivel raíz de la plantilla.
|
|
* Se corrigió el error visual donde el cuadro emergente temblaba, saltaba o se desplazaba por el recálculo de padding/scrollbar de Bootstrap en la celda de la tabla.
|
|
|
|
---
|
|
|
|
## 18. ABM de Comisiones con Hitos y Aula Virtual, Eliminación de Usuarios y Renombrado de Roles (Bedelía y Alumno)
|
|
* **Renombrado de Roles Institucionales ([init_db.py](file:///c:/Workspace/admin-edu-space/init_db.py), base de datos PostgreSQL):**
|
|
* `Operador` pasó a denominarse **`Bedelía`** con foco en la gestión operativa de aulas, sedes, reservas, comisiones, importación y cartelera.
|
|
* `Consulta` pasó a denominarse **`Alumno`** con acceso de solo lectura al cronograma general, asignaturas y aulas.
|
|
* Se ejecutó la actualización en caliente de los registros existentes en PostgreSQL y se actualizaron los sembrados en `init_db.py`.
|
|
* **Corrección Visual de Tipificaciones de Hitos ([app/templates/admin/milestone_types/list.html](file:///c:/Workspace/admin-edu-space/app/templates/admin/milestone_types/list.html)):**
|
|
* Se ajustó el contenedor a `pt-5 mt-4` evitando que el encabezado quede solapado bajo la barra de navegación fija.
|
|
* Se limpió la duplicación del nombre en la tabla (se eliminó la repetición del texto dentro de la celda).
|
|
* Se agregó la paleta rápida de colores institucionales UniCABA al modal de edición.
|
|
* Se agregó el botón y modal global de confirmación de eliminación `#deleteMilestoneTypeModal` sin saltos visuales.
|
|
* **Eliminación de Usuarios ([app/routes/admin.py](file:///c:/Workspace/admin-edu-space/app/routes/admin.py), [app/templates/admin/users/list.html](file:///c:/Workspace/admin-edu-space/app/templates/admin/users/list.html)):**
|
|
* Se implementó el endpoint `POST /admin/users/delete/<id>` protegido contra la eliminación del usuario en sesión activa y del administrador único.
|
|
* Desvinculación automática de comisiones como docente para prevenir violaciones de integridad referencial.
|
|
* Botón rojo de eliminación con ícono de papelera y modal global `#deleteUserModal` fuera de la tabla para evitar desplazamientos.
|
|
* **ABM Integral de Comisiones con Aulas Virtuales e Hitos ([app/models/subject.py](file:///c:/Workspace/admin-edu-space/app/models/subject.py), [app/models/milestone.py](file:///c:/Workspace/admin-edu-space/app/models/milestone.py), [app/routes/schedule.py](file:///c:/Workspace/admin-edu-space/app/routes/schedule.py), [app/templates/schedule/commissions.html](file:///c:/Workspace/admin-edu-space/app/templates/schedule/commissions.html), [app/templates/base.html](file:///c:/Workspace/admin-edu-space/app/templates/base.html)):**
|
|
* **Columna y Enlace de Aula Virtual:** Se añadió el campo `virtual_link` (VARCHAR 500) a `commissions`. Permite registrar enlaces directos a Zoom, Microsoft Teams, Google Meet o Campus Virtual.
|
|
* **Hitos de Evaluación vinculados a Comisiones:** Se añadió `commission_id` a `academic_milestones`. Permite asociar parciales, TPs y recuperatorios directamente a la comisión de cursada.
|
|
* **Permisos para Profesores, Bedelía y Admin:** Los roles `Docente`, `Bedelía` y `Admin` pueden configurar el aula virtual y registrar hitos académicos en sus comisiones.
|
|
* **Navegación:** Acceso directo a *Comisiones y Cursadas* disponible en la barra superior (menús *Schedule* y *Management*).
|
|
* **Modales interactivos:** Creación de comisión (`#modalAddCommission`), edición (`#modalEditCommission`), configuración de aula virtual (`#modalVirtualLink`), programación de hitos (`#modalAddMilestone`) y eliminación segura (`#deleteCommissionModal`).
|
|
|
|
---
|
|
|
|
## 19. Corrección de Redundancia en Nombre de Aula en Formulario y Resumen de Reserva
|
|
* **Desplegable de Selección de Aula ([app/routes/schedule.py](file:///c:/Workspace/admin-edu-space/app/routes/schedule.py)):**
|
|
* Se corrigió la tupla de opciones en `form.classroom_id.choices`. Anteriormente concatenaba `c.code_display` y `c.name` (ambas propiedades computaban `"Edificio Central-Aula 204"`), provocando el texto repetido `Edificio Central-Aula 204 - Edificio Central-Aula 204 (Cap: 35)`.
|
|
* Se simplificó a `f'{c.building} - {c.code} (Cap: {c.capacity_display})'`, mostrando limpiamente `Edificio Central - Aula 204 (Cap: 35)`.
|
|
* **Cuadro de Resumen en Tiempo Real ([app/templates/schedule/add.html](file:///c:/Workspace/admin-edu-space/app/templates/schedule/add.html)):**
|
|
* Se corrigió la función JavaScript `updateSummary()` que concatenaba `${code_display} - ${name}`.
|
|
* Ahora renderiza de forma limpia y directa `${classroomData[classroomId].code_display} (${capLabel}: ${classroomData[classroomId].capacity})`.
|
|
* **Formato de Códigos de Comisión ([app/models/subject.py](file:///c:/Workspace/admin-edu-space/app/models/subject.py)):**
|
|
* Se optimizó `Commission.get_full_code()` para no repetir el año cuando ya viene incluido en el string del semestre (ej: `2026-2`).
|
|
|
|
---
|
|
|
|
## 20. Refactorización Integral de Espacios Físicos: Desacoplamiento de Edificio, Piso y Aula
|
|
* **Modelo de Datos y Base de Datos ([app/models/classroom.py](file:///c:/Workspace/admin-edu-space/app/models/classroom.py), [app/models/building.py](file:///c:/Workspace/admin-edu-space/app/models/building.py)):**
|
|
* **Desacoplamiento de Edificio:** Se reforzó la clave foránea `Classroom.building_id` vinculada a `buildings.id`. El nombre del edificio se obtiene directamente a través de `building_entity` manteniendo retrocompatibilidad.
|
|
* **Pisos Flexibles (Alfanuméricos):** Se migró la columna `classrooms.floor` a `VARCHAR(50)`, permitiendo registrar tanto valores numéricos como designaciones textuales ("PB", "Planta Baja", "1", "2°P", "Subsuelo").
|
|
* **Propiedades de Formato:** Se incorporaron `floor_display` ("Planta Baja", "Piso X"), `is_virtual` y `location_display` (`Edificio · Piso · Aula`).
|
|
* **Rutina de Migración:** Se verificó la integridad referencial garantizando que todas las aulas existentes queden asociadas a su `building_id` correspondiente en PostgreSQL.
|
|
* **Formulario y Flujo Dinámico de Creación/Edición de Aulas ([app/forms/classroom.py](file:///c:/Workspace/admin-edu-space/app/forms/classroom.py), [app/routes/classrooms.py](file:///c:/Workspace/admin-edu-space/app/routes/classrooms.py), [app/templates/classrooms/add.html](file:///c:/Workspace/admin-edu-space/app/templates/classrooms/add.html), [app/templates/classrooms/edit.html](file:///c:/Workspace/admin-edu-space/app/templates/classrooms/edit.html)):**
|
|
* **Selector de Edificio con Alta Dinámica:** Desplegable con las sedes activas más la opción destacada `+ Crear nuevo edificio`. Al seleccionarla, despliega de forma inmediata un campo de texto para escribir el nuevo edificio sin abandonar la pantalla.
|
|
* **Sugerencia de Pisos:** Campo con datalist interactivo que sugiere los pisos ya cargados en la sede seleccionada o permite tipear uno nuevo libremente.
|
|
* **Validación de Unicidad:** Se valida tanto en cliente como en servidor que no existan aulas duplicadas dentro del mismo edificio y piso.
|
|
* **Selectores en Cascada para Reservas ([app/templates/schedule/add.html](file:///c:/Workspace/admin-edu-space/app/templates/schedule/add.html), [app/routes/schedule.py](file:///c:/Workspace/admin-edu-space/app/routes/schedule.py)):**
|
|
* **Flujo Dependiente:**
|
|
1. `Edificio / Sede`: Selección de sede física o modalidad `Campus Virtual`.
|
|
2. `Piso / Nivel`: Se puebla dinámicamente con los pisos disponibles de esa sede (se deshabilita automáticamente si es Virtual).
|
|
3. `Aula / Espacio`: Filtra y muestra únicamente las aulas del edificio y piso seleccionados con su capacidad.
|
|
* **Resumen Desglosado con Badges:**
|
|
* 🏢 **Edificio / Sede:** Muestra el nombre limpio de la sede.
|
|
* 🪜 **Piso / Nivel:** Muestra la planta o "Remoto (Virtual)".
|
|
* 🚪 **Aula Seleccionada:** Muestra el número de aula y su capacidad.
|
|
* **Filtros en Listado de Aulas y Calendario ([app/templates/classrooms/list.html](file:///c:/Workspace/admin-edu-space/app/templates/classrooms/list.html), [app/templates/schedule/calendar.html](file:///c:/Workspace/admin-edu-space/app/templates/schedule/calendar.html), [app/templates/schedule/view.html](file:///c:/Workspace/admin-edu-space/app/templates/schedule/view.html)):**
|
|
* **Listado de Aulas:** Incorporación de dropdowns independientes para filtrar por **Edificio** y **Piso** en la barra superior. Tarjetas rediseñadas con badges distintivos de sede y piso.
|
|
* **Calendario Semanal:** Agregado el filtro **Filtrar por Edificio** en la barra superior junto al filtro de Piso.
|
|
* **Modal Estilo Google Calendar:** La sección de espacio físico desglosa limpiamente en badges: 🏢 Edificio, 🪜 Piso y 🚪 Aula.
|
|
|
|
---
|
|
|
|
## 21. Corrección de Linter y Renderizado de Barras en Métricas de Ocupación (2026-09-04)
|
|
* **Plantilla de Métricas de Ocupación ([app/templates/admin/metrics/occupancy.html](file:///c:/Workspace/admin-edu-space/app/templates/admin/metrics/occupancy.html)):**
|
|
* **Eliminación de Falsos Positivos de CSS en el IDE:** Se resolvieron los 12 errores de sintaxis (`property value expected`, `at-rule or selector expected`) reportados por el analizador HTML/CSS del IDE en las tarjetas de KPI (Tasa de Ocupación Hoy, Semanal, Mensual) y en la distribución por Piso / Nivel.
|
|
* **Atributos Semánticos HTML5:** Se sustituyó la inyección directa de Jinja2 en atributos `style="width: {{ ... }}%;"` por el atributo de datos estándar `data-width="{{ ... }}%"`.
|
|
* **Inicialización y Animación Dinámica en JS:**
|
|
* Se configuró en CSS (`.metric-bar-fill { width: 0; }`) un ancho base inicial.
|
|
* Se implementó un script en el bloque `extra_js` que asigna el ancho dinámico al cargar el DOM (`DOMContentLoaded`).
|
|
* En conjunto con `transition: width 0.6s ease;`, las barras se expanden de forma fluida y visualmente atractiva al cargar la pantalla.
|
|
|
|
---
|
|
|
|
## 22. Actualización de Instalador, Backup de Base de Datos y Despliegue en Proxmox LXC (2026-09-04)
|
|
* **Backup de Base de Datos ([classrooms_db.sql](file:///c:/Workspace/admin-edu-space/classrooms_db.sql)):**
|
|
* **Extracción del Snapshot Completo:** Volcado íntegro de la base de datos PostgreSQL activa (`classrooms_db`) que alimenta el sistema en producción/local.
|
|
* **Contenido Respaldado:** 25 aulas físicas y virtuales, 206 comisiones, 206 asignaturas, 412 reservas, 24 carreras, 12 tipos de hitos, matrices de permisos RBAC y usuarios administradores.
|
|
* **Compatibilidad Multi-Versión:** Se sanitizó la directiva `\restrict` específica de PostgreSQL 18 para garantizar compatibilidad nativa con PostgreSQL 14, 15, 16, 17 y 18.
|
|
* **Actualización del Instalador del Sistema para Proxmox LXC ([install.sh](file:///c:/Workspace/admin-edu-space/install.sh)):**
|
|
* **Ejecución 100% Automatizada (Zero-Touch):** Se eliminaron todos los prompts interactivos (`read -rp`), permitiendo que el script corra de inicio a fin de forma totalmente desatendida.
|
|
* **Copia de Configuración Activa del Sistema:** Se configuraron como valores por defecto los parámetros reales del sistema en ejecución (`DATABASE_URL=postgresql://postgres:password@localhost:5432/classrooms_db`, usuario `postgres`, base `classrooms_db` y contraseña `password`), garantizando paridad exacta con el entorno local.
|
|
* **Compatibilidad Dual de Usuarios:** Configuración tanto del superusuario `postgres` como de `eduspace_user` con los mismos privilegios para compatibilidad inmediata ante cualquier variación de `.env`.
|
|
* **Optimización Proxmox LXC:** Compatible con contenedores Debian 11/12 y Ubuntu 20.04/22.04/24.04 en Proxmox VE.
|
|
* **Migración Automática de Directorio:** Si el repositorio se clona en `/root`, se traslada automáticamente a `/opt/admin-edu-space` para garantizar permisos de ejecución del usuario del servicio (`eduspace`).
|
|
* **Despliegue del Motor PostgreSQL Nativo:** Instalación desatendida del motor en el LXC, inicialización dinámica del servicio y bucle de healthcheck de conexión.
|
|
* **Restauración Automatizada y Permisos:** Detección automática de `classrooms_db.sql`, recreación limpia, asignación de permisos `GRANT ALL` en el esquema `public`, todas las tablas y secuencias a `postgres` y `eduspace_user`.
|
|
* **Entorno Virtual Nativo (`venv`):** Configuración en `/opt/admin-edu-space/venv` con dependencias del sistema y `gunicorn`.
|
|
* **Servicio Systemd de Producción:** Configuración y activación de `admin-edu-space.service` en el puerto 5000.
|
|
* **Ejecución Idempotente:** Integración de `init_db.py` tras la restauración para validar la coherencia del esquema y roles.
|
|
* **Utilidad de Backup Continuo ([backup_db.sh](file:///c:/Workspace/admin-edu-space/backup_db.sh)):**
|
|
* Script automatizado para generar copias de seguridad fechadas en `backups/` y actualizar simultáneamente `classrooms_db.sql` para facilitar la migración entre contenedores LXC.
|
|
* **Documentación y Tutorial en README ([README.md](file:///c:/Workspace/admin-edu-space/README.md)):**
|
|
* Guía paso a paso para la creación del contenedor LXC en Proxmox VE (especificaciones de CPU, RAM, disco y habilitación de `nesting=1`).
|
|
* Instrucciones completas de instalación desatendida con `install.sh`.
|
|
* Corrección de comandos de inicio apuntando al punto de entrada oficial [wsgi.py](file:///c:/Workspace/admin-edu-space/wsgi.py).
|
|
* Guía paso a paso para la generación y restauración de backups.
|
|
* **Dependencias ([requirements.txt](file:///c:/Workspace/admin-edu-space/requirements.txt)):**
|
|
* Se incorporó formalmente `gunicorn>=21.2.0` al listado de dependencias del proyecto.
|
|
|