Files
magistr/docs/BUSINESS_LOGIC.md

13 KiB
Raw Blame History

📋 Бизнес-логика

Ролевая модель

Система поддерживает три роли пользователей:

Роль Enum Возможности
Администратор (Деканат) ADMIN Полный доступ: CRUD пользователей, групп, аудиторий, дисциплин, расписания. Управление тенантами (БД).
Преподаватель TEACHER Просмотр своего расписания. В перспективе — подача заявок на перенос.
Студент STUDENT Только просмотр расписания (Read-only).

После авторизации пользователь перенаправляется на свой интерфейс:

  • ADMIN/admin/
  • TEACHER/teacher/
  • STUDENT/student/

Управление ресурсами

Кафедры (Departments)

Организационные единицы университета. К кафедре привязываются пользователи, группы и дисциплины.

  • Имеют уникальный числовой code
  • Предзаполнены: «Кафедра ИБ», «Кафедра ВТ», «Кафедра КТ»

Специальности (Specialties)

Учебные направления с кодом по ФГОС. У одной специальности может быть несколько профилей обучения, например базовый профиль и профиль конкретной образовательной программы.

  • Примеры: «Информационная безопасность» (10.03.01), «Программная инженерия» (09.03.04)
  • При создании специальности автоматически создаётся профиль Без профиля

Формы обучения (Education Forms)

Уровни/формы обучения для привязки к группам и календарным учебным графикам.

  • Предзаполнены: Бакалавриат, Магистратура, Специалитет
  • Нельзя удалить форму обучения, если к ней привязаны группы или календарные графики

Учебные группы (Student Groups)

  • Поля: Название, численность, форма обучения, кафедра, специальность, профиль обучения, год начала обучения
  • Курс: вычисляется относительно учебного года: год начала учебного года - year_start_study + 1
  • Подгруппы: Возможно деление группы на подгруппы (таблица subgroups)
  • Календарь: на каждый учебный год группе назначается конкретный календарный учебный график

Аудитории (Classrooms)

  • Поля: Название (уникальное), вместимость (> 0), корпус, этаж, доступность
  • Оборудование: К каждой аудитории привязывается список оборудования (Many-to-Many) с указанием количества
  • Статус: Флаг is_available для блокирования назначения пар

Оборудование (Equipments)

Каталог оборудования для привязки к аудиториям.

  • Предзаполнены: Проектор, ПК, Лаборатория, Интерактивная доска, Документ-камера, Аудиосистема
  • Уникальность по названию

Дисциплины (Subjects)

  • Поля: Название (уникальное), код, кафедра, описание
  • Привязка преподавателей через teacher_subjects (Many-to-Many)

Логика расписания

Динамическая модель расписания

Основная модель расписания строится из правил, а не из отдельных статических пар.

Компонент Назначение
academic_years / semesters Учебные годы и семестры. Неделя 1 считается от semesters.start_date
specialty_profiles Профили обучения внутри специальности
academic_calendars Календарный учебный график профиля, формы обучения и учебного года
academic_calendar_activity_types Коды Excel-графика: Т, Э, К, У, П, Пд, Н, Г, Д, ПА, С, *, =
academic_calendar_days Дневная сетка по курсу и дате
student_group_calendar_assignments Назначение конкретного графика группе на учебный год
time_slots Настраиваемая сетка пар для тенанта
schedule_rules Лимиты часов и недели начала по лекциям, лабораторным и практикам
schedule_rule_groups Группы правила, включая потоковые лекции
schedule_rule_slots День, чётность, слот, преподаватель, аудитория, тип и формат занятия
schedule_rule_slot_subgroups Подгруппы лабораторного слота

Генератор ScheduleGeneratorService рендерит расписание по запросу:

  1. Определяет семестр для каждой даты диапазона.
  2. Вычисляет номер недели и чётность.
  3. Находит назначенный группе календарный учебный график на учебный год даты.
  4. Определяет код активности по курсу группы и конкретной дате.
  5. Пропускает день, если код активности не разрешает обычные пары.
  6. Загружает правила группы или преподавателя.
  7. Для каждого типа занятия проверяет свою неделю начала в семестре.
  8. Подставляет эффективную сетку времени даты: ручную, субботнюю или базовую.
  9. Считает уже проведённые часы отдельно для лекций, практик и каждой лабораторной подгруппы.
  10. Останавливает вывод слотов конкретного типа, когда достигнут его лимит часов.

