feat: add .env.example file with environment variable configurations

This commit is contained in:
Artem Kashaev 2025-12-01 16:09:58 +05:00
parent dcd8bd30f6
commit eecb74c523
2 changed files with 178 additions and 27 deletions

31
.env.example Normal file
View File

@ -0,0 +1,31 @@
# --- Core metadata --------------------------------------------------------
PROJECT_NAME="Test Task CRM"
VERSION="0.1.0"
API_V1_PREFIX="/api/v1"
# --- Database (used when DATABASE_URL не задан) ---------------------------
DB_HOST="localhost"
DB_PORT="5432"
DB_NAME="test_task_crm"
DB_USER="postgres"
DB_PASSWORD="postgres"
# DATABASE_URL="postgresql+asyncpg://postgres:postgres@localhost:5432/test_task_crm"
# --- SQLAlchemy -----------------------------------------------------------
SQLALCHEMY_ECHO="false"
# --- JWT -----------------------------------------------------------------
JWT_SECRET_KEY="change-me"
JWT_ALGORITHM="HS256"
ACCESS_TOKEN_EXPIRE_MINUTES="30"
REFRESH_TOKEN_EXPIRE_DAYS="7"
# --- Redis cache for analytics -------------------------------------------
REDIS_ENABLED="false"
REDIS_URL="redis://localhost:6379/0"
ANALYTICS_CACHE_TTL_SECONDS="120"
ANALYTICS_CACHE_BACKOFF_MS="200"
# --- Frontend (Vite exposes только VITE_*) --------------------------------
VITE_API_URL="http://localhost:8000"
VITE_APP_URL="http://localhost:5173"

174
README.md
View File

