Мы продаём инженерные узлы для отопления и водоснабжения многоэтажек. Каждая сделка — расчёт под конкретный дом, коммерческое предложение, договор, закуп, сборка и отгрузки партиями по графику стройки. Ещё недавно эта цепочка жила в Битрикс24, отдельном калькуляторе, 1С и рабочих чатах.
Мы написали свою CRM. Раньше от заявки до подписанного договора проходило около двух месяцев, теперь — около месяца: сделки закрываются примерно вдвое быстрее. Сильнее всего сократился первый отрезок: раньше КП уходило заказчику через 3–4 дня после заявки, теперь — на следующий день. Ниже — где на самом деле терялось время, что мы для этого сделали и на какие грабли наступили.
Кто мы и что продаём
Наш товар нельзя взять с полки — его сначала нужно посчитать. Заказчик — застройщик жилого комплекса. Он покупает коллекторные узлы отопления на каждый этаж, этажные узлы холодной и горячей воды и трубную разводку по квартирам.
Узел собирается под этаж: число квартир задаёт число выходов, дальше следуют диаметры, балансировка, бренд арматуры. Один дом — это десятки узлов и тысячи фитингов: в одном реальном КП было 84 узла, в другом — 4 078 ниппелей. Заказчик видит в КП готовый узел с шифром, а снабжению и складу нужна каждая деталь внутри.
Ещё три обстоятельства, без которых дальше не понять:
-
Три юрлица. Два ТОО продают, третье ведёт монтаж. Учёт — в 1С.
-
Поставка партиями. Договор живёт месяцами: график отгрузок идёт за стройкой и меняется вместе с ней.
-
Много рук. Менеджер, инженер, коммерческий директор, юрист, руководство, снабженец, склад, водитель, бухгалтер. В системе сейчас 12 ролей, и почти каждая трогает сделку хотя бы раз.
Где терялось время
Время уходило не на работу, а на ожидание между работами. Расчёт, КП, согласование — каждая работа сама по себе недолгая. Дни уходили на то, чтобы каждый узнал: сейчас его ход.
До своей CRM сделка жила в четырёх местах:
-
Битрикс24 — сделки и контакты. У инженеров, снабжения и склада там своего места не было.
-
Калькулятор инженеров — отдельное браузерное приложение. Состав и сумма из него переезжали в сделку и в КП.
-
1С — счета, реализации, поступления. Данные сделки вносили туда ещё раз.
-
Чаты — всё остальное: «посчитай», «согласуй», «что с договором?», «когда отгрузка?».
Отсюда три вида потерь.
Ожидание на передаче. Менеджер ждёт расчёт, а инженер не знает, что его ждут. КП готово, но коммерческий директор увидит его, когда долистает чат. Каждая передача — это ожидание, а передач до первой отгрузки семь.

