You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
16 KiB
16 KiB
Анализ таблиц для тестирования сотрудников
Модуль TestingWebApp использует отдельную БД clinic_tests (см. PROJECT_STATUS.md и README.md). Ниже — разбор наследуемых / смежных сущностей в другой схеме, для сравнения и миграционных дискуссий.
Обзор существующих таблиц
В базе данных существуют следующие таблицы, связанные с тестированием:
1. training_questions - Вопросы обучения
| Колонка | Тип | Описание |
|---|---|---|
id |
integer | Первичный ключ |
position |
text | Должность/категория |
test_type |
text | Тип темы/теста |
question |
text | Текст вопроса |
answer_1 - answer_12 |
text | Варианты ответов |
answer_count |
smallint | Количество правильных ответов |
Проблемы:
- Отсутствует явное указание правильного ответа
- Нет типа вопроса (одиночный/множественный выбор, текстовый, сопоставление)
- Нет баллов за вопрос
- Нет порядка вопросов
- Поле
positionиспользуется как категория, но не связано с должностями
2. training_results - Результаты обучения
| Колонка | Тип | Описание |
|---|---|---|
id |
integer | Первичный ключ |
telegram_id |
bigint | ID сотрудника |
correct_answers |
integer | Правильные ответы |
total_questions |
integer | Всего вопросов |
score |
integer | Балл |
completed_at |
timestamp | Дата завершения |
passed |
boolean | Пройден/не пройден |
Индексы:
idx_training_results_telegram_id- по telegram_id
Проблемы:
- Нет связи с конкретным тестом (test_type)
- Нет количества попыток
- Нет детализации по ответам
3. training_settings - Настройки обучения
| Колонка | Тип | Описание |
|---|---|---|
id |
integer | Первичный ключ |
position |
varchar(100) | Должность |
question_count |
integer | Количество вопросов (по умолчанию 10) |
passing_score |
integer | Проходной балл (по умолчанию 70) |
time_limit |
integer | Ограничение времени в минутах (по умолчанию 30) |
active |
boolean | Активен/неактивен |
Индексы:
idx_training_settings_position- по position
Проблемы:
- Нет связи с категорией теста
- Нет ограничения количества попыток
- Нет настройки случайного порядка вопросов
4. test_assignments - Назначения тестов
| Колонка | Тип | Описание |
|---|---|---|
id |
integer | Первичный ключ |
la_name |
text | Название адаптации |
intern_fio |
text | ФИО стажера |
user_credentials |
text | Учетные данные |
test_theme |
text | Тема теста |
test_subtheme |
text | Подтема теста |
attempts_allowed |
integer | Количество попыток |
passing_score |
integer | Проходной балл |
la_id |
integer | Ссылка на адаптацию |
intern_id |
bigint | ID сотрудника (staff_members.id) |
deadline |
timestamp | Срок сдачи |
Внешние ключи:
intern_id->staff_members(id)la_id->learning_adaptations(id)
Проблемы:
- Назначения привязаны к конкретным сотрудникам, а не к должностям
- Нет статуса прохождения
- Нет связи с результатами
5. test_table - Таблица тестов
| Колонка | Тип | Описание |
|---|---|---|
id |
integer | Первичный ключ |
name |
varchar(100) | Название теста |
Проблемы:
- Минимальная структура, практически не используется
6. corp_groups_tester - Тестировщики (корпоративные группы)
| Колонка | Тип | Описание |
|---|---|---|
id |
integer | Первичный ключ |
fio |
text | ФИО |
telegram_id |
varchar(20) | Telegram ID |
position |
varchar(200) | Должность |
department |
varchar(200) | Отдел |
phone |
varchar(20) | Телефон |
email |
varchar(100) | |
hire_date |
date | Дата приема |
Проблемы:
- Дублирует данные staff_members
- Не используется в текущей системе
Рекомендуемая расширенная схема для ClinicTestingApp
Новые таблицы
1. tests - Основные тесты
CREATE TABLE tests (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL, -- Название теста
description TEXT, -- Описание
category VARCHAR(100), -- Категория (тема)
position VARCHAR(100), -- Должность (nullable - для всех)
question_count INTEGER DEFAULT 10, -- Количество вопросов в тесте
time_limit_minutes INTEGER, -- Ограничение времени (null = без ограничений)
attempts_allowed INTEGER DEFAULT 3, -- Количество попыток
passing_score_percent INTEGER DEFAULT 70, -- Проходной процент
random_questions BOOLEAN DEFAULT FALSE, -- Случайный порядок вопросов
is_active BOOLEAN DEFAULT TRUE, -- Активен
created_by INTEGER, -- ID администратора
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_tests_category ON tests(category);
CREATE INDEX idx_tests_position ON tests(position);
2. test_questions - Вопросы тестов
CREATE TABLE test_questions (
id SERIAL PRIMARY KEY,
test_id INTEGER NOT NULL REFERENCES tests(id) ON DELETE CASCADE,
question_text TEXT NOT NULL, -- Текст вопроса
question_type VARCHAR(50) NOT NULL, -- single_choice, multiple_choice, text, matching, ordering
points INTEGER DEFAULT 1, -- Баллы за вопрос
question_order INTEGER, -- Порядок вопроса
explanation TEXT, -- Пояснение к ответу
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_test_questions_test_id ON test_questions(test_id);
3. test_answers - Ответы на вопросы
CREATE TABLE test_answers (
id SERIAL PRIMARY KEY,
question_id INTEGER NOT NULL REFERENCES test_questions(id) ON DELETE CASCADE,
answer_text TEXT NOT NULL, -- Текст ответа
is_correct BOOLEAN DEFAULT FALSE, -- Правильный ответ
answer_order INTEGER, -- Порядок (для сопоставления/порядка)
points_if_correct INTEGER DEFAULT 1 -- Баллы (если отличаются от question.points)
);
CREATE INDEX idx_test_answers_question_id ON test_answers(question_id);
4. test_assignments_extended - Расширенные назначения тестов
CREATE TABLE test_assignments_extended (
id SERIAL PRIMARY KEY,
test_id INTEGER NOT NULL REFERENCES tests(id) ON DELETE CASCADE,
staff_id INTEGER NOT NULL REFERENCES staff_members(id) ON DELETE CASCADE,
assigned_by INTEGER, -- ID администратора
assigned_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deadline TIMESTAMP, -- Срок сдачи
attempts_allowed INTEGER, -- Переопределение количества попыток (null = из теста)
status VARCHAR(50) DEFAULT 'pending', -- pending, in_progress, completed, expired
UNIQUE(test_id, staff_id)
);
CREATE INDEX idx_test_assignments_test_id ON test_assignments_extended(test_id);
CREATE INDEX idx_test_assignments_staff_id ON test_assignments_extended(staff_id);
5. test_attempts - Попытки прохождения
CREATE TABLE test_attempts (
id SERIAL PRIMARY KEY,
assignment_id INTEGER NOT NULL REFERENCES test_assignments_extended(id) ON DELETE CASCADE,
attempt_number INTEGER NOT NULL, -- Номер попытки
started_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
completed_at TIMESTAMP, -- Завершена
score_points INTEGER, -- Набрано баллов
score_percent NUMERIC(5,2), -- Процент
passed BOOLEAN, -- Пройден/не пройден
time_spent_seconds INTEGER -- Потраченное время
);
CREATE INDEX idx_test_attempts_assignment_id ON test_attempts(assignment_id);
6. test_answers_given - Ответы пользователя
CREATE TABLE test_answers_given (
id SERIAL PRIMARY KEY,
attempt_id INTEGER NOT NULL REFERENCES test_attempts(id) ON DELETE CASCADE,
question_id INTEGER NOT NULL REFERENCES test_questions(id) ON DELETE CASCADE,
given_answer_ids INTEGER[], -- ID выбранных ответов (для choice)
given_text TEXT, -- Текстовый ответ
is_correct BOOLEAN, -- Правильный/неправильный
points_earned INTEGER, -- Полученные баллы
answered_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_test_answers_given_attempt_id ON test_answers_given(attempt_id);
7. test_categories - Категории тестов
CREATE TABLE test_categories (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL UNIQUE,
description TEXT,
parent_id INTEGER REFERENCES test_categories(id),
is_active BOOLEAN DEFAULT TRUE
);
8. test_reports - Сформированные отчеты
CREATE TABLE test_reports (
id SERIAL PRIMARY KEY,
report_type VARCHAR(50) NOT NULL, -- department, employee, category
parameters JSONB, -- Параметры отчета
file_path VARCHAR(500), -- Путь к файлу
format VARCHAR(10), -- pdf, xlsx
generated_by INTEGER, -- ID администратора
generated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Расширение существующих таблиц (миграции)
training_questions
-- Добавить тип вопроса
ALTER TABLE training_questions ADD COLUMN IF NOT EXISTS question_type VARCHAR(50) DEFAULT 'single_choice';
-- Добавить баллы
ALTER TABLE training_questions ADD COLUMN IF NOT EXISTS points INTEGER DEFAULT 1;
-- Добавить правильный ответ (индекс)
ALTER TABLE training_questions ADD COLUMN IF NOT EXISTS correct_answer_index INTEGER;
-- Добавить порядок
ALTER TABLE training_questions ADD COLUMN IF NOT EXISTS sort_order INTEGER;
-- Добавить пояснение
ALTER TABLE training_questions ADD COLUMN IF NOT EXISTS explanation TEXT;
training_results
-- Добавить связь с тестом
ALTER TABLE training_results ADD COLUMN IF NOT EXISTS test_id INTEGER REFERENCES tests(id);
-- Добавить номер попытки
ALTER TABLE training_results ADD COLUMN IF NOT EXISTS attempt_number INTEGER DEFAULT 1;
-- Добавить время прохождения
ALTER TABLE training_results ADD COLUMN IF NOT EXISTS time_spent_seconds INTEGER;
-- Добавить детализацию ответов (JSON)
ALTER TABLE training_results ADD COLUMN IF NOT EXISTS answers_detail JSONB;
training_settings
-- Добавить связь с тестом
ALTER TABLE training_settings ADD COLUMN IF NOT EXISTS test_id INTEGER REFERENCES tests(id);
-- Добавить категорию
ALTER TABLE training_settings ADD COLUMN IF NOT EXISTS category VARCHAR(100);
-- Добавить случайный порядок
ALTER TABLE training_settings ADD COLUMN IF NOT EXISTS random_order BOOLEAN DEFAULT FALSE;
Связь с staff_members
Текущая проблема: используется telegram_id для связи с сотрудниками.
Решение: перейти на использование staff_members.id как универсального идентификатора:
-- Добавить staff_id в training_results
ALTER TABLE training_results ADD COLUMN IF NOT EXISTS staff_id INTEGER REFERENCES staff_members(id);
-- Миграция данных
UPDATE training_results tr
SET staff_id = sm.id
FROM staff_members sm
WHERE tr.telegram_id = sm.telegram_id;
-- Создать внешний ключ после миграции
ALTER TABLE training_results
ADD CONSTRAINT training_results_staff_id_fkey
FOREIGN KEY (staff_id) REFERENCES staff_members(id);
Типы вопросов
| Тип | Код | Описание |
|---|---|---|
| Одиночный выбор | single_choice |
Один правильный ответ из нескольких |
| Множественный выбор | multiple_choice |
Несколько правильных ответов |
| Текстовый ответ | text |
Свободный текст |
| Сопоставление | matching |
Сопоставление пар |
| Порядок элементов | ordering |
Расстановка в правильном порядке |
API Endpoints (рекомендуемые)
Тесты
GET /api/tests- Список тестовPOST /api/tests- Создать тестGET /api/tests/{id}- Получить тест с вопросамиPUT /api/tests/{id}- Обновить тестDELETE /api/tests/{id}- Удалить тест
Вопросы
GET /api/tests/{test_id}/questions- Список вопросовPOST /api/tests/{test_id}/questions- Добавить вопросPUT /api/questions/{id}- Обновить вопросDELETE /api/questions/{id}- Удалить вопрос
Назначения
GET /api/assignments- Список назначенийPOST /api/assignments- Назначить тестGET /api/employees/{id}/assignments- Назначения сотрудника
Прохождение
POST /api/tests/{id}/start- Начать тестPOST /api/attempts/{id}/answer- Ответить на вопросPOST /api/attempts/{id}/complete- Завершить тест
Отчеты
GET /api/reports/department- Отчет по отделениямGET /api/reports/employee/{id}- Отчет по сотрудникуGET /api/reports/category/{id}- Отчет по категорииGET /api/reports/export- Экспорт отчета (PDF/Excel)