Привет, Хабр! Меня зовут Алексей, я разработчик в строительной компании ВитионГруп. Мы занимаемся ремонтом квартир в Москве, одновременно ведём 30–75 объектов, за 18 лет завершили более 1000 проектов.
В 2022 году я начал разрабатывать внутренний инструмент для управления ремонтными проектами. За три года из «чата с заказчиком» вырос полноценный продукт: PWA с чек-листами и таск-трекером, видеонаблюдением, конструктором смет, финансовым модулем и интеграцией с ИИ. Сейчас на базе этой системы работают два продукта по подписке, которыми пользуются строительные компании, а также частные мастера и их заказчики из разных регионов России и Казахстана.

В этой статье расскажу про архитектурные решения, грабли и нюансы, которые были неочевидны на старте.
Предметная область: почему готовые CRM не подходят
Прежде чем писать код, мы протестировали около 15 готовых решений. Проблема в том, что ремонтно-строительный проект — это не «сделка» и не «тикет». Это процесс на 6–18 месяцев, в котором параллельно участвуют:
заказчик (хочет видеть, что происходит, но не хочет вникать в детали);
сметчик (формализует пожелания заказчика и просчитывает объёмы работ и материалов)
менеджер (координирует всё);
руководитель (должен видеть картину по всем объектам одновременно, не погружаясь в каждый);
техконтроль (принимает работы у мастеров);
мастера разных специализаций (штукатуры, электрики, сантехники, плиточники — заезжают по очереди);
отдел снабжения (закупает и доставляет материалы).
Каждому нужен свой интерфейс, свой набор данных и свои права доступа. При этом все они работают над одним объектом, и информация должна быть синхронизирована в реальном времени.

Готовые CRM закрывали максимум 1–2 аспекта. Bitrix24, amoCRM — это воронки продаж, а не управление строительным проектом. Trello/Asana — управление задачами, но без смет, чек-листов с фотофиксацией и финансового контроля. Сметные программы содержат только функции по работе со сметой (а у нас, конечно же, давно составлена и отработана собственная смета). Специализированных решений для ремонта квартир, содержащих в себе все необходимые нам инструменты, на российском рынке мы не нашли.
Стек и архитектура
Почему PWA, а не нативное приложение
Ключевое требование: приложением пользуются все — от руководителя компании до мастера-штукатура. Мастера в основном работают на Android-смартфонах разных поколений, заказчики — часто на iPhone, менеджеры и сметчики иногда открывают систему с десктопа.
Три нативных приложения (iOS + Android + web) при нашем размере команды — нецелесообразно. PWA решила задачу: одна кодовая база, установка на рабочий стол, push-уведомления, работа без обновлений — пользователь всегда на актуальной версии.

Бэкенд реализован на PHP Laravel, фронтэнд - переработанный под нас шаблон AdminLTE (изначально для ускорения процесса разработки собирали интерфейс из простых готовых компонентов). Базовая (для собственного использования) версия программы сейчас представляет собой монолит с единой авторизацией и отдельными кабинетами для сотрудника, мастера и заказчика. В целом, такая схема на данный момент работает весьма сносно. Единственный глобальный момент, который не учли при планировании и пришлось подставить костыль - у одного заказчика может быть несколько объектов. Поэтому пришлось сделать возможность связки аккаунтов. В дальнейшем, для следующих версий программы, при проектировании уже сразу разделили аккаунты, профили и объекты.
Laravel отлично справляется с нашими задачами в первую очередь из-за своей распространённости: большинство из того, что нам на данный момент понадобилось, уже есть из коробки или в виде готовых пакетов. Пришлось делать самим только очевидные мелочи вроде отправки уведомлений в MAX - заодно оформили их отдельным пакетом по аналогии с laravel notification channels: уведомления отправляются стандартными средствами.
Разумеется, есть мелкие нюансы одного решения для всех платформ. На данный момент, например, есть один неприятный момент, решение которого пока не нашли: у нас в пушах о новых сообщениях в чате есть кнопки-экшны пометки сообщения прочитанным и ответа на него прямо из пуша. Так вот при прочтении сообщений кнопкой на некоторых версиях Android, шторка с пушами закрывается каждый раз при тыке кнопки прочтения - максимально неудобно, но со своей стороны пока сделать с этим ничего не можем.
По железной части: программа работает на виртуальном сервере reg.ru в Москве, для хранения загружаемых данных примонтирован сервер хранения с большим диском, арендуемых в FirstVDS, в постоянном режиме делаем бекапы всего на три разных сервера хранения, арендуемых у разных хостеров. Однажды полностью вышел из строя сервер хранения - пришлось заменить его другим и восстановить бекап - обошлось без потери данных, ну и пару раз находили понадобившуюся давно удалённую информацию. Других проблем, к счастью, пока не было. Хочется отметить отличную работу reg.ru: за всё время работы была только одна быстрая перезагрузка сервера, ничего по сути, нам не испортившая, и с тысячей извинений. В общем, ребята - молодцы.
Кодовую базу храним на GitHub - пока проблем, к счастью, нет, будем решать по мере появления. Деплой выполняется CI/CD скриптом, огромный плюс нашего "консервативного" фронтенда в том, что у него нет сборки - деплой простой, выполняется за считанные секунды "на горячую" - не прерывая работу программы. Благодаря этому имеем возможность публиковать все обновления максимально оперативно.
Архитектура ролей и прав доступа
В системе четыре типа кабинетов с принципиально разными интерфейсами:

