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

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

@@ -5,7 +5,7 @@
- **СУБД:** PostgreSQL (локально `postgres:16.3-alpine` с закреплённым digest, продакшн — managed PostgreSQL)
- **Управление схемой:** Flyway (программный запуск)
- **Hibernate DDL:** Отключён (`ddl-auto=none`)
- **Расширения:** `pgcrypto` (bcrypt-хеширование паролей), `btree_gist` (exclusion constraint временных слотов)
- **Расширения:** `pgcrypto` (bcrypt-хеширование паролей), `btree_gist` (exclusion constraints временных слотов и календарных периодов)
- **Мультитенантность:** Каждый тенант = отдельная БД
- **Абсолютное время:** `TIMESTAMPTZ`, Hibernate читает и записывает значения как UTC `Instant`
- **Календарные бизнес-даты:** `DATE`, интерпретируются в зоне `Europe/Moscow`
@@ -262,13 +262,12 @@ erDiagram
TIMESTAMPTZ updated_at
}
academic_calendar_days {
academic_calendar_periods {
BIGSERIAL id PK
BIGINT calendar_id FK
INT course_number
DATE date
INT week_number
INT day_of_week
DATE start_date
DATE end_date
BIGINT activity_type_id FK
}
@@ -375,10 +374,10 @@ erDiagram
specialties ||--o{ academic_calendars : "specialty_id"
specialty_profiles ||--o{ academic_calendars : "specialty_profile_id"
education_forms ||--o{ academic_calendars : "study_form_id"
academic_calendars ||--o{ academic_calendar_days : "calendar_id"
academic_calendars ||--o{ academic_calendar_periods : "calendar_id"
academic_calendars ||--o{ academic_calendar_subjects : "calendar_id"
academic_calendars ||--o{ student_group_calendar_assignments : "calendar_id"
academic_calendar_activity_types ||--o{ academic_calendar_days : "activity_type_id"
academic_calendar_activity_types ||--o{ academic_calendar_periods : "activity_type_id"
schedule_rules ||--o{ schedule_rule_groups : "schedule_rule_id"
schedule_rules ||--o{ schedule_rule_slots : "schedule_rule_id"
schedule_rule_slots ||--o{ schedule_rule_slot_subgroups : "schedule_rule_slot_id"
@@ -768,19 +767,22 @@ V1 создаёт GiST exclusion constraint `ex_academic_years_no_overlap` дл
группа стала несовместимой. Уменьшение `course_count` также запрещается, если в сетке
остаются строки старших курсов или дисциплины старших семестров.
#### `academic_calendar_days` — Дневная сетка календарного графика
#### `academic_calendar_periods` — Периоды активности календарного графика
| Колонка | Тип | Описание |
|---------|-----|----------|
| `id` | BIGSERIAL PK | ID |
| `calendar_id` | BIGINT FK → academic_calendars (CASCADE) | Календарный график |
| `course_number` | INT | Номер курса |
| `date` | DATE | Дата учебного года |
| `week_number` | INT | Номер периода `понедельник–воскресенье`; неделя 1 содержит начало учебного года |
| `day_of_week` | INT CHECK(1–7) | День недели ISO |
| `start_date` | DATE | Первая дата периода, включительно |
| `end_date` | DATE | Последняя дата периода, включительно |
| `activity_type_id` | BIGINT FK → academic_calendar_activity_types | Код активности |
Триггер `trg_calendar_days_dimensions` требует, чтобы `course_number` не превышал
`academic_calendars.course_count`, а дата находилась внутри учебного года графика.
Триггер `trg_calendar_periods_dimensions` требует, чтобы `course_number` не превышал
`academic_calendars.course_count`, обе границы находились внутри учебного года графика,
а `end_date` была не раньше `start_date`. Exclusion constraint
`ex_calendar_periods_no_overlap` запрещает пересечение периодов одного курса и графика.
Соседние даты с одинаковой активностью объединяет backend; номер недели и ISO-день
вычисляются при разворачивании периода в дневной REST-ответ и в таблице не дублируются.
#### `academic_calendar_subjects` — Дисциплины календарного графика
| Колонка | Тип | Описание |
@@ -921,12 +923,13 @@ lifecycle ресурсов, эффективная сетка целевого
| Файл | Описание |
|------|----------|
| `V1__init.sql` | Полная baseline-схема: справочники, роли, refresh-сессии JWT, PostgreSQL rate limit и аудит входа, lifecycle-поля, история кафедр, календарные графики с нумерацией недель `понедельник–воскресенье`, динамическое расписание, точечные изменения с переносом даты, seed, CHECK/UNIQUE/GiST-ограничения, конкурентно безопасные триггеры и комментарии |
| `V1__init.sql` | Полная baseline-схема: справочники, роли, refresh-сессии JWT, PostgreSQL rate limit и аудит входа, lifecycle-поля, история кафедр, календарные графики с интервальным хранением активностей и нумерацией недель `понедельник–воскресенье`, динамическое расписание, точечные изменения с переносом даты, seed, CHECK/UNIQUE/GiST-ограничения, конкурентно безопасные триггеры и комментарии |
### Этап разработки
По прямому решению владельца проекта разработческие миграции V2–V7 объединены в baseline
`V1`. Правильная нумерация недель календарного графика также входит непосредственно в V1.
`V1`. Интервальное хранение активностей и правильная нумерация недель календарного графика
также входят непосредственно в V1.
Перед применением этой редакции требуется полностью пустая tenant-схема.
### Полный сброс БД (локально)