3 Задача
This commit is contained in:
123
docs/DATABASE.md
123
docs/DATABASE.md
@@ -362,6 +362,50 @@ erDiagram
|
||||
TIMESTAMPTZ decided_at
|
||||
}
|
||||
|
||||
teacher_preferences {
|
||||
BIGSERIAL id PK
|
||||
BIGINT teacher_id FK
|
||||
BIGINT semester_id FK
|
||||
VARCHAR preference_type
|
||||
INT day_of_week
|
||||
BIGINT time_slot_id FK
|
||||
DATE preference_date
|
||||
TEXT comment
|
||||
VARCHAR status
|
||||
BIGINT requested_by FK
|
||||
BIGINT reviewed_by FK
|
||||
TEXT review_comment
|
||||
TIMESTAMPTZ reviewed_at
|
||||
TIMESTAMPTZ created_at
|
||||
TIMESTAMPTZ updated_at
|
||||
}
|
||||
|
||||
teacher_change_requests {
|
||||
BIGSERIAL id PK
|
||||
BIGINT teacher_id FK
|
||||
BIGINT base_rule_slot_id FK
|
||||
DATE lesson_date
|
||||
VARCHAR request_type
|
||||
DATE target_lesson_date
|
||||
BIGINT requested_time_slot_id FK
|
||||
BIGINT requested_classroom_id FK
|
||||
TEXT reason
|
||||
VARCHAR status
|
||||
BIGINT reviewed_by FK
|
||||
BIGINT applied_override_id FK
|
||||
TIMESTAMPTZ created_at
|
||||
TIMESTAMPTZ updated_at
|
||||
}
|
||||
|
||||
teacher_change_request_history {
|
||||
BIGSERIAL id PK
|
||||
BIGINT request_id FK
|
||||
VARCHAR status
|
||||
TEXT comment
|
||||
BIGINT actor_id FK
|
||||
TIMESTAMPTZ created_at
|
||||
}
|
||||
|
||||
schedule_rule_slot_subgroups {
|
||||
BIGINT schedule_rule_slot_id FK,PK
|
||||
BIGINT subgroup_id FK,PK
|
||||
@@ -418,6 +462,16 @@ erDiagram
|
||||
schedule_rule_slots ||--o{ teacher_absence_decisions : "base_rule_slot_id"
|
||||
schedule_overrides ||--o{ teacher_absence_decisions : "schedule_override_id"
|
||||
users ||--o{ teacher_absence_decisions : "decided_by"
|
||||
users ||--o{ teacher_preferences : "teacher_id/requested_by/reviewed_by"
|
||||
semesters ||--o{ teacher_preferences : "semester_id"
|
||||
time_slots ||--o{ teacher_preferences : "time_slot_id"
|
||||
users ||--o{ teacher_change_requests : "teacher_id/reviewed_by"
|
||||
schedule_rule_slots ||--o{ teacher_change_requests : "base_rule_slot_id"
|
||||
time_slots ||--o{ teacher_change_requests : "requested_time_slot_id"
|
||||
classrooms ||--o{ teacher_change_requests : "requested_classroom_id"
|
||||
schedule_overrides ||--o{ teacher_change_requests : "applied_override_id"
|
||||
teacher_change_requests ||--o{ teacher_change_request_history : "request_id"
|
||||
users ||--o{ teacher_change_request_history : "actor_id"
|
||||
time_slot_scopes ||--o{ time_slots : "time_slot_scope_id"
|
||||
time_slot_scopes ||--o{ time_slot_date_assignments : "time_slot_scope_id"
|
||||
time_slots ||--o{ schedule_rule_slots : "time_slot_id"
|
||||
@@ -976,6 +1030,69 @@ CHECK запрещает обратный период, пустую или сл
|
||||
одно занятие одного инцидента. При удалении override ссылка обнуляется, но аудиторская запись
|
||||
сохраняется.
|
||||
|
||||
#### `teacher_preferences` — Пожелания преподавателей на семестр
|
||||
|
||||
| Колонка | Тип | Описание |
|
||||
|---------|-----|----------|
|
||||
| `id` | BIGSERIAL PK | ID пожелания |
|
||||
| `teacher_id` | BIGINT FK → users | Преподаватель |
|
||||
| `semester_id` | BIGINT FK → semesters | Семестр действия |
|
||||
| `preference_type` | VARCHAR(30) | `HARD_UNAVAILABLE`, `SOFT_PREFERRED`, `SOFT_UNWANTED`, `CONSECUTIVE` или `NO_GAPS` |
|
||||
| `day_of_week` | SMALLINT NULL | День недели 1–7 для интервального пожелания |
|
||||
| `time_slot_id` | BIGINT FK → time_slots NULL | Пара базовой сетки времени |
|
||||
| `preference_date` | DATE NULL | Полностью недоступная дата при `HARD_UNAVAILABLE` |
|
||||
| `comment` | TEXT | Комментарий преподавателя |
|
||||
| `status` | VARCHAR(20) | `PENDING`, `APPROVED`, `REJECTED`, `CANCELLED` |
|
||||
| `requested_by` | BIGINT FK → users | Автор записи |
|
||||
| `reviewed_by` | BIGINT FK → users | Автор решения |
|
||||
| `review_comment` | TEXT | Комментарий согласования |
|
||||
| `reviewed_at` | TIMESTAMPTZ | Время решения |
|
||||
| `created_at`, `updated_at` | TIMESTAMPTZ | Аудит жизненного цикла |
|
||||
|
||||
CHECK-ограничение разделяет три допустимые формы записи: строгая недоступность по целой
|
||||
дате, строгое или мягкое пожелание по паре недели, либо пожелание компактности без даты и
|
||||
пары. Частичные индексы ускоряют проверку согласованной недоступности по интервалу и дате.
|
||||
Семантическая уникальность активных пожеланий проверяется сервисом, поскольку PostgreSQL
|
||||
считает значения `NULL` различными.
|
||||
|
||||
#### `teacher_change_requests` — Заявки на изменение занятия
|
||||
|
||||
| Колонка | Тип | Описание |
|
||||
|---------|-----|----------|
|
||||
| `id` | BIGSERIAL PK | ID заявки |
|
||||
| `teacher_id` | BIGINT FK → users | Преподаватель — автор заявки |
|
||||
| `base_rule_slot_id` | BIGINT FK → schedule_rule_slots | Базовый слот занятия |
|
||||
| `lesson_date` | DATE | Исходная дата занятия |
|
||||
| `request_type` | VARCHAR(30) | `MOVE`, `CHANGE_CLASSROOM` или `CANCEL` |
|
||||
| `target_lesson_date` | DATE NULL | Целевая дата переноса |
|
||||
| `requested_time_slot_id` | BIGINT FK → time_slots NULL | Запрошенная пара при переносе |
|
||||
| `requested_classroom_id` | BIGINT FK → classrooms NULL | Запрошенная аудитория |
|
||||
| `reason` | TEXT | Обязательное обоснование длиной 1–2000 символов |
|
||||
| `status` | VARCHAR(20) | `PENDING`, `APPROVED`, `REJECTED`, `CANCELLED` |
|
||||
| `reviewed_by` | BIGINT FK → users | Сотрудник учебного отдела |
|
||||
| `review_comment` | TEXT | Комментарий решения |
|
||||
| `reviewed_at` | TIMESTAMPTZ | Время решения |
|
||||
| `applied_override_id` | BIGINT FK → schedule_overrides NULL | Разовая правка одобренной заявки |
|
||||
| `created_at`, `updated_at` | TIMESTAMPTZ | Аудит жизненного цикла |
|
||||
|
||||
CHECK фиксирует допустимую форму каждого типа заявки. Частичный уникальный индекс по
|
||||
`(base_rule_slot_id, lesson_date)` запрещает две одновременно ожидающие заявки на одну пару.
|
||||
При удалении применённого override ссылка обнуляется, но заявка и история сохраняются.
|
||||
|
||||
#### `teacher_change_request_history` — История решений по заявке
|
||||
|
||||
| Колонка | Тип | Описание |
|
||||
|---------|-----|----------|
|
||||
| `id` | BIGSERIAL PK | ID события |
|
||||
| `request_id` | BIGINT FK → teacher_change_requests (CASCADE) | Заявка |
|
||||
| `status` | VARCHAR(20) | Зафиксированный статус заявки |
|
||||
| `comment` | TEXT | Обоснование или комментарий решения |
|
||||
| `actor_id` | BIGINT FK → users | Автор перехода |
|
||||
| `created_at` | TIMESTAMPTZ | Время события |
|
||||
|
||||
Записи добавляются при создании, принятии, отклонении и отзыве заявки. Индекс
|
||||
`(request_id, created_at, id)` обеспечивает стабильный хронологический вывод журнала.
|
||||
|
||||
---
|
||||
|
||||
## Flyway миграции
|
||||
@@ -996,12 +1113,14 @@ CHECK запрещает обратный период, пустую или сл
|
||||
|------|----------|
|
||||
| `V1__init.sql` | Полная baseline-схема: справочники, роли, refresh-сессии JWT, PostgreSQL rate limit и аудит входа, lifecycle-поля, история кафедр, календарные графики с интервальным хранением активностей и нумерацией недель `понедельник–воскресенье`, динамическое расписание, точечные изменения с переносом даты, seed, CHECK/UNIQUE/GiST-ограничения, конкурентно безопасные триггеры и комментарии |
|
||||
| `V2__teacher_absences_and_replacement_wizard.sql` | Реестр отсутствий преподавателей, статусы согласования и журнал применённых/отклонённых решений со ссылками на обычные `schedule_overrides` |
|
||||
| `V3__teacher_preferences_and_change_requests.sql` | Пожелания преподавателей на семестр, строгая и мягкая доступность, заявки на изменение занятия и неизменяемая история решений |
|
||||
|
||||
### Этап разработки
|
||||
|
||||
Исторические разработческие миграции V2–V7 по прямому решению владельца проекта были
|
||||
объединены в baseline `V1`. После фиксации baseline нумерация начата заново: текущая `V2`
|
||||
добавляет отсутствия и мастер замены, не изменяя контрольную сумму `V1`.
|
||||
объединены в baseline `V1`. После фиксации baseline нумерация начата заново: `V2`
|
||||
добавляет отсутствия и мастер замены, а `V3` — пожелания преподавателей и заявки на
|
||||
изменение занятий, не изменяя контрольную сумму `V1`.
|
||||
Интервальное хранение активностей и правильная нумерация недель календарного графика входят
|
||||
непосредственно в V1.
|
||||
Перед применением этой редакции требуется полностью пустая tenant-схема.
|
||||
|
||||
Reference in New Issue
Block a user