272 lines
25 KiB
Markdown
272 lines
25 KiB
Markdown
# Resumen de Cambios - Sesión de Desarrollo (Rama `dev`)
|
|
|
|
**Fecha:** 2026-09-02 / 2026-09-03
|
|
**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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|