баг-фикс завершён

This commit is contained in:
Zuev
2026-07-19 20:16:12 +03:00
parent bc0e1ab1b4
commit ee876f1acd
43 changed files with 1228 additions and 258 deletions

View File

@@ -273,6 +273,12 @@ GiST exclusion constraints и триггеры PostgreSQL, связывающи
ссылочные строки, поэтому гонка прямых записей или нескольких backend-pod не создаёт
устаревшее назначение.
Создание и обновление группы используют один validator положительных размерностей.
Уменьшение численности дополнительно сверяется с суммой активных подгрупп. CRUD подгрупп и
изменение группы захватывают строку родительской группы `FOR UPDATE`; V1 повторяет проверку
триггерами обеих таблиц. Поэтому конкурентно могут завершиться только совместимые
изменения, а сумма активных `student_capacity` никогда не превышает `group_size`.
`TeacherDepartmentService` является единым источником датированных решений о кафедре
преподавателя. Списки пользователей, кабинет кафедры, права на привязку дисциплин и отчёты
нагрузки читают `teacher_department_assignments` на целевую дату, не используют
@@ -329,6 +335,8 @@ rollback. Инвалидация кэша зарегистрирована че
lost update или проверке устаревшего снимка.
Генерация диапазона использует request-scoped снимки вместо запросов из вложенных циклов.
Обе границы диапазона включительны, поэтому общий лимит 120 дат вычисляется как
`endDate - startDate + 1` одинаково в query- и generator-слоях.
`ScheduleQueryService` передаёт набор групп одним вызовом `buildScheduleForGroups()`.
`AcademicDateService` одним запросом загружает пересекающиеся семестры, затем batch-набор
назначений календарей и дневную сетку от начала затронутого семестра до конца диапазона.
@@ -345,6 +353,23 @@ Teacher-only чтение строит базовое расписание на
---
## Временная модель
`BusinessTimeService` является единым источником текущей календарной даты и абсолютного
момента. Бизнес-дата вычисляется из инъецируемого `Clock` в зоне
`BUSINESS_TIME_ZONE` (по умолчанию `Europe/Moscow`), поэтому lifecycle, доступность
расписания, назначения кафедр и создание периодов не зависят от timezone JVM или хоста.
Абсолютные моменты представлены `Instant`, хранятся в PostgreSQL как `TIMESTAMPTZ` и
сериализуются в UTC. Hibernate принудительно использует `hibernate.jdbc.time_zone=UTC`,
Jackson — UTC. Отдельные календарные даты представлены `LocalDate`/SQL `DATE`; для них
смещение и время суток не передаются.
В production-конструкторах используется системный UTC clock. Тесты передают фиксированный
`Clock`, включая границу московской полуночи, поэтому переход бизнес-даты воспроизводим.
---
## Аутентификация
Система использует access JWT и отзывные refresh-токены без включения полноценного Spring Security flow: