Ctrl K
ComunidadGuías…

README.en.md

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

Archivo original ↗Preguntar a KiBot
# Teacher Cover, Substitutions & Exam Invigilation Manager

> **Open-source** web app, developed with **Claude Code**, to organise **teacher cover / substitutions** and
> **exam invigilation** in a school: automatic, fair duty assignment, PDF reports
> and timetable import from [FET](https://lalescu.ro/liviu/fet/).

[Català](README.md) · [Castellano](README.es.md) · **English**

[![License: AGPL v3+](https://img.shields.io/badge/License-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)

**Live demo:** [demo.gestor.alienamrt.org](https://demo.gestor.alienamrt.org) — log in with `user_demo` or `admin_demo` (to see the admin features), password `demo1234`. _The demo resets daily at 4:00._

> ⚠️ The demo is **public and shared**: other people may be using it at the same time and can see whatever you enter. Do not upload timetables or real personal data from your school.

<!--
  Keywords (for search discovery):
  teacher cover supervision · substitute teacher scheduling · relief teacher ·
  exam invigilation scheduler · invigilation rota · teacher absence management ·
  gestión de guardias y sustituciones · gestió de guàrdies i substitucions.
-->

If you are looking for **cover supervision software**, a **substitute teacher
scheduler** or a tool to build a fair **exam invigilation rota**, this project
covers the whole workflow in a single, self-hostable, free application.

---

## Screenshots

| Daily substitutions | Invigilation & groups | Exam scheduler |
|---|---|---|
| ![Substitutions view](docs/img/substitucions.png) | ![Invigilation view](docs/img/vigilancies.png) | ![Exam scheduler](docs/img/planificador.png) |

> _Screenshots use the sample institution (`Prof 1`, `Prof 2`…); no real data._

---

## Features

- **Daily cover & substitutions** with automatic substitute assignment
- **Exam invigilation** and management of groups without class
- **Fair workload distribution** based on load and configurable constraints
- **PDF export** (substitutions, invigilation, intervals, management reports)
- **Exam scheduler** with automatic optimisation (3 generation engines)
- **FET timetable import** (XML from _Free Timetabling Software_)
- **Multi-institution**: one database per school, global authentication
- **Roles**: `super_admin`, `admin`, `user`
- **Multilingual UI**: Catalan, Spanish, English and Italian

## Architecture

**Stack:** FastAPI + Vue 3 + PrimeVue · SQLite · Docker + Caddy

```
Caddy (reverse proxy + HTTPS)
  ├── /api/*  →  backend:8000  (FastAPI)
  └── /*      →  frontend:80   (Vue 3 + Nginx)

data/
  ├── auth.db          # Global users
  └── {institution}/
      ├── gestor.db    # School data
      ├── *.xml        # School's FET timetable
      └── exports/     # Generated PDFs
```

The FastAPI backend exposes the API under `/api/*`, handles XML timetable parsing,
automatic assignment of substitutes and invigilators, and PDF export. The Vue 3 +
PrimeVue frontend organises navigation into tabs: substitutions, invigilation,
groups and the exam scheduler. The scheduling engine (`scheduler_engine/`) ships
three generators (attempts, backtracking and Simulated Annealing) with a
configurable constraint model.

The logic called by the routes lives in `serveis/` (the state of a day,
`DiaEscolar`, and the single rule for when a substitute can no longer cover;
generating substitutions, marking absences, validating before the PDF), and the
assignment engine in `core/`.

### Rules

- A teacher is free if their group is marked as having no class at that hour
  (exactly, including combined groups) or if they are released.
- Only the "Generate pending", "Regenerate all" and "Reassign" (in the
  pre-PDF validation) buttons assign substitutes. Changes to the day (released groups, absences,
  covered absences) remove substitutes who can no longer cover and leave the row pending,
  with a notice.
- A teacher with a covered absence (their classes are covered in the XML, by a
  substitute or by other teachers) is left out of everything during the
  period: they neither cover, nor are covered, nor supervise.

Over 700 tests (`cd backend && pytest tests/`) on temporary institutions with
the sample timetable.

For the full dependency map and the rules in detail see
[ARQUITECTURA.md](ARQUITECTURA.md) (in Catalan).

---

## Quick local test

To try the app with the bundled sample data, without Docker or a domain.

**Requirements:** Python 3.10+ and Node.js 22+

### 1. Clone

```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
# Edit .env: set absolute paths in DATA_DIR and AUTH_DB_PATH pointing to
# {project path}/data and {project path}/data/auth.db

uvicorn main:app --reload --host 0.0.0.0 --port 8000
```

The backend automatically creates the databases (`auth.db` and
`data/{APP_INSTITUCIO}/gestor.db`) on first start and, if there are no users
yet, a super_admin from `ADMIN_USERNAME`/`ADMIN_PASSWORD` in `.env`.

API at `http://localhost:8000` · Docs at `http://localhost:8000/docs`.

### 3. Frontend

In another terminal:

```bash
cd frontend
npm install
npm run dev
```

Open `http://localhost:5173` and log in with the `super_admin` credentials defined
in the backend `.env`. The dev frontend proxies to the backend
via Vite.

### 4. Load the sample data

Once inside, go to **Settings > Import XML** and upload `data/exemple/teachers.xml`.
It is a sample timetable generated with FET.

---

## Local Docker (no domain)

To try it with Docker without configuring a domain or HTTPS, there is a
`docker-compose.local.yml.example` that starts only backend + frontend (no Caddy)
and serves the app at `http://localhost:8080`.

```bash
cp .env.example .env
cp docker-compose.local.yml.example docker-compose.local.yml
# Edit .env: generate SECRET_KEY (openssl rand -hex 32), set COOKIE_SECURE=false
# (required for plain HTTP) and an ADMIN_PASSWORD

docker compose -f docker-compose.local.yml up --build -d
```

Open `http://localhost:8080`.

> ⚠️ This mode has no HTTPS; local development only. **Do not use in production**,
> tokens travel in clear text.

---

## Production deployment

Recommended with Docker + Caddy (automatic HTTPS). You will need:

- A server with Docker and Docker Compose
- A domain pointing to the server

### 1. Clone and configure

```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
```

Edit `.env`:

```env
SECRET_KEY=        # required — generate with: openssl rand -hex 32
APP_INSTITUCIO=school_name          # slug without spaces/accents
ADMIN_INSTITUCIO=school_name        # identical to APP_INSTITUCIO
ADMIN_PASSWORD=a-strong-password
```

Edit `Caddyfile` and replace `el-teu-domini.exemple.com` with your real domain
(with DNS already pointing to the server).

### 2. Start

```bash
docker compose up --build -d
```

Caddy obtains the TLS certificate automatically. The app will be at
`https://{your-domain}`.

The application **will not start** without `SECRET_KEY`, or, on a new
installation (no users yet), without `ADMIN_PASSWORD`. Neither has a default
value, on purpose: no installation should end up exposed with credentials that
are published in this repository. If super_admin access is lost, it can be
recovered with `ADMIN_PASSWORD_RECUPERACIO` (see `.env.example`), which must be
removed from the environment after use.

### 3. First login

- Log in as `super_admin` with the password set in `ADMIN_PASSWORD`
- **Change the password** immediately from Settings > Users
- Upload your school's XML (generated by [FET](https://lalescu.ro/liviu/fet/))
  from Settings > Import XML

### Access log

If you enable the proxy's access log (see `Caddyfile.example`), IP addresses
are stored. The example ships with a configurable retention period.

### Updates

```bash
cd /path/to/project
git pull
docker compose up --build -d
```

---

## Sample data

The `data/exemple/` directory includes a `teachers.xml`: a sample timetable
generated with [FET](https://lalescu.ro/liviu/fet/).

---

## Backups

All data lives in the `./data/` folder. Make periodic copies of this folder with
your preferred tool (cron + rsync, rclone to a cloud, etc.).

```bash
# Minimal rsync example
rsync -a /opt/gestor/data/ /backup/gestor-data/
```

---

## License

Released under the [GNU Affero General Public License, version 3 or later](LICENSE).

Copyright (C) 2026 Martí Villaret Ausellé.