Кабинет заказчика — минимум интерфейса, максимум прозрачности. Заказчик видит: видеотрансляцию с камер на объекте, чат с компанией (по принципу «единого окна»), фото/видео-отчёты по этапам, текущую смету, план работ, имеет доступ к ИИ-инструментам: эксперту по вопросам ремонта и дизайнеру интерьеров (может загрузить фото до ремонта и получить рендеры готовых интерьеров согласно своим пожеланиям). Не видит внутреннюю кухню: переписку с мастерами, себестоимость работ и остальное.
Кабинет сотрудника — доступ с внутренней системе в соответствии с набором разрешений, выставленных сотруднику руководителем. Это может быть переписка с заказчиками, сводка по объектам (всем или разрешённым), ведение расходов, работа с мастерами, чек-листы, сметы, аналитика и другое.
Кабинет мастера — только объекты, работы на которых мастер выполняет, в отдельном интерфейсе с набором необходимых мастеру функций. Персональный план работ с обратным отсчётом, переписка с компанией, чек-листы с видеоинструкциями, смета для мастера (без цен для заказчика), заявки на доставку материалов и забор их остатков, заявки на оплату чеков и выполненных работ, и другое.
Кабинет руководителя — по сути, dashboard всей компании на экране телефона. Включает всё, что есть у сотрудника, плюс ряд критичных функций:
Контроль коммуникации с заказчиками. Руководитель видит всю переписку сотрудников с заказчиками в реальном времени. Это позволяет следить за тем, чтобы стандарты общения, принятые в компании, соблюдались на каждом объекте, без необходимости присутствовать на каждом звонке
Финансовая картина. Видит, какие оплаты запрашивают мастера за выполненные работы, сколько планируется доходов от объектов, сколько планируется расходов, есть ли кассовый разрыв. При возникновении вопросов по тратам — может посмотреть, кто на что потратил, и задать вопрос техконтролю или снабжению
Управление пересменками бригад. Видит, какие работы заканчиваются и какие начинаются — чтобы максимально сократить технические перерывы между сменой бригад. Это критично: затянувшаяся пересменка — потерянные дни и деньги
Выборочный контроль качества. Может в любой момент открыть чек-лист по любой скрытой работе (электрика, сантехника) и посмотреть фотографии, как она была выполнена — даже спустя месяцы после завершения этапа
Мгновенное внедрение улучшений. Если при посещении объекта или по жалобе заказчика обнаруживается системный недочёт — руководитель добавляет новый пункт в чек-лист прямо со смартфона. С этого момента каждый мастер на каждом объекте обязан этот пункт заполнить. Не нужны инструкции, обучения, совещания — изменение внедряется мгновенно
Прогноз спроса. Отслеживает статистику по расчётам стоимости ремонта — видит, растёт спрос или падает, и может прогнозировать загрузку компании.
Технически в системе реализовано три отдельных интерфейса: кабинет заказчика, мастера и сотрудника. Кабинет руководителя - это кабинет интерфейс сотрудника с полным набором функций. Система позволяет завести нескольких руководителей по аналогии с сотрудниками. Разрешения выставляются каждому индивидуально, также есть "должности" - по сути наборы разрешений.
Чат как единое «единое окно»: нетривиальная маршрутизация сообщений
Одна из ключевых архитектурных задач — чат, в котором заказчик общается «с компанией», а не с конкретным человеком. При этом внутри компании сообщение видят все участники проекта и любой может ответить.

