# Gestor de Guardias, Sustituciones y Vigilancias de Exámenes > Aplicación web **de código abierto**, desarrollada con **Claude Code**, para organizar las **guardias y sustituciones** > del profesorado y las **vigilancias de exámenes** de un centro educativo: asignación > automática y equitativa, informes en PDF e importación del horario desde > [FET](https://lalescu.ro/liviu/fet/). [Català](README.md) · **Castellano** · [English](README.en.md) [![Licencia: AGPL v3+](https://img.shields.io/badge/Licencia-AGPLv3%2B-blue.svg)](LICENSE) ![Stack](https://img.shields.io/badge/FastAPI-Vue%203-009688) ![Self-hosted](https://img.shields.io/badge/self--hosted-Docker%20%2B%20Caddy-2496ED) **Demo pública:** [demo.gestor.alienamrt.org](https://demo.gestor.alienamrt.org) — entra con `user_demo` o `admin_demo` (para ver las funciones de administración), contraseña `demo1234`. _La demo se reinicia cada día a las 4:00._ > ⚠️ La demo es **pública y compartida**: otras personas pueden estar trabajando a la vez y ver lo que introduzcáis. No subáis horarios ni datos personales reales de vuestro centro. Si buscas un **programa de guardias escolares**, un **gestor de sustituciones del profesorado** o una herramienta para **repartir vigilancias de exámenes** de forma justa, este proyecto cubre todo el flujo en una sola aplicación, autoalojable y gratuita. --- ## Capturas de pantalla | Sustituciones diarias | Vigilancias y grupos | Planificador de exámenes | |---|---|---| | ![Vista de sustituciones](docs/img/substitucions.png) | ![Vista de vigilancias](docs/img/vigilancies.png) | ![Planificador de exámenes](docs/img/planificador.png) | > _Capturas hechas con la institución de ejemplo (`Prof 1`, `Prof 2`…); ningún dato real._ --- ## Funcionalidades - **Guardias y sustituciones diarias** con asignación automática de sustitutos - **Vigilancias de exámenes** y gestión de grupos sin clase - **Reparto equitativo** de tareas según carga y restricciones configurables - **Exportación a PDF** (sustituciones, vigilancias, intervalos, informes de dirección) - **Planificador de exámenes** con optimización automática (3 motores de generación) - **Importación de horario desde FET** (XML de _Free Timetabling Software_) - **Multi-institución**: una base de datos por centro, autenticación global - **Roles**: `super_admin`, `admin`, `user` - **Multilingüe**: catalán, castellano, inglés e italiano ## Arquitectura **Stack:** FastAPI + Vue 3 + PrimeVue · SQLite · Docker + Caddy ``` Caddy (reverse proxy + HTTPS) ├── /api/* → backend:8000 (FastAPI) └── /* → frontend:80 (Vue 3 + Nginx) data/ ├── auth.db # Usuarios globales └── {institucion}/ ├── gestor.db # Datos del centro ├── *.xml # Horario FET del centro └── exports/ # PDFs generados ``` El backend (FastAPI) expone la API en `/api/*`, gestiona el parseo del horario XML, la asignación automática de sustitutos y vigilantes, y la exportación a PDF. El frontend (Vue 3 + PrimeVue) organiza la navegación por pestañas: sustituciones, vigilancias, grupos y planificador de exámenes. El motor de planificación (`scheduler_engine/`) incluye 3 generadores (intentos, backtracking y Simulated Annealing) con un modelo de restricciones configurable. La lógica que llaman las rutas está en `serveis/` (el estado de un día, `DiaEscolar`, y la regla de cuándo un sustituto ya no puede serlo; generar las sustituciones, marcar ausencias, validar antes del PDF), y el motor de asignación en `core/`. ### Reglas de funcionamiento - Un profesor queda libre si su grupo está marcado sin clase a esa hora (exactamente, también las agrupaciones) o si él está liberado. - Solo asignan sustitutos los botones «Generar pendientes», «Regenerar todo» y «Reasignar» (en la validación antes del PDF). Los cambios del día (liberados, ausencias, ausencias cubiertas) quitan los sustitutos que ya no pueden serlo y dejan la fila pendiente, con un aviso. - Un profesor con una ausencia cubierta (tiene las clases cubiertas en el XML, por un sustituto o por otros profesores) queda fuera de todo durante el período: ni sustituye, ni es sustituido, ni vigila. Más de 700 tests (`cd backend && pytest tests/`) sobre instituciones temporales con el horario de ejemplo. Para el mapa de dependencias completo y las reglas en detalle, ver [ARQUITECTURA.md](ARQUITECTURA.md) (en catalán). --- ## Prueba rápida en local Para probar la aplicación con los datos de ejemplo incluidos, sin Docker ni dominio. **Requisitos:** Python 3.10+ y Node.js 22+ ### 1. Clonar ```bash git clone https://github.com/mrtvillaret/fet-substitutions-manager.git cd fet-substitutions-manager ``` ### 2. Backend ```bash cd backend python3 -m venv venv source venv/bin/activate # Linux/macOS # venv\Scripts\activate # Windows pip install -r requirements.txt cp .env.example .env # Edita .env: pon rutas absolutas en DATA_DIR y AUTH_DB_PATH apuntando a # {ruta del proyecto}/data y {ruta del proyecto}/data/auth.db uvicorn main:app --reload --host 0.0.0.0 --port 8000 ``` El backend crea automáticamente las BD (`auth.db` y `data/{APP_INSTITUCIO}/gestor.db`) en el primer arranque y, si aún no hay ningún usuario, un super_admin según `ADMIN_USERNAME`/`ADMIN_PASSWORD` del `.env`. API disponible en `http://localhost:8000` · Documentación en `http://localhost:8000/docs`. ### 3. Frontend En otra terminal: ```bash cd frontend npm install npm run dev ``` Abre `http://localhost:5173` y entra con las credenciales `super_admin` definidas en el `.env` del backend. El frontend en dev apunta al backend mediante el proxy de Vite. ### 4. Cargar los datos de ejemplo Una vez dentro, ve a **Configuración > Importar XML** y sube `data/exemple/teachers.xml`. Es un horario de ejemplo generado con FET. --- ## Docker local (sin dominio) Si quieres probarlo con Docker sin configurar dominio ni HTTPS, hay un `docker-compose.local.yml.example` que levanta solo backend + frontend (sin Caddy) y sirve la app en `http://localhost:8080`. ```bash cp .env.example .env cp docker-compose.local.yml.example docker-compose.local.yml # Edita .env: genera SECRET_KEY (openssl rand -hex 32), pon COOKIE_SECURE=false # (necesario para HTTP plano) y una ADMIN_PASSWORD docker compose -f docker-compose.local.yml up --build -d ``` Abre `http://localhost:8080`. > ⚠️ Este modo no tiene HTTPS; solo para desarrollo local. **No usar en > producción**, los tokens viajan en claro. --- ## Desplegar en producción Recomendado con Docker + Caddy (HTTPS automático). Necesitarás: - Un servidor con Docker y Docker Compose - Un dominio apuntando al servidor ### 1. Clonar y configurar ```bash git clone https://github.com/mrtvillaret/fet-substitutions-manager.git cd fet-substitutions-manager cp .env.example .env cp Caddyfile.example Caddyfile cp docker-compose.yml.example docker-compose.yml ``` Edita el `.env`: ```env SECRET_KEY= # obligatoria — genérala con: openssl rand -hex 32 APP_INSTITUCIO=nombre_del_centro # slug sin espacios/acentos ADMIN_INSTITUCIO=nombre_del_centro # idéntico a APP_INSTITUCIO ADMIN_PASSWORD=una-contrasena-segura ``` Edita el `Caddyfile` y sustituye `el-teu-domini.exemple.com` por tu dominio real (con DNS apuntando ya al servidor). ### 2. Arrancar ```bash docker compose up --build -d ``` Caddy obtiene el certificado TLS automáticamente. La aplicación estará en `https://{tu-dominio}`. La aplicación **no arranca** si falta `SECRET_KEY` o, en una instalación nueva (sin ningún usuario), `ADMIN_PASSWORD`. No tienen valor por defecto a propósito: así ninguna instalación queda abierta con credenciales que constan en este repositorio. Si se pierde el acceso del superadmin, se recupera con `ADMIN_PASSWORD_RECUPERACIO` (ver `.env.example`), que hay que quitar del entorno después de usarla. ### 3. Primer acceso - Entra como `super_admin` con la contraseña definida en `ADMIN_PASSWORD` - **Cambia la contraseña** de inmediato desde Configuración > Usuarios - Sube el XML de tu centro (generado por [FET](https://lalescu.ro/liviu/fet/)) desde Configuración > Importar XML ### Registro de accesos Si activáis el `access log` del proxy (ver `Caddyfile.example`), se guardan direcciones IP. El ejemplo trae un plazo de conservación configurable. ### Actualizaciones ```bash cd /ruta/al/proyecto git pull docker compose up --build -d ``` --- ## Datos de ejemplo El directorio `data/exemple/` incluye un `teachers.xml`: un horario de ejemplo generado con [FET](https://lalescu.ro/liviu/fet/). --- ## Copias de seguridad Todos los datos están en la carpeta `./data/`. Haz copias periódicas de esta carpeta con la herramienta que prefieras (cron + rsync, rclone a la nube, etc.). ```bash # Ejemplo mínimo con rsync rsync -a /opt/gestor/data/ /backup/gestor-data/ ``` --- ## Licencia Publicado bajo la [GNU Affero General Public License, versión 3 o posterior](LICENSE). Copyright (C) 2026 Martí Villaret Ausellé.