сделал настройку временных слотов
This commit is contained in:
38
docs/API.md
38
docs/API.md
@@ -116,7 +116,7 @@
|
||||
| `startDate` | Да | Начало периода в формате `YYYY-MM-DD` |
|
||||
| `endDate` | Да | Конец периода в формате `YYYY-MM-DD` |
|
||||
|
||||
Передаётся ровно один параметр: `groupId` или `teacherId`. Максимальный диапазон — 120 дней. Если у группы нет назначения календарного графика на учебный год даты, расписание для неё возвращается пустым списком.
|
||||
Передаётся ровно один параметр: `groupId` или `teacherId`. Максимальный диапазон — 120 дней. Если у группы нет назначения календарного графика на учебный год даты, расписание для неё возвращается пустым списком. Время пары берётся из базового слота правила, но для конкретной даты может быть заменено субботней или ручной сеткой времени из `/api/admin/time-slots`.
|
||||
|
||||
**Пример:**
|
||||
```http
|
||||
@@ -160,25 +160,51 @@ GET /api/schedule?groupId=1&startDate=2026-04-27&endDate=2026-05-03
|
||||
|
||||
### `GET /api/admin/time-slots`
|
||||
|
||||
Список временных слотов занятий. CRUD доступен по:
|
||||
Список временных слотов занятий. Слот принадлежит конкретной сетке времени: базовой, автоматической субботней или ручной.
|
||||
|
||||
| Метод | URL | Назначение |
|
||||
|-------|-----|------------|
|
||||
| `GET` | `/api/admin/time-slots` | Список слотов |
|
||||
| `GET` | `/api/admin/time-slots/effective?date=2026-05-02` | Эффективные слоты для даты |
|
||||
| `POST` | `/api/admin/time-slots` | Создать слот |
|
||||
| `PUT` | `/api/admin/time-slots/{id}` | Обновить слот |
|
||||
| `DELETE` | `/api/admin/time-slots/{id}` | Удалить слот |
|
||||
| `GET` | `/api/admin/time-slots/scopes` | Список сеток времени |
|
||||
| `POST` | `/api/admin/time-slots/scopes` | Создать ручную сетку |
|
||||
| `PUT` | `/api/admin/time-slots/scopes/{id}` | Переименовать ручную сетку |
|
||||
| `DELETE` | `/api/admin/time-slots/scopes/{id}` | Удалить ручную сетку |
|
||||
| `GET` | `/api/admin/time-slots/date-assignments` | Ручные назначения дат |
|
||||
| `POST` | `/api/admin/time-slots/date-assignments` | Применить ручную сетку к дате |
|
||||
| `DELETE` | `/api/admin/time-slots/date-assignments/{id}` | Убрать ручное назначение |
|
||||
|
||||
**Тело создания/обновления:**
|
||||
```json
|
||||
{
|
||||
"orderNumber": 1,
|
||||
"scopeId": 1,
|
||||
"startTime": "08:00:00",
|
||||
"endTime": "09:30:00",
|
||||
"durationMinutes": 90
|
||||
}
|
||||
```
|
||||
|
||||
**Создание ручной сетки:**
|
||||
```json
|
||||
{
|
||||
"name": "Праздничная сетка"
|
||||
}
|
||||
```
|
||||
|
||||
**Ручное применение сетки к дате:**
|
||||
```json
|
||||
{
|
||||
"date": "2026-05-08",
|
||||
"scopeId": 3
|
||||
}
|
||||
```
|
||||
|
||||
Базовая сетка применяется по умолчанию. Субботняя сетка применяется автоматически по субботам. Ручные сетки применяются только на датах из `date-assignments` и имеют приоритет над автоматической субботней сеткой. В правилах расписания выбираются только базовые слоты; эффективное время пары подставляется при генерации.
|
||||
|
||||
### Учебные годы, семестры и коды календарного графика
|
||||
|
||||
| Метод | URL | Назначение |
|
||||
@@ -281,6 +307,8 @@ CRUD доступен по:
|
||||
| `PUT` | `/api/admin/schedule-rules/{id}` | Обновить правило |
|
||||
| `DELETE` | `/api/admin/schedule-rules/{id}` | Удалить правило |
|
||||
|
||||
`timeSlotId` должен ссылаться на базовый слот (`scopeApplyMode = DEFAULT`). Субботняя и ручные сетки не выбираются в правиле напрямую.
|
||||
|
||||
### `GET /api/lesson-types`
|
||||
|
||||
Справочник типов занятий для конструктора правил расписания.
|
||||
@@ -436,7 +464,7 @@ CRUD доступен по:
|
||||
}
|
||||
```
|
||||
|
||||
Назначаемый график должен относиться к тому же учебному году, специальности и профилю, что и группа.
|
||||
Назначаемый график должен относиться к тому же учебному году, специальности, профилю и форме обучения, что и группа.
|
||||
|
||||
---
|
||||
|
||||
@@ -453,6 +481,8 @@ CRUD доступен по:
|
||||
"id": 1,
|
||||
"name": "101 Ленинская",
|
||||
"capacity": 120,
|
||||
"building": "Главный корпус",
|
||||
"floor": 2,
|
||||
"isAvailable": true,
|
||||
"equipments": [
|
||||
{ "id": 1, "name": "Проектор" },
|
||||
@@ -470,6 +500,8 @@ CRUD доступен по:
|
||||
{
|
||||
"name": "404 Лаборатория",
|
||||
"capacity": 30,
|
||||
"building": "Лабораторный корпус",
|
||||
"floor": 4,
|
||||
"isAvailable": true,
|
||||
"equipmentIds": [1, 2, 3]
|
||||
}
|
||||
|
||||
@@ -94,29 +94,34 @@
|
||||
5. Пропускает день, если код активности не разрешает обычные пары.
|
||||
6. Загружает правила группы или преподавателя.
|
||||
7. Симулирует уже проведённые занятия от `active_from_date`.
|
||||
8. Останавливает вывод правила, когда достигнут `total_academic_hours`.
|
||||
8. Подставляет эффективную сетку времени даты: ручную, субботнюю или базовую.
|
||||
9. Останавливает вывод правила, когда достигнут `total_academic_hours`.
|
||||
|
||||
Обычные пары генерируются только на коде `Т` (`allow_schedule = true`). Экзамены, каникулы, практики, нерабочие дни, праздники `*` и дни вне учебного года `=` считаются пропуском: занятие не переносится и не списывает академические часы. Если у группы нет назначения графика на учебный год, `GET /api/schedule` возвращает пустой список для этой группы без ошибки.
|
||||
|
||||
### Временны́е слоты
|
||||
### Временные слоты
|
||||
|
||||
Сетка пар хранится в `time_slots` и настраивается для каждого тенанта. При миграции создаются базовые слоты:
|
||||
Сетки времени хранятся в `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:30 – 15:00 |
|
||||
| 4 | 13:20 – 14:50 |
|
||||
| 5 | 15:00 – 16:30 |
|
||||
| 6 | 16:40 – 18:10 |
|
||||
| 6 | 16:50 – 18:20 |
|
||||
| 7 | 18:30 – 20:00 |
|
||||
|
||||
### Валидация правил расписания
|
||||
|
||||
- **Правило:** обязательны дисциплина, семестр, дата начала, положительный лимит академических часов и хотя бы одна группа.
|
||||
- **Слот:** день недели должен быть от 1 до 7, чётность недели обязательна.
|
||||
- **Связанные сущности:** временной слот, преподаватель, аудитория и тип занятия должны существовать в БД.
|
||||
- **Связанные сущности:** базовый временной слот, преподаватель, аудитория и тип занятия должны существовать в БД.
|
||||
- **Формат:** `lessonFormat` обязателен и хранится в слоте правила.
|
||||
|
||||
---
|
||||
|
||||
@@ -19,7 +19,7 @@ erDiagram
|
||||
VARCHAR name
|
||||
BIGINT code UK
|
||||
}
|
||||
|
||||
|
||||
specialties {
|
||||
BIGSERIAL id PK
|
||||
VARCHAR name
|
||||
@@ -125,14 +125,31 @@ erDiagram
|
||||
BIGINT lesson_type_id FK,PK
|
||||
}
|
||||
|
||||
time_slot_scopes {
|
||||
BIGSERIAL id PK
|
||||
VARCHAR code UK
|
||||
VARCHAR name
|
||||
VARCHAR apply_mode
|
||||
INT day_of_week
|
||||
BOOLEAN system_scope
|
||||
INT display_order
|
||||
}
|
||||
|
||||
time_slots {
|
||||
BIGSERIAL id PK
|
||||
INT order_number UK
|
||||
BIGINT time_slot_scope_id FK
|
||||
INT order_number
|
||||
TIME start_time
|
||||
TIME end_time
|
||||
INT duration_minutes
|
||||
}
|
||||
|
||||
time_slot_date_assignments {
|
||||
BIGSERIAL id PK
|
||||
DATE assignment_date UK
|
||||
BIGINT time_slot_scope_id FK
|
||||
}
|
||||
|
||||
academic_years {
|
||||
BIGSERIAL id PK
|
||||
VARCHAR title UK
|
||||
@@ -244,6 +261,8 @@ erDiagram
|
||||
academic_calendar_activity_types ||--o{ academic_calendar_days : "activity_type_id"
|
||||
schedule_rules ||--o{ schedule_rule_groups : "schedule_rule_id"
|
||||
schedule_rules ||--o{ schedule_rule_slots : "schedule_rule_id"
|
||||
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"
|
||||
subgroups ||--o{ schedule_rule_slots : "subgroup_id"
|
||||
users ||--o{ schedule_rule_slots : "teacher_id"
|
||||
@@ -390,15 +409,38 @@ erDiagram
|
||||
| `subject_id` | BIGINT PK, FK → subjects (CASCADE) | Дисциплина |
|
||||
| `lesson_type_id` | BIGINT PK, FK → lesson_types (CASCADE) | Тип занятия |
|
||||
|
||||
#### `time_slot_scopes` — Сетки времени
|
||||
| Колонка | Тип | Описание |
|
||||
|---------|-----|----------|
|
||||
| `id` | BIGSERIAL PK | ID |
|
||||
| `code` | VARCHAR(50) UNIQUE | Системный код сетки |
|
||||
| `name` | VARCHAR(120) | Название в интерфейсе |
|
||||
| `apply_mode` | VARCHAR(20) | `DEFAULT`, `WEEKDAY`, `MANUAL` |
|
||||
| `day_of_week` | INT NULL | День недели для автоматической сетки |
|
||||
| `system_scope` | BOOLEAN | Защищает базовую и субботнюю сетки от удаления |
|
||||
| `display_order` | INT | Порядок в списках |
|
||||
|
||||
Seed создаёт `Базовая сетка` (`DEFAULT`) и `Субботняя сетка` (`WEEKDAY`, `day_of_week = 6`). Дополнительные сетки создаются как `MANUAL` и применяются только через ручные назначения дат.
|
||||
|
||||
#### `time_slots` — Временные слоты занятий
|
||||
| Колонка | Тип | Описание |
|
||||
|---------|-----|----------|
|
||||
| `id` | BIGSERIAL PK | ID |
|
||||
| `order_number` | INT UNIQUE | Номер пары в дне |
|
||||
| `time_slot_scope_id` | BIGINT FK → time_slot_scopes | Сетка времени |
|
||||
| `order_number` | INT | Номер пары в дне |
|
||||
| `start_time` | TIME | Время начала |
|
||||
| `end_time` | TIME | Время окончания |
|
||||
| `duration_minutes` | INT | Длительность в минутах |
|
||||
|
||||
Уникальность задаётся индексом `(time_slot_scope_id, order_number)`: в одной сетке может быть только один слот с номером пары.
|
||||
|
||||
#### `time_slot_date_assignments` — Ручные назначения сеток времени
|
||||
| Колонка | Тип | Описание |
|
||||
|---------|-----|----------|
|
||||
| `id` | BIGSERIAL PK | ID |
|
||||
| `assignment_date` | DATE UNIQUE | Дата ручного применения |
|
||||
| `time_slot_scope_id` | BIGINT FK → time_slot_scopes | Ручная сетка времени |
|
||||
|
||||
#### `academic_years` — Учебные годы
|
||||
| Колонка | Тип | Описание |
|
||||
|---------|-----|----------|
|
||||
@@ -481,7 +523,7 @@ erDiagram
|
||||
| `schedule_rule_id` | BIGINT FK → schedule_rules | Правило |
|
||||
| `day_of_week` | INT CHECK(1–7) | День недели: 1 — понедельник |
|
||||
| `parity` | VARCHAR(10) | `BOTH`, `EVEN`, `ODD` |
|
||||
| `time_slot_id` | BIGINT FK → time_slots | Временной слот |
|
||||
| `time_slot_id` | BIGINT FK → time_slots | Базовый временной слот |
|
||||
| `subgroup_id` | BIGINT FK → subgroups, NULL | Подгруппа |
|
||||
| `teacher_id` | BIGINT FK → users | Преподаватель |
|
||||
| `classroom_id` | BIGINT FK → classrooms | Аудитория |
|
||||
|
||||
@@ -43,7 +43,7 @@ frontend/
|
||||
│ │ ├── equipments.js # Управление оборудованием
|
||||
│ │ ├── edu-forms.js # Формы обучения
|
||||
│ │ ├── profiles.js # Профили обучения специальностей
|
||||
│ │ ├── schedule.js # Конструктор правил расписания и сетки пар
|
||||
│ │ ├── schedule.js # Конструктор правил расписания
|
||||
│ │ ├── academic-calendar.js # Календарные учебные графики
|
||||
│ │ ├── database.js # Управление тенантами
|
||||
│ │ └── departments-data.js # Создание кафедры/специальности
|
||||
@@ -66,9 +66,12 @@ frontend/
|
||||
│ │ ├── main.css # CSS-переменные, базовые стили
|
||||
│ │ └── layout.css # Sidebar, topbar, content
|
||||
│ ├── js/
|
||||
│ │ └── main.js # Навигация по вкладкам настроек
|
||||
│ │ ├── main.js # Навигация по вкладкам настроек
|
||||
│ │ └── views/
|
||||
│ │ └── time-slots.js # Настройка временных слотов
|
||||
│ └── views/
|
||||
│ └── general.html # Общие настройки (заглушка)
|
||||
│ ├── general.html # Общие настройки (заглушка)
|
||||
│ └── time-slots.html # Базовая, субботняя и ручные сетки времени
|
||||
│
|
||||
├── teacher/ # 👩🏫 Интерфейс преподавателя
|
||||
│ └── index.html # Недельный просмотр динамического расписания преподавателя
|
||||
@@ -109,18 +112,18 @@ frontend/
|
||||
| `equipments` | Оборудование | `/api/equipments` |
|
||||
| `classrooms` | Аудитории | `/api/classrooms` |
|
||||
| `subjects` | Дисциплины | `/api/subjects` |
|
||||
| `schedule` | Конструктор правил динамического расписания и сетка пар | `/api/admin/schedule-rules`, `/api/admin/time-slots`, `/api/admin/calendar/years`, `/api/lesson-types` |
|
||||
| `schedule` | Конструктор правил динамического расписания | `/api/admin/schedule-rules`, `/api/admin/time-slots`, `/api/admin/calendar/years`, `/api/lesson-types` |
|
||||
| `academic-calendar` | Учебные годы, семестры, создание календарных графиков и Excel-подобный редактор дневной сетки | `/api/admin/calendar`, `/api/admin/academic-calendars`, `/api/admin/calendar/activity-types`, `/api/education-forms` |
|
||||
| `auditorium-workload` | Загруженность аудиторий: аудитории в строках, временные слоты в столбцах | mock-данные |
|
||||
| `auditorium-workload` | Динамическая загруженность аудиторий: аудитории в строках, временные слоты в столбцах | `/api/classrooms`, `/api/admin/time-slots`, `/api/equipments`, `/api/groups`, `/api/schedule` |
|
||||
| `database` | Тенанты | `/api/database` |
|
||||
| `departments-data` | Создание, редактирование и удаление кафедр/специальностей | `/api/departments`, `/api/specialties` |
|
||||
|
||||
### Особенности админских вкладок
|
||||
|
||||
- Вкладка `groups` загружает кафедры, специальности, профили, учебные годы и календарные графики. Группа создаётся через `/api/groups` с `specialtyId` и `specialtyProfileId`, а блок назначений использует `/api/groups/{id}/calendar-assignments`.
|
||||
- Вкладка `auditorium-workload` показывает матрицу загруженности: строки — аудитории, столбцы — временные слоты.
|
||||
- Вкладка `auditorium-workload` показывает матрицу загруженности по выбранной дате: строки — реальные аудитории из `/api/classrooms`, столбцы — эффективные временные слоты выбранного дня из `/api/admin/time-slots/effective`, занятость собирается из динамического расписания `/api/schedule` по группам. Фильтры корпуса, вместимости и оборудования заполняются из API.
|
||||
- Вкладка `profiles` выделена под профили обучения: администратор выбирает специальность, создаёт профиль, редактирует описание и удаляет неиспользуемые профили.
|
||||
- Вкладка `schedule` не обращается к старым `lessons` API. Создание и редактирование расписания выполняется через правила `/api/admin/schedule-rules`, где каждое правило содержит группы и набор слотов. Из календарной системы здесь используется только список семестров для выбора периода действия правила.
|
||||
- Вкладка `schedule` не обращается к старым `lessons` API. Создание и редактирование расписания выполняется через правила `/api/admin/schedule-rules`, где каждое правило содержит группы и набор базовых слотов. Из календарной системы здесь используется только список семестров для выбора периода действия правила.
|
||||
- Вкладка `academic-calendar` полностью отделяет календарную систему от расписания занятий: администратор создаёт учебные годы и семестры, заводит календарные графики, выбирает форму обучения из общего справочника `/api/education-forms`, заполняет дневную сетку по курсам и кодам активностей, а сохранение сетки идёт через `/api/admin/academic-calendars/{id}/grid`.
|
||||
- Редактор годового графика во вкладке `academic-calendar` показывает мелкую табличную сетку: каждый курс разделён на семестры (`1`/`2`, `3`/`4` и далее), внутри семестра столбцы подписаны номерами недель учебного года, строки — днями недели, а ячейки содержат буквенный код активности. Подробная расшифровка и изменение кода открываются в модальном окне по клику на ячейку.
|
||||
- Вкладка `departments-data` использует модальные формы редактирования и маршруты `PUT/DELETE /api/departments/{id}` и `PUT/DELETE /api/specialties/{id}`.
|
||||
@@ -133,6 +136,7 @@ frontend/
|
||||
- Кнопка «Назад в панель» для возврата в `/admin/`
|
||||
- Текущие вкладки:
|
||||
- **Общие настройки** — заглушка (в разработке)
|
||||
- **Временные слоты** — выбор сетки через выпадающий список, CRUD слотов выбранной сетки, добавление/удаление ручных сеток и назначение ручной сетки на конкретную дату. Базовая сетка применяется по умолчанию, субботняя — автоматически по субботам.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user