Skip to content

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

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:

git clone <repository-url>
cd rota-cc
cp .env.example .env

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:

docker compose up --build

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):

docker compose exec web uv run python manage.py populate_dev_data

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:

git clone <repository-url>
cd rota-cc
uv sync

2. Configure environment:

cp .env.example .env

For local development with SQLite (no PostgreSQL needed), keep the defaults in .env and set:

DJANGO_SETTINGS_MODULE=rota.settings.dev

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:

uv run python manage.py migrate
uv run python manage.py createsuperuser

4. Load sample data (optional):

uv run python manage.py populate_dev_data

5. Start the development server:

uv run python manage.py runserver

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:

uv run celery -A rota worker -l info

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: