1 Задача
This commit is contained in:
71
docs/API.md
71
docs/API.md
@@ -841,6 +841,77 @@ API возвращает `409 Conflict`; соседние интервалы и
|
||||
}
|
||||
```
|
||||
|
||||
### Отсутствия преподавателей и мастер замены
|
||||
|
||||
| Метод | URL | Назначение |
|
||||
|-------|-----|------------|
|
||||
| `GET` | `/api/teacher-absences?status=` | Доступный текущей роли реестр отсутствий |
|
||||
| `POST` | `/api/teacher-absences` | Зарегистрировать отсутствие или отправить преподавательскую заявку |
|
||||
| `POST` | `/api/teacher-absences/{id}/review` | Подтвердить или отклонить заявку преподавателя |
|
||||
| `DELETE` | `/api/teacher-absences/{id}` | Отменить ожидающее или ещё не обработанное отсутствие |
|
||||
| `GET` | `/api/teacher-absences/{id}/wizard` | Затронутые занятия, проверенные кандидаты и журнал решений |
|
||||
| `POST` | `/api/teacher-absences/{id}/resolve` | Атомарно применить выбранные решения |
|
||||
|
||||
Доступ имеют `ADMIN`, `EDUCATION_OFFICE`, `DEPARTMENT` и `TEACHER`. Преподаватель видит и
|
||||
создаёт только собственные заявки; они получают статус `PENDING`. Кафедра работает только с
|
||||
преподавателями, назначенными ей на период отсутствия. Ответственный сотрудник создаёт
|
||||
сразу согласованную запись `APPROVED`, а кафедра, учебный отдел или администратор могут
|
||||
перевести преподавательскую заявку в `APPROVED` либо `REJECTED`.
|
||||
|
||||
```json
|
||||
{
|
||||
"teacherId": 15,
|
||||
"startDate": "2026-09-10",
|
||||
"endDate": "2026-09-12",
|
||||
"reason": "Командировка"
|
||||
}
|
||||
```
|
||||
|
||||
Для роли `TEACHER` поле `teacherId` игнорируется в пользу ID текущего пользователя. Период
|
||||
включительный, не длиннее 120 дней и не может пересекаться с другой активной записью того
|
||||
же преподавателя.
|
||||
|
||||
`GET /{id}/wizard` ищет фактические занятия через `ScheduleQueryService`. Кандидат на замену
|
||||
должен иметь связь с дисциплиной; если для этой связи настроены `teacher_lesson_types`, тип
|
||||
занятия также обязан совпасть. Из списка исключаются архивные, занятые и отсутствующие
|
||||
преподаватели. Варианты переноса выбираются среди ближайших учебных дат вне периода
|
||||
отсутствия, аудитории — среди активных и свободных. Каждый кандидат заранее проходит тот же
|
||||
валидатор `ScheduleOverrideService`, что и обычная разовая правка.
|
||||
|
||||
Пример группового подтверждения:
|
||||
|
||||
```json
|
||||
{
|
||||
"decisions": [
|
||||
{
|
||||
"baseRuleSlotId": 31,
|
||||
"lessonDate": "2026-09-10",
|
||||
"resolution": "REPLACE_TEACHER",
|
||||
"newTeacherId": 28,
|
||||
"comment": "Согласовано кафедрой"
|
||||
},
|
||||
{
|
||||
"baseRuleSlotId": 44,
|
||||
"lessonDate": "2026-09-11",
|
||||
"resolution": "MOVE_TIME",
|
||||
"targetLessonDate": "2026-09-14",
|
||||
"newTimeSlotId": 3
|
||||
},
|
||||
{
|
||||
"baseRuleSlotId": 52,
|
||||
"lessonDate": "2026-09-12",
|
||||
"resolution": "REJECT"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Допустимые решения: `REPLACE_TEACHER`, `MOVE_TIME`, `CHANGE_CLASSROOM`, `CANCEL`, `REJECT`.
|
||||
Первые четыре создают обычный `schedule_override`; `REJECT` фиксирует осознанное отклонение
|
||||
без изменения расписания. Весь пакет выполняется в одной транзакции: конфликт любого
|
||||
выбранного действия возвращает `409` и откатывает остальные. Незаполненные занятия не
|
||||
меняются. Когда обработаны все оставшиеся занятия, отсутствие получает статус `RESOLVED`.
|
||||
|
||||
## Загруженность
|
||||
|
||||
| Метод | URL | Назначение |
|
||||
|
||||
@@ -312,6 +312,35 @@ constraint. При чтении API разворачивает периоды о
|
||||
для backend-pod, поэтому два конкурентных переноса с разных исходных дат на одну целевую
|
||||
дату и одинаковые ресурсы проверяются последовательно.
|
||||
|
||||
### Отсутствия преподавателей и мастер замены
|
||||
|
||||
Отсутствие хранится отдельно от базовых правил расписания и проходит жизненный цикл
|
||||
`PENDING → APPROVED → RESOLVED`; отклонённые и отменённые записи получают соответственно
|
||||
`REJECTED` и `CANCELLED`. Преподаватель создаёт заявку только для себя со статусом
|
||||
`PENDING`. Администратор, учебный отдел и кафедра могут регистрировать согласованное
|
||||
отсутствие сразу. Кафедра видит и подтверждает только преподавателей, назначенных ей на
|
||||
выбранный период через `teacher_department_assignments`.
|
||||
|
||||
Для согласованного отсутствия `ScheduleQueryService` строит фактические занятия
|
||||
преподавателя в пределах периода. Мастер предлагает не более пяти проверенных вариантов
|
||||
каждого типа:
|
||||
|
||||
- преподавателей со связью по дисциплине и допустимому типу занятия;
|
||||
- ближайшие учебные даты вне периода отсутствия и эффективные временные слоты;
|
||||
- активные свободные аудитории;
|
||||
- отмену занятия или явное отклонение предложений.
|
||||
|
||||
Если у связи преподавателя с дисциплиной нет настроенных строк `teacher_lesson_types`, она
|
||||
считается разрешающей все типы; при наличии настроек требуется точное совпадение типа.
|
||||
Кандидаты-замены исключаются, если архивированы, заняты или сами отсутствуют в дату пары.
|
||||
Каждый вариант до показа проходит read-only проверку `ScheduleOverrideService`, а выбранный
|
||||
пакет повторно валидируется и сохраняется в одной транзакции. Поэтому время, аудитория,
|
||||
группы и подгруппы проверяются тем же механизмом, что и ручные точечные изменения.
|
||||
|
||||
Применённые действия создают обычные `schedule_overrides`; базовое правило семестра не
|
||||
изменяется. Таблица `teacher_absence_decisions` фиксирует как применённые, так и отклонённые
|
||||
решения. Незаполненные строки мастер не меняет, и к ним можно вернуться позже.
|
||||
|
||||
---
|
||||
|
||||
## Привязка преподаватель ↔ дисциплина
|
||||
@@ -335,6 +364,9 @@ constraint. При чтении API разворачивает периоды о
|
||||
- **Вместимость:** Суммарная численность всех групп в слоте не должна превышать вместимость аудитории
|
||||
|
||||
### Управление инцидентами
|
||||
- Регистрация отсутствия преподавателя (болезнь, командировка) с указанием периода
|
||||
- Автоматическая подсветка конфликтующих пар (Red Zone)
|
||||
- Resolution Wizard: предложение замены преподавателя или переноса занятия
|
||||
|
||||
Регистрация отсутствий и Resolution Wizard реализованы. Дальнейшее развитие этого контура:
|
||||
|
||||
- автоматическая рассылка уведомлений группам и преподавателям;
|
||||
- пакетная обработка нескольких одновременных отсутствий;
|
||||
- ранжирование вариантов по окнам и дополнительной нагрузке.
|
||||
|
||||
@@ -334,6 +334,34 @@ erDiagram
|
||||
TEXT comment
|
||||
}
|
||||
|
||||
teacher_absences {
|
||||
BIGSERIAL id PK
|
||||
BIGINT teacher_id FK
|
||||
DATE start_date
|
||||
DATE end_date
|
||||
TEXT reason
|
||||
VARCHAR status
|
||||
BIGINT requested_by FK
|
||||
BIGINT reviewed_by FK
|
||||
TEXT review_comment
|
||||
TIMESTAMPTZ reviewed_at
|
||||
TIMESTAMPTZ created_at
|
||||
TIMESTAMPTZ updated_at
|
||||
}
|
||||
|
||||
teacher_absence_decisions {
|
||||
BIGSERIAL id PK
|
||||
BIGINT absence_id FK
|
||||
BIGINT base_rule_slot_id FK
|
||||
DATE lesson_date
|
||||
VARCHAR resolution
|
||||
VARCHAR decision_status
|
||||
BIGINT schedule_override_id FK
|
||||
TEXT comment
|
||||
BIGINT decided_by FK
|
||||
TIMESTAMPTZ decided_at
|
||||
}
|
||||
|
||||
schedule_rule_slot_subgroups {
|
||||
BIGINT schedule_rule_slot_id FK,PK
|
||||
BIGINT subgroup_id FK,PK
|
||||
@@ -385,6 +413,11 @@ erDiagram
|
||||
time_slots ||--o{ schedule_overrides : "new_time_slot_id"
|
||||
classrooms ||--o{ schedule_overrides : "new_classroom_id"
|
||||
users ||--o{ schedule_overrides : "new_teacher_id"
|
||||
users ||--o{ teacher_absences : "teacher_id/requested_by/reviewed_by"
|
||||
teacher_absences ||--o{ teacher_absence_decisions : "absence_id"
|
||||
schedule_rule_slots ||--o{ teacher_absence_decisions : "base_rule_slot_id"
|
||||
schedule_overrides ||--o{ teacher_absence_decisions : "schedule_override_id"
|
||||
users ||--o{ teacher_absence_decisions : "decided_by"
|
||||
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"
|
||||
@@ -905,6 +938,44 @@ V1 добавляет `uq_schedule_rule_slots_exact_payload`: в одном пр
|
||||
lifecycle ресурсов, эффективная сетка целевого дня, реальность изменения и ресурсные
|
||||
конфликты проверяются транзакционным сервисом, а не SQL CHECK.
|
||||
|
||||
#### `teacher_absences` — Отсутствия преподавателей
|
||||
|
||||
| Колонка | Тип | Описание |
|
||||
|---------|-----|----------|
|
||||
| `id` | BIGSERIAL PK | ID отсутствия |
|
||||
| `teacher_id` | BIGINT FK → users | Отсутствующий преподаватель |
|
||||
| `start_date`, `end_date` | DATE | Включительные границы периода |
|
||||
| `reason` | TEXT | Причина длиной 1–2000 символов |
|
||||
| `status` | VARCHAR(20) | `PENDING`, `APPROVED`, `REJECTED`, `RESOLVED`, `CANCELLED` |
|
||||
| `requested_by` | BIGINT FK → users | Автор регистрации или заявки |
|
||||
| `reviewed_by` | BIGINT FK → users | Подтвердивший или отклонивший сотрудник |
|
||||
| `review_comment` | TEXT | Комментарий согласования |
|
||||
| `reviewed_at` | TIMESTAMPTZ | Время согласования |
|
||||
| `created_at`, `updated_at` | TIMESTAMPTZ | Аудит жизненного цикла |
|
||||
|
||||
CHECK запрещает обратный период, пустую или слишком длинную причину и неизвестный статус.
|
||||
Индекс `(teacher_id, start_date, end_date)` ускоряет поиск пересекающихся отсутствий и
|
||||
проверку кандидатов мастера.
|
||||
|
||||
#### `teacher_absence_decisions` — Журнал мастера замены
|
||||
|
||||
| Колонка | Тип | Описание |
|
||||
|---------|-----|----------|
|
||||
| `id` | BIGSERIAL PK | ID записи журнала |
|
||||
| `absence_id` | BIGINT FK → teacher_absences | Инцидент отсутствия |
|
||||
| `base_rule_slot_id` | BIGINT FK → schedule_rule_slots | Базовый слот занятия |
|
||||
| `lesson_date` | DATE | Исходная дата занятия |
|
||||
| `resolution` | VARCHAR(30) | Замена, перенос, аудитория, отмена или отклонение |
|
||||
| `decision_status` | VARCHAR(20) | `APPLIED` либо `REJECTED` |
|
||||
| `schedule_override_id` | BIGINT FK → schedule_overrides | Созданная разовая правка, если есть |
|
||||
| `comment` | TEXT | Комментарий ответственного сотрудника |
|
||||
| `decided_by` | BIGINT FK → users | Автор решения |
|
||||
| `decided_at` | TIMESTAMPTZ | Время решения |
|
||||
|
||||
Уникальность `(absence_id, base_rule_slot_id, lesson_date)` не позволяет повторно обработать
|
||||
одно занятие одного инцидента. При удалении override ссылка обнуляется, но аудиторская запись
|
||||
сохраняется.
|
||||
|
||||
---
|
||||
|
||||
## Flyway миграции
|
||||
@@ -924,12 +995,15 @@ lifecycle ресурсов, эффективная сетка целевого
|
||||
| Файл | Описание |
|
||||
|------|----------|
|
||||
| `V1__init.sql` | Полная baseline-схема: справочники, роли, refresh-сессии JWT, PostgreSQL rate limit и аудит входа, lifecycle-поля, история кафедр, календарные графики с интервальным хранением активностей и нумерацией недель `понедельник–воскресенье`, динамическое расписание, точечные изменения с переносом даты, seed, CHECK/UNIQUE/GiST-ограничения, конкурентно безопасные триггеры и комментарии |
|
||||
| `V2__teacher_absences_and_replacement_wizard.sql` | Реестр отсутствий преподавателей, статусы согласования и журнал применённых/отклонённых решений со ссылками на обычные `schedule_overrides` |
|
||||
|
||||
### Этап разработки
|
||||
|
||||
По прямому решению владельца проекта разработческие миграции V2–V7 объединены в baseline
|
||||
`V1`. Интервальное хранение активностей и правильная нумерация недель календарного графика
|
||||
также входят непосредственно в V1.
|
||||
Исторические разработческие миграции V2–V7 по прямому решению владельца проекта были
|
||||
объединены в baseline `V1`. После фиксации baseline нумерация начата заново: текущая `V2`
|
||||
добавляет отсутствия и мастер замены, не изменяя контрольную сумму `V1`.
|
||||
Интервальное хранение активностей и правильная нумерация недель календарного графика входят
|
||||
непосредственно в V1.
|
||||
Перед применением этой редакции требуется полностью пустая tenant-схема.
|
||||
|
||||
### Полный сброс БД (локально)
|
||||
|
||||
@@ -53,6 +53,10 @@
|
||||
|
||||
## 1. Отсутствия преподавателей и мастер замены
|
||||
|
||||
**Статус: реализовано в MVP.** Реестр, согласование преподавательских заявок, поиск
|
||||
затронутых занятий, проверенные варианты, групповое применение `schedule_overrides` и журнал
|
||||
решений доступны в системе.
|
||||
|
||||
### Проблема и пользователи
|
||||
|
||||
Болезнь, командировка или другое временное отсутствие преподавателя затрагивает сразу
|
||||
@@ -60,9 +64,8 @@
|
||||
доступность ресурсов и создать каждое точечное изменение. Функция нужна учебному отделу,
|
||||
кафедрам и преподавателям.
|
||||
|
||||
Регистрация отсутствий и мастер разрешения инцидентов уже обозначены как планируемые
|
||||
бизнес-правила в [BUSINESS_LOGIC.md](BUSINESS_LOGIC.md), но отдельной модели и рабочего
|
||||
сценария пока нет. Существующая Red Zone уже выявляет конфликты сформированного расписания;
|
||||
Регистрация отсутствий и мастер разрешения инцидентов реализуют правила из
|
||||
[BUSINESS_LOGIC.md](BUSINESS_LOGIC.md). Существующая Red Zone уже выявляет конфликты сформированного расписания;
|
||||
новизна этого направления заключается в реестре причин, массовом поиске затронутых занятий
|
||||
и управляемом подборе решений.
|
||||
|
||||
@@ -504,4 +507,4 @@ Red Zone уже выявляет накладки и превышение вме
|
||||
|
||||
**Ожидаемый результат:** новый самостоятельный контур учебного процесса на основе уже
|
||||
существующих справочников и календаря. **Сложность:** L. **Демонстрационный эффект:**
|
||||
максимальный.
|
||||
максимальный.
|
||||
|
||||
@@ -34,6 +34,7 @@ frontend/
|
||||
│ ├── dashboard-conflicts.test.mjs # Регрессии дат и состояний проверки конфликтов
|
||||
│ ├── schedule-overrides.test.mjs # Действия, роли, недельный выбор и подбор времени разовой правки
|
||||
│ ├── schedule-view-semesters.test.mjs # Выбор семестра и расчёт двухнедельного диапазона просмотра
|
||||
│ ├── teacher-absences.test.mjs # Payload мастера замены и доступность вкладки по ролям
|
||||
│ └── security-policy.test.mjs # Web Storage, XSS, пароли, язык, CSP и Dockerfile
|
||||
├── index.html # 🔐 Страница авторизации (общая)
|
||||
├── script.js # Логика авторизации
|
||||
@@ -49,7 +50,8 @@ frontend/
|
||||
│ │ ├── components.css # Кнопки, таблицы, карточки, формы
|
||||
│ │ ├── modals.css # Модальные окна
|
||||
│ │ ├── auditorium-workload.css # Таблицы расписаний и загруженности
|
||||
│ │ └── departments-data.css # Стили создания кафедры/специальности
|
||||
│ │ ├── departments-data.css # Стили создания кафедры/специальности
|
||||
│ │ └── teacher-absences.css # Реестр инцидентов и полноэкранный мастер замены
|
||||
│ ├── js/
|
||||
│ │ ├── main.js # Инициализация, маршрутизация, навигация
|
||||
│ │ ├── role-capabilities.js # Единая матрица вкладок admin/settings по ролям
|
||||
@@ -68,6 +70,7 @@ frontend/
|
||||
│ │ ├── department-workspace.js # Кабинет кафедры в общей панели
|
||||
│ │ ├── schedule-view.js # Просмотр расписаний и запуск разовой правки из карточки
|
||||
│ │ ├── schedule-override-panel.js # Боковая панель и реестр разовых изменений
|
||||
│ │ ├── teacher-absences.js # Реестр, согласование и групповой мастер замены
|
||||
│ │ ├── schedule.js # Конструктор правил расписания
|
||||
│ │ ├── academic-calendar-grid.js # Расчёт ISO-недели дневной сетки
|
||||
│ │ ├── academic-calendar-title.js # Название из кода, профиля, формы и года
|
||||
@@ -83,6 +86,7 @@ frontend/
|
||||
│ │ ├── university-structure.html
|
||||
│ │ ├── department-workspace.html
|
||||
│ │ ├── schedule-view.html
|
||||
│ │ ├── teacher-absences.html
|
||||
│ │ ├── schedule.html
|
||||
│ │ ├── academic-calendar.html
|
||||
│ │ └── auditorium-workload.html
|
||||
@@ -142,8 +146,8 @@ frontend/
|
||||
| Роль | Доступные вкладки |
|
||||
|------|-------------------|
|
||||
| `ADMIN` | Все вкладки |
|
||||
| `EDUCATION_OFFICE` | Просмотр расписаний, конструктор расписания, календарный график, загруженность и аудитории; в settings — временные слоты и формы обучения |
|
||||
| `DEPARTMENT` | Кабинет кафедры, просмотр расписаний |
|
||||
| `EDUCATION_OFFICE` | Просмотр и конструктор расписаний, отсутствия и замены, календарный график, загруженность и аудитории; в settings — временные слоты и формы обучения |
|
||||
| `DEPARTMENT` | Кабинет кафедры, просмотр расписаний, отсутствия и подтверждение заявок своих преподавателей |
|
||||
| `SCHEDULE_VIEWER` | Только просмотр расписаний |
|
||||
|
||||
Пути `/department/` и `/edu-office/` оставлены как входные redirect-страницы в общую панель. Отдельные кабинеты не дублируют UI админ-панели.
|
||||
@@ -166,6 +170,7 @@ frontend/
|
||||
| `university-structure` | Кафедры, специальности и профили обучения; профили доступны отдельной внутренней вкладкой и через кнопку специальности | `/api/departments`, `/api/specialties`, `/api/specialties/{id}/profiles` |
|
||||
| `department-workspace` | Кабинет кафедры: дисциплины, импорт, комментарии, преподаватели, привязка преподавателей, заявки на новых преподавателей и нагрузка | `/api/department/*`, `/api/department/teacher-requests`, `/api/workload/teachers` |
|
||||
| `schedule-view` | Просмотр расписаний: семестр выбирается в дополнительных фильтрах, для учебного периода строится двухнедельный диапазон, найденные расписания выбираются в переключателе, а `ADMIN` и `EDUCATION_OFFICE` редактируют конкретное занятие в боковой панели без изменения правила | `/api/schedule/semesters`, `/api/schedule/search`, `/api/edu-office/schedule/overrides`, `/api/admin/time-slots/effective` |
|
||||
| `teacher-absences` | Реестр отсутствий, подтверждение преподавательских заявок, проверенные варианты замен/переносов и журнал решений | `/api/teacher-absences`, `/api/users/teachers` |
|
||||
| `schedule` | Конструктор правил динамического расписания с выезжающей визуальной матрицей групп по дням и времени | `/api/admin/schedule-rules`, `/api/admin/time-slots`, `/api/admin/calendar/years`, `/api/lesson-types`, `/api/subgroups` |
|
||||
| `academic-calendar` | Учебные годы, семестры, создание календарных графиков, Excel-подобный редактор дневной сетки и привязка дисциплин к семестрам графика | `/api/admin/calendar`, `/api/admin/academic-calendars`, `/api/admin/academic-calendars/{id}/subjects`, `/api/admin/calendar/activity-types`, `/api/specialties`, `/api/specialties/{id}/profiles`, `/api/education-forms`, `/api/subjects` |
|
||||
| `auditorium-workload` | Динамическая загруженность аудиторий, преподавателей и кафедр: сводная матрица по дате или совмещённая таблица выбранной сущности по чётной/нечётной неделе | `/api/classrooms`, `/api/users/teachers`, `/api/departments`, `/api/admin/time-slots`, `/api/equipments`, `/api/groups`, `/api/schedule`, `/api/admin/calendar/years` |
|
||||
@@ -181,6 +186,11 @@ frontend/
|
||||
- Вкладка `teacher-requests` показывает pending-заявки кафедр на создание преподавателей. Администратор может скорректировать кафедру, логин, ФИО и должность, задать пароль минимум 8 символов в скрытом поле с `autocomplete="new-password"`, затем одобрить заявку через `/api/teacher-requests/{id}/approve` или отклонить её через `/api/teacher-requests/{id}/reject`. Для роли `ADMIN` счётчик pending-заявок выводится в пункте меню «Заявки» и рядом с заголовком страницы, чтобы очередь была видна без открытия вкладки.
|
||||
- Вкладка `department-workspace` в блоке преподавателей объединяет данные `/api/department/teachers` и `/api/workload/teachers`: каждый преподаватель показывается одной карточкой с должностью и нагрузкой за выбранный период, преподаватели без занятий получают нулевую нагрузку, а преподаватели из расписания добавляются без дублей. Если дата начала периода выбрана позже даты окончания, поле окончания очищается, а расчёт нагрузки ждёт корректный период.
|
||||
- Вкладка `department-workspace` позволяет кафедре добавить существующего активного преподавателя на свою кафедру через `/api/department/teachers/{teacherId}/assignments`, отправить заявку на нового преподавателя через `/api/department/teacher-requests` и видеть статусы собственных заявок в таблице.
|
||||
- Вкладка `teacher-absences` доступна администратору, учебному отделу и кафедре. Верхний
|
||||
командный блок показывает очередь инцидентов, форма регистрирует преподавателя, период и
|
||||
причину, а реестр разделяет статусы согласования. Полноэкранный мастер выводит каждое
|
||||
затронутое занятие отдельной строкой и предлагает только кандидатов, уже проверенных
|
||||
backend. Пустая строка не отправляется; выбранные решения применяются одним пакетом.
|
||||
- Компоновка `department-workspace` использует собственные CSS-сетки `department-workspace-filter-grid` и `department-workspace-actions-grid`: фильтры периода отделены от сеток расписания, загрузка дисциплин занимает широкую колонку, формы преподавателей выравниваются справа, а списки и таблицы идут полноширинными блоками ниже.
|
||||
- Вкладка `schedule-view` показывает найденные занятия в режиме одной активной таблицы. Пользователь выбирает, что смотреть: группу, преподавателя, аудиторию или кафедру; основная кнопка `Показать` расположена в заголовке блока параметров, а пустое состояние таблицы с подсказкой об обновлении содержит дополнительную кнопку `Показать расписание`. В дополнительных фильтрах доступен семестр из справочника `/api/schedule/semesters`, предназначенного только для чтения. Для текущего семестра сохраняется текущая двухнедельная точка просмотра, а при выборе другого семестра диапазон начинается с понедельника его первой недели. Frontend запрашивает две недели и собирает найденные расписания в переключатель результатов. На странице не выводится стек таблиц: виден один выбранный результат, а остальные доступны через чипы и кнопки предыдущего/следующего расписания; чипы результатов переносятся и отделены от счётчика стабильным отступом. Для режима кафедры и роли `DEPARTMENT` расписание ограничивается кафедрой пользователя; преподавательские и студенческие отдельные страницы пока остаются самостоятельными. Таблица строится как строки пар и столбцы дней недели. Нечётная неделя отображается в верхней половине ячейки, чётная — в нижней, а одинаковые занятия в обе недели схлопываются в цельную ячейку. Бейдж диапазона недель скрывается для занятий на весь семестр, а для занятий до конца семестра показывает только неделю начала в формате `(с 5 нед.)`. На мобильной ширине вместо широкой недельной матрицы показывается один день активного расписания с переключателем дней.
|
||||
- Для `ADMIN` и `EDUCATION_OFFICE` карточка занятия содержит кнопку `Изменить`, а уже изменённая пара — индикатор разовой правки. Справа открывается полупрозрачная боковая панель с размытием содержимого под ней; внешний затемнённый слой также размывает страницу, а на мобильном устройстве панель занимает весь экран. Режим `Редактирование` сравнивает `Было по правилу / Станет`, позволяет изменить дату, эффективный временной слот, преподавателя, аудиторию, формат и комментарий, отменить занятие или удалить override через `Вернуть по правилу`. Селект аудитории получает записи из `/api/classrooms`, но показывает только поле `name`, без корпуса и этажа. По умолчанию выводятся семь дней исходной недели; кнопка `Выбрать другую дату` раскрывает календарь всего семестра, где неучебные даты отключены. После смены даты загружается эффективная сетка дня: сначала выбирается тот же ID слота, затем совпадающий интервал, иначе требуется ручной выбор. Дата или время формируют `MOVE`, а только преподаватель, аудитория или формат — `REPLACE`.
|
||||
@@ -325,6 +335,9 @@ if (!session || !AUTHORIZED_ROLES.includes(session.role)) {
|
||||
- выбор даты через `input[type="date"]`;
|
||||
- запрос `GET /api/schedule?teacherId={userId}&startDate={YYYY-MM-DD}&endDate={YYYY-MM-DD}`;
|
||||
- отображение дисциплины, времени, типа занятия, лабораторных подгрупп, аудитории и всех групп правила.
|
||||
- форма собственной заявки на отсутствие через `POST /api/teacher-absences`;
|
||||
- список статусов заявок и отмена ещё не подтверждённой записи через
|
||||
`DELETE /api/teacher-absences/{id}`.
|
||||
|
||||
Если refresh-cookie недействительна или роль не `TEACHER`, страница возвращает пользователя на вход.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user