исправил качество правил и изменение расписания (не черновика)

This commit is contained in:
Zuev
2026-08-12 01:07:35 +03:00
parent 18a97b293a
commit 491e373cc3
23 changed files with 826 additions and 316 deletions

View File

@@ -267,23 +267,27 @@ constraint. При чтении API разворачивает периоды о
- **Доступность аудитории:** `is_available=false` запрещает новые назначения, но не удаляет историю.
- **Конфликты слотов:** сначала попарно проверяются слоты самого нового payload, включая точные дубли, затем — активные правила той же версии. Конфликт возникает при пересечении дня, базового временного слота, чётности (`BOTH` пересекается с любой чётностью) и активных недель слота, если совпадает преподаватель, аудитория или учебная группа. `ODD` и `EVEN` между собой не конфликтуют. Активные недели считаются из лимита часов типа занятия, недели начала, чётности и порядка слотов внутри правила; например, занятие на 1-3 неделях не конфликтует с тем же ресурсом с 4 недели. Для лабораторных занятий разные подгруппы одной группы могут идти параллельно, но занятие для всей группы конфликтует с любой её подгруппой. Backend возвращает `409 Conflict`; `conflictRule` присутствует только для конфликта с сохранённым правилом, а внутренний конфликт описывается полями и русскими причинами без искусственной записи.
- **Конкурентная запись:** публичные методы `ScheduleRuleService` являются транзакционными. Создание блокирует строку семестра и выбранную версию, а update — правило, версию и старый/новый семестры в стабильном порядке. Публикация блокирует версию до завершения полной проверки, поэтому другой backend-pod не может дописать правило после валидации черновика.
- **Связанные слоты:** update сохраняет ID переданных существующих слотов, чтобы не разрывать точечные изменения и операционный аудит. Удаление слота отклоняется, если на него ссылаются override, заявка преподавателя или решение по отсутствию.
### Черновики, версии и публикация
Правила каждого семестра принадлежат явной версии расписания. Жизненный цикл версии:
1. `DRAFT` создаётся пустым или как полная копия выбранной версии.
2. Конструктор добавляет, изменяет и архивирует правила только в выбранном черновике.
3. Полная проверка выявляет внутренние конфликты правил; diff сопоставляет правила по
1. При создании семестра автоматически появляется пустая версия 1 `PUBLISHED` — основное расписание.
2. Конструктор по умолчанию открывает опубликованное расписание: изменения его правил сразу
видны конечным пользователям. Пользователь может переключиться на существующий `DRAFT`.
3. `DRAFT` создаётся пустым через API или прямо в конструкторе как полная копия выбранной
опубликованной либо черновой версии; после создания он сразу становится текущим.
4. Полная проверка выявляет внутренние конфликты правил; diff сопоставляет правила по
стабильному `version_group_id` и отдельно сравнивает сформированные занятия семестра.
4. Публикация требует причины и в одной транзакции архивирует прежнюю публикацию, затем
5. Публикация требует причины и в одной транзакции архивирует прежнюю публикацию, затем
переводит проверенный черновик в `PUBLISHED`.
5. Ранее опубликованная версия получает `ARCHIVED` и может быть восстановлена такой же
6. Ранее опубликованная версия получает `ARCHIVED` и может быть восстановлена такой же
атомарной операцией с обязательной причиной.
На уровне БД частичный уникальный индекс допускает только одну `PUBLISHED`-версию на
семестр. Блокировки версии и набора версий семестра не позволяют публикации пересечься с
редактированием черновика или конкурентной публикацией. Каждое создание, архивирование,
редактированием расписания или конкурентной публикацией. Каждое создание, архивирование,
публикация и восстановление записывается в неизменяемый журнал с автором, временем и
причиной.