Лабораторные работы могут делиться на подгруппы через schedule_rule_slot_subgroups. Если подгруппы выбраны, занятие выводится только для родительских групп этих подгрупп, а лимит лабораторных часов списывается отдельно по каждой подгруппе. Если лабораторная проводится у нескольких групп одновременно, один слот может содержать разные подгруппы разных групп. Лекции и практики не делятся на подгруппы.

Обычные пары генерируются только на коде Т (allow_schedule = true). Экзамены, каникулы, практики, нерабочие дни, праздники * и дни вне учебного года = считаются пропуском: занятие не переносится и не списывает академические часы. Если у группы нет назначения графика на учебный год, GET /api/schedule возвращает пустой список для этой группы без ошибки.

Временные слоты

Сетки времени хранятся в time_slot_scopes, сами пары — в time_slots. Базовая сетка (DEFAULT) применяется по умолчанию, субботняя (WEEKDAY, day_of_week = 6) применяется автоматически по субботам, а пользовательские сетки (MANUAL) применяются только через time_slot_date_assignments на конкретные даты. Ручное назначение выполняется из ячейки редактора календарного графика, потому что оно относится к конкретной учебной дате.

Правило расписания выбирает базовую пару по номеру. При генерации ScheduleGeneratorService сначала проверяет ручное назначение даты, затем автоматическую субботнюю сетку, затем базовую сетку. Если в выбранной сетке нет пары с нужным номером, используется базовый слот. Ручная сетка меняет только время занятий и не включает пары в дни, где календарный учебный график запрещает обычное расписание.

При миграции одинаковые стартовые слоты создаются для базовой и субботней сетки:

Время
1 08:00 09:30
2 09:40 11:10
3 11:40 13:10
4 13:20 14:50
5 15:00 16:30
6 16:50 18:20
7 18:30 20:00

Валидация правил расписания

  • Правило: обязательны дисциплина, семестр, хотя бы один положительный лимит часов по типу занятий, положительные недели начала и хотя бы одна группа.
  • Покрытие типов: если для лекций, лабораторных или практик указан лимит часов, должен быть хотя бы один слот этого типа; слот типа не сохраняется с нулевым лимитом часов.
  • Слот: день недели должен быть от 1 до 7, чётность недели обязательна.
  • Связанные сущности: базовый временной слот, преподаватель, аудитория и тип занятия должны существовать в БД.
  • Подгруппы: subgroupIds разрешены только для лабораторных слотов, должны относиться к группам правила, и в одном слоте можно выбрать не больше одной подгруппы каждой группы.
  • Формат: lessonFormat обязателен и хранится в слоте правила.

Привязка преподаватель ↔ дисциплина

Связь Many-to-Many через таблицу teacher_subjects:

  • Указывается, какие дисциплины может вести конкретный преподаватель
  • Дополнительные поля: qualification_level, experience_years

Дополнительная связь через teacher_lesson_types:

  • Определяет, какие типы занятий (лекция, практика, лаба) может вести преподаватель по конкретной дисциплине

Бизнес-правила (планируемые)

Примечание: Следующие правила описаны в требованиях, но пока не полностью реализованы в коде.

Проверка конфликтов

  • Критический конфликт: Преподаватель не может одновременно находиться в двух разных аудиториях
  • Исключение: Преподаватель может вести несколько пар одновременно (потоковая лекция), если все группы в одной аудитории
  • Вместимость: Суммарная численность всех групп в слоте не должна превышать вместимость аудитории

Управление инцидентами

  • Регистрация отсутствия преподавателя (болезнь, командировка) с указанием периода
  • Автоматическая подсветка конфликтующих пар (Red Zone)
  • Resolution Wizard: предложение замены преподавателя или переноса занятия