141 lines
8.4 KiB
Markdown
141 lines
8.4 KiB
Markdown
# 📋 Бизнес-логика
|
||
|
||
## Ролевая модель
|
||
|
||
Система поддерживает три роли пользователей:
|
||
|
||
| Роль | 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` |
|
||
| `holidays` | Даты, когда занятия не проводятся и часы не списываются |
|
||
| `academic_calendar_matrix` | Тип недели для курса и специальности: теория, сессия, каникулы, практика |
|
||
| `time_slots` | Настраиваемая сетка пар для тенанта |
|
||
| `schedule_rules` | Лимит часов дисциплины в семестре |
|
||
| `schedule_rule_groups` | Группы правила, включая потоковые лекции |
|
||
| `schedule_rule_slots` | День, чётность, слот, преподаватель, аудитория, тип и формат занятия |
|
||
|
||
Генератор `ScheduleGeneratorService` рендерит расписание по запросу:
|
||
1. Определяет семестр для каждой даты диапазона.
|
||
2. Вычисляет номер недели и чётность.
|
||
3. Проверяет праздники и матрицу учебного графика.
|
||
4. Загружает правила группы или преподавателя.
|
||
5. Симулирует уже проведённые занятия от `active_from_date`.
|
||
6. Останавливает вывод правила, когда достигнут `total_academic_hours`.
|
||
|
||
Праздник считается пропуском: занятие не переносится и не списывает академические часы.
|
||
|
||
### Временны́е слоты
|
||
|
||
Сетка пар хранится в `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: предложение замены преподавателя или переноса занятия
|