Contínuos CRR

A shift rota application built with FastAPI, SQLite/SQLAlchemy, and server-rendered Jinja templates. It manages night and lunch schedules, teams, shared user logins, shift swaps, calendar subscriptions, and optional email notifications.

Run locally

With Python 3.12+ (including venv/pip) and make installed, run:

make dev

This creates/reuses .venv, installs development dependencies, creates data/, and starts Uvicorn with auto-reload at http://localhost:8000. Startup applies migrations and seeds the initial administrator and schedules. Stop it with Ctrl+C. No virtualenv activation, Docker, or separate database setup is needed.

The app reads .env if present; otherwise it uses its development defaults, including data/bar_rota.db and the initial login admin / change-me-now. Use a local SQLite path in DATABASE_URL and SESSION_HTTPS_ONLY=false for local HTTP development. Settings such as INITIAL_ADMIN_USERNAME and INITIAL_ADMIN_PASSWORD override the defaults when the database is first seeded.

To use another port:

make dev PORT=8001

Update BASE_URL to match if using email notification links. The Makefile port defaults to 8000; override it on the command line or through an exported PORT.

Run with Docker Compose

compose.yaml is a minimal deployment example. With Docker and Docker Compose installed, copy the example settings and edit .env:

cp .env.example .env

Set SECRET_KEY to a long random value and choose INITIAL_ADMIN_PASSWORD before the first start. Set BASE_URL to the address users will access; SMTP is optional.

Build and start the application:

docker compose up --build -d

Open http://localhost:8000 and sign in with INITIAL_ADMIN_USERNAME and INITIAL_ADMIN_PASSWORD. Startup applies database migrations and creates the initial administrator and schedules automatically. Initial administrator settings only apply when the database is first seeded.

  • PORT selects the host port (default 8000); update BASE_URL if you change it.
  • DATA_DIR selects the host data directory (default ./data). The SQLite database and default startup backups persist there across container rebuilds and restarts.
  • Compose sets DATABASE_URL to sqlite:////app/data/bar_rota.db so the database stays inside the persistent mount. If setting BACKUP_DIR, use a container path beneath /app/data to persist backups too.
  • For a reverse proxy, set BASE_URL to the public URL, ROOT_PATH if served under a sub-path, and SESSION_HTTPS_ONLY=true when served over HTTPS.

View logs or stop the service:

docker compose logs -f app
docker compose down

Stopping the service leaves the host data directory intact.

Add shifts to a phone's calendar

Sign in, open Calendário from the rota, and choose your team's calendar (administrators can also choose Rota completa):

  • iPhone / Apple Calendar opens the native subscription confirmation.
  • Google Calendar / Android opens Google Calendar on the web. Google requires its desktop interface to add subscriptions: request the desktop site in your phone's browser, or add it on a computer, then enable the calendar in the mobile app.
  • Outlook opens the web subscription screen; use the same account as the mobile app.
  • Copiar endereço supplies the feed URL for another app or manual setup.

The page includes step-by-step instructions for each platform. Subscribe by URL rather than importing a downloaded .ics file so future changes appear automatically. Providers control refresh timing; updates may take several hours. Google and Outlook need an Internet-accessible feed address.

Run tests

From the repository root, run one command:

make test

You need Python 3.12+ with venv/pip and make. The command automatically creates .venv if needed, installs requirements-dev.txt (including application dependencies), and runs pytest. Dependency installation needs package-index access on the first run. You do not need to activate a virtualenv, start the application, or run Docker or database setup commands.

The framework is pytest, with HTTPX available for FastAPI's TestClient. Configuration is in pyproject.toml; tests are discovered under tests/. The suite covers PDF downloads, date boundaries, permissions, preservation of assignments and single-page A4 output. Fixtures use temporary SQLite storage and disable SMTP. Actual failures and pytest errors return a nonzero status.

Optional pytest arguments use the same command:

make test ARGS="-k rotation -v"

Adding tests

  • Put files in tests/test_*.py, name functions test_*, and use plain assert.
  • Use pytest's tmp_path and monkeypatch for isolated data and settings.
  • Add database and HTTP client fixtures to tests/conftest.py as they become needed. Fixtures should initialize a fresh temporary SQLite database and clean up FastAPI dependency overrides automatically. Do not require manual migrations or seeding.
  • Set environment variables before importing app modules: settings read .env, and the SQLAlchemy engine is created at import time. Tests must use temporary databases and disable real SMTP rather than inherit local application settings.
  • HTTP tests use fastapi.testclient.TestClient. Its context manager runs the app's lifespan, including backups, migrations, and initial data; configure those against temporary storage before entering it.
  • Test observable behavior: scheduling boundaries, preservation of existing shifts, permissions/CSRF, swap ownership and transitions, calendar output, and email failure handling. Use fixed dates and explicit data so tests do not depend on execution order.

Repository documentation

S
Description
No description provided
Readme
1.1 MiB
Languages
Python 74.3%
HTML 21.1%
CSS 3.8%
Dockerfile 0.3%
Mako 0.3%
Other 0.2%