Getting Started¶
This guide walks you through setting up RotaCC locally for development. You can choose between Docker Compose (quickest path) or a full local development setup (most control).
Prerequisites¶
| Tool | Version | Notes |
|---|---|---|
| Python | 3.11+ | Required for local dev |
| PostgreSQL | 15+ | Required for local dev (or use SQLite) |
| Redis | 7+ | Required for Celery (or use Docker just for Redis) |
| Docker & Docker Compose | Any recent | Optional but recommended |
| uv | Latest | Install uv |
Option 1: Docker Compose (Recommended)¶
The fastest way to get the full stack running — PostgreSQL, Redis, Celery worker, and the Django app, all containerized.
1. Clone the repository and configure environment:
Edit .env and set at minimum:
SECRET_KEY=change-this-to-something-secure
DJANGO_SUPERUSER_USERNAME=admin
DJANGO_SUPERUSER_EMAIL=admin@example.com
DJANGO_SUPERUSER_PASSWORD=changeme
2. Build and start all services:
This starts four services: web (Gunicorn on port 8000), celery_worker (task processing with beat scheduler), postgres (15-alpine), and redis (7-alpine). The entrypoint script runs migrations and creates the superuser automatically.
3. Open the application:
4. Load sample data (optional):
Useful commands for working with the Docker setup:
docker compose logs -f # Stream logs from all services
docker compose logs -f web # Stream logs from web only
docker compose down # Stop all services
docker compose down -v # Stop services and delete volumes (resets DB)
Option 2: Local Development¶
This gives you the most control. The dev settings module (rota.settings.dev) uses SQLite and in-memory cache by default, so you do not need PostgreSQL or Redis for basic development.
1. Clone the repository and install dependencies:
2. Configure environment:
For local development with SQLite (no PostgreSQL needed), keep the defaults in .env and set:
The dev settings module overrides the database to SQLite, uses in-memory cache instead of Redis, enables the Django Debug Toolbar, and disables SSL/CSRF security requirements.
3. Run migrations and create an admin user:
4. Load sample data (optional):
5. Start the development server:
6. Start Celery (separate terminal):
For Celery you need Redis running. You can either install Redis locally or run just the Redis container:
# Option A: Run Redis via Docker
docker run -d --name redis -p 6379:6379 redis:7-alpine
# Option B: If Redis is installed locally
# No action needed
Then start the Celery worker:
Note
Without Celery running, rota generation tasks will not execute. The rest of the app (viewing shifts, managing leave, etc.) works fine without it.
7. Open the application:
Using PostgreSQL locally¶
If you prefer to run against PostgreSQL instead of SQLite, set these in your .env:
DB_ENGINE=django.db.backends.postgresql
DB_NAME=rota_db
DB_USER=rota_user
DB_PASSWORD=rota_password
DB_HOST=localhost
DB_PORT=5432
REDIS_HOST=localhost
CELERY_BROKER_URL=redis://localhost:6379/0
CELERY_RESULT_BACKEND=redis://localhost:6379/0
You can still use DJANGO_SETTINGS_MODULE=rota.settings.dev alongside these database settings — the dev settings provide the debug toolbar and development-friendly defaults.
Running Tests¶
Tests use pytest with django-configurations. The development settings module (rota.settings.dev) is used for testing, configured automatically via pyproject.toml.
# Run all tests
uv run pytest
# Run with coverage report (generates htmlcov/)
uv run pytest --cov=. --cov-report=html
# Run tests for a specific app
uv run pytest config/tests/
# Run tests in parallel (uses pytest-xdist)
uv run pytest -n auto
# Run a specific test file
uv run pytest rota_generation/tests/test_algorithm.py
# Verbose output
uv run pytest -v
Code Quality¶
The project uses ruff for linting and formatting, and mypy for type checking.
# Lint (check for errors and style issues)
uv run ruff check .
# Auto-fix lint issues
uv run ruff check --fix .
# Format code
uv run ruff format .
# Check formatting without writing
uv run ruff format --check .
# Type checking
uv run mypy .
Environment Variables¶
All configuration is loaded from a .env file in the project root using python-decouple. Copy .env.example to .env to get started.
Core Settings¶
| Variable | Required | Default | Description |
|---|---|---|---|
SECRET_KEY |
Yes (prod) | Insecure fallback | Django secret key |
DEBUG |
No | False |
Enable Django debug mode |
DEPLOYMENT_ENV |
No | PROD |
Environment banner: DEV, STAGING, or PROD |
ALLOWED_HOSTS |
No | localhost,127.0.0.1 |
Comma-separated allowed hosts |
CSRF_TRUSTED_ORIGINS |
No | http://localhost:8000 |
Comma-separated CSRF trusted origins |
DJANGO_SETTINGS_MODULE |
No | rota.settings.base |
Settings module to load |
Database¶
| Variable | Required | Default | Description |
|---|---|---|---|
DB_ENGINE |
No | django.db.backends.sqlite3 |
Database backend (django.db.backends.postgresql or django.db.backends.sqlite3) |
DB_NAME |
No | rota_db |
Database name (or path for SQLite) |
DB_USER |
No | rota_user |
Database user (PostgreSQL only) |
DB_PASSWORD |
No | rota_password |
Database password (PostgreSQL only) |
DB_HOST |
No | localhost |
Database host (postgres in Docker) |
DB_PORT |
No | 5432 |
Database port |
Redis and Celery¶
| Variable | Required | Default | Description |
|---|---|---|---|
REDIS_HOST |
No | localhost |
Redis host (redis in Docker) |
REDIS_PORT |
No | 6379 |
Redis port |
REDIS_DB |
No | 0 |
Redis database number |
REDIS_USER |
No | (empty) | Redis username (for authenticated providers) |
REDIS_PASS |
No | (empty) | Redis password (for authenticated providers) |
CELERY_BROKER_URL |
No | Built from Redis config | Celery broker URL |
CELERY_RESULT_BACKEND |
No | Same as broker | Celery result backend URL |
Email¶
| Variable | Required | Default | Description |
|---|---|---|---|
EMAIL_PROVIDER |
No | smtp |
Email provider: smtp, mailgun, sendgrid, postmark, resend, or console |
DEFAULT_FROM_EMAIL |
No | noreply@rota.system |
Default sender address |
EMAIL_HOST |
No | localhost |
SMTP server hostname |
EMAIL_PORT |
No | 587 |
SMTP server port |
EMAIL_HOST_USER |
No | (empty) | SMTP username |
EMAIL_HOST_PASSWORD |
No | (empty) | SMTP password |
EMAIL_USE_TLS |
No | False |
Enable TLS for SMTP |
MAILGUN_API_KEY |
No | (empty) | Mailgun API key |
MAILGUN_SENDER_DOMAIN |
No | (empty) | Mailgun sender domain |
SENDGRID_API_KEY |
No | (empty) | SendGrid API key |
POSTMARK_SERVER_TOKEN |
No | (empty) | Postmark server token |
RESEND_API_KEY |
No | (empty) | Resend API key |
SITE_URL |
No | http://localhost:8000 |
Base URL used in email links |
Security (Production)¶
| Variable | Required | Default | Description |
|---|---|---|---|
SECURE_SSL_REDIRECT |
No | True |
Redirect HTTP to HTTPS |
SECURE_HSTS_SECONDS |
No | 31536000 |
HSTS max-age (1 year) |
DJANGO_LOG_LEVEL |
No | INFO |
Logging level: DEBUG, INFO, WARNING, ERROR, CRITICAL |
Application¶
| Variable | Required | Default | Description |
|---|---|---|---|
FIXED_PERIOD_WEEKS |
No | 6 |
Number of weeks in the fixed period |
CURRENT_DATE |
No | Today's date | Override current date (format: YYYY-MM-DD) |
Superuser (Auto-Creation)¶
| Variable | Required | Default | Description |
|---|---|---|---|
DJANGO_SUPERUSER_USERNAME |
No | (empty) | Auto-created superuser username |
DJANGO_SUPERUSER_EMAIL |
No | (empty) | Auto-created superuser email |
DJANGO_SUPERUSER_PASSWORD |
No | (empty) | Auto-created superuser password |
Leave all three empty to skip auto-creation.
Management Commands¶
These are Django management commands you will use during development and operations.
| Command | Description |
|---|---|
uv run python manage.py populate_dev_data |
Load sample data for development (clinicians, shifts, leave) |
uv run python manage.py ensure_superuser |
Create superuser from env vars (idempotent) |
uv run python manage.py create_clinician_user |
Create a clinician user interactively |
uv run python manage.py run_celery |
Start Celery worker (wrapper command) |
uv run python manage.py backup_data |
Export data as JSON backup |
uv run python manage.py restore_data |
Restore from JSON backup |
uv run python manage.py pg_dump_backup |
PostgreSQL-level dump backup |
uv run python manage.py pg_restore_backup |
Restore from PostgreSQL dump |
uv run python manage.py cleanup_old_backups |
Remove backups older than retention period |
uv run python manage.py clear_audit_log |
Clear the audit trail |
Settings Architecture¶
Django settings are split across three modules:
| Module | Purpose |
|---|---|
rota.settings.base |
Shared configuration — database, Celery, email, installed apps, middleware |
rota.settings.dev |
Development overrides — SQLite, LocMem cache, Debug Toolbar, verbose logging |
rota.settings.prod |
Production overrides — PostgreSQL, Redis, Gunicorn, security hardening |
To switch between them, set DJANGO_SETTINGS_MODULE in your .env:
# Development (SQLite, no external services needed)
DJANGO_SETTINGS_MODULE=rota.settings.dev
# Production config (used by Docker Compose)
DJANGO_SETTINGS_MODULE=rota.settings.prod
Next Steps¶
Once you have the application running:
- Architecture — Understand the system design and how the apps fit together
- User Guide — Learn the clinician and admin workflows
- Admin Guide — Admin configuration and rota generation
- Technical Reference — API endpoints, models, and algorithm details
- Operations — Deployment, backup, and monitoring