# Система тестирования сотрудников клиники Веб-приложение для проведения внутреннего тестирования сотрудников клиники. Руководители подразделений и HR-менеджеры создают тесты и назначают их сотрудникам. Система фиксирует все попытки и результаты. **Версия ТЗ:** 1.2 **Дата:** 2026-03-21 **Статус:** Согласовано --- ## Содержание - [Технологический стек](#технологический-стек) - [Функциональные возможности](#функциональные-возможности) - [Роли и права доступа](#роли-и-права-доступа) - [База данных](#база-данных) - [API Endpoints](#api-endpoints) - [Структура проекта](#структура-проекта) - [Установка и запуск](#установка-и-запуск) - [План разработки](#план-разработки) --- ## Технологический стек | Компонент | Выбор | |-----------|-------| | Backend | Node.js + Express | | Frontend | React (SPA) | | Database | PostgreSQL | | Authentication | JWT (токен в httpOnly cookie) | | Password | bcrypt | --- ## Функциональные возможности ### 4.1 Управление пользователями и подразделениями - Создание/редактирование/деактивация учётных записей сотрудников - Каждый сотрудник принадлежит одному подразделению - Создание/редактирование справочника подразделений - Назначение роли сотруднику: HR-менеджер / Руководитель подразделения / Сотрудник ### 4.2 Создание и редактирование тестов **Тест содержит:** - Название теста - Описание (опционально) - Список вопросов (минимум 7) - Порог зачёта — минимальный % правильных ответов - Таймер прохождения — лимит в минутах (опционально) **Вопрос содержит:** - Текст вопроса - Минимум 3 варианта ответа - Один или несколько правильных ответов **Настройки теста:** - Разрешить возврат к предыдущему вопросу: да / нет **Версионирование:** - Автор может редактировать тест пока никто его не проходил - Если тест уже проходили — создаётся новая версия (`version + 1`), старая сохраняется - Все версии теста хранятся; результаты привязаны к конкретной версии - Активная версия — та, которую видят сотрудники; автор может вручную переключить активную версию - Тест можно деактивировать (скрыть из списка, не удалять) ### 4.3 Назначение теста - Список получателей (отдел или конкретные сотрудники) - Срок сдачи — дата дедлайна - Допустимое количество попыток (1 или более) ### 4.4 Прохождение теста - На главной странице сотрудник видит список назначенных тестов со статусами: - `Не начат` — ещё не открывал - `В процессе` — начал, не завершил - `Завершён` — сдал/не сдал - `Просрочен` — дедлайн прошёл, не сдан - Если задан таймер — отображается обратный отсчёт, по истечении тест завершается автоматически - Порядок вопросов **случайный** при каждом прохождении - Возможность вернуться к предыдущему вопросу — определяется настройкой теста ### 4.5 Результаты после завершения теста - Итоговый балл и процент правильных ответов - Факт зачёта: **сдал / не сдал** - Разбор ошибок: по каждому вопросу — его ответ и правильный ответ ### 4.6 Трекер попыток Единый интерфейс просмотра всех попыток прохождения тестов: - Фильтрация по подразделению, сотруднику, тесту, статусу, результату - Пагинация и сортировка ### 4.7 AI-помощник (DeepSeek) Интеграция с LLM DeepSeek для помощи при создании тестов: | Функция | Описание | |---------|----------| | Генерация теста | AI генерирует готовый набор вопросов с вариантами ответов по теме | | Улучшение формулировки | AI переформулирует выбранный вопрос более чётко | | Добавление дистракторов | AI генерирует правдоподобные неправильные варианты ответов | | Проверка качества | AI анализирует весь тест и выдаёт рекомендации | --- ## Роли и права доступа | Роль | Кто | Создаёт тесты | Назначает тесты | Видит результаты | |------|-----|:---:|:---:|:---:| | **HR-менеджер** | Руководитель службы HR, Директор клиники | ✅ | Всем сотрудникам клиники | Всех сотрудников | | **Руководитель подразделения** | Главный врач, рук. службы администраторов | ✅ | Только своему подразделению | Только своего подразделения | | **Сотрудник** | Все остальные работники | ❌ | ❌ | Только свои | --- ## База данных ### Схема таблиц #### `departments` — Подразделения | Поле | Тип | Описание | |------|-----|----------| | id | UUID | PK | | name | VARCHAR(255) | Название подразделения | | created_at | TIMESTAMP | Дата создания | | updated_at | TIMESTAMP | Дата обновления | #### `users` — Пользователи | Поле | Тип | Описание | |------|-----|----------| | id | UUID | PK | | login | VARCHAR(100) | Уникальный логин | | password_hash | VARCHAR(255) | Хеш пароля | | full_name | VARCHAR(255) | ФИО | | role | ENUM | 'hr', 'manager', 'employee' | | department_id | UUID | FK -> departments | | is_active | BOOLEAN | Активна ли учётная запись | | created_at | TIMESTAMP | Дата создания | | updated_at | TIMESTAMP | Дата обновления | #### `tests` — Тесты | Поле | Тип | Описание | |------|-----|----------| | id | UUID | PK | | title | VARCHAR(255) | Название теста | | description | TEXT | Описание (опционально) | | passing_threshold | INTEGER | Порог зачёта (%) | | time_limit | INTEGER | Таймер в минутах (nullable) | | allow_back | BOOLEAN | Возврат к предыдущему | | is_active | BOOLEAN | Активен | | is_versioned | BOOLEAN | Есть версии | | created_by | UUID | FK -> users | | created_at | TIMESTAMP | Дата создания | | updated_at | TIMESTAMP | Дата обновления | #### `test_versions` — Версии тестов | Поле | Тип | Описание | |------|-----|----------| | id | UUID | PK | | test_id | UUID | FK -> tests | | version | INTEGER | Номер версии | | is_active | BOOLEAN | Активная версия | | created_at | TIMESTAMP | Дата создания | #### `questions` — Вопросы | Поле | Тип | Описание | |------|-----|----------| | id | UUID | PK | | test_version_id | UUID | FK -> test_versions | | text | TEXT | Текст вопроса | | question_order | INTEGER | Порядок вопроса | | has_multiple_answers | BOOLEAN | Несколько правильных | #### `answer_options` — Варианты ответов | Поле | Тип | Описание | |------|-----|----------| | id | UUID | PK | | question_id | UUID | FK -> questions | | text | TEXT | Текст варианта | | is_correct | BOOLEAN | Правильный ответ | | option_order | INTEGER | Порядок варианта | #### `test_assignments` — Назначения тестов | Поле | Тип | Описание | |------|-----|----------| | id | UUID | PK | | test_version_id | UUID | FK -> test_versions | | assigned_by | UUID | FK -> users | | deadline | DATE | Срок сдачи | | max_attempts | INTEGER | Допустимое число попыток | | created_at | TIMESTAMP | Дата назначения | #### `test_assignment_targets` — Получатели назначений | Поле | Тип | Описание | |------|-----|----------| | id | UUID | PK | | assignment_id | UUID | FK -> test_assignments | | target_type | ENUM | 'department', 'user' | | target_id | UUID | FK (department или user) | #### `test_attempts` — Попытки прохождения | Поле | Тип | Описание | |------|-----|----------| | id | UUID | PK | | test_version_id | UUID | FK -> test_versions | | user_id | UUID | FK -> users | | attempt_number | INTEGER | Номер попытки | | status | ENUM | 'in_progress', 'completed', 'expired' | | started_at | TIMESTAMP | Начало | | completed_at | TIMESTAMP | Завершение | | correct_count | INTEGER | Правильных ответов | | total_questions | INTEGER | Всего вопросов | | passed | BOOLEAN | Зачёт | #### `user_answers` — Ответы пользователя | Поле | Тип | Описание | |------|-----|----------| | id | UUID | PK | | attempt_id | UUID | FK -> test_attempts | | question_id | UUID | FK -> questions | | selected_options | UUID[] | Выбранные варианты | #### `settings` — Настройки | Поле | Тип | Описание | |------|-----|----------| | key | VARCHAR(100) | PK | | value | TEXT | Значение | --- ## API Endpoints ### Аутентификация | Метод | Эндпоинт | Описание | |-------|----------|----------| | POST | `/api/auth/login` | Вход в систему | | POST | `/api/auth/logout` | Выход из системы | ### Подразделения | Метод | Эндпоинт | Описание | |-------|----------|----------| | GET | `/api/departments` | Список подразделений | | POST | `/api/departments` | Создать подразделение | | PUT | `/api/departments/:id` | Редактировать | | DELETE | `/api/departments/:id` | Деактивировать | ### Пользователи | Метод | Эндпоинт | Описание | |-------|----------|----------| | GET | `/api/users` | Список сотрудников | | POST | `/api/users` | Создать сотрудника | | GET | `/api/users/:id` | Карточка сотрудника | | PUT | `/api/users/:id` | Редактировать | | DELETE | `/api/users/:id` | Деактивировать | ### Тесты | Метод | Эндпоинт | Описание | |-------|----------|----------| | GET | `/api/tests` | Список тестов | | POST | `/api/tests` | Создать тест | | GET | `/api/tests/:id` | Тест с вопросами | | PUT | `/api/tests/:id` | Редактировать | | DELETE | `/api/tests/:id` | Деактивировать | ### Назначения тестов | Метод | Эндпоинт | Описание | |-------|----------|----------| | GET | `/api/assignments` | Список назначений | | POST | `/api/assignments` | Назначить тест | | GET | `/api/assignments/:id` | Детали назначения | | PUT | `/api/assignments/:id` | Редактировать | | DELETE | `/api/assignments/:id` | Удалить | | GET | `/api/my-assignments` | Назначенные тесты (для сотрудника) | ### Прохождение теста | Метод | Эндпоинт | Описание | |-------|----------|----------| | POST | `/api/attempts/start` | Начать попытку | | GET | `/api/attempts/:id` | Получить вопросы | | POST | `/api/attempts/:id/answers` | Отправить ответ | | GET | `/api/attempts/:id/answers` | Получить текущий прогресс | | POST | `/api/attempts/:id/complete` | Завершить тест | ### Результаты | Метод | Эндпоинт | Описание | |-------|----------|----------| | GET | `/api/attempts/:id/result` | Получить результат | | GET | `/api/attempts/:id/review` | Получить разбор | ### Трекер попыток | Метод | Эндпоинт | Описание | |-------|----------|----------| | GET | `/api/tracker` | Список всех попыток | ### AI-помощник | Метод | Эндпоинт | Описание | |-------|----------|----------| | POST | `/api/ai/generate-test` | Сгенерировать тест | | POST | `/api/ai/improve-question` | Улучшить вопрос | | POST | `/api/ai/add-distractors` | Добавить неправильные варианты | | POST | `/api/ai/check-quality` | Проверить качество теста | ### Настройки | Метод | Эндпоинт | Описание | |-------|----------|----------| | GET | `/api/settings` | Получить настройки | | PUT | `/api/settings` | Обновить настройки | | POST | `/api/settings/test-connection` | Проверить подключение к DeepSeek | --- ## Структура проекта ``` TestingWebApp/ ├── docs/ # Документация │ ├── ТЗ.md # Техническое задание │ └── шаги/ # План разработки (11 шагов) ├── backend/ # Node.js + Express │ ├── src/ │ │ ├── index.js # Точка входа │ │ ├── db/ # Работа с БД │ │ │ ├── db.js # Подключение к PostgreSQL │ │ │ ├── migrate.js # Миграции │ │ │ └── migrations/ │ │ │ └── 001_initial.sql │ │ ├── routes/ # API роуты │ │ │ └── auth.js │ │ ├── middleware/ # Промежуточное ПО │ │ │ └── auth.js │ │ └── utils/ # Утилиты │ │ └── auth.js │ └── package.json ├── frontend/ # React SPA │ ├── src/ │ │ ├── main.jsx # Точка входа │ │ └── App.jsx # Главный компонент │ ├── index.html │ ├── vite.config.js │ └── package.json ├── docker-compose.yml # PostgreSQL └── README.md # Этот файл ``` --- ## Установка и запуск ### Требования - Node.js 18+ - PostgreSQL 14+ - Docker (для PostgreSQL) ### Шаги 1. **Клонировать репозиторий** 2. **Настроить окружение** Создать файл `backend/.env`: ```env DATABASE_URL=postgresql://user:password@localhost:5432/clinic_tests JWT_SECRET=your-secret-key PORT=3000 ``` 3. **Запустить PostgreSQL** ```bash docker-compose up -d ``` 4. **Установить зависимости и запустить backend** ```bash cd backend npm install npm run dev ``` 5. **Запустить frontend** ```bash cd frontend npm install npm run dev ``` 6. **Открыть приложение** - Frontend: http://localhost:5173 - Backend API: http://localhost:3000 --- ## План разработки | Шаг | Название | Описание | |-----|----------|----------| | 1 | Проект и инфраструктура | Структура проекта, Docker, настройка окружения | | 2 | Проектирование БД | Создание всех таблиц и миграций | | 3 | Аутентификация и авторизация | JWT, login/logout, RBAC | | 4 | Управление пользователями | CRUD сотрудников и подразделений | | 5 | Управление тестами | Создание, редактирование, версионирование | | 6 | Назначение тестов | Выбор получателей, дедлайн, лимит попыток | | 7 | Интерфейс прохождения | Прохождение с таймером, случайный порядок вопросов | | 8 | Результаты и разбор | Итоговый балл, разбор ошибок | | 9 | Трекер попыток | Единый интерфейс просмотра попыток | | 10 | AI-помощник | Интеграция с DeepSeek | | 11 | Страница настроек | Управление API ключами | --- ## Нефункциональные требования | Параметр | Значение | |----------|----------| | Количество пользователей | 50–200 человек | | Платформа | Веб-приложение, браузер (desktop-first) | | Доступность | Внутренняя сеть клиники | | Язык интерфейса | Русский | | Время отклика | < 2 секунды | --- ## Вне scope (не реализуется в данной версии) - Интеграция с AD/LDAP - Мобильное приложение - Вопросы с вложениями (изображения, видео) - Экспорт отчётов в Excel / PDF - Уведомления в MAX (отдельный спринт)