# Система тестирования сотрудников клиники Веб-приложение для проведения внутреннего тестирования сотрудников клиники. Руководители подразделений и HR-менеджеры создают тесты и назначают их сотрудникам. Все попытки и результаты сохраняются. - **Прод:** **[https://edullm.pirogov.ai/](https://edullm.pirogov.ai/)** - **Ветка разработки:** `dev` - **ТЗ:** v1.2 от 2026-03-21 (статус — согласовано) --- ## Стек и состояние **Целевой и единственный рабочий стек** — Python 3.11 + Flask 3 + Jinja2 + Tailwind CDN + SQLAlchemy / psycopg2, код в [`flask_app/`](flask_app/). На нём работает и прод, и dev (`:3108`). Старые каталоги `backend/` (Node.js / Express) и `frontend/` (React + Vite) — **архив**: не разворачиваются, в `docker-compose.dev.yml` поднимается только сервис `testing-flask`, удаление папок запланировано в спринте **E1.6**. Использовать их не надо, миграции и SQL-схема сохранены в `backend/src/db/migrations/` исключительно как источник структуры БД. БД — **`clinic_tests`** (PostgreSQL, UUID-ключи). В Этапе 1 схема не меняется. **Этап 2** — слияние с общим HR-кабинетом `HR_TG_Bot/tgFlaskForm` — запланирован на будущее, сейчас не делается. План: [`docs/migration-to-tgflaskform.md`](docs/migration-to-tgflaskform.md) ([простыми словами](docs/migration-to-tgflaskform-plain.md)). --- ## Что уже работает на новом (Flask) контуре E1.0–E1.3 и E1.8 закрыты. Чек-лист и журнал — [`docs/migration-final.md`](docs/migration-final.md). - **Авторизация** через куки-сессию Flask: bcrypt (локальные пользователи `clinic_tests.users`) или Werkzeug-хеши при включённом `HR_AUTH=1` (UPSERT в `clinic_tests.users` по `staff_id` из `hr_bot_test`). UI: `/login`, JSON: `/api/auth/{login,logout,me}`. - **Каталог тестов** `/tests` (видны активные + блок «Скрытые вами»), создание теста через модалку. - **Редактор** `/tests//edit`: правка названия/описания/проходного балла, добавление/удаление/перемещение вопросов и вариантов, переключатель «Цепочка активна», авто-форк новой версии при правке после первой попытки. - **AI-помощник** в редакторе: - «По названию» — генерация всего теста по теме (количество вопросов и вариантов задаёт автор); - «По текущей сетке» — генерация по уже расставленным карточкам; - «Проверить» — рецензия теста с вердиктом и разделами рекомендаций; - «Улучшить» — массовое «было → стало» с чекбоксами; - «AI: вопрос/переформулировать» — на отдельной карточке вопроса. - **Импорт документа** в редакторе: PDF / DOCX / TXT / MD до 16 МБ, через `pypdf` и `python-docx` → AI-черновик. - **Настройки** `/settings` — статус общего LLM-ключа из ENV (DeepSeek или OpenAI-совместимый), кнопка «Проверить подключение». Подробная инструкция для тестировщика (только UI, без консоли) — [`docs/QA-versioning-and-ai.md`](docs/QA-versioning-and-ai.md). ## Что ещё не реализовано | Спринт | Что включает | |---|---| | **E1.4** — Назначение и прохождение | Назначить тест сотруднику, экран прохождения, экран результата с разбором ошибок. | | **E1.5** — Трекер и настройки модуля | Единый список попыток с фильтрами, страница настроек цепочки. | | **E1.6** — Cutover внутри репозитория | Удаление `backend/` и `frontend/`, чистка `docker-compose.dev.yml` от legacy-сервисов. | | **E1.7** — UX-полировка редактора | 4 аккордеона (Шапка / AI / Вопросы / Действия) и drag-n-drop из [Спринта 3](docs/СПРИНТЫ_МОБИЛЬНЫЙ_ДИЗАЙН.md). | --- ## Установка и запуск ### Предпосылка: общий Postgres Используется **тот же** PostgreSQL, что и в [Postgres_TG_Bots](../Postgres_TG_Bots) (контейнер `hr_postgres_dev`, сеть `hr_postgres_dev_net`, учётка `hr_bot_user`). ```bash # (один раз) создать базу psql "postgresql://hr_bot_user:hrbot123@localhost:5432/postgres" \ -c "CREATE DATABASE clinic_tests;" # (один раз) внешняя сеть, если ещё не создана соседом docker network create hr_postgres_dev_net || true ``` ### Dev-стенд Выбор интерфейса задаётся через env-переменную `COMPOSE_PROFILES`: - `modern` — основной интерфейс на Flask/Jinja; - `legacy` — legacy-раскладка интерфейса на том же Flask-стеке. ```bash # Новый стек (рекомендуется) COMPOSE_PROFILES=modern docker compose -f docker-compose.dev.yml up -d --build # Legacy-раскладка (тот же Flask) COMPOSE_PROFILES=legacy docker compose -f docker-compose.dev.yml up -d --build ``` | Что | URL | |---|---| | Приложение (Flask modern) | | | Health-check | | | Приложение (Flask legacy) | | `docker-compose.dev.yml` пробрасывает в `testing-flask`: - `DATABASE_URL` (по умолчанию на контейнерный Postgres `clinic_tests`); - `HR_AUTH=1` / `HR_DATABASE_URL` по умолчанию — вход через HR-кабинет; - `DEEPSEEK_API_KEY` / `OPENAI_API_KEY` / `LLM_BASE_URL` / `LLM_MODEL` — для AI-функций. Достаточно положить ключ в корневой `.env` репозитория. ### Локально без Docker См. [`flask_app/README.md`](flask_app/README.md) — `venv` + `pip install -r requirements.txt` + `python run.py`. --- ## Данные и интеграция с HR - **Две роли кластера Postgres.** В **`clinic_tests`** — только сущности модуля тестирования (тесты, версии, назначения, попытки, локальные технические учётки). В **`hr_bot_test`** (Postgres_TG_Bots / hr_web_viewer) — штат, справочники, RBAC и веб-логины. Схемы не смешиваем, второй кадровый учёт в `clinic_tests` не ведём. - **Сотрудник** во всех бизнес-процессах — по **`staff_members.id`** из `hr_bot_test`. В `clinic_tests` храним тот же идентификатор; ФИО / отдел / роли подтягиваем из HR при отображении. - **`telegram_id` сотрудника** в бизнес-логике модуля **не участвует** (ни вход, ни проверка прав, ни выбор сотрудника, ни фильтрация). - **Целевой RBAC** — единая система разрешений HR (`staff_role_assignments`, `permissions`). Модуль тестирования не дублирует матрицу; пока единый API не готов — в `clinic_tests` допустимы временные флаги, явно помеченные как MVP. - **`HR_AUTH=1`**: в Flask-контуре включает вход через `hr_bot_test.users` (Werkzeug-хеши) с UPSERT в `clinic_tests.users`. См. [`flask_app/.env.example`](flask_app/.env.example). --- ## Роли и права (по ТЗ) | Роль | Кто | Создаёт тесты | Назначает | Видит результаты | |---|---|:---:|:---:|:---:| | **HR-менеджер** | Руководитель HR, директор | ✅ | Всем | Всех | | **Руководитель подразделения** | Главврач, рук. отделения | ✅ | Только своему подразделению | Только своего подразделения | | **Сотрудник** | Все остальные | ❌ | ❌ | Только свои | > На текущем Flask-контуре (E1.0–E1.3, E1.8) проверяется только > `@login_required`; разделение по ролям задействуется на E1.4–E1.5. --- ## Нефункциональные требования | Параметр | Значение | |---|---| | Количество пользователей | 50–200 человек | | Платформа | Веб, браузер; mobile-friendly | | Доступность | Внутренняя сеть клиники | | Язык интерфейса | Русский | | Время отклика | < 2 секунды | ## Вне scope (в текущей версии не делаем) - Интеграция с AD / LDAP. - Нативное мобильное приложение. - Вопросы с вложениями (картинки, видео). - Экспорт отчётов в Excel / PDF. - Уведомления в MAX (отдельный спринт). --- ## Документация | Файл | О чём | |---|---| | [`docs/PROJECT_STATUS.md`](docs/PROJECT_STATUS.md) | Что работает «прямо сейчас», что в работе, что в бэклоге. | | [`docs/migration-final.md`](docs/migration-final.md) | Главный трекер миграции: спринты Этапа 1, журнал, критерии готовности. | | [`docs/migration-final-inventory.md`](docs/migration-final-inventory.md) | Карта 22 эндпоинтов Express + gap-analysis с `tgFlaskForm`. | | [`docs/migration-to-tgflaskform.md`](docs/migration-to-tgflaskform.md) | План Этапа 2 (слияние с HR-кабинетом). | | [`docs/QA-versioning-and-ai.md`](docs/QA-versioning-and-ai.md) | Инструкция для тестировщика — только через сайт. | | [`docs/СПРИНТЫ_МОБИЛЬНЫЙ_ДИЗАЙН.md`](docs/СПРИНТЫ_МОБИЛЬНЫЙ_ДИЗАЙН.md) | Целевой мобильный UX редактора (база для E1.7). | | [`docs/РУКОВОДСТВО_КАБИНЕТ_ТЕСТОВ.md`](docs/РУКОВОДСТВО_КАБИНЕТ_ТЕСТОВ.md) | Кратко для врачей-кураторов. | | [`flask_app/README.md`](flask_app/README.md) | Конкретные команды для нового контура. | | [`docs/ТЗ.md`](docs/ТЗ.md) | Исходное ТЗ заказчика. |