Aplicació web de codi obert, desenvolupada amb Claude Code, per organitzar les guàrdies i substitucions del professorat i les vigilàncies d'exàmens d'un centre educatiu: assignació automàtica i equitativa, informes en PDF i importació de l'horari des de FET.
Català · Castellano · English
Demo pública: gestor.alienamrt.org — entra amb user_demo o admin_demo (per veure les funcions d'administració), contrasenya demo1234. La demo es reinicia cada dia a les 4:00.
⚠️ La demo és pública i compartida: altres persones hi poden estar treballant alhora i veure el que hi introduïu. No hi pugeu horaris ni dades personals reals del vostre centre.
Si busques un programa de guàrdies escolars, un gestor de substitucions de professorat o una eina per repartir vigilàncies d'exàmens de manera justa, aquest projecte cobreix tot el flux en una sola aplicació, autoallotjable i gratuïta.
| Substitucions diàries | Vigilàncies i grups | Planificador d'exàmens |
|---|---|---|
![]() |
![]() |
![]() |
Captures fetes amb la institució d'exemple (
Prof 1,Prof 2…); cap dada real.
- Guàrdies i substitucions diàries amb assignació automàtica de substituts
- Vigilàncies d'exàmens i gestió de grups sense classe
- Repartiment equitatiu de tasques segons càrrega i restriccions configurables
- Exportació a PDF (substitucions, vigilàncies, intervals, informes de direcció)
- Planificador d'exàmens amb optimització automàtica (3 motors de generació)
- Importació d'horari des de FET (XML de Free Timetabling Software)
- Multi-institució: una base de dades per centre, autenticació global
- Rols:
super_admin,admin,user - Multilingüe: català, castellà i anglès
Stack: FastAPI + Vue 3 + PrimeVue · SQLite · Docker + Caddy
Caddy (reverse proxy + HTTPS)
├── /api/* → backend:8000 (FastAPI)
└── /* → frontend:80 (Vue 3 + Nginx)
data/
├── auth.db # Usuaris globals
└── {institucio}/
├── gestor.db # Dades del centre
├── *.xml # Horari FET del centre
└── exports/ # PDFs generats
main.py— punt d'entrada, registra 15 routers a/api/*routes/— endpoints per àrea funcional (substitucions, vigilàncies, scheduler, informes, PDFs, auth, files, settings...)core/— lògica de negoci (parseig d'horari XML, assignació automàtica de substituts i vigilàncies, gestió d'absències i baixes)scheduler_engine/— motor de planificació d'exàmens amb 3 generadors (v2-intents, v2-backtrack, v3-SA Simulated Annealing) i model de restriccions configurableexport/— exportadors PDF (substitucions, vigilàncies, intervals, informes de direcció i professorat)repositories.py+models.py— accés a dades SQLAlchemyauth_utils.py— autenticació JWT amb cookie httpOnly
- Sense Vue Router: navegació per pestanyes amb PrimeVue TabView
- 4 vistes principals:
SubstitucionsView,VigilanciesView,GrupsView,SchedulerView(planificador d'exàmens) - Composables a
views/scheduler/use*.jsper a la lògica de cada subàrea del planificador (API, resultats, restriccions, slots, incidències) - i18n amb
vue-i18n: traduccions alocales/{ca,es,en}.json - Pinia per a estat compartit (preparada però amb poc ús actual)
Per al mapa de dependències complet veure ARQUITECTURA.md.
Per provar l'aplicació amb les dades d'exemple incloses, sense Docker ni domini.
Requisits: Python 3.10+ i Node.js 18+
git clone https://github.com/mrtvillaret/fet-substitutions-manager.git
cd fet-substitutions-managercd 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: posa rutes absolutes a DATA_DIR i AUTH_DB_PATH apuntant a
# {ruta del projecte}/data i {ruta del projecte}/data/auth.db
uvicorn main:app --reload --host 0.0.0.0 --port 8000El backend crea automàticament les BDs (auth.db i data/{APP_INSTITUCIO}/gestor.db)
al primer arrencat, i un super_admin segons ADMIN_USERNAME/ADMIN_PASSWORD del .env.
API disponible a http://localhost:8000 · Documentació a http://localhost:8000/docs
(només amb ENVIRONMENT=development; en qualsevol altre entorn no es publica).
En una altra terminal:
cd frontend
npm install
npm run devObre http://localhost:5173 i entra amb les credencials super_admin definides
al .env del backend. El frontend en dev apunta al backend
mitjançant el proxy de Vite.
Un cop dins, ves a Configuració > Importar XML i puja data/exemple/teachers.xml.
És un horari d'exemple generat amb FET.
cd backend
pip install -r requirements-dev.txt
pytest tests/tests/test_api.py són comprovacions de fum contra un backend engegat: si no
n'hi ha cap a http://localhost:8000, se salten. Els tests de regressió del
planificador comparen la sortida del motor amb un resultat fix i necessiten el
conjunt de dades que el va generar, que no es distribueix; apunta-hi
TEST_DATA_DIR si en tens un de propi.
Si vols provar-ho amb Docker sense haver de configurar un domini ni HTTPS, hi ha un
docker-compose.local.yml.example que aixeca només backend + frontend (sense Caddy)
i serveix l'app a http://localhost:8080.
cp .env.example .env
cp docker-compose.local.yml.example docker-compose.local.yml
# Edita .env: genera SECRET_KEY (openssl rand -hex 32), posa COOKIE_SECURE=false
# (cal per HTTP plain) i una ADMIN_PASSWORD
docker compose -f docker-compose.local.yml up --build -dObre http://localhost:8080.
⚠️ Aquest mode no té HTTPS; només per a desenvolupament local. No usar en producció, els tokens viatgen en clar.
Recomanat amb Docker + Caddy (HTTPS automàtic). Et caldrà:
- Un servidor amb Docker i Docker Compose
- Un domini apuntant al servidor
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.ymlEdita el .env:
SECRET_KEY= # obligatòria — genera-la amb: openssl rand -hex 32
APP_INSTITUCIO=nom_del_centre # slug sense espais/accents
ADMIN_INSTITUCIO=nom_del_centre # idèntic a APP_INSTITUCIO
ADMIN_PASSWORD=una-contrasenya-segura # obligatòria al primer arrencadaEdita el Caddyfile i substitueix el-teu-domini.exemple.com pel teu domini real
(amb DNS apuntant ja al servidor).
docker compose up --build -dCaddy obté el certificat TLS automàticament. L'aplicació estarà a
https://{el-teu-domini}.
L'aplicació no arrenca si falta SECRET_KEY o, quan encara no existeix
l'administrador, ADMIN_PASSWORD. No tenen valor per defecte a propòsit: així
cap instal·lació queda oberta amb credencials que consten en aquest repositori.
- Entra com a
super_adminamb la contrasenya definida aADMIN_PASSWORD - Canvia la contrasenya immediatament des de Configuració > Usuaris
- Puja l'XML del teu centre (generat per FET) des de Configuració > Importar XML
Si activeu l'access log del proxy (vegeu Caddyfile.example), es desen
adreces IP. L'exemple porta un termini de conservació configurable.
cd /ruta/al/projecte
git pull
docker compose up --build -dfet-substitutions-manager/
├── backend/
│ ├── main.py # FastAPI app + startup
│ ├── routes/ # Endpoints: substitucions, vigilancies, scheduler...
│ ├── core/ # Lògica de negoci (horari, alliberats, substitucions)
│ ├── scheduler_engine/ # Motor de planificació d'exàmens
│ ├── config/ # Configuració, constants, settings
│ ├── repositories.py # Accés a dades (SQLAlchemy)
│ ├── requirements.txt
│ ├── Dockerfile
│ └── .env.example
├── frontend/
│ ├── src/
│ │ ├── App.vue
│ │ ├── views/ # SubstitucionsView, VigilanciesView, SchedulerView...
│ │ ├── components/ # Dialogs, navbar, etc.
│ │ └── locales/ # Traduccions ca/es/en
│ ├── Dockerfile
│ └── package.json
├── data/
│ └── exemple/
│ └── teachers.xml # Horari d'exemple generat amb FET
├── scripts/
│ ├── setup-server.sh # Preparació inicial del servidor
│ └── sync-server.sh.example # Script de sincronització al servidor
├── docker-compose.yml.example # Plantilla Docker Compose (copia a docker-compose.yml)
├── docker-compose.local.yml.example # Plantilla per a proves locals sense domini
├── Caddyfile.example # Plantilla Caddy (copia a Caddyfile)
└── .env.example # Plantilla variables d'entorn (copia a .env)
El directori data/exemple/ inclou un teachers.xml: un horari d'exemple
generat amb FET.
Totes les dades es troben a la carpeta ./data/. Fes còpies periòdiques d'aquesta carpeta amb l'eina que prefereixis (cron + rsync, rclone a un núvol, etc.).
# Exemple mínim amb rsync
rsync -a /opt/gestor/data/ /backup/gestor-data/Publicat sota la GNU Affero General Public License, versió 3 o posterior.
Copyright (C) 2026 Martí Villaret Ausellé.