Вот как это работает:
Заказчик пишет в чат — сообщение появляется у всех сотрудников, привязанных к объекту.
Любой сотрудник отвечает — заказчик видит ответ от «компании», с указанием конкретного сотрудника.
Это выглядит не как групповой чат, а как личный: у заказчика есть его сообщения и сообщения компании, у сотрудников - сообщения заказчика выглядят, как сообщения собеседника, а все сообщении компании - как свои.
По такому же принципу реализован и чат с мастером: на одной стороне мастер, на другой - компания - все сотрудники.
Есть возможность переслать сообщение заказчика мастеру и наоборот.
В чате с заказчиком допускаются только текстовые сообщения - таким образом вся переписка автоматически документируется, и как показал наш опыт, при возникновении споров это отлично работает в суде. В чате с мастером допускается отправка голосовых сообщений: информацию до мастера иногда можно донести только при помощи интонаций.
Чат работает на вебсокетах, отправка уведомлений о новых сообщениях реализована с 5-секундной задержкой: это позволяет в момент отправки уведомления определить, не было ли оно уже прочитано получателем и отменить отправку: ведь нет смысла отправлять уведомление, если пользователь итак уже находится в чате и увидел сообщение.

Пуши с новыми сообщениями содержат две action-кнопки: "Прочитать" и "Ответить". Первая позволяет пометить сообщение прочитанным, а вторая - ответить на него сразу из пуша, не открывая чат. На айфоне это, к сожалению, не поддерживается.
Конструктор смет c экселькой под капотом
На протяжении многих лет мы оттачивали свою смету. Естественно, в эксельке. В итоге получился идеальный по точности шаблон сметы: файл с несколькими листами на тысячи строк, связанных друг с другом формулами. Отказываться от него никто категорически не захотел, поэтому пришлось вокруг него и построить сметную систему: добавили в каждую строку набор технических кодов, по которому её содержимое связывается с чем-либо в программе, добавили макросы.
На данный момент в нашей внутренней системе это работает так:
Смета каждого объекта формируется сметчиком в эксельке на основе шаблона, при помощи макроса в ней появляются отдельные листы со сметой для заказчика (только выполняемые на объекте работы и материалы, для них используемые), сметой для мастера (только работы со стоимостью для мастера), списком черновых материалов для закупки нашим снабжением и чистовых материалов для самостоятельной закупки заказчиком.
Этот файл загружается в программу и разбирается на составляющие: заказчик видит свою смету (уже в PDF) и список чистовых материалов для самостоятельной закупки, мастер - список работ для выполнения с их объёмами и стоимостью, снабженец - списки материалов для закупки с необходимым количеством и разделением по этапам закупки. На основании объёмов выполняемых работ программа формирует план работ по объекту с учётом выходных дней и праздников.
Все эти данные автоматически попадают в заявки на оплату работ, заказа материалов и тд - пользователям остаётся только проверить уже заполненные формы и при необходимости внести соответствующие изменения. Также, благодаря этому в любой момент программа знает, какие работы уже оплачены, какие материалы уже заказаны и сколько ещё осталось оплатить и заказать на объект.
В смету же вносятся оплаты работ заказчиками и они также попадают в программу. Всё это базово формирует финансовый модуль, сотрудникам остаётся лишь подтверждать оплаты и заводить организационные расходы.
Дальше - интереснее: удалось формализовать логику формирования сметы человеком - составили список вопросов, на основании которых она формируется, добавили каждой работе ещё один технический код, составили алгоритм, который формирует состав и объём выполняемых работ на основе ответов на вопросы. Материалы экселька рассчитывает сама по формулам. Упаковали список вопросов в телеграм-бот и форму на сайте, потестировали, причесали и отладили, и вот вам настоящая магия: за 30 секунд без смс и регистраций любой желающий может просчитать стоимость своего ремонта с точностью 85% (и то только потому что дальше уже идут детали и не-типовые решения): программа всего лишь заполняет эксельку и возвращает из неё итоговые суммы и сроки выполения работ.

