исправление хранения календаря

This commit is contained in:
Zuev
2026-07-31 21:24:11 +03:00
parent 87f3d98621
commit cc422255a2
31 changed files with 825 additions and 425 deletions

View File

@@ -317,10 +317,12 @@ pod не сохраняют два конфликтующих правила п
`AcademicCalendarController` делегирует полную замену дневной сетки
`AcademicCalendarGridService`. Публичный `replaceGrid()` проходит через транзакционный
Spring proxy: весь payload и все activity types проверяются до bulk delete, затем выполняются
`delete → flush → saveAll → flush`. Исключение не перехватывается внутри сервиса и вызывает
rollback. Инвалидация кэша зарегистрирована через transaction synchronization и выполняется
только после успешного commit.
Spring proxy: весь payload и все activity types проверяются до bulk delete, затем соседние
даты одного курса с одинаковой активностью сжимаются в периоды и выполняются
`delete → flush → saveAll → flush`. При чтении контроллер разворачивает интервалы обратно
в дневной REST-контракт и вычисляет номер недели и ISO-день. Исключение не перехватывается
внутри сервиса и вызывает rollback. Инвалидация кэша зарегистрирована через transaction
synchronization и выполняется только после успешного commit.
`ScheduleOverrideController` является HTTP-адаптером, а create/update/delete выполняет
`ScheduleOverrideService` через вызываемые Spring proxy-методы с `@Transactional`.
@@ -339,7 +341,8 @@ lost update или проверке устаревшего снимка.
`endDate - startDate + 1` одинаково в query- и generator-слоях.
`ScheduleQueryService` передаёт набор групп одним вызовом `buildScheduleForGroups()`.
`AcademicDateService` одним запросом загружает пересекающиеся семестры, затем batch-набор
назначений календарей и дневную сетку от начала затронутого семестра до конца диапазона.
назначений календарей и пересекающиеся периоды активности от начала затронутого семестра
до конца диапазона.
`ScheduleGeneratorService` отдельно batch-загружает правила и сетки звонков и строит lookup
по датам, группам, учебным годам, календарям и номерам пар. Снимки живут только во время
одного построения: изменения следующего запроса видны сразу, а singleton-кэш отсутствует.