Константин Лебединский f1f5223076 feat(test detail): regroup sections, copy, and editor affordances
- AccSection: optional subtitle; disclosure body top padding
- Renames: О тесте, Вопросы, История (Версии + Прохождения), Показ в каталоге
- Move import into Вопросы as «Документ в вопросы»; remove duplicate import section
- Merge publication + assignment with subheads Видимость / Кому выдать; non-full-width actions
- Assign: «Выбрать всех (N)»; search row height tweaks
- Editor: крестик удаления варианта; единый футер + вариант/удалить вопрос; + вопрос в отдельной полосе
- AI block: test-detail-ai-panel (lighter, aligned with rest)
- History: empty state for runs; attempts error only in section (remove hero duplicate)

Made-with: Cursor
2026-04-27 20:36:09 +05:00
2026-03-21 16:06:24 +05:00

Система тестирования сотрудников клиники

Веб-приложение для проведения внутреннего тестирования сотрудников клиники. Руководители подразделений и HR-менеджеры создают тесты и назначают их сотрудникам. Система фиксирует все попытки и результаты.

Версия ТЗ: 1.2
Дата: 2026-03-21
Статус: Согласовано

Актуальное состояние кода (не ТЗ, а «что уже есть»): docs/PROJECT_STATUS.md · инструкция для проверяющих на dev.
Перенос на стек кабинета / мини-приложения: docs/migration-to-tgflaskform.md · простым языком. Отдельный Flask-контур: flask_app/README.md.


Стек технологий

Этот репозиторий (TestingWebApp)

Слой Технологии
Backend Node.js (ESM), Express 4, pg, миграции SQL; аутентификация — cookie + JWT (jsonwebtoken), пароли bcryptjs; опционально вход через HR (HR_AUTH, отдельное подключение к БД HR).
Frontend React 18, React Router 6, сборка Vite 5; статика в проде через Nginx (см. docker-compose.dev.yml).
Данные PostgreSQL, отдельная БД clinic_tests: UUID-ключи, таблицы tests, test_versions, questions, answer_options, назначения, попытки (см. backend/src/db/migrations/).
Прочее Извлечение текста из PDF/DOCX (pdf-parse, mammoth), опционально LLM для черновиков тестов; dotenv, cors, multer.

Целевой стек (Flask, как в кабинете / мини-приложении)

Тот же класс технологий, что в HR_TG_Bot/tgFlaskForm: Python, Flask, шаблоны, Postgres. Сейчас допускается отдельный деплой нового контура из каталога flask_app/; позже — слияние с полным кабинетом при необходимости.

Эталон реализации модуля в монорепозитории HR — общий веб-кабинет HR_TG_Bot/tgFlaskForm:

Слой Технологии
Приложение Python 3, Flask 3, шаблоны Jinja2 + PyPug, blueprint /cabinet/testing; прод-сервер типично waitress.
Данные SQLAlchemy 2, psycopg2, БД hr_bot_test: таблицы testing_*, связи с staff_members.
Клиент HTML-шаблоны кабинета, JS в webApp/templates/static/js/cabinet/ (без отдельного SPA в этом репозитории).
Инфра Тот же кластер Postgres, что и у Postgres_TG_Bots / HR (см. раздел установки ниже).

Подробности переноса и миграции данных: docs/migration-to-tgflaskform.md.
Скрипт ETL в монорепозитории HR: ../HR_TG_Bot/tgFlaskForm/tools/migrate_clinic_tests_to_hr.py (--dry-run / --apply, переменные CLINIC_TESTS_URL и HR_BOT_URL).


Содержание


Состояние реализации (сводка)

Коротко и по-человечески: docs/PROJECT_STATUS.md (черновики и версии, разбор попыток, список тестов, dev-стенд).
Как пользоваться локальным dev без чтения кода: docs/DEV_CONTOUR_USER_GUIDE.md.


Функциональные возможности

Управление пользователями и подразделениями

  • Создание/редактирование/деактивация учётных записей сотрудников
  • Каждый сотрудник принадлежит одному подразделению
  • Создание/редактирование справочника подразделений
  • Назначение роли сотруднику: HR-менеджер / Руководитель подразделения / Сотрудник

Создание и редактирование тестов

Тест содержит:

  • Название теста
  • Описание (опционально)
  • Список вопросов (минимум 7)
  • Порог зачёта — минимальный % правильных ответов
  • Таймер прохождения — лимит в минутах (опционально)

Вопрос содержит:

  • Текст вопроса
  • Минимум 3 варианта ответа
  • Один или несколько правильных ответов

Настройки теста:

  • Разрешить возврат к предыдущему вопросу: да / нет

Версионирование:

  • Автор может редактировать тест пока никто его не проходил
  • Если тест уже проходили — создаётся новая версия (version + 1), старая сохраняется
  • Все версии теста хранятся; результаты привязаны к конкретной версии
  • Активная версия — та, которую видят сотрудники; автор может вручную переключить активную версию
  • Тест можно деактивировать (скрыть из списка, не удалять)

Назначение теста

  • Список получателей (отдел или конкретные сотрудники)
  • Срок сдачи — дата дедлайна
  • Допустимое количество попыток (1 или более)

Прохождение теста

  • На главной странице сотрудник видит список назначенных тестов со статусами:
    • Не начат — ещё не открывал
    • В процессе — начал, не завершил
    • Завершён — сдал/не сдал
    • Просрочен — дедлайн прошёл, не сдан
  • Если задан таймер — отображается обратный отсчёт, по истечении тест завершается автоматически
  • Порядок вопросов случайный при каждом прохождении
  • Возможность вернуться к предыдущему вопросу — определяется настройкой теста

