--- paths: - "cofee_backend/cpv3/**/*.py" --- # Backend Module Rules ## Module Structure (strict — do not deviate) Every module contains exactly these files — no more, no subdirectories: ``` modules// ├── __init__.py ├── models.py # SQLAlchemy models ├── schemas.py # Pydantic DTOs (*Create, *Update, *Read) ├── repository.py # Database CRUD ├── service.py # Business logic + Dramatiq actors └── router.py # FastAPI endpoints ``` When in doubt, put logic in `service.py`. Cross-cutting concerns go in `infrastructure/`, not in module subdirectories. ## Repository Pattern - One repository per model, accepts `AsyncSession` in constructor. - Filter soft-deleted records (`is_deleted`) by default. - Methods should be atomic and focused. ## Schemas - Inherit from `cpv3.common.schemas.Schema` (Pydantic with `from_attributes=True`). - Suffix names: `*Create`, `*Update`, `*Read`. - Use `Literal` types for enums with string values. ## Models - Inherit from `Base` + `BaseModelMixin` (`cpv3.db.base`). - Use explicit column types, add indexes for frequently queried fields. - Soft deletes via `is_deleted` flag. ## Endpoints - Use dependency injection for DB session (`get_db`), auth (`get_current_user`), and services. - Return typed response models. Use appropriate HTTP status codes. ## Settings - All config via `get_settings()` from `cpv3.infrastructure.settings.py` (cached with `@lru_cache`). - Never hardcode configuration values. ## Style - Python 3.11+, `from __future__ import annotations` for forward references. - Line length: 100 characters (Ruff). Type hints on all function signatures. - Async-first for I/O. Use `anyio.to_thread.run_sync` for CPU-bound work in async context. - Store error messages as module-level constants with `ERROR_` prefix.