Ctrl K
ComunidadGuías…

README.es.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# 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.

<!--
  Palabras clave (para descubrimiento en buscadores):
  gestión de guardias · sustituciones del profesorado · reparto de guardias ·
  vigilancias de exámenes · cobertura de ausencias · guardias docentes ·
  teacher cover / substitute scheduling · exam invigilation · cover supervision.
-->

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é.