С основными сложностями в этой схеме мы столкнулись при переработке нашей внутренней программы в программу для других ремонтных компаний по подписке. За основу также был взят наш шаблон сметы, цены в нём обнулены, так как у каждой компании в своём регионе цены разные. Из эксельки программа делает форму, в ней компания заполняет свои расценки и добавляет свои работы и материалы - вся эта информация уже хранится в БД. При формировании сметы объекта шаблон-экселька копируется в конкретную смету, в ней опять же формой-таблицей проставляются расценки компании и объёмы работ, и всё это сохраняется в файл. Макросы пришлось заменить PHP-кодом, но логика осталась прежней: на основании этой эксельки формируются разные сметы и списки.
Очевидно, что схема максимально нетривиальна, плюс, как показала практика, компании, пользующиеся программой по подписке всё же любят полностью заполнять всё своими данными, даже если в итоге получается то же самое, что им изначально предлагалось нами. К тому же, в нашей внутренней программе затруднено оперативное редактирование сметы: ведь это делается в эксельке, а значит нужно иметь под рукой ноутбук. Поэтому мы всё же решились отказаться от экселек и сейчас занимаемся реализацией всего, что они умеют, сразу в программе: работа большая, но то, что получается, нам уже нравится - должно быть интересно.
Чек-листы: формализация строительных процессов
Это, пожалуй, самая интересная часть с точки зрения предметной области. Мы взяли 18 лет опыта ремонтных работ и формализовали каждый вид работ в структурированный чек-лист.
Каждый чек-лист содержит:
текстовое описание каждого шага выполнения работы
фото- и видеообразцы правильного выполнения
обязательные фото или видео, которые мастер должен загрузить по завершении
пункты проверки для техконтроля

Архитектура наследования: базовые чек-листы создаются нами (ВитионГруп) во внутренней системе. Они автоматически синхронизируются в программу «Управление ремонтом» для внешних компаний. При этом каждая компания может убрать ненужные виды работ из своего перечня или добавить свои виды работ с собственными чек-листами — кастомизация одной компании не влияет на другие.
По сути, это многослойная система контента: базовый слой (наш) + пользовательский слой (для каждой компании).
Технически программы полностью разделены и независимы друг от друга, имеют разные БД. Раз в сутки в автоматическом режиме из внутренней программы во внешнюю выгружаются обновления. Встроенные данные хранятся отдельно от пользовательских. Таким образом, все компании получают динамично развивающуюся систему с ежедневными обновлениями и автоматическим внедрением всех нововведений как по функциональной части, так и по наполнению.
Видеонаблюдение
На каждом объекте устанавливаются IP-камеры, трансляция доступна заказчику прямо в личном кабинете. Это оказалось критически важным для дистанционных проектов — у нас есть заказчики, которые ни разу не были на объекте до сдачи. Мы используем камеры Ростелекома - у них есть возможность предоставления доступа к трансляции по ссылке.

Подключаем их к интернету при помощи модемов с сим-картами. Интересно, что никто из заказчиков почему-то не соглашается заранее проводить интернет к себе в квартиру - мы даже перестали предлагать это.
Интеграция с ИИ
В системе три точки интеграции с ИИ:
1. Редактирование текста в чате. Кнопка «волшебная палочка» — исправляет орфографические и синтаксические ошибки в сообщении перед отправкой. Особенно полезно при наборе текста голосом, а также для мастеров, которые допускают столько ошибок, что сообщение становится буквально нечитаемым. ИИ-шка каким-то чудом их понимает и всё правильно исправляет.

Используем для этого гига-чат. Сейчас такую функцию уже предлагают многие телефоны "из коробки", но иметь дополнительную функцию на виду прямо в чате всё ещё удобно и привычно.
2. Виртуальный эксперт. Отвечает на вопросы заказчиков, мастеров и сотрудников о строительстве и ремонте. Работает с изображениями.

Это снова гига-чат с соответствующим контекстом
3. Дизайнер интерьеров. По фотографии помещения до ремонта и пожеланиям пользователя генерирует идеи дизайна интерьера. Тут пока используем иностранные разработки - отечественных аналогов, хорошо справляющихся с задачей ещё не нашли.

