Флагманский проект

Национальный ЭКГ-рейтинг ответственного бизнеса

Оценка ответственности бизнеса из ручной методики превратилась в работающую систему на 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 — и та проходит двойную экспертную проверку.

Реальная разбивка из карточки АО «Атомэнергопром». Каждое направление со своим потолком, итог — их сумма: 23 + 50 + 59 из 25 + 70 + 75.

Как это выглядит

Публичная карточка компании. Дерево показателей раскрыто: видно, какая часть балла посчитана автоматически из данных ФНС, а какая пришла из анкеты и прошла экспертную проверку. Ровно то, ради чего строилась вся система оценки.

Масштаб

~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 10GraphQLMySQLMeilisearchRedis + HorizonNuxt 3Vue 3Docker

Кто работал

  • Бэкенд: Laravel, GraphQL, интеграции, импорт данных
  • Фронтенд: публичный сайт на Nuxt, админка на Vue
  • Инфраструктура: Docker, очереди, поиск, деплой

Система работает прямо сейчас: экг-рейтинг.рф

Следующий шаг

Похожая задача?