Files
magistr/docs/BUSINESS_LOGIC.md

148 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 📋 Бизнес-логика
## Ролевая модель
Система поддерживает три роли пользователей:
| Роль | 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: предложение замены преподавателя или переноса занятия