# 📋 Бизнес-логика ## Ролевая модель Система поддерживает три роли пользователей: | Роль | 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` | День, чётность, слот, преподаватель, аудитория, тип и формат занятия | Генератор `ScheduleGeneratorService` рендерит расписание по запросу: 1. Определяет семестр для каждой даты диапазона. 2. Вычисляет номер недели и чётность. 3. Находит назначенный группе календарный учебный график на учебный год даты. 4. Определяет код активности по курсу группы и конкретной дате. 5. Пропускает день, если код активности не разрешает обычные пары. 6. Загружает правила группы или преподавателя. 7. Симулирует уже проведённые занятия от `active_from_date`. 8. Останавливает вывод правила, когда достигнут `total_academic_hours`. Обычные пары генерируются только на коде `Т` (`allow_schedule = true`). Экзамены, каникулы, практики, нерабочие дни, праздники `*` и дни вне учебного года `=` считаются пропуском: занятие не переносится и не списывает академические часы. Если у группы нет назначения графика на учебный год, `GET /api/schedule` возвращает пустой список для этой группы без ошибки. ### Временны́е слоты Сетка пар хранится в `time_slots` и настраивается для каждого тенанта. При миграции создаются базовые слоты: | № | Время | |---|-------| | 1 | 08:00 – 09:30 | | 2 | 09:40 – 11:10 | | 3 | 11:40 – 13:10 | | 4 | 13:30 – 15:00 | | 5 | 15:00 – 16:30 | | 6 | 16:40 – 18:10 | | 7 | 18:30 – 20:00 | ### Валидация правил расписания - **Правило:** обязательны дисциплина, семестр, дата начала, положительный лимит академических часов и хотя бы одна группа. - **Слот:** день недели должен быть от 1 до 7, чётность недели обязательна. - **Связанные сущности:** временной слот, преподаватель, аудитория и тип занятия должны существовать в БД. - **Формат:** `lessonFormat` обязателен и хранится в слоте правила. --- ## Привязка преподаватель ↔ дисциплина Связь Many-to-Many через таблицу `teacher_subjects`: - Указывается, какие дисциплины может вести конкретный преподаватель - Дополнительные поля: `qualification_level`, `experience_years` Дополнительная связь через `teacher_lesson_types`: - Определяет, какие **типы занятий** (лекция, практика, лаба) может вести преподаватель по конкретной дисциплине --- ## Бизнес-правила (планируемые) > **Примечание:** Следующие правила описаны в требованиях, но пока не полностью реализованы в коде. ### Проверка конфликтов - **Критический конфликт:** Преподаватель не может одновременно находиться в двух разных аудиториях - **Исключение:** Преподаватель может вести несколько пар одновременно (потоковая лекция), если все группы в одной аудитории - **Вместимость:** Суммарная численность всех групп в слоте не должна превышать вместимость аудитории ### Управление инцидентами - Регистрация отсутствия преподавателя (болезнь, командировка) с указанием периода - Автоматическая подсветка конфликтующих пар (Red Zone) - Resolution Wizard: предложение замены преподавателя или переноса занятия