# План спринтов **Дата:** 2026-03-21 **Статус:** Согласовано --- ## Принцип Каждый спринт — это готовое работающее приложение (frontend + backend), которое можно запустить локально командой `docker compose up` и протестировать вручную в браузере. --- ## Спринт 1 — Инфраструктура + Создание тестов ✅ **Результат:** Поднят весь стек, можно зайти на страницу и создать тест. **Статус:** Завершён и протестирован вручную в браузере. ### Инфраструктура - [x] Структура репозитория: `backend/`, `frontend/`, `nginx/`, `docker-compose.yml` - [x] `docker-compose.yml`: сервисы `db`, `backend`, `frontend`, `nginx` - [x] PostgreSQL: контейнер, volume для данных - [x] FastAPI: контейнер, `GET /api/health` → `{"status": "ok"}` - [x] Alembic: инициализирован, первая миграция (`001_init`) - [x] React + Vite: контейнер, базовая страница открывается в браузере - [x] Nginx: `/` → React SPA, `/api/` → FastAPI ### Создание тестов (без авторизации) - [x] Модели БД: `Test`, `Question`, `Answer` - [x] API: `POST /api/tests` — создать тест с вопросами и ответами - [x] API: `GET /api/tests` — список тестов - [x] API: `GET /api/tests/{id}` — детали теста - [x] Фронт: страница создания теста (название, вопросы, варианты, настройки) - [x] Фронт: список тестов - [x] Фронт: страница просмотра теста **Настройки теста:** порог зачёта (%), таймер (опционально), разрешить возврат к предыдущему вопросу ### Баги, найденные и исправленные при тестировании - [x] `permission denied` на `entrypoint.sh` — volume mount перекрывал `chmod +x` из Dockerfile → исправлено: `CMD ["bash", "entrypoint.sh"]` - [x] `No module named 'app'` в Alembic — Python не видел `/app` → исправлено: `ENV PYTHONPATH=/app` в Dockerfile - [x] `host not found in upstream "backend"` в nginx — nginx резолвил хост при старте, до поднятия backend → исправлено: Docker DNS resolver + `set $backend` - [x] `http://localhost/api/docs` → 404 — FastAPI отдавал docs по `/docs`, а не `/api/docs` → исправлено: явные `docs_url`, `redoc_url`, `openapi_url` в FastAPI --- ## Спринт 2 — Прохождение теста ✅ **Результат:** Можно выбрать тест из списка и пройти его, увидеть результат и разбор ошибок. **Статус:** Завершён и протестирован вручную в браузере. - [x] Модели БД: `TestAttempt`, `AttemptAnswer` - [x] API: `POST /api/attempts` — начать попытку (фиксируем время начала) - [x] API: `POST /api/attempts/{id}/submit` — завершить попытку, подсчитать результат - [x] API: `GET /api/attempts/{id}/result` — результат с разбором ошибок - [x] Фронт: страница прохождения теста - Случайный порядок вопросов - Таймер с обратным отсчётом (если задан) — автосабмит по истечении - Навигация назад (если разрешена настройкой теста) - [x] Фронт: страница результата - Балл и процент - Сдал / Не сдал (относительно порога) - Разбор ошибок: вопрос, ответ сотрудника, правильный ответ - [x] Фронт: кнопка «Пройти тест» прямо в строке таблицы списка тестов ### Баги, найденные и исправленные при тестировании - [x] «Не удалось загрузить тест» × 2 при нажатии «Пройти тест» — миграция `002_attempts` не применилась, т.к. `--reload` перезапускает только код приложения, но не `entrypoint.sh` → исправлено: `docker compose restart backend` --- ## Спринт 3 — Трекер результатов **Результат:** Таблица всех попыток прохождения тестов. - [ ] API: `GET /api/attempts` — все попытки (с фильтрами по тесту, дате) - [ ] Фронт: страница трекера - Таблица: сотрудник, тест, № попытки, начало, завершение, результат, зачёт - Фильтрация по тесту и дате - Пагинация --- ## Спринт 4 — Авторизация и управление пользователями **Результат:** Вход по логину/паролю, роли ограничивают доступ. Можно создавать сотрудников и подразделения. ### Авторизация - [ ] Модели БД: `User`, `Department` - [ ] API: `POST /api/auth/login` → JWT access token - [ ] API: `POST /api/auth/logout` - [ ] API: `GET /api/auth/me` - [ ] Middleware: проверка JWT на защищённых эндпоинтах - [ ] Фронт: страница входа - [ ] Фронт: защищённые роуты (редирект на логин если нет токена) ### Роли и права | Роль | Тесты | Назначение | Трекер | |------|-------|-----------|--------| | HR-менеджер / Директор | Создаёт, все тесты | Всем сотрудникам | Вся клиника | | Руководитель подразделения | Создаёт, свои тесты | Только своему отделу | Только свой отдел | | Сотрудник | Только назначенные | — | Только свои | ### Управление пользователями - [ ] API: CRUD подразделений - [ ] API: CRUD пользователей (создание, редактирование, деактивация) - [ ] Фронт: страница управления подразделениями (HR) - [ ] Фронт: страница управления сотрудниками (HR / руководитель) ### Назначение тестов - [ ] Модели БД: `TestAssignment` - [ ] API: `POST /api/assignments` — назначить тест (получатели, дедлайн, кол-во попыток) - [ ] Фронт: форма назначения теста - [ ] Фронт: дашборд сотрудника — список назначенных тестов со статусами (`Не начат`, `В процессе`, `Завершён`, `Просрочен`) ### Версионирование тестов - [ ] При попытке редактировать назначенный тест — создаётся новая версия - [ ] Результаты привязаны к конкретной версии теста --- ## Спринт 5 — Уведомления в MAX **Результат:** Сотрудники получают уведомления в мессенджер MAX. - [ ] Изучить документацию MAX API - [ ] Реализовать сервис уведомлений в backend - [ ] Уведомление при назначении теста сотруднику - [ ] Уведомление за N дней до дедлайна (настраивается) - [ ] Поле `max_user_id` в профиле пользователя - [ ] Фронт: в профиле пользователя — поле для MAX ID --- ## Структура репозитория (целевая после Спринта 1) ``` qa_test_app/ ├── backend/ │ ├── app/ │ │ ├── api/ ← роутеры FastAPI │ │ ├── models/ ← SQLAlchemy модели │ │ ├── schemas/ ← Pydantic схемы │ │ ├── services/ ← бизнес-логика │ │ └── main.py │ ├── alembic/ │ ├── Dockerfile │ └── requirements.txt ├── frontend/ │ ├── src/ │ │ ├── api/ ← Axios + TanStack Query │ │ ├── components/ ← переиспользуемые компоненты │ │ ├── pages/ ← страницы │ │ └── main.tsx │ ├── Dockerfile │ └── package.json ├── nginx/ │ └── nginx.conf ├── docker-compose.yml └── DOC/ ```