Флагманский проект
Национальный ЭКГ-рейтинг ответственного бизнеса
Оценка ответственности бизнеса из ручной методики превратилась в работающую систему на 7,8 млн компаний с публичной карточкой у каждой
- Государственный рейтинг, ГОСТ Р 71198
- 7,8 млн компаний, 96 таблиц, 202 тыс. строк кода
- Мы на проекте с июня 2025; система в разработке с 2022, публичный сайт с апреля 2024
Было
Система работала с апреля 2024, но её делала другая команда. В июне 2025 разработку передали нам целиком — вместе с чужой кодовой базой на 200 тысяч строк и обязательствами перед государственным заказчиком.
Сделали
Приняли систему и ведём её с тех пор: перевели рейтинг на новую версию ГОСТ, переписали поиск и фильтр, добавили меры поддержки, новости с модерацией и интеграции с площадками вакансий.
Стало
Две трети всей истории проекта — коммиты после нашего прихода. У каждой из 7,8 млн компаний публичная карточка с баллом; правки выходят каждую неделю.
Что это за система
ЭКГ-рейтинг оценивает компании по трём направлениям — экология, кадры, государство. Часть баллов считается автоматически из выгрузки ФНС, часть компания заявляет сама в анкете, а эксперты её проверяют.
Система состоит из четырёх частей: публичный сайт с карточкой на каждую компанию, личные кабинеты компаний и регионов, административная панель для экспертов и операторов рейтинга, и внешнее API.
Оператор первого этапа — Ассоциация «Центральный Федеральный Округ» при технологической поддержке ФНС России. Операторы второго этапа — НИУ ВШЭ, Финансовый университет при Правительстве РФ, Государственный университет управления и РЭУ им. Плеханова. Координация — Аппарат полномочного представителя Президента РФ в ЦФО.
Как собирается балл
- Экология
- 23 из 25
- Кадры
- 50 из 70
- Государство
- 59 из 75
Выбросы, отходы, водопотребление
Оплата труда, стабильность состава, демографическая политика
Финансовая устойчивость, налоговая история, благонадёжность
Итоговая оценка
132 из 170
Часть слагаемых считается автоматически из выгрузки ФНС, часть компания заявляет в анкете по ГОСТ Р 71198 — и та проходит двойную экспертную проверку.
Как это выглядит
Масштаб
- ~7,8 млн
- Компаний в базе
- 243 / ~96
- Миграций / таблиц
- 81 модель, 113 DTO
- Моделей и DTO
- 69 узлов, 4 уровня, 57 листьев
- Дерево ГОСТ
- 120 валидных из 160 комбинаций
- Профилей компаний
- 57 вопросов, 161 вариант ответа, 11 статусов
- Анкета
- 8 ролей, 25 политик доступа
- Роли и права
- админка 65, публичный сайт 34
- Экранов
- 117 GraphQL-запросов, 134 мутации, 35 REST
- API
- 9 систем
- Внешних интеграций
- 27 задач, 4 очереди, 96 команд
- Фоновая обработка
- ~202 тыс. строк, 6778 коммитов
- Кодовая база
Числа посчитаны по коду и схеме базы. Объёмы данных взяты из комментариев в коде, а не из замера на продакшене, — там, где это так, сказано отдельно.
Фильтр по дереву ГОСТ на 7,8 млн компаний
- В чём сложность
- Проверка «прошла ли компания узел дерева» шла по таблице результатов в сотни миллионов строк. LEFT JOIN с условием OR давал полный скан — интерактивным фильтр при этом быть не мог.
- Что рассматривали
- Оставить запрос по таблице результатов и оптимизировать индексы. Материализовать связь «компания — пройденный узел». Вынести фильтрацию в поисковый движок.
- Что выбрали и почему
- Сделали материализованную таблицу и три стратегии запроса по числу выбранных узлов: один узел — обычный WHERE, до шестидесяти — self-JOIN, дальше — GROUP BY HAVING. Выбор не на глаз: в проекте живёт команда-бенчмарк, прогоняющая шесть вариантов запроса по секциям дерева.
- Что из этого вышло
- Позже глубокую выдачу перенесли в поисковый движок целиком, а SQL-метод оставили помеченным как справочный. Отдельно нашлась пересборка на 52 минуты — джойн ради одного поля; убрали, блок стал index-only.
Граница в шестьдесят узлов не выбрана из соображений красоты: MySQL не допускает больше 61 таблицы в одном JOIN.
Полный реиндекс поиска без простоя
- В чём сложность
- Штатный импорт в поисковый движок не подошёл: он перестраивает фасеты на каждом батче. В комментарии зафиксировано 75–155 секунд на батч при полутора сотнях батчей.
- Что рассматривали
- Смириться со временем и индексировать ночью. Резать батчи мельче. Написать свой заливщик.
- Что выбрали и почему
- Написали свой: заливка во временный индекс, настройки фильтров ставятся ПОСЛЕ заливки, затем атомарная подмена индексов. Формула рейтинга намеренно продублирована в SQL-выражении — вызывать сервис на каждую из миллионов записей нельзя.
- Что из этого вышло
- После инцидента, когда таймаут ронял задачу до подмены и боевой индекс оставался пустым, добавили запрет параллельного запуска и проверку после подмены.
Двойная экспертная проверка анкет
- В чём сложность
- Оценку компании ставит эксперт. Одного эксперта мало: рейтинг государственный, и субъективность одного человека в нём недопустима.
- Что рассматривали
- Привязать оценки к анкете и перезаписывать. Ввести раунды проверки.
- Что выбрали и почему
- Оценки привязаны не к анкете, а к раунду: эксперт → региональный эксперт → второй эксперт из другой команды → администратор. Принципиальное решение — админский раунд наследует предыдущие оценки, а экспертские нет. Иначе второй эксперт видел бы решение первого, и независимость проверки пропадала.
- Что из этого вышло
- Схема работает, но идеальной не оказалась: в июле выяснилось, что итог считался строго по последнему админскому раунду и пустой раунд обнулял анкету. Починили, данные восстановили.
Текстовое описание компании: языковую модель попробовали и отказались
- В чём сложность
- Каждой компании нужно текстовое пояснение к оценке — почему балл такой и на что обратить внимание.
- Что рассматривали
- Генерировать языковой моделью. Собирать из шаблонов.
- Что выбрали и почему
- Пробовали генеративную модель — в репозитории остались промпт на 301 строку и примеры ответов. В продукт пошёл детерминированный шаблонный движок: заказчику нужны согласованные формулировки с точностью до слова, вплоть до того, где допустимо слово «риски», а тексты ступеней должны редактироваться из админки.
- Что из этого вышло
- Генеративная модель этого не гарантирует. Отказались осознанно, а не потому что не получилось.
Импорт выгрузки ФНС
- В чём сложность
- У ФНС нет API — только ручная выгрузка нестандартным CSV с разделителем «доллар», 88 колонок, полтора гигабайта, 7,7 млн строк.
- Что рассматривали
- Разложить файл по очереди задач. Обрабатывать потоком в одном процессе. Резать файл и обрабатывать параллельно.
- Что выбрали и почему
- Физическое разрезание файла и параллельные процессы. Число воркеров пересчитывается под железо на каждом деплое, причём одно ядро намеренно оставлено базе и поиску. Повторный импорт делается не через UPSERT — в комментарии зафиксировано «в 5–10 раз медленнее», — а созданием новой таблицы с переносом только нужных строк и переименованием.
- Что из этого вышло
- Импорт перестал быть ночным событием, требующим присмотра.
Продукт внутри продукта
Что было, когда мы пришли
Систему запустили в апреле 2024, делала её другая команда. В июне 2025 разработку передали нам — целиком, вместе с работающим государственным сервисом, который нельзя останавливать.
Передача видна прямо в истории репозиториев: до мая 2025 в авторах один набор имён, с июня 2025 — другой. Это была не помощь чужой команде, а полная смена подрядчика на живой системе.
Принимать чужой код на 200 тысяч строк без автотестов — отдельная задача. Первые месяцы ушли на то, чтобы разобраться в методике расчёта, в импорте из ФНС и в том, почему поиск ведёт себя так, как ведёт. Правки в этот период выглядят соответствующе: «Фикс поиска 01», «Фикс поиска 08» — восемь заходов подряд, пока не стало понятно устройство.
Что сделали с июня 2025
Перевели рейтинг на новую версию ГОСТ. Стандарт поменялся, а вместе с ним — вся методика расчёта: другие показатели, другие максимумы, другие профили компаний. Самая крупная работа за весь период: 663 слияния в отдельную ветку, публичная часть переделывалась с ноября 2025.
Переписали поиск и фильтр. Фильтр по дереву ГОСТ на миллионах компаний, глубокий поиск с кэшем. Кэш пришлось учить сбрасываться после фиксации транзакции, а не до — иначе он успевал прогреться старыми данными.
Добавили меры поддержки и кабинеты регионов. Регион заходит в свой кабинет и ведёт реестр ответственных предприятий на своей карточке.
Сделали новости с модерацией. Компания предлагает материал из своего кабинета, редакция проверяет и публикует.
Подключили площадки вакансий. На карточке компании видно её вакансии с HeadHunter, «Работы России» и SuperJob, со счётчиком переходов.
Открыли данные наружу. REST-интерфейс глубокого фильтра, чтобы сторонние сайты могли строить выборки по рейтингу.
Привели в порядок то, что достали. Один пример вместо общих слов: 109 ошибок проверки типов в публичной части — теперь ноль.
Что было сложным
Объём. Миллионы компаний и сотни миллионов строк результатов при требовании держать фильтр и поиск интерактивными.
Источник данных. У ФНС нет API — только ручная выгрузка нестандартным форматом.
Регуляторика. Методика задана ГОСТ. Максимумы баллов не выдумываются, а разбираются скриптом из методички: справочник на 1576 пар «профиль — показатель».
Персональные данные. Личные кабинеты, вход через ЕСИА, приватное хранилище с временными ссылками.
Работа на живой системе. Миграции и полный реиндекс без остановки публичного сайта.
Легаси. Совместимость с анкетами прошлого стандарта и импорт баллов со старого сайта.
Откуда эти цифры
- июнь 2025
- Мы на проекте с
- 4489 из 6778 за всю историю проекта — 66%
- Коммитов после нашего прихода
- 663
- Слияний в ветку перехода на новый ГОСТ
- 2022
- Система в разработке с
- апрель 2024
- Публичный сайт с
- ~202 тыс. строк
- Кодовая база без зависимостей
- да, правки этой недели
- Сопровождается
Всё в таблице посчитано по истории трёх репозиториев заказчика. Открыть их посторонним мы не можем, поэтому проверить эти числа со стороны нельзя — показываем на экране при разговоре. Проверить можно другое: сам сайт открыт, зайдите и посмотрите, работает ли то, что здесь описано. Бизнес-метрик заказчика тут нет вовсе — их не измеряли и нам не передавали.
Чего в проекте нет
Автотестов практически нет: 12 классов и 34 метода на бэкенде, один смоук-тест в админке, на публичном сайте ни одного. В непрерывной сборке стадии тестирования нет вовсе.
Это осознанная позиция владельца продукта, а не упущение подрядчика. Пишем об этом прямо: кейс, в котором всё безупречно, не бывает правдой.
Что умеет система
- Публичная карточка с оценкой у каждой компании из базы
- Поиск и фасетная фильтрация по всей базе
- Фильтр по дереву показателей ГОСТ
- Личные кабинеты компаний и регионов
- Анкетирование с двойной экспертной проверкой
- Импорт выгрузки ФНС
- Реестр региональных мер поддержки
- Административная панель для экспертов и операторов
Технологии
Кто работал
- Бэкенд: Laravel, GraphQL, интеграции, импорт данных
- Фронтенд: публичный сайт на Nuxt, админка на Vue
- Инфраструктура: Docker, очереди, поиск, деплой
Система работает прямо сейчас: экг-рейтинг.рф
Следующий шаг