Объединяем два крупнейших Ecom на разных стеках в одну общую CRM

509
#Разработка 18 января 2024
Привет! Меня зовут Данила Соловьёв, я руковожу направлением PHP — самым крупным подразделением в отделе разработки AGIMA. Поделюсь историей о том, как мы встроили новую CRM-систему в два абсолютно незнакомых нам IT-ландшафта и тем самым спасли сейлзов двух крупных интернет-магазинов от бесконечных табличек в почте. Подробно опишу, какие данные мы выгружали, как их дедуплицировали и какие сервисы использовали для их валидации. Поехали!

Предпосылки. Как появилась задача?

Два федеральных интернет-магазина, для удобства назовем их А и Б. В каждом независимо друг от друга велась клиентская база юридических лиц с накопленными данными за весь период работы.
Работа с B2B-клиентами происходила по принципу «всё в почте». Менеджеры по продажам пересылают кучу неактуальных эксель-таблиц. К таким процессам были готовы не все, и менеджеры часто увольнялись в первые рабочие дни.


Бизнес был настроен изменить данный процесс, автоматизировать все возможные процессы, таким образом активно развивать B2B-направление и инвестировать в него.

Ограничения

Основными ограничения стали:

  • Срок MVP — полгода (с июня-июля до нового года). Заказчик пришел летом. Релиз-фриз перед новым годом.
  • Бюджет. Лепить огромного, отказоустойчивого и, как следствие, дорогого мастодонта нет возможности. Бизнес хочет тестировать гипотезы, чем быстрее, тем лучше.

Также были сопутствующие ограничения:

  • Сервис одного окна. У менеджеров по продажам должен быть единый инструмент для ведения клиентов. Отправка почты, IP-телефония, формирование отчетов, просмотр всех клиентов и их заказов.
  • Низкий порог входа для менеджеров. Интерфейс системы должен быть прост и интуитивно понятен.

Ключевая задача

Создать единую клиентскую базу юридических лиц и обогатить ее данными из двух существующих баз данных (БД) интернет-магазинов для последующих продаж.
Для этого нужно:

  • Получить необходимый набор данных и сложить в нашу новую систему, чтобы менеджеры могли заходить и работать с ними.
  • Превратить их в сущности CRM. В качестве CRM выбрали решение от Bitrix24.

Выбор Bitrix24 обусловлен ограничениями, которые описаны выше + коробка предлагает достаточно широкий функционал:
  • интеграция с AD/LDAP, которая нам и требовалась в качестве SSO;
  • интеграции с IP-телефониями;
  • интеграция с почтой;
  • понятный и анимированный интерфейс.

Данные. Что выгружаем?

Приступаем к сбору информации о том, что мы хотим видеть в нашей CRM-системе. Определяем основные сущности и их свойства, требуемые для заполнения, а также устанавливаем критерии проверки данных. Таким образом, мы формируем желаемый итог нашей работы.
В рамках Bitrix24 нам предстоит взаимодействовать с двумя основными сущностями:


Компания — информация о юридическом лице, включая организационно-правовую форму, а также банковские реквизиты.

Контакт — карточка с данными о конкретном контактном лице, например менеджере по закупкам. Этот контакт привязан к конкретной компании.


Затем определяем бизнес-требования к Bitrix24:

  • Выгружаются только активные компании.
  • Исключаются дубликаты контактов и компаний.

Этап технического ППО. Работаем в чужой инфраструктуре

Мы заходили в чужую инфраструктуру двух огромных екомов, в которой мы совсем не ориентируемся. Поэтому на этом этапе нам предстояло ответить на следующие вопросы:
  • Кто может помочь со стороны интернет-магазинов интегрироваться (конкретные команды и люди)? К кому идти? Кто может рассказать про сетевую связность, про продукты и системы, которые есть внутри каждого из магазинов?
  • Как будет происходить обмен данными? Realtime? Огромные файлы выгрузки? Брокеры сообщений? REST?
  • Потребуются ли доработки со стороны интернет-магазинов?
  • Какой стек технологий потребуется (помимо Bitrix24, PHP и MySQL)?
  • Как оперативно мы должны и можем получать данные (технические возможности)? Важно! Мы не должны нашими обменами положить ни интернет-магазины, ни себя :)
Чтобы разобраться в инфраструктуре, мы встретились с представителями интернет-магазинов и обсудили важные детали:
  • Как забирать данные для каждой сущности (REST, брокеры, файлы и т.д.)?
  • В каком формате (json, xml, csv и т.д.)?
  • Как оперативно?
  • С какой периодичностью возможен обмен?

Проектирование. Выбор реализации. Архитектура

На этапе ППО мы определили:
  • Способы интеграции.
  • Режимы работы выгрузки.
  • Спойлер: их два (полный и дельта).
  • Способы валидации компаний, чтобы не тащить «мусор» и дубли в новую систему.
  • Как «сырые» данные преобразовывать в сущности CRM.

Механизм: Извлечение. Преобразование. Загрузка

В этом блоке расскажу о том, как мы выгружали данные, и опишу технические моменты.
Для решения задачи было необходимо реализовать два режима выгрузки данных:


  1. Полная выгрузка — все данные за текущий и предыдущие годы.
  2. Выгрузка обновлений — периодически мы должны получать данные о новых компаниях из интернет-магазинов.

Объем данных получился таким:
  • В интернет-магазине А — 75 000 контактов, 53 000 компаний.
  • В интернет-магазине Б — 600 000 контактов, 125 000 компаний.
