4.8 KiB
Repository guide
Project and layout
Contínuos CRR is a server-rendered shift rota application. It uses Python
(the Docker runtime is 3.12), FastAPI, synchronous SQLAlchemy, SQLite, Jinja2,
and Alembic. Dependencies live in requirements.txt; development dependencies
live in requirements-dev.txt.
app/main.py: FastAPI application, lifespan, middleware, templates, static files.app/web.py: routes, session authentication, CSRF, administration, swap workflows.app/models.py: SQLAlchemy schema and relationships.app/database.py: engine, sessions, migrations, SQLite backups.app/config.py: Pydantic settings, environment/.envloading, proxy-path helpers.app/scheduling.py: monthly pattern and rotation generation.app/bootstrap.py: initial administrator and seeded schedules.app/calendar.py: iCalendar feeds;app/i18n.py: Portuguese labels and formatting.app/notifications.py: synchronous SMTP delivery and notification history.app/security.py: password hashing and CSRF token generation.app/cli.py: database initialization/migration, demo seeding, shell, reminders.app/templates/,app/static/: Jinja HTML and CSS/assets; no frontend build step.migrations/: Alembic environment and the squashed0001_initialrevision.alembic.ini: migration paths and logging; the database URL comes from settings.compose.yaml: example production deployment with persistent SQLite storage.tests/: pytest discovery directory; currently empty.
Read docs/DOMAIN.md for business rules and docs/ARCHITECTURE.md for lifecycle
and deployment details. See README.md for the test workflow.
Local development
Run make dev to create/reuse .venv, install development dependencies, create
data/, and start Uvicorn with auto-reload on 127.0.0.1:8000. Use
make dev PORT=8001 to change the port. Application settings come from the
environment and optional .env; database migrations and initial seeding run on
startup. No separate setup command is needed.
Development conventions
- Follow existing typed Python, snake_case names, and SQLAlchemy 2 mapped models. Keep database and request handling synchronous, consistent with the application.
- Keep scheduling calculations in
app/scheduling.py, persistence in models/database, and HTTP orchestration inapp/web.py. Reuse existing helpers. - Keep user-facing text in Portuguese and reuse
app/i18n.pyand template filters. - Build internal links with
settings.url()(app_pathin templates) and use_redirect()in routes so deployments underROOT_PATHkeep working. - Preserve session authorization and CSRF checks when adding form actions.
- Change the model and add an Alembic revision together for schema changes.
app/database.pybuilds the migration configuration using the rootalembic.iniand the database URL from settings.
Domain invariants
- Users are logins; teams own shifts. One user may control several teams.
- Night assignments follow a repeating day-of-month pattern. Saturday and Sunday lunch rotations are independent and continue from the previous actual assignee.
- Ordinary generation fills missing assignments only. Existing assignments change through explicit administration or swap actions; preserve manual/swapped rows when an operation calls for changing only generated rows.
- Swaps exchange two shifts in the same schedule atomically. Check current ownership and cancel conflicting open requests when assignments change.
- Commit scheduling changes before notifications. Email failures must not undo them.
Testing
Run from the repository root:
make test
This creates/reuses .venv, installs development dependencies, and runs pytest.
No activation, application server, Docker service, or separate setup command is
needed. Python 3.12+ with venv/pip and make are prerequisites.
- Use pytest functions and plain assertions in
tests/test_*.py. - Use FastAPI's
TestClient(backed by HTTPX) for HTTP tests. - Add shared fixtures to
tests/conftest.pywhen needed. Fixtures must manage temporary databases, initialization, dependency overrides, and cleanup somake testremains the only command required. - Settings and the database engine are created at import time. Set test environment
values before importing app modules; use temporary SQLite data, disable real SMTP,
and keep tests independent of local
.envvalues and persistent application data. - Prefer behavior and domain invariants over assertions about implementation details.
- An empty suite succeeds through
make test; test failures and pytest errors still fail the command. No tests or application fixtures have been added yet.
Run make test after relevant changes and report its result accurately. An empty
suite verifies the runner only, not application behavior.