91 lines
4.8 KiB
Markdown
91 lines
4.8 KiB
Markdown
# 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/`.env` loading, 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/pdf.py`: single-page A4 schedule lists using ReportLab.
|
|
- `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 squashed `0001_initial` revision.
|
|
- `alembic.ini`: migration paths and logging; the database URL comes from settings.
|
|
- `compose.yaml`: example production deployment with persistent SQLite storage.
|
|
- `tests/`: export behavior tests and isolated database/client fixtures.
|
|
|
|
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 in `app/web.py`. Reuse existing helpers.
|
|
- Keep user-facing text in Portuguese and reuse `app/i18n.py` and template filters.
|
|
- Build internal links with `settings.url()` (`app_path` in templates) and use
|
|
`_redirect()` in routes so deployments under `ROOT_PATH` keep 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.py` builds the migration configuration using the root `alembic.ini`
|
|
and 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:
|
|
|
|
```sh
|
|
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.py` when needed. Fixtures must manage
|
|
temporary databases, initialization, dependency overrides, and cleanup so
|
|
`make test` remains 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 `.env` values 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. PDF tests inspect downloaded documents with pypdf.
|
|
|
|
Run `make test` after relevant changes and report its result accurately. An empty
|
|
suite verifies the runner only, not application behavior.
|