@ -1,40 +1,160 @@
# Test Task CRM # Test Task CRM
FastAPI backend template that follows the architecture described in the system prompt: async SQLAlchemy ORM, Alembic-ready models, service/repository layers, JWT auth helpers, and Pydantic v2 schemas. Многопользовательская mini-CRM на FastAPI + PostgreSQL c сервисно-репозиторной архитектурой, JWT-аутентификацией, Alembic-миграциями и готовым React/Vite фронтендом.
## Quick start ## Стек и особенности
1. Create a `.env` file based on variables in `app/core/config.py`. - Python 3.10+, FastAPI, SQLAlchemy Async ORM, Alembic.
2. Install dependencies: - Pydantic Settings для конфигурации, JWT access/refresh токены, кеш аналитики в Redis.
```bash - Frontend: Vite + React + TypeScript (см. `frontend/`).
uv sync - Докер-окружение для разработки (`docker-compose-dev.yml`) и деплоя (`docker-compose-ci.yml`).
```
3. Run the development server:
```bash
uv run python main.py
```
## Project layout ## Структура проекта
``` ```text
app/ app/
api/ # FastAPI routers and dependencies api/ # FastAPI-роуты и зависимости
core/ # Settings, database, security helpers core/ # Настройки, база, безопасность
models/ # SQLAlchemy models and Pydantic schemas models/ # SQLAlchemy-модели
repositories/ # Data access layer (SQLAlchemy ORM usage) repositories/ # Работа с БД
services/ # Business logic (auth, users, etc.) services/ # Бизнес-правила и сценарии
frontend/ # Vite + React SPA
migrations/ # Alembic-миграции
tests/ # Pytest (unit + интеграции)
``` ```
Add new routers under `app/api/v1`, repositories under `app/repositories`, and keep business rules inside `app/services`. ## Переменные окружения
## Redis analytics cache 1. Скопируйте шаблон: `cp .env.example .env`.
2. Обновите секреты (`DB_PASSWORD`, `JWT_SECRET_KEY`, и т.д.) перед запуском.
3. Все переменные описаны в `app/core/config.py`; Vite читает только ключи с префиксом `VITE_`.
Analytics endpoints can use a Redis cache (TTL 120 seconds). The cache is disabled by default, so the service falls back to the database. ### Backend
| Переменная | Значение по умолчанию | Назначение |
| --- | --- | --- |
| `PROJECT_NAME` | `"Test Task CRM"` | Заголовки/метаданные API |
| `VERSION` | `"0.1.0"` | Версия приложения |
| `API_V1_PREFIX` | `/api/v1` | Базовый префикс REST |
| `DB_HOST` | `localhost` | Хост PostgreSQL |
| `DB_PORT` | `5432` | Порт PostgreSQL |
| `DB_NAME` | `test_task_crm` | Имя БД |
| `DB_USER` | `postgres` | Пользователь БД |
| `DB_PASSWORD` | `postgres` | Пароль пользователя |
| `DATABASE_URL` | — | Полный DSN (перекрывает `DB_*`), формат `postgresql+asyncpg://user:pass@host:port/db` |
| `SQLALCHEMY_ECHO` | `false` | Логирование SQL |
| `JWT_SECRET_KEY` | `change-me` | Секрет для подписи JWT |
| `JWT_ALGORITHM` | `HS256` | Алгоритм JWT |
| `ACCESS_TOKEN_EXPIRE_MINUTES` | `30` | TTL access-токена |
| `REFRESH_TOKEN_EXPIRE_DAYS` | `7` | TTL refresh-токена |
| `REDIS_ENABLED` | `false` | Включить кеш аналитики |
| `REDIS_URL` | `redis://localhost:6379/0` | Строка подключения к Redis |
| `ANALYTICS_CACHE_TTL_SECONDS` | `120` | TTL кэша аналитики |
| `ANALYTICS_CACHE_BACKOFF_MS` | `200` | max задержка при ретраях записи в кеш |
### Frontend (Vite)
| Переменная | Значение по умолчанию | Назначение |
| --- | --- | --- |
| `VITE_API_URL` | `http://localhost:8000``.env.example`), в `src/config/env.ts` дефолт `https://kitchen-crm.k1nq.tech` | Базовый URL бекенда (без завершающего `/`) |
| `VITE_APP_URL` | `http://localhost:5173` | URL SPA, используется для deeplink'ов и редиректов |
⚠️ В `frontend/src/config/env.ts` зашит production URL (`https://kitchen-crm.k1nq.tech`). При деплое в другое место обязательно обновите `VITE_API_URL`/`VITE_APP_URL` в `.env` или настройте переменные окружения на уровне хостинга.
## Локальный запуск без Docker
### Предварительные требования
- Python 3.10+ и [uv](https://github.com/astral-sh/uv).
- PostgreSQL 16+ (локально или через Docker).
- (Опционально) Redis 7+ для кеша аналитики.
### Backend (API)
```bash
# 1. Готовим окружение
cp .env.example .env
# отредактируйте .env: базы, секреты, VITE_* (если нужен фронтенд)
# 2. Устанавливаем зависимости
uv sync
# 3. Применяем миграции
uv run alembic upgrade head
# 4. Запускаем API
uv run uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
```
PostgreSQL/Redis можно поднять вручную или командой `docker compose -f docker-compose-dev.yml up postgres redis -d`.
### Frontend
```bash
cd frontend
npm install
npm run dev -- --host
```
Фронтенд ожидает, что `VITE_API_URL` указывает на работающий бекенд (например, `http://localhost:8000`).
## Запуск через Docker Compose
### Локальная разработка (`docker-compose-dev.yml`)
- Собирает бекенд из `app/Dockerfile`, поднимает `postgres:16-alpine` и `redis:7-alpine`.
- Порты по умолчанию: API `8000`, Postgres `5432`, Redis `6379`.
- Все переменные берутся из `.env`.
```bash
docker compose -f docker-compose-dev.yml up --build
# или в фоне
docker compose -f docker-compose-dev.yml up --build -d
```
### Прод/CI стек (`docker-compose-ci.yml`)
1. Соберите образы и статику:
```bash
docker build -f app/Dockerfile -t <registry>/test-task-crm:app .
docker build -f migrations/Dockerfile -t <registry>/test-task-crm:migrations .
cd frontend && npm install && npm run build && cd ..
```
2. Залейте `frontend/dist` (используется как read-only volume) и задайте `GIT_HOST`, `GIT_USER`, `GIT_REPO` в `.env`.
3. Запустите стек:
```bash
docker compose -f docker-compose-ci.yml up -d
```
В этом режиме `migrations` прогоняется один раз, `app` слушает порт `80`, Postgres хранит данные на `/mnt/data/postgres` (смонтируйте хостовую директорию заранее).
## Redis для аналитики
Кеш аналитики выключен по умолчанию. Чтобы включить:
1. Поднимите Redis (`docker compose ... redis` или любым другим способом).
2. В `.env` выставьте:
- `REDIS_ENABLED=true`
- `REDIS_URL=redis://<host>:6379/0`
- (опционально) `ANALYTICS_CACHE_TTL_SECONDS` и `ANALYTICS_CACHE_BACKOFF_MS`.
3. При недоступности Redis сервис автоматически возвращается к прямым запросам в PostgreSQL и пишет предупреждения в лог.
## Тестирование
Все тесты находятся в каталоге `tests/` (unit на бизнес-правила и интеграционные сценарии API). Запуск:
```bash
uv run pytest
```
Полезные варианты:
- Запустить только юнит-тесты сервисов: `uv run pytest tests/services -k service`.
- Запустить конкретный сценарий API: `uv run pytest tests/api/v1/test_deals.py -k won`.
Перед деплоем рекомендуется прогонять миграции на чистой БД и выполнять `uv run pytest` для проверки правил ролей/стадий.
1. Start Redis and set the following variables:
- `REDIS_ENABLED=true`
- `REDIS_URL=redis://localhost:6379/0`
- `ANALYTICS_CACHE_TTL_SECONDS` (optional, defaults to 120)
- `ANALYTICS_CACHE_BACKOFF_MS` (max delay for write/delete retries, defaults to 200)
2. When Redis becomes unavailable, middleware logs the degradation and responses transparently fall back to database queries until connectivity is restored.