Files
magistr/docs/DATABASE.md

24 KiB
Raw Blame History

🗄 База данных

Общая информация

  • СУБД: PostgreSQL (локально postgres:alpine3.23, продакшн — managed PostgreSQL)
  • Управление схемой: Flyway (программный запуск)
  • Hibernate DDL: Отключён (ddl-auto=none)
  • Расширения: pgcrypto (bcrypt-хеширование паролей)
  • Мультитенантность: Каждый тенант = отдельная БД

ER-диаграмма

erDiagram
    departments {
        BIGSERIAL id PK
        VARCHAR name
        BIGINT code UK
    }

    specialties {
        BIGSERIAL id PK
        VARCHAR name
        VARCHAR specialty_code UK
    }

    specialty_profiles {
        BIGSERIAL id PK
        BIGINT specialty_id FK
        VARCHAR name
        TEXT description
    }
    
    users {
        BIGSERIAL id PK
        VARCHAR username UK
        VARCHAR password
        VARCHAR role
        VARCHAR full_name
        VARCHAR job_title
        BIGINT department_id FK
        TIMESTAMP created_at
        TIMESTAMP updated_at
    }
    
    education_forms {
        BIGSERIAL id PK
        VARCHAR name UK
        TEXT description
        TIMESTAMP created_at
    }
    
    student_groups {
        BIGSERIAL id PK
        VARCHAR name
        BIGINT group_size
        BIGINT education_form_id FK
        BIGINT department_id FK
        BIGINT specialty_id FK
        BIGINT specialty_profile_id FK
        BIGINT year_start_study
        TIMESTAMP created_at
    }
    
    subgroups {
        BIGSERIAL id PK
        BIGINT group_id FK
        VARCHAR name
        INT student_capacity
    }
    
    subjects {
        BIGSERIAL id PK
        VARCHAR name UK
        VARCHAR code
        BIGINT department_id FK
        TEXT description
        TIMESTAMP created_at
    }
    
    lesson_types {
        BIGSERIAL id PK
        VARCHAR name UK
        VARCHAR color_code
        INT duration_minutes
    }
    
    equipments {
        BIGSERIAL id PK
        VARCHAR name UK
        TEXT description
        VARCHAR inventory_number
    }
    
    classrooms {
        BIGSERIAL id PK
        VARCHAR name UK
        INT capacity
        VARCHAR building
        INT floor
        BOOLEAN is_available
        TEXT description
        TIMESTAMP created_at
    }
    
    classroom_equipments {
        BIGINT classroom_id FK,PK
        BIGINT equipment_id FK,PK
        INT quantity
        TEXT notes
    }
    
    teacher_subjects {
        BIGINT user_id FK,PK
        BIGINT subject_id FK,PK
        VARCHAR qualification_level
        INT experience_years
    }
    
    teacher_lesson_types {
        BIGINT user_id FK,PK
        BIGINT subject_id FK,PK
        BIGINT lesson_type_id FK,PK
    }
    
    time_slot_scopes {
        BIGSERIAL id PK
        VARCHAR code UK
        VARCHAR name
        VARCHAR apply_mode
        INT day_of_week
        BOOLEAN system_scope
        INT display_order
    }

    time_slots {
        BIGSERIAL id PK
        BIGINT time_slot_scope_id FK
        INT order_number
        TIME start_time
        TIME end_time
        INT duration_minutes
    }

    time_slot_date_assignments {
        BIGSERIAL id PK
        DATE assignment_date UK
        BIGINT time_slot_scope_id FK
    }

    academic_years {
        BIGSERIAL id PK
        VARCHAR title UK
        DATE start_date
        DATE end_date
    }

    semesters {
        BIGSERIAL id PK
        BIGINT academic_year_id FK
        VARCHAR semester_type
        DATE start_date
        DATE end_date
    }

    academic_calendar_activity_types {
        BIGSERIAL id PK
        VARCHAR code UK
        VARCHAR name
        BOOLEAN allow_schedule
        VARCHAR color_code
        INT display_order
    }

    academic_calendars {
        BIGSERIAL id PK
        VARCHAR title
        BIGINT academic_year_id FK
        BIGINT specialty_id FK
        BIGINT specialty_profile_id FK
        BIGINT study_form_id FK
        INT course_count
        TIMESTAMP created_at
        TIMESTAMP updated_at
    }

    academic_calendar_days {
        BIGSERIAL id PK
        BIGINT calendar_id FK
        INT course_number
        DATE date
        INT week_number
        INT day_of_week
        BIGINT activity_type_id FK
    }

    student_group_calendar_assignments {
        BIGSERIAL id PK
        BIGINT group_id FK
        BIGINT academic_year_id FK
        BIGINT calendar_id FK
    }

    schedule_rules {
        BIGSERIAL id PK
        BIGINT subject_id FK
        BIGINT semester_id FK
        INT lecture_academic_hours
        INT laboratory_academic_hours
        INT practice_academic_hours
        INT lecture_start_week
        INT laboratory_start_week
        INT practice_start_week
    }

    schedule_rule_groups {
        BIGINT schedule_rule_id FK,PK
        BIGINT group_id FK,PK
    }

    schedule_rule_slots {
        BIGSERIAL id PK
        BIGINT schedule_rule_id FK
        INT day_of_week
        VARCHAR parity
        BIGINT time_slot_id FK
        BIGINT subgroup_id FK
        BIGINT teacher_id FK
        BIGINT classroom_id FK
        BIGINT lesson_type_id FK
        VARCHAR lesson_format
    }
    
    departments ||--o{ users : "department_id"
    departments ||--o{ student_groups : "department_id"
    departments ||--o{ subjects : "department_id"
    education_forms ||--o{ student_groups : "education_form_id"
    specialties ||--o{ specialty_profiles : "specialty_id"
    specialties ||--o{ student_groups : "specialty_id"
    specialty_profiles ||--o{ student_groups : "specialty_profile_id"
    student_groups ||--o{ subgroups : "group_id"
    student_groups ||--o{ schedule_rule_groups : "group_id"
    student_groups ||--o{ student_group_calendar_assignments : "group_id"
    users ||--o{ teacher_subjects : "user_id"
    users ||--o{ teacher_lesson_types : "user_id"
    subjects ||--o{ teacher_subjects : "subject_id"
    subjects ||--o{ teacher_lesson_types : "subject_id"
    subjects ||--o{ schedule_rules : "subject_id"
    lesson_types ||--o{ teacher_lesson_types : "lesson_type_id"
    lesson_types ||--o{ schedule_rule_slots : "lesson_type_id"
    classrooms ||--o{ schedule_rule_slots : "classroom_id"
    classrooms ||--o{ classroom_equipments : "classroom_id"
    equipments ||--o{ classroom_equipments : "equipment_id"
    academic_years ||--o{ semesters : "academic_year_id"
    academic_years ||--o{ academic_calendars : "academic_year_id"
    academic_years ||--o{ student_group_calendar_assignments : "academic_year_id"
    semesters ||--o{ schedule_rules : "semester_id"
    specialties ||--o{ academic_calendars : "specialty_id"
    specialty_profiles ||--o{ academic_calendars : "specialty_profile_id"
    education_forms ||--o{ academic_calendars : "study_form_id"
    academic_calendars ||--o{ academic_calendar_days : "calendar_id"
    academic_calendars ||--o{ student_group_calendar_assignments : "calendar_id"
    academic_calendar_activity_types ||--o{ academic_calendar_days : "activity_type_id"
    schedule_rules ||--o{ schedule_rule_groups : "schedule_rule_id"
    schedule_rules ||--o{ schedule_rule_slots : "schedule_rule_id"
    time_slot_scopes ||--o{ time_slots : "time_slot_scope_id"
    time_slot_scopes ||--o{ time_slot_date_assignments : "time_slot_scope_id"
    time_slots ||--o{ schedule_rule_slots : "time_slot_id"
    subgroups ||--o{ schedule_rule_slots : "subgroup_id"
    users ||--o{ schedule_rule_slots : "teacher_id"

Описание таблиц

Справочники высшего уровня

departments — Кафедры

Колонка Тип Описание
id BIGSERIAL PK ID кафедры
name VARCHAR(255) Название кафедры
code BIGINT UNIQUE Код кафедры

specialties — Специальности

Колонка Тип Описание
id BIGSERIAL PK ID специальности
name VARCHAR(255) Название специальности
specialty_code VARCHAR(255) UNIQUE Код ФГОС (напр. 10.03.01)

specialty_profiles — Профили обучения

Колонка Тип Описание
id BIGSERIAL PK ID профиля
specialty_id BIGINT FK → specialties Специальность, внутри которой существует профиль
name VARCHAR(255) Название профиля, уникально внутри специальности
description TEXT Описание профиля

Пользователи

users — Пользователи системы

Колонка Тип Описание
id BIGSERIAL PK ID пользователя
username VARCHAR(50) UNIQUE Логин
password VARCHAR(255) bcrypt-хеш пароля
role VARCHAR(20) ADMIN, TEACHER, STUDENT
full_name VARCHAR(255) ФИО
job_title VARCHAR(255) Должность
department_id BIGINT FK → departments Кафедра
created_at TIMESTAMP Дата создания
updated_at TIMESTAMP Дата обновления (авто-триггер)

Триггер: update_users_updated_at автоматически обновляет updated_at при любом UPDATE.

Учебный процесс

education_forms — Формы обучения

Колонка Тип Описание
id BIGSERIAL PK ID
name VARCHAR(100) UNIQUE Название (Бакалавриат, Магистратура, Специалитет)
description TEXT Описание

Эта таблица используется и группами (student_groups.education_form_id), и календарными учебными графиками (academic_calendars.study_form_id). Отдельного справочника форм обучения для календарей нет.

student_groups — Учебные группы

Колонка Тип Описание
id BIGSERIAL PK ID
name VARCHAR(100) Название группы (напр. ИВТ-21-1), не уникальное
group_size BIGINT Количество студентов
education_form_id BIGINT FK → education_forms Форма обучения
department_id BIGINT FK → departments Кафедра
specialty_id BIGINT FK → specialties Специальность
specialty_profile_id BIGINT FK → specialty_profiles Профиль обучения группы
year_start_study BIGINT Год начала обучения, используется для вычисления текущего курса

subgroups — Подгруппы

Колонка Тип Описание
id BIGSERIAL PK ID
group_id BIGINT FK → student_groups (CASCADE) Родительская группа
name VARCHAR(100) Название подгруппы
student_capacity INT Количество студентов

subjects — Дисциплины

Колонка Тип Описание
id BIGSERIAL PK ID
name VARCHAR(200) UNIQUE Название
code VARCHAR(20) Код предмета
department_id BIGINT FK → departments Кафедра
description TEXT Описание

Аудиторный фонд

classrooms — Аудитории

Колонка Тип Описание
id BIGSERIAL PK ID
name VARCHAR(50) UNIQUE Название (напр. 101 Ленинская)
capacity INT CHECK(> 0) Вместимость
building VARCHAR(50) Корпус
floor INT Этаж
is_available BOOLEAN Доступна для назначения пар
description TEXT Описание

equipments — Оборудование

Колонка Тип Описание
id BIGSERIAL PK ID
name VARCHAR(50) UNIQUE Название
description TEXT Описание
inventory_number VARCHAR(50) Инвентарный номер

classroom_equipments — Привязка оборудования к аудиториям

Колонка Тип Описание
classroom_id BIGINT PK, FK → classrooms (CASCADE) Аудитория
equipment_id BIGINT PK, FK → equipments (CASCADE) Оборудование
quantity INT CHECK(> 0) Количество единиц
notes TEXT Примечания

Расписание

lesson_types — Типы занятий (справочник)

Колонка Тип Описание
id BIGSERIAL PK ID
name VARCHAR(50) UNIQUE Название типа
color_code VARCHAR(7) HEX-цвет для UI (напр. #FF6B6B)
duration_minutes INT Длительность (по умолчанию 90)

Связи «Преподаватель ↔ Дисциплина»

teacher_subjects — Квалификация преподавателей

Колонка Тип Описание
user_id BIGINT PK, FK → users (CASCADE) Преподаватель
subject_id BIGINT PK, FK → subjects (CASCADE) Дисциплина
qualification_level VARCHAR(50) Уровень квалификации
experience_years INT Стаж

teacher_lesson_types — Типы занятий преподавателя

Колонка Тип Описание
user_id BIGINT PK, FK → users (CASCADE) Преподаватель
subject_id BIGINT PK, FK → subjects (CASCADE) Дисциплина
lesson_type_id BIGINT PK, FK → lesson_types (CASCADE) Тип занятия

time_slot_scopes — Сетки времени

Колонка Тип Описание
id BIGSERIAL PK ID
code VARCHAR(50) UNIQUE Системный код сетки
name VARCHAR(120) Название в интерфейсе
apply_mode VARCHAR(20) DEFAULT, WEEKDAY, MANUAL
day_of_week INT NULL День недели для автоматической сетки
system_scope BOOLEAN Защищает базовую и субботнюю сетки от удаления
display_order INT Порядок в списках

Seed создаёт Базовая сетка (DEFAULT) и Субботняя сетка (WEEKDAY, day_of_week = 6). Дополнительные сетки создаются как MANUAL и применяются только через ручные назначения дат.

time_slots — Временные слоты занятий

Колонка Тип Описание
id BIGSERIAL PK ID
time_slot_scope_id BIGINT FK → time_slot_scopes Сетка времени
order_number INT Номер пары в дне
start_time TIME Время начала
end_time TIME Время окончания
duration_minutes INT Длительность в минутах

Уникальность задаётся индексом (time_slot_scope_id, order_number): в одной сетке может быть только один слот с номером пары.

time_slot_date_assignments — Ручные назначения сеток времени

Колонка Тип Описание
id BIGSERIAL PK ID
assignment_date DATE UNIQUE Дата ручного применения
time_slot_scope_id BIGINT FK → time_slot_scopes Ручная сетка времени

academic_years — Учебные годы

Колонка Тип Описание
id BIGSERIAL PK ID
title VARCHAR(20) UNIQUE Название, например 2025-2026
start_date DATE Дата начала
end_date DATE Дата окончания

semesters — Семестры

Колонка Тип Описание
id BIGSERIAL PK ID
academic_year_id BIGINT FK → academic_years Учебный год
semester_type VARCHAR(20) autumn или spring
start_date DATE Дата начала, от неё считается неделя 1
end_date DATE Дата окончания

academic_calendar_activity_types — Коды активностей графика

Колонка Тип Описание
id BIGSERIAL PK ID
code VARCHAR(10) UNIQUE Код из Excel-графика: Т, Э, К, У, П, Пд, Н, Г, Д, ПА, С, *, =
name VARCHAR(100) Расшифровка кода
allow_schedule BOOLEAN Разрешает генерацию обычных пар
color_code VARCHAR(7) HEX-цвет для редактора
display_order INT Порядок вывода в UI
description TEXT Дополнительное описание

academic_calendars — Календарные учебные графики

Колонка Тип Описание
id BIGSERIAL PK ID
title VARCHAR(255) Название графика
academic_year_id BIGINT FK → academic_years Учебный год
specialty_id BIGINT FK → specialties Специальность
specialty_profile_id BIGINT FK → specialty_profiles Профиль обучения
study_form_id BIGINT FK → education_forms Форма обучения из общего справочника
course_count INT CHECK(> 0) Количество курсов в сетке
created_at TIMESTAMP Дата создания
updated_at TIMESTAMP Дата обновления

academic_calendar_days — Дневная сетка календарного графика

Колонка Тип Описание
id BIGSERIAL PK ID
calendar_id BIGINT FK → academic_calendars (CASCADE) Календарный график
course_number INT Номер курса
date DATE Дата учебного года
week_number INT Номер недели от начала учебного года
day_of_week INT CHECK(17) День недели ISO
activity_type_id BIGINT FK → academic_calendar_activity_types Код активности

student_group_calendar_assignments — Назначения графиков группам

Колонка Тип Описание
id BIGSERIAL PK ID
group_id BIGINT FK → student_groups (CASCADE) Учебная группа
academic_year_id BIGINT FK → academic_years (CASCADE) Учебный год
calendar_id BIGINT FK → academic_calendars (CASCADE) Назначенный график

schedule_rules — Правила расписания

Колонка Тип Описание
id BIGSERIAL PK ID
subject_id BIGINT FK → subjects Дисциплина
semester_id BIGINT FK → semesters Семестр
lecture_academic_hours INT Лимит академических часов лекций
laboratory_academic_hours INT Лимит академических часов лабораторных работ
practice_academic_hours INT Лимит академических часов практик
lecture_start_week INT Неделя семестра, с которой начинаются лекции
laboratory_start_week INT Неделя семестра, с которой начинаются лабораторные
practice_start_week INT Неделя семестра, с которой начинаются практики

schedule_rule_groups — Группы правила

Колонка Тип Описание
schedule_rule_id BIGINT PK, FK → schedule_rules Правило
group_id BIGINT PK, FK → student_groups Группа

schedule_rule_slots — Слоты правила

Колонка Тип Описание
id BIGSERIAL PK ID
schedule_rule_id BIGINT FK → schedule_rules Правило
day_of_week INT CHECK(17) День недели: 1 — понедельник
parity VARCHAR(10) BOTH, EVEN, ODD
time_slot_id BIGINT FK → time_slots Базовый временной слот
subgroup_id BIGINT FK → subgroups, NULL Подгруппа
teacher_id BIGINT FK → users Преподаватель
classroom_id BIGINT FK → classrooms Аудитория
lesson_type_id BIGINT FK → lesson_types Тип занятия
lesson_format VARCHAR(30) Очно или Онлайн

Flyway миграции

Правила работы

  1. Все миграции находятся в backend/src/main/resources/db/migration/
  2. Формат имени: V{номер}__{описание}.sql (напр. V1__init.sql, V2__add_departments.sql)
  3. ЗАПРЕЩЕНО изменять уже закоммиченные файлы миграций — это сломает контрольные суммы Flyway
  4. Flyway запускается программно при первом обращении к БД тенанта (TenantConfigWatcher.initDatabaseForTenant())
  5. Настройка baselineOnMigrate=true — если в БД уже есть данные, Flyway начнёт с baseline

Текущая ветка календарного учебного графика является осознанным исключением: V1__init.sql переписан как новая базовая схема, а применение предполагает полный сброс БД без переноса старых данных.

Текущие миграции

Файл Описание
V1__init.sql Инициализация: справочники, профили специальностей, календарные учебные графики, динамическое расписание с раздельными часами и стартовыми неделями по типам занятий, тестовые правила, триггеры, комментарии

Накатывание на существующих тенантов

Для применения новой базовой схемы к уже существующим тенантам нужен полный сброс БД. Перезапуск backend без сброса не изменит уже применённую V1__init.sql.

# Kubernetes
kubectl rollout restart deployment backend -n magistr

# Docker Compose (локально)
docker compose restart backend

Полный сброс БД (локально)

docker compose down -v    # Удаляет volumes (данные)
docker compose up -d      # Пересоздаёт БД с нуля