Результаты после завершения теста

  • Итоговый балл и процент правильных ответов
  • Факт зачёта: сдал / не сдал
  • Разбор ошибок: по каждому вопросу — его ответ и правильный ответ

Трекер попыток

Единый интерфейс просмотра всех попыток прохождения тестов:

  • Фильтрация по подразделению, сотруднику, тесту, статусу, результату
  • Пагинация и сортировка

AI-помощник

Интеграция с LLM для помощи при создании тестов:

Функция Описание
Генерация теста AI генерирует готовый набор вопросов с вариантами ответов по теме
Улучшение формулировки AI переформулирует выбранный вопрос более чётко
Добавление дистракторов AI генерирует правдоподобные неправильные варианты ответов
Проверка качества AI анализирует весь тест и выдаёт рекомендации

Роли и права доступа

Роль Кто Создаёт тесты Назначает тесты Видит результаты
HR-менеджер Руководитель службы HR, Директор клиники ✅ Всем сотрудникам клиники Всех сотрудников
Руководитель подразделения Главный врач, рук. службы администраторов ✅ Только своему подразделению Только своего подразделения
Сотрудник Все остальные работники ❌ ❌ Только свои

Установка и запуск

База данных (как в HR_TG_Bot / Postgres_TG_Bots)

Используется тот же экземпляр PostgreSQL, что и в Postgres_TG_Bots (docker-compose.dev.yml, контейнер hr_postgres_dev, учётка hr_bot_user / сеть hr_postgres_dev_net — см. HR_TG_Bot docker-compose).

Схема приложения (таблицы users, tests, departments, …) не совмещается с БД hr_bot_test — для TestingWebApp заведена отдельная база clinic_tests.

  1. Поднять Postgres из Postgres_TG_Bots (и при необходимости внешнюю сеть: docker network create hr_postgres_dev_net — как в compose этих репозиториев).
  2. Один раз создать базу:
    psql "postgresql://hr_bot_user:hrbot123@localhost:5432/postgres" -c "CREATE DATABASE clinic_tests;"
  3. Скопировать backend/.env.example в backend/.env, при необходимости поправить DATABASE_URL (внутри Docker кластера — хост hr_postgres_dev, порт 5432).
  4. Миграции: из каталога backend/: npm run migrate, затем npm start (и фронт из frontend/ — npm run dev).

Docker (UI + API + общий Postgres): поднять Postgres_TG_Bots (сеть hr_postgres_dev_net), создать БД clinic_tests, затем из корня TestingWebApp:
docker compose -f docker-compose.dev.yml up --build — интерфейс http://localhost:3107 (Nginx проксирует /api в backend), API с хоста http://localhost:3001 (см. docker-compose.dev.yml, миграции в entrypoint). Новый Flask-контур (тот же стек, что кабинет HR): http://localhost:3108 — сервис testing-flask, см. flask_app/README.md. Локальный npm run dev фронта (Vite) — тоже :3107, прокси /api на :3001. В БД clinic_tests для локального логина нужен активный users с bcrypt-паролем, либо включите HR_AUTH=1 + HR_DATABASE_URL в compose/.env (см. backend/.env.example). В backend/.env задайте PORT=3001, если поднимаете API отдельно от compose.

docker compose -f docker-compose.dev.yml down — остановка.

Без общего кластера (только отладка): docker compose --profile standalone up -d в TestingWebApp — Postgres на 5433, тогда в .env укажите DATABASE_URL=...localhost:5433/clinic_tests или DB_PORT=5433 с DB_NAME/DB_USER из compose.

Если npm run migrate пишет ECONNREFUSED ...:5433: в backend/.env нет (или кривой) DATABASE_URL на 5432, и сработал старый DB_PORT=5433. Задайте DATABASE_URL как в backend/.env.example для общего Postgres.

Данные, сотрудники, интеграция с HR

  • Две роли кластера Postgres: в clinic_tests — только сущности модуля тестирования (тесты, версии, назначения, попытки, локальные технические учётки при необходимости). В hr_bot_test (Postgres_TG_Bots / hr_web_viewer) — штат, справочники, существующий RBAC и веб-логины. Так мы не смешиваем схемы и не дублируем «источник правды» по людям.
  • Сотрудник в процессах (назначения, дашборды, доступ к результатам) — везде по staff_members.id. Ссылки в clinic_tests храним как тот же идентификатор (логическая связь с staff_members в hr_bot_test); ФИО, отдел, роли подтягиваем из HR при отображении или кэшируем по согласованной политике, а не ведём второй кадровый учёт.
  • telegram_id в данных сотрудника не участвует в бизнес-логике модуля: ни вход, ни проверка прав, ни выбор сотрудника в сценариях, ни фильтрация — только справочная информация при необходимости (отображение, история).
  • RBAC в перспективе: единая система разрешений — та, что уже в HR (роли, staff_role_assignments, permissions). Модуль тестирования не развивает отдельную полную копию матрицы; проверка действий в целевом виде — через HR (внутренний API / токен / согласованные запросы к БД). Пока договор и API не готовы — допустимы временные флаги в clinic_tests, явно помечаемые как MVP.

Детализация задач и варианты A.x: docs/revision_task/card1.md.


Нефункциональные требования

Параметр Значение
Количество пользователей 50–200 человек
Платформа Веб-приложение, браузер (desktop-first)
Доступность Внутренняя сеть клиники
Язык интерфейса Русский
Время отклика < 2 секунды

Вне scope (не реализуется в данной версии)

  • Интеграция с AD/LDAP
  • Мобильное приложение
  • Вопросы с вложениями (изображения, видео)
  • Экспорт отчётов в Excel / PDF
  • Уведомления в MAX (отдельный спринт)
S
Description
No description provided
Readme 2.4 MiB