Восемь шагов и семь передач. До CRM ни одна передача не сигналила сама: следующий узнавал о своём ходе из чата или звонка.
Перенос руками. Калькулятор → сделка → КП → 1С. Каждый перенос — время и шанс ошибиться. В одном КП из старого калькулятора 12 узлов ушли по 194 ₸ вместо 262 763 ₸ за штуку. Недобор — 3,15 млн ₸, около 15% суммы, а в строке «ИТОГО» стояло 68 узлов вместо 84. Причина нашлась позже: калькулятор молча ставил 0 ₸ детали без привязки к каталогу.
Никто не знает, у кого сделка. Чтобы ответить на «на чём застряли?», руководитель обзванивал людей. Стадия в Битриксе показывала, где сделка была вчера, а не чей сейчас ход.
Почему своё, а не коробка
Коробочная CRM знает сделку и товар, но не знает узел. А у нас всё держится на узле: заказчик покупает его целиком, снабжение закупает по деталям, склад собирает и отгружает партиями по графику стройки. Состав коллекторного узла выводится из параметров этажа по девятнадцати связанным правилам. Допиливать это в Битрикс роботами и смарт‑процессами значило бы держать бизнес‑логику в чужой системе и потом переносить её дважды.
Мы записали один принцип и держимся его: наша база — источник истины для всего, что не является бухгалтерией. Сделки, расчёты, КП, договоры, графики, закуп и склад живут у нас. В 1С остаются номенклатура, цены и бухгалтерские документы. Битрикс и 1С подключены через адаптеры, и любой можно выключить без потери ядра.
Из Битрикса уходим поэтапно: сначала зеркалим его сделки, потом синхронизируем в обе стороны, потом сами становимся мастером. Критерий перехода между этапами — не технический: месяц без жалоб «а в Битриксе было удобнее». Резкий переезд убил бы продажи: менеджеры там живут.
Стек скучный, и это специально:
|
Слой |
Чем сделан |
|---|---|
|
Бэкенд |
PHP 8.3, Laravel 13, модули по предметным областям (CRM, продажи, калькулятор, закуп, склад, исполнение, интеграции и др.) |
|
База |
PostgreSQL, около 116 таблиц |
|
Фронтенд |
Vue 3, PrimeVue 4, Vite |
|
Телефон |
PWA с Web Push — без отдельного мобильного приложения |
|
Интеграции |
1С по OData, Битрикс24 по REST и вебхукам |
|
Тесты |
около 1 600 автотестов + сквозной прогон по ролям в браузере |
Что сделали
Мы били по передачам. Цель — чтобы человек узнавал, что ход за ним, в ту же минуту и попадал на экран, где нужная кнопка уже под рукой.
1. «Мой день» вместо чатов
Рабочий день начинается с экрана «Мой день». На нём только карточки дел, которые ждут именно этого человека: «Ждут вашего решения», «Новый расчёт», «Узлам не хватает деталей» и так далее. Дела других людей, за которыми руководителю надо присматривать, убраны в свёрнутый блок «Присмотр», чтобы «моё» не тонуло в «чужом».
Карточка ведёт не в сделку вообще, а на вкладку с нужной кнопкой. Это проверяет робот в браузере: до правки сразу на нужную кнопку вели 3 карточки из 8, после — 7 из 8.
2. Пуш на каждое новое дело
CRM ставится на телефон как PWA, отдельного приложения нет. Раз в минуту сервер собирает «Мой день» каждого сотрудника и сравнивает со снимком. Появилось новое дело — уходит Web Push на iPhone или Android.
Две детали, без которых это не работает:
-
Каждая строка карточки отдаёт стабильный id: сущность плюс номер, а для события — ещё и состояние. Иначе сравнение снимков либо молчит, либо спамит.
-
За один проход — не больше пяти пушей на человека, остальное сворачивается в «ещё N». Первый проход после включения только снимает снимок, иначе человек получит пуш на каждое старое дело.
3. «Что дальше» в шапке сделки и договора
Под шапкой сделки одна строка в одном из трёх состояний: «сделайте вот это», «ждём такого‑то» или «готово». На вопрос «у кого сделка» теперь отвечает экран, а не телефон. Правило интерфейса: подпись кнопки в этой строке слово в слово совпадает с подписью на вкладке, потому что человек ищет глазами ту же надпись.
4. Расчёт → спецификация → КП без перепечатки
Калькулятор теперь внутри CRM. Менеджер запрашивает расчёт прямо из сделки: раздел, срок «нужен к», пояснение. Инженер получает карточку и пуш. Готовый расчёт он замораживает версией, и дальше всё читает этот снимок: спецификация, КП в PDF, потом закуп и сборка.
Узел продаётся как товар с шифром. Заказчик видит в КП готовый узел, а снабжение из того же снимка видит каждую деталь и чего не хватает по каждому узлу. Ручной перенос исчез — а вместе с ним и узлы по 194 ₸.
5. Три способа получить работу — намеренно
Мы не стали сводить всё к одной схеме «назначить ответственного». У разных ролей работа приходит по‑разному, и система это повторяет:
|
Кто |
Как получает работу |
Почему так |
|---|---|---|
|
Менеджер |
закреплён за сделкой, передаёт главный менеджер |
сделка длинная, у заказчика один собеседник |
|
Инженер |
расчёт назначает главный инженер |
загрузку знает только он; сам инженер выберет проект по вкусу |
|
Снабжение, склад |
берут сами кнопкой «Беру» |
раздавать заявки по одной некому, а справится любой |
6. Решения в одном месте
Согласование КП и договора — одна карточка «Ждут вашего решения» и две кнопки на всех экранах: «Согласовать» и «Вернуть». Вернуть можно только с причиной — иначе автор идёт в чат спрашивать «а что не так?», и передача снова висит.
7. Заявка по ссылке
Первую передачу мы отдали заказчику. Менеджер отправляет ссылку, заказчик сам заполняет объект и контакты, и сделка появляется в CRM уже с данными — без переписывания из письма.
Откуда «вдвое»
|
Отрезок |
Было |
Стало |
|---|---|---|
|
От заявки до КП у заказчика |
3–4 дня |
около 1 дня |
|
От заявки до подписанного договора |
около 2 месяцев |
около 1 месяца |
Это оценка команды по сделкам, а не строгий замер. И оговорка: «на 50% меньше времени» — это и есть «в два раза быстрее». А «на 50% быстрее» значило бы в полтора раза.
КП ускорилось в 3–4 раза, а весь цикл — в два. Разница понятна: дальше по цепочке много времени уходит на сторону заказчика — переговоры, его юристов, его бюджет. На это CRM почти не влияет.
Как сделаем строгий замер. Медиана дней от создания сделки до подписания договора. Проигранные и тестовые сделки не считаем. «До» берём из истории Битрикса, «после» — из журнала CRM. Медиана, а не среднее: одна сделка, которая полгода ждёт финансирования застройщика, сдвигает среднее сильнее любых наших правок.
Чего эти цифры не доказывают. Система работает недавно, сделок через неё прошло пока немного, а стройка сезонная. Семь правок мы выкатывали подряд, поэтому какая из них дала больше всего, не знаем. Через квартал посчитаем по журналу и напишем, подтвердилось ли.
Грабли
«Готово» в дорожной карте — не значит «работает»
На аудите выяснилось, что сделка ни разу не прошла цепочку целиком. Все пункты дорожной карты стояли с галочками, тесты были зелёными. Но тесты звали сервер с параметрами, которых интерфейс не шлёт, и тупики прошли мимо CI. Из интерфейса сделка доходила до КП, а после договора в базе не было ни одной записи.
Помогли две вещи. HTTP‑тесты пишем «как шлёт интерфейс», а не «как удобно тесту». И регулярно гоняем сквозной прогон по ролям в браузере, с подменной 1С. Первый такой прогон дал 15 находок. В боевой базе есть галочка «Прогон»: такая сделка живёт на отдельном складе и в 1С ничего не отправляет.
1С по OData врёт с кодом 200
Все пять ловушек мы нашли на живой базе, а не в документации:
-
Страницы без
$orderbyприходят в произвольном порядке. Из 4 550 позиций справочника дошло 1 177 уникальных. При этом строк было ровно 4 550, и с$countвсё сходилось. Сверяйте число уникальных ключей, а не строк. -
If-Matchигнорируется. PATCH с чужой версией отвечает 200 и пишет. Версию сверяем сами чтением в том же сеансе. -
Длины режутся молча. Номер документа — 11 знаков, и «ОТ-2026-1000» станет «ОТ-2026-100», обновив чужой документ. В
$metadataдлин нет, мы добыли их опытом. -
Сумма документа не пишется. PATCH отвечает 200, значение остаётся нулём.
-
Даты уходят без зоны. Платформа читает присланное смещение как своё.
Поэтому правила обмена жёсткие. Метода DELETE в клиенте нет физически. Документы создаём только непроведёнными — проводит бухгалтер. Перед любой правкой спрашиваем, не проведён ли документ. Оплаты только читаем, регистры не трогаем. Запись в боевую 1С пока выключена.
Артикул — не ключ
Номенклатуру из 1С мы сначала сопоставляли по артикулу. Оказалось, что один артикул стоит у 52 разных позиций: тройники, гильзы, угольники. При первом приёме 197 карточек свернулись в 115 наших позиций. Ошибки в коде не было — негодной оказалась сама предпосылка. Теперь артикул — подсказка для человека, а не тождество. Проверка в одну строку: число непустых артикулов против числа различных.
Гонка на остатках
Склад списывал остаток по схеме «прочитал — проверил — записал» без блокировки. Две одновременные выдачи одной позиции обе проходили проверку и затирали друг друга. Транзакция не спасает: уровень READ COMMITTED в PostgreSQL от такой потери не защищает. Такое расхождение всплывает только на инвентаризации. Закрыли SELECT … FOR UPDATE на строке остатка.
Два калькулятора не сверить чтением кода
Новый калькулятор должен был считать как старый, только без его ошибок. Два дня мы сверяли исходники построчно и пропустили 9 расхождений: значения по умолчанию, умножение количеств, связи между полями. Сработало другое: гонять оба движка на одних данных и сравнивать результат. Эталоном стало реальное КП: 23 шифра узлов с ценами, новый движок восстанавливает все 23. Именно так и нашлись те самые узлы по 194 ₸.
Итоги
Сделки ускорила не какая‑то одна функция. Их ускорило то, что каждый теперь видит свой следующий шаг, узнаёт о нём с телефона и делает его в одно нажатие.
Если вы думаете о своей CRM для сложного товара, вот что мы бы сделали с самого начала:
-
Нарисуйте передачи, а не стадии. Стадия говорит, где сделка. Передача говорит, кто её сейчас держит. Время теряется на втором.
-
Начинайте с экрана «что мне сегодня делать», а не со списка сделок. Список сделок нужен руководителю. Исполнителю нужен список дел.
-
Один источник данных от расчёта до отгрузки. Замороженная версия расчёта кормит и КП, и закуп, и сборку. Любой ручной перенос рано или поздно даст свои 194 ₸.
-
Тестируйте сделку целиком, глазами каждой роли. Зелёный CI и галочки в дорожной карте ничего не говорят о том, дойдёт ли сделка до отгрузки.
-
В 1С пишите непроведённым и не верьте коду 200. Проверяйте записанное обратным чтением.
Дальше в планах: счета поставщиков и согласование оплат в закупе, лиды из WhatsApp и полный уход из Битрикса. Через квартал вернёмся с точным замером. Вопросы про архитектуру, 1С и калькулятор — в комментарии.
ссылка на оригинал статьи https://habr.com/ru/articles/1095456/