# 11. Отчёт этапа 1: identity **Дата:** 2026-10-23. **Статус:** этап 1 выполнен; этап 2 (academic) — следующий. ## 1. Что сделано ### Роли и аккаунты - Добавлена роль `TEACHER` в `LmsRole`; БД уже допускает её миграцией `V4`. - `Account` получил `status` (`ACTIVE/ARCHIVED`) и `archivedAt`. - Вход запрещён для архивных аккаунтов и студентов в статусах `EXPELLED/GRADUATED/ARCHIVED`. ### Группы-когорты - `GroupEntity`: `stream`, `course`, `number`, `degree`, `enrollmentYear`, `status` (`ACTIVE/GRADUATED/ARCHIVED`). - `name` больше не уникально; уникальность — по кортежу когорты. - `GroupNameParser` разбирает `ПИ-11БО`, `ИВТ-ТОП-12БО` и т.п. - `GroupCohortResolver` валидирует степень, курс, номер и год набора, вычисляет год набора по умолчанию. - Создание группы через админку — по полям, имя собирается автоматически. ### Студенты и история - `Student`: `status` и `enrollmentYear`. - `MembershipHistory`: `ENROLL`, `TRANSFER`, `IMPORT`, `EXPELL` и остальные действия; записи создаются при зачислении, переводе, импорте и отчислении. - При отчислении студент получает `EXPELLED`, аккаунт и данные сохраняются. - Повторное зачисление возвращает `ACTIVE` и пишет `TRANSFER`. ### Импорт Excel/CSV v2 Шаблон: ```text поток | курс | номер | степень | год набора | ФИО | № | база ``` - Поддерживаются `.xls`, `.xlsx`, `.csv`, разделители `;`, `,`, tab. - ФИО можно одной колонкой или отдельными `Фамилия/Имя/Отчество`. - Все строки должны быть одной группой. - Проверяются степень, диапазон курса, год набора, пустые поля, дубли `№` внутри файла. - Импорт атомарный: при ошибках данные не меняются, возвращается отчёт с номерами строк. - Ключ слияния — `student_no`; группа ищется по кортежу, при отсутствии создаётся. - Новые студенты получают временный пароль; пароли показываются один раз. ### UI - Страница групп: год набора, статус, создание по полям, описание нового импорта. - Страница группы: год набора, статус группы, статус студента. - Страница пользователей: статус студента. - При ошибке импорта показывается таблица «строка — ошибка». ## 2. Тесты Добавлены: - `GroupNameParserTest` — разбор имени, диапазоны курсов; - `StudentImportParserTest` — валидный шаблон, дубли, разные группы, недопустимый курс, неизвестная шапка; - `GroupServiceIntegrationTest` — создание когорты, дубликат, импорт, атомарность ошибок, перевод, отчисление, запрет входа после отчисления. Проверки: - `./gradlew :services:identity-service:test :web:test` — успешно; - `ktlintCheck` и `detekt` для identity/web — успешно. ## 3. Ограничения этапа - Импорт поддерживает одну группу на файл; мультигрупповой файл — позже. - Номер группы числовой (`01` и `1` — одно значение). Отдельный строковый номер и различие `ПИ-11БО`/`ПИ-101БО` как разных когорт не требуются; имя группы по-прежнему строится из полей. - Роль `TEACHER` уже есть в домене, но кабинет преподавателя и назначения на курс — этапы 2–3. - `ACADEMIC_LEAVE` пока может входить; режим «только чтение» — этап 3. - Отчисление пока простое; причины, подтверждение и аудит — этап 4. - Старый формат импорта (только студенческие колонки) больше не поддерживается. ## 4. Следующий этап Этап 2 — academic: - курсы, `course_teachers`, `course_groups`; - `course_no` и `/learn/course/{course_no}/...`; - `labs.course_id` и перенос лаб в курс C; - `chapters.course_id/audience`, перенос материалов; - активы и копирование лабораторных; - админ-UI курсов.