Отмечу, что эти цифры, если их сложить, с итоговыми не сойдутся. Всё потому, что произошла дедупликация, и мусорные компании тоже были отброшены.
За основу реализации взяли процесс ETL. Аббревиатура ETL (Extract. Transform. Load) означает «Извлечение, Преобразование, Загрузка». Остановимся подробнее на каждом из этапов.
Фотография

Extract — Извлечение
Это, наверное, самый сложный этап из всех трех, которые нас ждали.


На данном шаге мы должны реализовать интеграцию с интернет-магазинами для получение «сырых» данных. Важно понимать, что «сырые» они только для новой CRM, в то время как для интернет-магазина это полноценный объем данных в его базе.

Полная выгрузка:

Также мы прикрутили к нашему проекту компонент Symfony Console, чтобы с помощью него запускать полную выгрузку из MySQL и другие фоновые задачи.

Дельта выгрузка:
  • ИМ А — slave реплика MySQL (cronjob + symfony console command)
  • ИМ Б — kafka (php extension RdKafka + supervisor + symfony console command)

Отдельно остановлюсь на интернет-магазине Б — у них был SAP CRM, где они хранили всех клиентов. У SAP CRM был веб-сервис, который умел продюсировать свои изменения в Kafka. Нам предоставили отдельный топик. Мы на своей стороне реализовали консюмер, для этого нам пришлось установить PHP-расширение RdKafka. Консюмер представлял собой бесконечный цикл, поэтому сверху мы накрыли его еще Supervisor’ом, чтобы он за ним следил, и если падает — переподнимал его. А в сам Supervisor передали команду через Symfony Console.

Transform — Преобразование
Теперь важно реализовать очистку и преобразование данных для будущих сущностей, чтобы они соответствовали потребностям бизнес-модели. Для этого мы:

  • удаляли компании, которые приходили без ИНН;
  • преобразовали кодировку Windows-1251 в UTF-8;
  • преобразовали номера телефонов в общий формат данных;
  • удаляли лишние пробелы из текстовых полей;
  • контакты и компании укладывали в DTO.

Load — Загрузка
Теперь мы получили очищенные данные и готовы сохранять их в БД как сущности CRM (компании и контакты).


Этот шаг был одинаковым для всех трех источников (БД, Kafka, файлы). Так как мы всё грузим в одно хранилище, организовать надо единообразно.


Одновременно с этим происходила валидация компаний, т. к. нужны только действующие. Для реализации этого требования мы воспользовались сервисом ЕГРЮЛ, где присутствуют необходимые данные о компаниях. Отмечу, что у Bitrix24 есть готовый модуль «из коробки» для получения сведений из ЕГРЮЛ по ИНН.


Но данные приходили «сырые». Перед тем как сделать запрос в ЕГРЮЛ, мы должны были убедиться, что ИНН валидный. Такой запрос стоил времени, на него уходило 0,4 секунды, что уменьшало скорость обработки выгрузки. Поэтому для ИНН реализовали стандартную проверку на длину и символы: ИНН должен состоять из 10 или 12 цифр. Также реализовали проверку контрольных чисел, она определяет корректность номера ИНН с помощью математической формулы. Данная формула — унифицированная для всех ИНН.


По итогам проверки в ЕГРЮЛ отправляются запросы только с валидным ИНН, что сократило этап загрузки на 30–40%. Невалидные компании в процессе загрузки складывали в отдельную табличку.

Релизы

Первым релизом мы выпустили выгрузку из интернет-магазина А с общим загрузчиком.

Вторым релизом вышла дельта из интернет-магазина Б.

Третьим — полная выгрузка исторических данных из интернет-магазина Б.


Таким образом, даже на этапе разработки мы непрерывно снабжали новыми данными менеджеров по продажам.

Итоговый стек и архитектура

В ходе проекта нами использовался следующий стек:
  • B2B CRM — Bitrix 24.
  • База данных — MySQL.
  • Брокер сообщений — Kafka.
  • ETL — PHP-пакет flow-php/etl.
  • Большие json — PHP-пакет halaxa/json-machine.
  • Чтение из Slave-реплики — symfony/console + сron.
  • Консюмеры Kafka — symfony/console + supervisor.
Фотография

Как видим, у нас было три экстрактора: общий для магазина А и два отдельных для магазина Б (один для Kafka, другой для Json). Два трансформера — для каждого магазина свой, они выдавали одинаковые DTO и передавали их в лоадер. Дальше лоадер закидывал всё в B2B CRM.

Заключение

Bitrix24 был успешно доработан. Нам удалось выгрузить свыше 170 000 активных компаний и более 264 000 контактов из обоих интернет-магазинов.
Менеджерам по продажам была предоставлена обширная клиентская база двух интернет-магазинов. Это позволяет эффективно работать со старыми клиентами и добиваться повторных продаж, используя функционал CRM Bitrix24. Все отчеты и аналитические данные стали доступны в один клик. И больше никаких табличек в почте. Ура!


Только благодаря правильно выстроенному взаимодействию между бизнесом и разработчиками, нам удалось реализовать поставленные цели.


Больше о разработке мы рассказываем в нашем телеграм-канале «Заметки тимлида». Приходите обсудить статью. А еще мы раз в месяц проводим закрытые встречи для еком-директоров разных компаний — обсуждаем там насущные проблемы, слушаем доклады и просто знакомимся. Будем рады новым участникам!

Контент-хаб

0 / 0
+7 495 981-01-85 + Стать клиентом
Услуги Кейсы Контент-хаб