Files
magistr/docs/API.md

14 KiB
Raw Blame History

🔌 REST API

Все эндпоинты имеют префикс /api/. Ответы возвращаются в формате JSON.


Аутентификация

POST /api/auth/login

Вход в систему.

Тело запроса:

{
  "username": "admin",
  "password": "admin"
}

Успешный ответ (200):

{
  "success": true,
  "message": "OK",
  "token": "550e8400-e29b-41d4-a716-446655440000",
  "role": "ADMIN",
  "redirect": "/admin/",
  "departmentId": 1,
  "userId": 1
}

Ошибка (401):

{
  "success": false,
  "message": "Неверное имя пользователя или пароль",
  "token": null,
  "role": null,
  "redirect": null,
  "departmentId": null,
  "userId": null
}

После получения токена клиент должен передавать его в заголовке: Authorization: Bearer <token>


Пользователи

GET /api/users

Список всех пользователей.

Ответ:

[
  { "id": 1, "username": "admin", "role": "ADMIN", "fullName": "Иванов Админ Иванович", "jobTitle": "Доцент", "departmentName": "Кафедра ИБ" },
  { "id": 2, "username": "Тестовый преподаватель", "role": "TEACHER", "fullName": "Петров Препод Петрович", "jobTitle": "Профессор", "departmentName": "Кафедра ВТ" }
]

GET /api/users/teachers

Список только преподавателей (роль TEACHER).

GET /api/users/teachers/{departmentId}

Список преподавателей привязанных к конкретной кафедре (роль TEACHER, код кафедры departmentId).

POST /api/users

Создание пользователя.

Тело запроса:

{
  "username": "teacher1",
  "password": "password",
  "role": "TEACHER",
  "fullName": "Test Teacher",
  "jobTitle": "Proffessor",
  "departmentId": 1
}

Валидация:

  • username — обязателен и уникален
  • password — минимум 4 символа
  • roleADMIN, TEACHER или STUDENT
  • fullName — обязателен
  • departmentId — обязателен

DELETE /api/users/{id}

Удаление пользователя.


Динамическое расписание

Новая модель расписания строится из правил (schedule_rules) и слотов (schedule_rule_slots). Фактические занятия рендерятся на диапазон дат.

GET /api/schedule

Получение расписания группы или преподавателя за период.

Параметры:

Параметр Обязателен Описание
groupId Да, если нет teacherId ID учебной группы
teacherId Да, если нет groupId ID преподавателя
startDate Да Начало периода в формате YYYY-MM-DD
endDate Да Конец периода в формате YYYY-MM-DD

Передаётся ровно один параметр: groupId или teacherId. Максимальный диапазон — 120 дней.

Пример:

GET /api/schedule?groupId=1&startDate=2026-04-27&endDate=2026-05-03

Ответ:

[
  {
    "scheduleRuleId": 10,
    "scheduleRuleSlotId": 31,
    "date": "2026-04-27",
    "dayOfWeek": 1,
    "dayName": "Понедельник",
    "weekNumber": 13,
    "parity": "ODD",
    "timeSlotId": 3,
    "timeSlotOrder": 3,
    "startTime": "11:40:00",
    "endTime": "13:10:00",
    "subjectId": 1,
    "subjectName": "Высшая математика",
    "teacherId": 2,
    "teacherName": "Петров Препод Петрович",
    "classroomId": 1,
    "classroomName": "101 Ленинская",
    "lessonTypeId": 1,
    "lessonTypeName": "Лекция",
    "lessonFormat": "Очно",
    "subgroupId": null,
    "groupIds": [1],
    "groupNames": ["ИВТ-21-1"],
    "activityType": "THEORY",
    "totalAcademicHours": 72,
    "consumedAcademicHoursBeforeLesson": 24,
    "remainingAcademicHoursAfterLesson": 46
  }
]

GET /api/admin/time-slots

Список временных слотов занятий. CRUD доступен по:

Метод URL Назначение
GET /api/admin/time-slots Список слотов
POST /api/admin/time-slots Создать слот
PUT /api/admin/time-slots/{id} Обновить слот
DELETE /api/admin/time-slots/{id} Удалить слот

Тело создания/обновления:

{
  "orderNumber": 1,
  "startTime": "08:00:00",
  "endTime": "09:30:00",
  "durationMinutes": 90
}

Календарный график администратора

Метод URL Назначение
GET /api/admin/calendar/years Учебные годы с семестрами
POST /api/admin/calendar/years Создать учебный год
PUT /api/admin/calendar/years/{id} Обновить учебный год
DELETE /api/admin/calendar/years/{id} Удалить учебный год
GET /api/admin/calendar/years/{academicYearId}/semesters Семестры учебного года
POST /api/admin/calendar/years/{academicYearId}/semesters Создать семестр
PUT /api/admin/calendar/semesters/{id} Обновить семестр
GET /api/admin/calendar/holidays?academicYearId=1 Праздники учебного года
POST /api/admin/calendar/holidays Создать праздник
PUT /api/admin/calendar/holidays/{id} Обновить праздник
DELETE /api/admin/calendar/holidays/{id} Удалить праздник
GET /api/admin/calendar/matrix?semesterId=1&courseNumber=1&specialtyId=2 Матрица учебного графика
PUT /api/admin/calendar/matrix Массовое сохранение матрицы

POST /api/admin/schedule-rules

Создание правила динамического расписания.

{
  "subjectId": 1,
  "semesterId": 1,
  "activeFromDate": "2026-02-01",
  "totalAcademicHours": 72,
  "groupIds": [1, 2],
  "slots": [
    {
      "dayOfWeek": 1,
      "parity": "BOTH",
      "timeSlotId": 3,
      "subgroupId": null,
      "teacherId": 2,
      "classroomId": 1,
      "lessonTypeId": 1,
      "lessonFormat": "Очно"
    }
  ]
}

