Платформу с нуля можно завалить двумя способами. Гнать ядро ради скорости — и на третьем-четвёртом заказе доработок начнётся переписывание. Вылизывать архитектуру без оглядки на сроки — и заказчик перестанет понимать, за что платит, а проект забуксует на старте. Мы развели эти риски на уровне договоров: их было два. Первый закрывал ядро, второй добавлял модули, и с самого старта действовало правило «ядро не торопить ради модулей». С даты первого договора до сдачи платформы прошло 152 дня. На этом ядре потом выросло всё остальное: за следующие четыре с лишним года через тот же чат прошло несколько десятков заказов и ТЗ, и ни один не потребовал переписать ядро.
Сводка
| Отрасль конечного клиента | Сертификация продукции, B2B-аналитика рынка |
| Конечный клиент | «Аналитика сертификатов» — группа компаний, внутренняя платформа |
| Формат сотрудничества | Прямая разработка по ТЗ, два последовательных договора |
| Тип проекта | Административная B2B-платформа аналитики рынка сертификации, написанная с нуля на замену старой системе |
| Объём работ | Внутренний административный интерфейс над государственными реестрами аккредитованных лиц, деклараций и сертификатов соответствия; заложен под несколько стран ЕАЭС |
| Дата проекта | 17 сентября 2021 — 15 февраля 2022 (152 дня) |
| Трудозатраты | 342 часа (170 ч ядро + 172 ч модули) |
| Команда | Антон Херсун (руководитель проекта) и разработчик аналитической панели — он ведёт это направление с первого дня и до сегодня |
| Технологический стек | Laravel 8 · PHP 8 · Sencha 6 (ExtJS) · MariaDB · модульная архитектура |
| Сдано | Работающее ядро и шесть модулей на замену старой версии аналитика, которую закрыли в марте 2022. На этом ядре за следующие годы выпустили несколько десятков итераций доработок. |
Постановка задачи
Заказчик работает с рынком сертификации продукции. У него уже была система аналитики, заточенная под узкий набор данных, и её решили закрыть. Понадобилась новая платформа, которая держала бы государственные реестры с разными структурами данных в одной аналитической среде и развивалась годами, а не до первого крупного изменения.
ТЗ заказчик расписал по функциональным разделам: «Аккредитованные лица», «Декларации ТР ТС», «Сертификаты соответствия» и так далее. Платформа задумывалась как внутренний административный интерфейс: без публичной части, без внешнего API, доступ только сотрудникам группы.
Что в этом сложного. Риск при найме партнёра под разработку с нуля простой: через полгода ядро упирается в архитектурные ограничения, и платить приходится второй раз — за то, что недавно приняли в эксплуатацию. В момент подписания ТЗ заказчик ещё не знает, какие из перечисленных разделов через год станут центральными, а какие отвалятся. Поэтому ядро мы делали с расчётом на десятую итерацию, а не на первую: каждый раздел сделан как самостоятельная единица, общий код между разделами не писали, а точки приёмки развели отдельно на ядро и на модули.
Как мы это сделали
1. Два договора вместо одного: сначала ядро, потом модули.
Договор №1 от 17 сентября 2021 закрывал только ядро: серверная часть на Laravel 8 и PHP 8 (80 ч) и клиентская часть на Sencha 6 (90 ч), итого 170 ч. Договор №2 от 22 сентября добавлял модули поверх ядра: конструктор табличных данных, подключение существующих баз, выгрузку в Excel, фильтрацию-поиск-группировку, архивирование, документирование кода (172 ч). У бюджета появились две точки приёмки: заказчик увидел работающее ядро, и только после этого пошли модули.
2. Sencha 6 (ExtJS) для административной части, а не React.
«Почему не React?» — этот вопрос в 2021-м мы слышали чаще всего. Потому что речь об административном интерфейсе с тяжёлыми таблицами на сотни тысяч строк: Sencha grid держит их из коробки, а на React пришлось бы наращивать обвес из сторонних библиотек. Вторая причина — заявленный срок поддержки: на 2021 год у Sencha 6 он был семь и более лет, для внутреннего B2B-инструмента это весомее модности стека. К 2026 году выбор себя оправдал: интерфейс ни разу не переписывали по «технологическим» причинам, только расширяли под новые модули.
3. Каждый раздел как самостоятельный модуль, без общего кода между реестрами.
Реестров несколько, и у каждого своя структура полей. Если связать их общим кодом, любая правка под один реестр ломает соседний. Поэтому сделали иначе: один общий конструктор табличного отображения и отдельный конфиг полей для каждого раздела. Добавить новый реестр — это новый конфиг и, при необходимости, отдельный парсер источника; в общий код залезать не нужно. Решение окупилось не раз. Когда через год понадобился модуль «Аккредитованные лица» примерно на 30 тысяч записей, он подключился как новый раздел, без правок ядра.
4. Документирование кода как отдельная строка в смете на 10 часов.
В Договоре №2 есть явная строка «Документирование программного кода — 10 ч». На проектах с нуля это редкость: документацию обычно сдвигают на «потом», а оно так и не наступает. Здесь её внесли в объём работ и сдали по приёмке вместе с остальным. Для заказчика это страховка на случай смены разработчика: направление с первого дня ведёт один человек, но если когда-нибудь придётся передавать, будет с чего начать.
5. Конструктор полей вместо жёстко прописанного списка в коде.
Главное архитектурное решение модульной части, 40 часов в смете: администратор сам выбирает поля для отображения, подробного просмотра, выгрузки и поиска и привязывает таблицы к разделам меню. Без конструктора каждое изменение списка полей оборачивалось бы правкой кода и выкаткой новой версии; с ним настройка идёт через интерфейс, без перезапуска. Тот же конструктор позже лёг в основу всех табличных отчётов и групповой статистики, которые наращивались поверх платформы в следующие месяцы.
Что показала первая зима эксплуатации
Старую систему не выключили в день сдачи. Её гасили постепенно, по мере того как новая платформа забирала на себя данные, и окончательно вход в старый аналитик закрыли в начале марта 2022 года, когда заказчик подтвердил, что нужды в нём больше нет. Осторожность себя оправдала.
В январе 2022-го при переносе исторических данных всплыл дефект старой схемы хранения: даты когда-то копировались по неправильному алгоритму, и у порядка 26 тысяч записей за 2018 год день превратился в год. Источник правки в старой системе было уже не найти. Разобрали алгоритм, исправили испорченные записи, а исторический пласт, который заказчику в общей таблице был не нужен, увели в архив. Здесь и пригодился модуль архивирования из Договора №2: данные не удаляются и не теряются, а уходят в отдельный слой. В новой платформе даты с самого начала лежат как даты, без копировальных схем, так что повтор инцидента исключён.
Тогда же на платформе появились первые заказы поверх ядра, и не все они «взлетели». Один из ранних модулей, поиск продукции по сводным кодам ТР ТС и ТН ВЭД, мы сделали полностью: собрали базу примерно на 26 тысяч позиций, подняли формы поиска, сдали по акту — а применения заказчик ему в работе так и не нашёл. Вместо того чтобы дорабатывать впустую за оставшиеся в ТЗ часы, мы сами предложили закрыть направление и пустить остаток на полезную мелочь: честный статус «сделано, но не нашло применения» дороже, чем закрытый акт ради акта. Идея при этом не умерла. В 2023-м заказчик вернулся к ней с модулем «предложки», где сотрудники подают запросы-предложения со статусами и перепиской; ТЗ проработали и одобрили, но запуск заказчик отложил, и статус этой ветки прежний: одобрено, не запущено.
Результаты
| Метрика | Значение |
|---|---|
| Часы по ТЗ | 170 ч (ядро) + 172 ч (модули) = 342 ч |
| Календарь | 17.09.2021 — 15.02.2022 · около 5 месяцев · 152 дня |
| Команда | 2 специалиста |
| Модули в ядре | конструктор таблиц, подключение баз, выгрузка в Excel, фильтрация-поиск-группировка, архивирование, документирование |
| Замена старой системы | старый аналитик погашен постепенно и закрыт в марте 2022, с переносом и чисткой исторических данных |
| Развитие после сдачи | несколько десятков заказов и ТЗ за следующие четыре с лишним года — без переписывания ядра |
Что получилось: административная B2B-платформа с собственным конструктором табличных данных, модульной архитектурой по реестрам, выгрузкой в Excel и системой архивирования. На этом ядре за следующие годы выросло несколько крупных направлений: парсинг иностранных реестров, аналитика и групповая статистика, конструктор шаблонных документов, интеграции с amoCRM и Битрикс24.
Процесс и хронология
| Этап | Когда | Результат |
|---|---|---|
| Исследование задачи, ТЗ на ядро | сентябрь 2021 | Договор №1 подписан 17.09.2021, ТЗ зафиксировано, выбран стек |
| Сборка ядра | сентябрь–октябрь 2021 | Серверная часть на Laravel, клиентская часть на Sencha 6 (170 ч) |
| ТЗ на модули, параллельный старт | 22.09.2021 | Договор №2 подписан до завершения ядра, чтобы команда не простаивала |
| Сборка модулей | осень 2021 — зима 2022 | 6 модулей по плану (172 ч) |
| Первые заказы поверх ядра | декабрь 2021 — февраль 2022 | Групповая статистика открыта пользователям 17.12.2021; доп. функционал отчётов на тесте 20.01.2022 |
| Перенос данных, исправление дат | январь 2022 | Дефект старой схемы дат локализован и исправлен, исторический пласт уведён в архив |
| Приёмка и замена старой системы | февраль–март 2022 | Платформа принята, старый аналитик закрыт окончательно |
Договор №2 подписан до завершения ядра, чтобы этапы шли внахлёст и команда не простаивала между ними. Разница между суммой рабочих этапов и 152 календарными днями — это ритм согласований у заказчика и обычные праздничные паузы.
Команда
- Антон Херсун, Xaver Pro, руководитель проекта, архитектор, формализация ТЗ, работа с заказчиком
- Разработчик аналитической панели: ведёт основную платформу с первого дня и до сегодня. Кто написал модуль в 2021-м, тот его и правит сейчас. Любая доработка спустя годы остаётся в руках того же человека, без передачи кода между людьми.
Скриншоты и материалы
Будут добавлены отдельным проходом после согласования с заказчиком: внутренний интерфейс требует обработки приватности перед публикацией.
Если планируете сборку B2B-аналитики с нуля и не уверены, что выбрать в стеке, пришлите бриф и список интеграций. Скажем, где можно сэкономить на стандартных модулях и где придётся писать руками. Разбор бесплатный.