Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
## API

- [Описание API](api.md)
- [Справочник вузов и сохранение старых названий](university-directory.md)
- [Ролевой виджет программы для Angular](modules/program-role-widget.md)
- [Swagger](https://api.procollab.ru/swagger)
- [Redoc](https://api.procollab.ru/redoc)
Expand Down
98 changes: 98 additions & 0 deletions docs/university-directory.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# Справочник вузов

Поле учреждения в профиле предлагает список и поиск по `/auth/universities/?search=...`.
Пустой запрос открывает список по алфавиту, `limit`/`offset` позволяют просмотреть остальные
записи. Поиск учитывает название, сокращения, город и полное название, игнорирует регистр,
различие `е`/`ё` и пунктуацию. Все слова запроса должны присутствовать в записи.

В Django-админке раздел **Пользователи → Вузы (справочник)** позволяет добавлять и менять
названия, сокращения, город, источник и дату проверки. Флаг «Показывать в списке» скрывает
запись из подсказок. Через публичный API справочник можно только читать.

`UserEducation.organization_name` продолжает хранить строку без связи со справочником.
Миграции не изменяют образование пользователей. Переименование, скрытие или удаление вуза
не меняет уже сохранённые названия. При открытии старой записи её текст сохраняется,
даже если его нет в новом списке. Пользователь сам выбирает новое название при редактировании.
«Другое» сохраняет введённое название школы, колледжа или отсутствующего учреждения;
поисковый запрос до выбора подсказки не считается новым названием.

## Начальное заполнение и источники

Миграция `0063` создаёт справочник; `0064` загружает первоначальный снимок из
`users/data/universities_20261004.json`; `0065` расширяет его из зафиксированного файла
`users/data/universities_20261004_full.json`. Итоговое начальное заполнение — **1 337
доступных записей**, включая филиалы и отдельно представленные ведомственные институты.
Число записей с признаком филиала в источнике — **534**. Это количество вариантов выбора,
а не статистическое число головных юридических лиц.

Снимок собран **4 октября 2026 года**:

- **1 229 записей** — весь публичный [каталог vuzbase](https://vuzbase.ru/universities),
все 62 страницы и все 1 229 карточек. По [описанию источников](https://vuzbase.ru/sources)
каталог использует мониторинг Минобрнауки и копии реестров Рособрнадзора. У всех карточек
указан действующий статус лицензии; 1 227 имеют последний мониторинг 2025 года, две —
мониторинг 2024 года; у 1 179 опубликованы сведения о приёме 2026 года. В JSON для каждой
карточки сохранены идентификатор мониторинга, ссылка на первоисточник, год данных,
ИНН/ОГРН, сведения о лицензии и ссылка на карточку.
- **108 дополнительных записей** — ведомственные учреждения и отсутствующие в основном
каталоге варианты: Минобороны (43), ФСБ (13), ФСИН (9), МВД (28), Росгвардия (4),
МЧС (7), ФСО (1), СВР (1), Институт медицинского образования НМИЦ имени Алмазова и
Балтийский филиал РГИСИ (2). Для каждой записи есть собственная ссылка на источник.
Ведомственные колледжи, кадетские училища и учреждения только дополнительного
профессионального образования в перечень вузов не включались.

Полные источники ведомств и даты документов перечислены в `departmental_sources` JSON.
Использованы [перечень Минобороны](https://vuz.mil.ru/Vysshie-uchebnye-zavedeniya) и
[официальная карта](https://vuz.mil.ru/map),
[перечень ФСБ](http://www.fsb.ru/fsb/supplement/employ/doc4.htm),
[перечень ФСИН](https://xn--h1akkl.xn--p1ai/organization/educate/) (обновлён 15.09.2026),
[структура Росгвардии](https://rosguard.gov.ru/ru/page/index/structure),
[перечень МЧС](https://mchs.gov.ru/contacts/uchrezhdeniya-i-organizacii/obrazovatelnye-uchrezhdeniya),
[материалы приёма ФСО 2026](https://fso.gov.ru/wp-content/uploads/2025/10/FSO2026.pdf) и
[материалы приёма СВР 2026](https://svr.gov.ru/upload/iblock/615/10122025r.pdf).
Ставропольский институт ФСБ дополнен по [публикации о приёме 2026](https://gnkk.ru/news/krasnoyarskikh-vypusknikov-priglashayut/).
Для МВД использован [оригинальный документ министерства 2024 года в архиве](https://app-prod-1.declarator.org/office/view-file/218057/):
более новая полная выгрузка ведомства при сборе не была доступна. Это ограничение
явно записано в метаданных; ссылки отдельных учреждений сохранены в записях.

Первоначальные **461 вуз и филиал** происходили из [навигатора приёма иностранных
студентов Минобрнауки](https://russia-edu.minobrnauki.gov.ru/) по циклу 2026/27 и всем
498 направлениям бакалавриата, специалитета и магистратуры. Этот узкий каталог больше
не определяет покрытие справочника. При сопоставлении сохранены коды 460 исходных
записей, а старые названия добавлены в поисковые сокращения и альтернативные названия.
ГАУ Северного Зауралья, [включённый в Тюменский госуниверситет](https://www.utmn.ru/o-tyumgu/reorganizatsiya/),
переходит в альтернативные названия преемника; отдельная исходная подсказка скрывается.

Миграция `0065` обновляет только записи, полностью совпадающие с исходным заполнением
`0064`. Любая правка названия, полного названия, сокращений, города, источника, даты
проверки или активности сохраняет всю запись администратора. Новые коды добавляются.
Вручную добавленные записи остаются. Повторное заполнение не создаёт дублей.
Обратный проход миграций заполнения не удаляет данные администратора.

Это проверенный снимок доступных публичных каталогов, **не гарантия полного состава
живого реестра лицензий на конкретную минуту**. Копии реестров у основного источника
обновляются ежемесячно и могут отставать до месяца; сам реестр Рособрнадзора был
недоступен для непосредственной сверки. Год мониторинга и дата получения снимка —
разные величины. Автоматического фонового обновления нет: список меняется в админке
или проверенным импортом, без перезаписи образования пользователей.

## Импорт обновлённого списка

Администратор может менять записи вручную или импортировать проверенный JSON того же
формата (`source_url`, `checked_at`, `universities` с `source_id`, `name`, `full_name`,
`aliases`, `city`; необязательный `source_url` отдельной записи заменяет общий источник):

```bash
python manage.py migrate
python manage.py import_universities path/to/checked-directory.json
```

По умолчанию импорт только добавляет отсутствующие коды, сохраняя ручные правки.
`--update-existing` явно обновляет сведения для существующих кодов; флаг активности,
ручные записи с другими кодами и образование пользователей сохраняются.
Исчезновение вуза из внешнего списка не приводит к автоматическому удалению или скрытию.
Перед импортом валидируется весь файл, запись выполняется в транзакции.

Фронтенд поддерживает названия до 255 символов — длину существующего поля backend.
При недоступности API остаётся ручной ввод через «Другое»; ошибка не выдаётся за отсутствие
совпадений. Для выкладки сначала применить backend-миграции, затем обновить фронтенд.
10 changes: 10 additions & 0 deletions users/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
Mentor,
UserAchievement,
UserEducation,
University,
UserLanguages,
UserLink,
UserSkillConfirmation,
Expand Down Expand Up @@ -439,6 +440,15 @@ def email(self, obj):
return obj.user.email


@admin.register(University)
class UniversityAdmin(admin.ModelAdmin):
list_display = ("name", "city", "is_active", "source_checked_at", "updated_at")
list_editable = ("is_active",)
list_filter = ("is_active", "source_checked_at")
search_fields = ("name", "full_name", "aliases", "city", "source_id")
readonly_fields = ("updated_at",)


@admin.register(UserEducation)
class UserEducationAdmin(admin.ModelAdmin):
list_display = ("id", "user", "organization_name", "entry_year")
Expand Down
Loading
Loading