написал обработку количества часов лекций лабораторных и практик по отдельности
This commit is contained in:
18
docs/API.md
18
docs/API.md
@@ -101,7 +101,7 @@
|
||||
|
||||
## Динамическое расписание
|
||||
|
||||
Новая модель расписания строится из правил (`schedule_rules`) и слотов (`schedule_rule_slots`). Фактические занятия рендерятся на диапазон дат только для дней, где календарный учебный график группы имеет код, разрешающий обычные пары.
|
||||
Новая модель расписания строится из правил (`schedule_rules`) и слотов (`schedule_rule_slots`). В правиле отдельно хранятся часы и стартовые недели для лекций, лабораторных и практик. Фактические занятия рендерятся на диапазон дат только для дней, где календарный учебный график группы имеет код, разрешающий обычные пары.
|
||||
|
||||
### `GET /api/schedule`
|
||||
|
||||
@@ -151,9 +151,9 @@ GET /api/schedule?groupId=1&startDate=2026-04-27&endDate=2026-05-03
|
||||
"groupIds": [1],
|
||||
"groupNames": ["ИВТ-21-1"],
|
||||
"activityType": "Т",
|
||||
"totalAcademicHours": 72,
|
||||
"consumedAcademicHoursBeforeLesson": 24,
|
||||
"remainingAcademicHoursAfterLesson": 46
|
||||
"lessonTypeAcademicHours": 32,
|
||||
"consumedLessonTypeAcademicHoursBeforeLesson": 12,
|
||||
"remainingLessonTypeAcademicHoursAfterLesson": 18
|
||||
}
|
||||
]
|
||||
```
|
||||
@@ -279,8 +279,12 @@ GET /api/schedule?groupId=1&startDate=2026-04-27&endDate=2026-05-03
|
||||
{
|
||||
"subjectId": 1,
|
||||
"semesterId": 1,
|
||||
"activeFromDate": "2026-02-01",
|
||||
"totalAcademicHours": 72,
|
||||
"lectureAcademicHours": 32,
|
||||
"laboratoryAcademicHours": 16,
|
||||
"practiceAcademicHours": 24,
|
||||
"lectureStartWeek": 1,
|
||||
"laboratoryStartWeek": 3,
|
||||
"practiceStartWeek": 2,
|
||||
"groupIds": [1, 2],
|
||||
"slots": [
|
||||
{
|
||||
@@ -309,6 +313,8 @@ CRUD доступен по:
|
||||
|
||||
`timeSlotId` должен ссылаться на базовый слот (`scopeApplyMode = DEFAULT`). Субботняя и ручные сетки не выбираются в правиле напрямую.
|
||||
|
||||
Часы и недели начала задаются отдельно для лекций, лабораторных и практик. Если для типа занятий указан ненулевой лимит часов, в правиле должен быть хотя бы один слот этого типа; если слот типа есть, его лимит часов должен быть больше нуля.
|
||||
|
||||
### `GET /api/lesson-types`
|
||||
|
||||
Справочник типов занятий для конструктора правил расписания.
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
| `academic_calendar_days` | Дневная сетка по курсу и дате |
|
||||
| `student_group_calendar_assignments` | Назначение конкретного графика группе на учебный год |
|
||||
| `time_slots` | Настраиваемая сетка пар для тенанта |
|
||||
| `schedule_rules` | Лимит часов дисциплины в семестре |
|
||||
| `schedule_rules` | Лимиты часов и недели начала по лекциям, лабораторным и практикам |
|
||||
| `schedule_rule_groups` | Группы правила, включая потоковые лекции |
|
||||
| `schedule_rule_slots` | День, чётность, слот, преподаватель, аудитория, тип и формат занятия |
|
||||
|
||||
@@ -93,9 +93,10 @@
|
||||
4. Определяет код активности по курсу группы и конкретной дате.
|
||||
5. Пропускает день, если код активности не разрешает обычные пары.
|
||||
6. Загружает правила группы или преподавателя.
|
||||
7. Симулирует уже проведённые занятия от `active_from_date`.
|
||||
7. Для каждого типа занятия проверяет свою неделю начала в семестре.
|
||||
8. Подставляет эффективную сетку времени даты: ручную, субботнюю или базовую.
|
||||
9. Останавливает вывод правила, когда достигнут `total_academic_hours`.
|
||||
9. Считает уже проведённые часы отдельно для лекций, лабораторных и практик.
|
||||
10. Останавливает вывод слотов конкретного типа, когда достигнут его лимит часов.
|
||||
|
||||
Обычные пары генерируются только на коде `Т` (`allow_schedule = true`). Экзамены, каникулы, практики, нерабочие дни, праздники `*` и дни вне учебного года `=` считаются пропуском: занятие не переносится и не списывает академические часы. Если у группы нет назначения графика на учебный год, `GET /api/schedule` возвращает пустой список для этой группы без ошибки.
|
||||
|
||||
@@ -119,7 +120,8 @@
|
||||
|
||||
### Валидация правил расписания
|
||||
|
||||
- **Правило:** обязательны дисциплина, семестр, дата начала, положительный лимит академических часов и хотя бы одна группа.
|
||||
- **Правило:** обязательны дисциплина, семестр, хотя бы один положительный лимит часов по типу занятий, положительные недели начала и хотя бы одна группа.
|
||||
- **Покрытие типов:** если для лекций, лабораторных или практик указан лимит часов, должен быть хотя бы один слот этого типа; слот типа не сохраняется с нулевым лимитом часов.
|
||||
- **Слот:** день недели должен быть от 1 до 7, чётность недели обязательна.
|
||||
- **Связанные сущности:** базовый временной слот, преподаватель, аудитория и тип занятия должны существовать в БД.
|
||||
- **Формат:** `lessonFormat` обязателен и хранится в слоте правила.
|
||||
|
||||
@@ -207,8 +207,12 @@ erDiagram
|
||||
BIGSERIAL id PK
|
||||
BIGINT subject_id FK
|
||||
BIGINT semester_id FK
|
||||
DATE active_from_date
|
||||
INT total_academic_hours
|
||||
INT lecture_academic_hours
|
||||
INT laboratory_academic_hours
|
||||
INT practice_academic_hours
|
||||
INT lecture_start_week
|
||||
INT laboratory_start_week
|
||||
INT practice_start_week
|
||||
}
|
||||
|
||||
schedule_rule_groups {
|
||||
@@ -507,8 +511,12 @@ Seed создаёт `Базовая сетка` (`DEFAULT`) и `Субботня
|
||||
| `id` | BIGSERIAL PK | ID |
|
||||
| `subject_id` | BIGINT FK → subjects | Дисциплина |
|
||||
| `semester_id` | BIGINT FK → semesters | Семестр |
|
||||
| `active_from_date` | DATE | Дата начала действия правила |
|
||||
| `total_academic_hours` | INT | Лимит академических часов |
|
||||
| `lecture_academic_hours` | INT | Лимит академических часов лекций |
|
||||
| `laboratory_academic_hours` | INT | Лимит академических часов лабораторных работ |
|
||||
| `practice_academic_hours` | INT | Лимит академических часов практик |
|
||||
| `lecture_start_week` | INT | Неделя семестра, с которой начинаются лекции |
|
||||
| `laboratory_start_week` | INT | Неделя семестра, с которой начинаются лабораторные |
|
||||
| `practice_start_week` | INT | Неделя семестра, с которой начинаются практики |
|
||||
|
||||
#### `schedule_rule_groups` — Группы правила
|
||||
| Колонка | Тип | Описание |
|
||||
@@ -548,11 +556,11 @@ Seed создаёт `Базовая сетка` (`DEFAULT`) и `Субботня
|
||||
|
||||
| Файл | Описание |
|
||||
|------|----------|
|
||||
| `V1__init.sql` | Инициализация: справочники, профили специальностей, календарные учебные графики, динамическое расписание, тестовые правила, триггеры, комментарии |
|
||||
| `V1__init.sql` | Инициализация: справочники, профили специальностей, календарные учебные графики, динамическое расписание с раздельными часами и стартовыми неделями по типам занятий, тестовые правила, триггеры, комментарии |
|
||||
|
||||
### Накатывание на существующих тенантов
|
||||
|
||||
Для применения новой миграции к уже существующим тенантам необходимо перезапустить backend:
|
||||
Для применения новой базовой схемы к уже существующим тенантам нужен полный сброс БД. Перезапуск backend без сброса не изменит уже применённую `V1__init.sql`.
|
||||
|
||||
```bash
|
||||
# Kubernetes
|
||||
|
||||
107
docs/DYNAMIC_SCHEDULE_IMPLEMENTATION.md
Normal file
107
docs/DYNAMIC_SCHEDULE_IMPLEMENTATION.md
Normal file
@@ -0,0 +1,107 @@
|
||||
# Реализация динамического расписания
|
||||
|
||||
Файл фиксирует текущий результат внедрения динамического расписания и календарных учебных графиков.
|
||||
|
||||
## Статус
|
||||
|
||||
Новая модель является базовой схемой проекта и создаётся в `backend/src/main/resources/db/migration/V1__init.sql`. Раздельные часы и недели начала по типам занятий уже включены в эту базовую схему; применение рассчитано на полный сброс БД.
|
||||
|
||||
Старый ручной слой занятий удалён. Динамическое расписание строится из правил `schedule_rules`, слотов `schedule_rule_slots` и календарного учебного графика группы.
|
||||
|
||||
## База данных
|
||||
|
||||
`V1__init.sql` создаёт и заполняет:
|
||||
|
||||
| Таблица | Назначение |
|
||||
|---------|------------|
|
||||
| `specialties` | Коды и названия специальностей |
|
||||
| `specialty_profiles` | Профили обучения внутри специальности |
|
||||
| `student_groups` | Группы со ссылками на специальность и профиль |
|
||||
| `education_forms` | Общий справочник форм обучения для групп и календарных графиков |
|
||||
| `academic_calendar_activity_types` | Коды активностей из Excel-графика |
|
||||
| `academic_calendars` | Календарные графики профиля, формы обучения и учебного года |
|
||||
| `academic_calendar_days` | Дневная сетка графика по курсу и дате |
|
||||
| `student_group_calendar_assignments` | Назначения графиков группам по учебному году |
|
||||
| `time_slots` | Настраиваемая сетка пар |
|
||||
| `schedule_rules` | Правила проведения дисциплин с отдельными часами и стартовыми неделями лекций, лабораторных и практик |
|
||||
| `schedule_rule_groups` | Группы правила |
|
||||
| `schedule_rule_slots` | Шаблонные слоты правила |
|
||||
|
||||
Праздничные и неучебные дни больше не хранятся отдельной сущностью: они задаются кодами `*` и `=` в дневной сетке.
|
||||
|
||||
## Backend
|
||||
|
||||
Добавлены сущности и репозитории для профилей, календарей, кодов активностей, дневной сетки и назначений группам.
|
||||
|
||||
Ключевые сервисы:
|
||||
|
||||
| Сервис | Назначение |
|
||||
|--------|------------|
|
||||
| `AcademicDateService` | Семестр по дате, номер недели, чётность, курс группы, активность дня по назначенному графику |
|
||||
| `ScheduleGeneratorService` | Рендер расписания группы или преподавателя на диапазон дат |
|
||||
|
||||
`ScheduleGeneratorService` пропускает день, если код активности не разрешает обычные пары. Для лекций, лабораторных и практик генератор отдельно проверяет стартовую неделю и отдельно списывает академические часы. Если у группы нет назначенного графика на учебный год, расписание этой группы возвращается пустым списком.
|
||||
|
||||
## API
|
||||
|
||||
Просмотр расписания:
|
||||
|
||||
```http
|
||||
GET /api/schedule?groupId=1&startDate=2026-04-27&endDate=2026-05-03
|
||||
GET /api/schedule?teacherId=2&startDate=2026-04-27&endDate=2026-05-03
|
||||
```
|
||||
|
||||
Административные API:
|
||||
|
||||
| API | Назначение |
|
||||
|-----|------------|
|
||||
| `/api/admin/time-slots` | CRUD временных слотов |
|
||||
| `/api/admin/calendar/years` | CRUD учебных годов |
|
||||
| `/api/admin/calendar/years/{academicYearId}/semesters` | Семестры учебного года |
|
||||
| `/api/admin/calendar/semesters/{id}` | Обновление семестра |
|
||||
| `/api/admin/calendar/activity-types` | CRUD кодов активностей |
|
||||
| `/api/admin/academic-calendars` | CRUD календарных учебных графиков |
|
||||
| `/api/admin/academic-calendars/{id}/grid` | Получение и сохранение дневной сетки |
|
||||
| `/api/specialties/{id}/profiles` | CRUD профилей специальности |
|
||||
| `/api/groups/{id}/calendar-assignments` | Назначения графиков группе |
|
||||
| `/api/admin/schedule-rules` | CRUD правил расписания |
|
||||
|
||||
## Frontend
|
||||
|
||||
Админский экран `schedule` содержит:
|
||||
|
||||
- конструктор правил динамического расписания;
|
||||
- отдельные поля часов и недель начала для лекций, лабораторных и практик;
|
||||
- управление временными слотами;
|
||||
- учебные годы и семестры;
|
||||
- CRUD календарных графиков;
|
||||
- Excel-подобный редактор дневной сетки по курсам, датам и кодам активностей.
|
||||
|
||||
Экран `groups` создаёт и редактирует группы с профилем обучения, а также назначает календарный график группе на учебный год.
|
||||
|
||||
Экран `departments-data` управляет кафедрами, специальностями и профилями специальностей.
|
||||
|
||||
## Проверки
|
||||
|
||||
Доступные локальные проверки:
|
||||
|
||||
```bash
|
||||
node --check frontend/admin/js/views/schedule.js
|
||||
node --check frontend/admin/js/views/groups.js
|
||||
node --check frontend/admin/js/views/departments-data.js
|
||||
git diff --check
|
||||
```
|
||||
|
||||
Полная проверка требует окружения с Maven и доступом к Docker:
|
||||
|
||||
```bash
|
||||
mvn -DskipTests compile
|
||||
docker compose down -v
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
## Следующие этапы
|
||||
|
||||
- Добавить интеграционные тесты генерации по кодам `Т`, `Э`, `К`, `*`, `=`.
|
||||
- Добавить строгую backend-валидацию конфликтов преподавателей, аудиторий и групп при сохранении правил.
|
||||
- Добавить связь пользователя-студента с учебной группой, чтобы кабинет студента не требовал ручного выбора группы.
|
||||
@@ -123,7 +123,7 @@ frontend/
|
||||
- Вкладка `groups` загружает кафедры, специальности, профили, учебные годы и календарные графики. Группа создаётся через `/api/groups` с `specialtyId` и `specialtyProfileId`, а блок назначений использует `/api/groups/{id}/calendar-assignments`.
|
||||
- Вкладка `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}`.
|
||||
|
||||
48
docs/SCHEDULE_PROPOSAL.md
Normal file
48
docs/SCHEDULE_PROPOSAL.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# Концепция динамической генерации расписания
|
||||
|
||||
Документ фиксирует актуальную концепцию после внедрения календарных учебных графиков. Подробная продуктовая модель описана в [`docs/ACADEMIC_CALENDAR.md`](docs/ACADEMIC_CALENDAR.md), REST API — в [`docs/API.md`](docs/API.md), схема БД — в [`docs/DATABASE.md`](docs/DATABASE.md).
|
||||
|
||||
## Базовая идея
|
||||
|
||||
Фактические занятия не хранятся отдельными строками на каждую дату. Система хранит:
|
||||
|
||||
- календарный учебный график по специальности, профилю, форме обучения и учебному году;
|
||||
- правила расписания дисциплин;
|
||||
- слоты правил: день недели, чётность, пара, преподаватель, аудитория, тип занятия и формат;
|
||||
- назначение конкретного календарного графика учебной группе на учебный год.
|
||||
|
||||
При запросе `GET /api/schedule` backend рендерит расписание на диапазон дат. Если дата не является днём теоретического обучения по назначенному группе графику, обычные пары не выводятся и академические часы не списываются.
|
||||
|
||||
## Слои модели
|
||||
|
||||
### Календарный слой
|
||||
|
||||
- `academic_years` и `semesters` задают границы учебного года и семестров.
|
||||
- `specialties` и `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` хранит шаблонные занятия правила.
|
||||
|
||||
## Алгоритм генерации
|
||||
|
||||
1. Для даты определяется семестр.
|
||||
2. Для группы находится назначенный календарный учебный график.
|
||||
3. По году начала обучения вычисляется текущий курс группы.
|
||||
4. По курсу и дате находится код активности.
|
||||
5. Обычные пары генерируются только для кода, где `allow_schedule = true`; в seed-данных это `Т`.
|
||||
6. Для разрешённого дня выбираются активные правила и слоты.
|
||||
7. Лимит часов считается только по реально проведённым занятиям.
|
||||
|
||||
Если назначение графика отсутствует, расписание группы возвращается пустым списком без ошибки.
|
||||
|
||||
## Административный сценарий
|
||||
|
||||
Администратор создаёт специальность и профиль, затем создаёт группу с этой связкой. В разделе расписания он создаёт учебный год, семестры и календарный график, заполняет дневную сетку кодами активностей и назначает график группе. После сохранения графика или назначения кэш генератора очищается, поэтому следующие запросы расписания используют новые правила сразу.
|
||||
33
docs/SCHEDULE_TASKS.md
Normal file
33
docs/SCHEDULE_TASKS.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# Задачи: динамическое расписание и календарный учебный график
|
||||
|
||||
Актуальная декомпозиция относится к модели, где календарный учебный график хранится дневной сеткой и назначается группе на учебный год.
|
||||
|
||||
## Выполнено
|
||||
|
||||
- [x] Переписана базовая схема `V1__init.sql` под полный сброс БД.
|
||||
- [x] Добавлены специальности, профили обучения и связь группы с профилем.
|
||||
- [x] Добавлены формы обучения календарного графика.
|
||||
- [x] Добавлен справочник кодов активностей Excel-графика.
|
||||
- [x] Добавлены календарные графики, дневная сетка и назначения графиков группам.
|
||||
- [x] Обновлён `AcademicDateService`: активность дня определяется по назначенному группе графику.
|
||||
- [x] Обновлён `ScheduleGeneratorService`: обычные пары генерируются только на разрешённых днях.
|
||||
- [x] В `V1__init.sql` добавлены отдельные часы и недели начала для лекций, лабораторных и практик.
|
||||
- [x] Добавлены API профилей, календарей, дневной сетки, кодов активностей и назначений группам.
|
||||
- [x] Обновлены админские экраны специальностей, групп и расписания.
|
||||
- [x] Добавлена документация `docs/ACADEMIC_CALENDAR.md`.
|
||||
|
||||
## Оставшиеся задачи
|
||||
|
||||
- [ ] Добавить интеграционные тесты генерации расписания для кодов `Т`, `Э`, `К`, `*`, `=`.
|
||||
- [ ] Добавить проверку конфликтов преподавателей, аудиторий и групп при сохранении правил.
|
||||
- [ ] Добавить модель связи пользователя-студента с учебной группой.
|
||||
- [ ] Добавить импорт календарного графика из Excel, если он понадобится после ручного редактора.
|
||||
|
||||
## Проверочный сценарий
|
||||
|
||||
1. Полностью сбросить локальную БД.
|
||||
2. Запустить приложение и применить `V1__init.sql`.
|
||||
3. Создать профиль специальности.
|
||||
4. Создать календарный график и заполнить дневную сетку.
|
||||
5. Назначить график группе.
|
||||
6. Проверить `GET /api/schedule` на дне теории и на днях, где пары запрещены.
|
||||
Reference in New Issue
Block a user