CRUD доступен по:

Метод URL Назначение
GET /api/admin/schedule-rules Список правил, фильтры semesterId, groupId
GET /api/admin/schedule-rules/{id} Одно правило
POST /api/admin/schedule-rules Создать правило
PUT /api/admin/schedule-rules/{id} Обновить правило
DELETE /api/admin/schedule-rules/{id} Удалить правило

GET /api/lesson-types

Справочник типов занятий для конструктора правил расписания.

Ответ:

[
  { "id": 1, "name": "Лекция" },
  { "id": 2, "name": "Практика" }
]

Кафедры и специальности

Кафедры

Метод URL Назначение
GET /api/departments Список кафедр
POST /api/departments Создать кафедру
PUT /api/departments/{id} Обновить кафедру
DELETE /api/departments/{id} Удалить кафедру

Тело создания/обновления:

{
  "departmentName": "Кафедра ИБ",
  "departmentCode": 1
}

Специальности

Метод URL Назначение
GET /api/specialties Список специальностей
POST /api/specialties Создать специальность
PUT /api/specialties/{id} Обновить специальность
DELETE /api/specialties/{id} Удалить специальность

Тело создания/обновления:

{
  "specialityName": "Программная инженерия",
  "specialityCode": "09.03.04"
}

Группы

GET /api/groups

Список всех групп.

Ответ:

[
  {
    "id": 1,
    "name": "ИВТ-21-1",
    "groupSize": 25,
    "educationFormId": 1,
    "educationFormName": "Бакалавриат",
    "departmentId": 1,
    "course": 3,
    "specialityCode": 1
  }
]

GET /api/groups/{departmentId}

Список всех групп привязанных к конкретной кафедре.

POST /api/groups

Создание группы.

{
  "name": "ИВТ-11",
  "groupSize": 12,
  "educationFormId": 1,
  "departmentId": 1,
  "yearStartStudy": 2026,
  "specialityCode": 1
}

specialityCode исторически содержит ID записи из /api/specialties; текущий курс вычисляется из yearStartStudy.

DELETE /api/groups/{id}

Удаление группы.


Аудитории

GET /api/classrooms

Список аудиторий с привязанным оборудованием.

Ответ:

[
  {
    "id": 1,
    "name": "101 Ленинская",
    "capacity": 120,
    "isAvailable": true,
    "equipments": [
      { "id": 1, "name": "Проектор" },
      { "id": 4, "name": "Интерактивная доска" }
    ]
  }
]

POST /api/classrooms

Создание аудитории.

{
  "name": "404 Лаборатория",
  "capacity": 30,
  "isAvailable": true,
  "equipmentIds": [1, 2, 3]
}

PUT /api/classrooms/{id}

Обновление аудитории (partial update).

DELETE /api/classrooms/{id}

Удаление аудитории.


Дисциплины

GET /api/subjects

Список всех дисциплин.

{ 
  "name": "Физика",
  "code": null,
  "departmentId": 1
}

GET /api/subjects/{departmentId}

Список всех дисциплин привязанных к кафедре.

POST /api/subjects

{ 
  "name": "Физика",
  "code": null,
  "departmentId": 1
}

DELETE /api/subjects/{id}

Удаление дисциплины.


Оборудование

GET /api/equipments

Список всего оборудования.

POST /api/equipments

{ "name": "3D-принтер" }

DELETE /api/equipments/{id}

Удаление оборудования.


Формы обучения

GET /api/education-forms

Список форм обучения.

Ответ:

[
  { "id": 1, "name": "Бакалавриат" },
  { "id": 2, "name": "Магистратура" }
]

POST /api/education-forms

{ "name": "Аспирантура" }

DELETE /api/education-forms/{id}

Удаление формы обучения. Невозможно, если к ней привязаны группы.


Привязка «Преподаватель ↔ Дисциплина»

GET /api/teacher-subjects

Список всех привязок.

Ответ:

[
  {
    "userId": 2,
    "userName": "Тестовый преподаватель",
    "subjectId": 1,
    "subjectName": "Высшая математика"
  }
]

POST /api/teacher-subjects

{
  "userId": 2,
  "subjectId": 3
}

DELETE /api/teacher-subjects

{
  "userId": 2,
  "subjectId": 3
}

Управление тенантами (Базы данных)

GET /api/database/status

Статус текущего подключения (определяется по домену запроса).

Ответ:

{
  "tenant": "default",
  "connected": true,
  "configured": true,
  "name": "Default",
  "url": "jdbc:postgresql://db:5432/app_db"
}

GET /api/database/tenants

Список всех тенантов.

POST /api/database/tenants

Добавление нового тенанта.

{
  "name": "СВФУ",
  "domain": "swsu",
  "url": "jdbc:postgresql://db-host:5432/swsu_db",
  "username": "dbuser",
  "password": "dbpass"
}

Логика:

  1. Создаёт HikariCP пул для нового тенанта
  2. Запускает Flyway миграции на его БД
  3. Обновляет Kubernetes ConfigMap

DELETE /api/database/tenants/{domain}

Удаление тенанта.

POST /api/database/test

Тест подключения к произвольной БД (без регистрации тенанта).

{
  "url": "jdbc:postgresql://host:5432/testdb",
  "username": "user",
  "password": "pass"
}

Ответ:

{
  "success": true,
  "message": "Подключение успешно!"
}

Коды ответов

Код Описание
200 Успех
400 Ошибка валидации (с message в теле)
401 Неверные учётные данные
404 Ресурс / тенант не найден
500 Внутренняя ошибка сервера