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

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

@@ -8,7 +8,7 @@
```json
{
"timestamp": "2026-05-27T19:47:54",
"timestamp": "2026-05-27T16:47:54Z",
"status": 400,
"error": "Некорректный запрос",
"message": "Некорректные параметры запроса",
@@ -18,6 +18,11 @@
Контроллеры, у которых исторически есть собственная обработка ошибок, могут возвращать более короткий объект с полем `message`.
Все поля момента времени (`createdAt`, `updatedAt`, `reviewedAt`, `archivedAt` и
аналогичные) сериализуются как ISO-8601 UTC с суффиксом `Z`. Поля календарной даты
(`date`, `validFrom`, `validTo`, `activeFrom`, `activeTo`) остаются строками `YYYY-MM-DD`
без часового пояса и вычисляются по бизнес-зоне `Europe/Moscow`.
Нарушения ограничений PostgreSQL также обрабатываются централизованно. Известные CHECK
возвращают `400`, а UNIQUE, FK и GiST exclusion conflicts — `409` с безопасным русским
сообщением. Тексты JDBC, SQL, имена ограничений и внутренние причины исключений в JSON не
@@ -360,7 +365,13 @@ Refresh-токен ротируется при каждом успешном о
| `startDate` | Да | Начало периода в формате `YYYY-MM-DD` |
| `endDate` | Да | Конец периода в формате `YYYY-MM-DD` |
Передаётся ровно один параметр: `groupId` или `teacherId`. Максимальный диапазон — 120 дней. Если у группы нет назначения календарного графика на учебный год даты, расписание для неё возвращается пустым списком. Время пары берётся из базового слота правила, но для конкретной даты может быть заменено субботней или ручной сеткой времени из `/api/admin/time-slots`.
Передаётся ровно один параметр: `groupId` или `teacherId`. Максимальный диапазон — 120
календарных дат с учётом обеих границ: например, период с 1 января по 30 апреля
невисокосного года содержит ровно 120 дат и разрешён, а по 1 мая — уже 121 дата и
отклоняется. Если у группы нет назначения календарного графика на учебный год даты,
расписание для неё возвращается пустым списком. Время пары берётся из базового слота
правила, но для конкретной даты может быть заменено субботней или ручной сеткой времени из
`/api/admin/time-slots`.
**Пример:**
```http
@@ -973,7 +984,11 @@ payload обрабатываются один раз, используется
}
```
`specialtyId` и `specialtyProfileId` обязательны. Поле `specialityCode` сохранено как legacy-alias для старых клиентов и исторически содержит ID записи из `/api/specialties`. Текущий курс вычисляется из `yearStartStudy`, но не опускается ниже `0`, если обучение ещё не началось.
`groupSize`, `yearStartStudy` и все связанные идентификаторы должны быть положительными;
`specialtyId` и `specialtyProfileId` обязательны. Поле `specialityCode` сохранено как
legacy-alias для старых клиентов и исторически содержит ID записи из
`/api/specialties`. Текущий курс вычисляется из `yearStartStudy`, но не опускается ниже
`0`, если обучение ещё не началось.
Поле `active` показывает, можно ли выбирать группу в текущих рабочих сценариях. `studyState` принимает значения `ACTIVE`, `NOT_STARTED`, `GRADUATED`, `INACTIVE`, `ARCHIVED`.
@@ -1000,6 +1015,10 @@ payload обрабатываются один раз, используется
Несовместимое изменение возвращает `409 Conflict`; группа и её назначения остаются без
изменений.
Если у группы есть активные подгруппы, `groupSize` нельзя уменьшить ниже суммы их
`studentCapacity`. Такой запрос отклоняется без изменения группы. Параллельные изменения
группы и подгрупп сериализуются на backend и проверяются ограничениями PostgreSQL.
### `DELETE /api/groups/{id}`
Архивирование группы. Запись остаётся в истории, поэтому расписание за прошлые даты не теряет связь с группой.
@@ -1012,7 +1031,10 @@ payload обрабатываются один раз, используется
Подгруппы используются только для деления лабораторных занятий. Лекции и практики не принимают `subgroupId` и `subgroupIds`.
Для одной учебной группы сумма численностей активных подгрупп не может превышать численность самой группы. Frontend на вкладке `groups` настраивает деление как один из режимов: без подгрупп, две подгруппы или три подгруппы.
`studentCapacity` обязателен и должен быть больше нуля. Для одной учебной группы сумма
численностей активных подгрупп не может превышать численность самой группы. Frontend на
вкладке `groups` настраивает деление как один из режимов: без подгрупп, две подгруппы или
три подгруппы.
Имена подгрупп уникальны только среди активных подгрупп одной группы, поэтому после архивирования можно создать новую `Подгруппа 1`.
Частичное удаление подгруппы из активного деления запрещено, если после удаления оставшиеся подгруппы не покрывают всю численность группы. Количество подгрупп меняется через настройку режима деления.