По интеграции всё стандартно: API, вебхуки, оплата по токенам за использованные ресурсы. Выбрали GigaChat из-за хранения данных на российских серверах и отсутствия рисков с зарубежными API, а также, чтобы поддержать отечественного производителя, ну и вообще мы - патриоты.
Мультитенантность: от внутреннего инструмента к SaaS
Самый интересный архитектурный вызов возник, когда мы решили сделать из внутреннего инструмента продукт по подписке.
Проблема: наша внутренняя система («Личный кабинет») постоянно развивается и наполняется. Продукт для внешних компаний («Управление ремонтом») должен получать все обновления базового контента (чек-листы, виды работ, инструкции), но при этом у каждой компании — своя клиентская база, свои сметы, свои настройки, свои мастера.
Решение: двухслойная архитектура данных.
Базовый слой — заполняется нами в «Личном кабинете», автоматически синхронизируется в «Управление ремонтом». Это виды работ, списки материалов, чек-листы, видеоинструкции, шаблоны смет и так далее
Пользовательский слой — данные каждой компании. Изолированы, невидимы для других компаний
При обновлении базового слоя компании автоматически получают новый контент. Их собственные кастомизации при этом не затрагиваются.
Архитектурное решение весьма простое: взяли БД внутренней программы, ко всему добавили "tenant_id" - ID компании. Для данных, выгружаемых из внутренней программы он - NULL. Значения сортировок сделали очень большими числами, сделали таблицу сущностей, удалённых компаниями. Таким образом, компании могут добавлять свои данные, ставить их между встроенными, удалять (фактически - скрывать) встроенные данные, получать все обновления встроенных данных, и никак не влиять на данные друг друга.
Программа для заказчиков и мастеров
Одновременно с разработкой "Управления ремонтом" реализовали ещё одну идею (а точнее просьбу подписчиков нашего YouTube-канала) - программу для взаимодействия заказчиков и частных мастеров - "Мой ремонт". Здесь мы не просто урезали функции базовой версии, а выпустили полноценное, заточенное под свои задачи приложение, на другом стеке и с другой архитектурой: для бэкенда снова используем любимый Laravel, а для фронтенда выбрали React. Получились два отдельных проекта, взаимодействующих по API с документацией в Swagger. Работает очень быстро, выглядит красиво и современно, но деплой фронтенда занимает какое-то время на сборку - работу программы приходится приостанавливать. В планах сделать бесшовно - собирать и уже затем заменять файлы, но пока это не критично - деплоим "оптом" и не в "прайм-тайм".

В эту программу также ежедневно выгружаются новые данные из внутренней программы, некоторые разделы похожи: есть чек-лист, фото-отчёты, смета и проект, но здесь другая логика: заказчик сам управляет всем процессом, самостоятельно находит мастеров и добавляет их к объекту, ведёт расчёты, принимает работы по чек-листу и тд.
Из интересного по наполнению: на основании нашего шаблона сметы сделали в программе раздел рекомендуемых цен для частных мастеров на все виды работ. Программа также предлагает их при заполнении сметы. Расценки - самый часто задаваемый вопрос, как от заказчиков, так и от мастеров.
По технике: в этой программе удалось реализовать максимально крутой чат, как внешне, так и технически, с пагинацией, быстрым поиском, возможностью создания групповых чатов, кучей функций и стабильной работой на всех устройствах. Гоняли его на миллиардах сообщений: работает отлично. В целом, если бы не MAX, можно было бы и запустить его как отдельный продукт) В общем, всей командой получили удовольствие как от работы над ним, так и от полученного результата.
Уведомления: Push, Email, Telegram и MAX
Система отправляет уведомления по нескольким каналам:
Push-уведомления (через PWA Service Worker)
Email (на почту организации или индивидуальные для пользователей)
Telegram (при помощи бота)
MAX (при помощи бота)
Все уведомления отправляются при помощи Laravel Notifications, для MAX выпустили свой пакет. Каждый пользователь может выбрать виды уведомлений, которые он получает и канал их доставки.
Цифры
Одновременно ведём от 30 до 75 объектов
Более 1000 завершённых проектов за всё время
Экономим 50% рабочего времени сотрудников (вместо разъездов — приёмка в приложении)
50% заказчиков обращаются повторно
Пользователи внешних программ из разных регионов России и Казахстана
Что дальше
Планы:
Усиление ИИ-компонентов: в первую очередь думаем над разработкой полноценного ИИ-сотрудника, который всегда в курсе всей информацией и может ответственно и безошибочно ответить на вопросы вида "что решил заказчик объекта N по такому-то вопросу", "проводились ли такие-то работы и когда", "что там в смете по вопросу X" и так далее
Адаптация программы под строительство частных домов: мы сами занимаемся этим и активно дорабатываем чек-листы, шаблоны смет и добавляем новые функции
Внедрение управления умным домом: уже интегрировались по MQTT-протоколу с нашим партнёром по системам умного дома, но пока много вопросов, в первую очередь к ним
Вместо заключения
Строительная отрасль — один из последних бастионов «аналогового» бизнеса. Большинство компаний до сих пор управляют проектами через мессенджеры и таблицы. При этом потребности те же, что в любой другой сфере: прозрачность, контроль, масштабируемость.
Мы не пытались сделать «платформу для всех» — мы автоматизировали собственные процессы, отточенные за 18 лет работы. И оказалось, что этот опыт востребован: другие компании из регионов подписываются на систему, чтобы не проходить тот же путь с нуля.
Прикладываю большой видеообзор всех программ, о которых шла речь:
Спасибо, если вы вдруг дочитали это до конца. Буду рад ответить на вопросы в комментариях — и про архитектуру, и про предметную область. Строительный бизнес изнутри выглядит неожиданно интересно с точки зрения разработки.
