Skip to content
04КейсSW · 04 из 10

Многоарендная платформа чат-ботов для автодилеров с тремя базами данных, каждая из которых заслуживает своё место.

У автодилеров были данные — инвентарь vAuto, оценки TradePending, характеристики ChromeData — но не было способа донести их до покупателей в нужный момент. Мы построили многоарендный SaaS: визуальный конструктор сценариев для дилеров, чат-виджет для покупателей и три базы данных под капотом.

КлиентКонфиденциально
Год2017 — 2019
Длительность3 yrs
СтекPHP · Laravel · MongoDB · MySQL · Elasticsearch · Redis
Hero image for enterprise-conversational-data-platformFIG 01 · Главное изображение

Данные были. Пути к ним — не было.

Автодилер несёт массу данных: живой инвентарь с ценами и наличием, характеристики авто, привязанные к VIN, оценки trade-in, меняющиеся изо дня в день, варианты финансирования, слоты сервиса. Эти данные были разбросаны по vAuto для инвентаря, TradePending для оценок trade-in, ChromeData для характеристик автомобилей и собственной CRM каждого дилера. Ничего из этого не доносилось до покупателей в момент, когда они принимали решение.

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

Бриф: разместить на сайте каждого дилера чат-интерфейс, способный отвечать на эти вопросы в реальном времени, подключённый к системам, у которых ответы уже были.

Визуальный конструктор для дилеров, чат-виджет для покупателей.

У платформы было две разные поверхности. Дилеры пользовались визуальным конструктором сценариев в админке — редактором графа карточек, где они строили диалоговые сценарии, соединяя карточки-вопросы, ветви-ответы и карточки-действия: показать инвентарь, получить оценку trade-in, записать на сервис, захватить лид. Без кода. Каждый дилер собирал своего бота; платформа отвечала за отрисовку и маршрутизацию.

Покупатели видели встраиваемый чат-виджет на сайте дилера. Виджет выполнял настроенные сценарии, подтягивал живой инвентарь из vAuto, выводил оценки trade-in от TradePending прямо в диалоге, когда покупатель описывал свою текущую машину, и захватывал контактные данные в формате ADF для CRM дилера. Разговор выстраивался вокруг того, что настроил дилер и о чём спрашивал покупатель.

Платформа была многоарендной с первого дня. Каждый дилер получал свою конфигурацию бота, свой граф сценариев, своё подключение к инвентарю и CRM. Один аккаунт мог управлять несколькими дилерскими центрами. Аутентификация, биллинг и разграничение аренды жили в MySQL; всё остальное жило в хранилищах, которые ему подходили.

F · 01Визуальный конструктор сценариев
Дилеры строили диалоговые сценарии в редакторе графа карточек — вопросы, ветви ответов, обращения к инвентарю, оценки trade-in, захват лидов. Без кода. Каждый дилер настраивал своего бота.
F · 02Фид инвентаря vAuto
Задача очереди на базе Redis парсила FTP-экспорты vAuto, обновляла данные о товарах в MongoDB и переиндексировала Elasticsearch по дилеру. Изменения фида были изолированы в одной задаче.
F · 03Интеграция trade-in с TradePending
Чат-виджет получал оценки trade-in от TradePending прямо в диалоге, выводя оценку в разговоре, когда покупатель описывал свой текущий автомобиль.
F · 04Экспорт лидов в ADF
Контактные данные покупателя, захваченные в чате, форматировались как ADF XML и направлялись в CRM дилера. Отраслевой стандартный формат означал отсутствие кастомной интеграции под каждый дилерский центр.
F · 05Бэкенд на трёх базах данных
MongoDB для эволюционирующих схем ботов и инвентаря, MySQL для многоарендной аутентификации и биллинга, Elasticsearch для поиска по инвентарю каждого дилера. Каждое хранилище владело одной работой.
F · 06Набор тестов браузерной автоматизации
Laravel Dusk покрывал полные диалоговые сценарии от начала до конца. Изменения типов карточек и схем в MongoDB не ломали пути виджета; набор тестов ловил это, если они их ломали.

Три базы данных, каждая заслуживает своё место.

Решение вести три хранилища параллельно было осознанным и обоснованным с первого дня. Соблазн в проекте вроде этого — нормализовать всё в одно хранилище и смириться с трением на стыках. Мы этого не сделали.

MongoDB хранил конфигурации ботов и диалоговые сценарии — типы карточек, логику ветвления, варианты быстрых ответов, эволюционирующую схему отображения инвентаря. Эта схема менялась каждый спринт по мере роста набора функций. Реляционная миграция при каждом добавлении типа карточки задушила бы поставку. MongoDB поглощал эти изменения без церемоний.

MySQL брал на себя всё, что требовало транзакционной целостности: аутентификацию, биллинг и границы аренды дилеров. Мы не собирались подпускать итоговую согласованность близко к контролю доступа или состоянию подписки. Elasticsearch индексировал каждый активный товар инвентаря по дилеру, обогащённый данными фида vAuto, а также предложениями и интерактивами, которые настроил каждый дилер. Когда покупатель спрашивал о конкретной машине в чате, виджет обращался к Elasticsearch, а не к реляционной таблице. Качество выдачи соответствовало тому, что требовалось сценарию использования.

Три базы данных — это не сложность, а точность. Одно хранилище, пытающееся делать все три работы, было бы как раз сложным выбором.

Интеграция с vAuto работала как выделенный воркер очереди. vAuto публиковал файлы инвентаря по FTP; задача очереди Laravel на базе Redis забирала их, парсила фид, обновляла MongoDB новыми данными о товарах и переиндексировала затронутый инвентарь в Elasticsearch. Каждый шаг был изолирован. Когда vAuto менял формат файла, менялась одна задача, а не весь стек. Набор тестов браузерной автоматизации на Laravel Dusk не давал полным диалоговым сценариям регрессировать по мере эволюции типов карточек и схем. 1 736 коммитов примерно за два года. Архитектура держалась.

Два года в продакшене; ноль переписываний.

Платформа вышла к первым дилерам в конце 2017 года. Многобазовый дизайн — который на диаграмме архитектуры выглядел как сложность — доказал свою ценность в эксплуатации. Сбои локализовались в своём слое. Сбой парсинга фида vAuto не затрагивал биллинг. Переиндексация Elasticsearch не блокировала разговор с покупателем. Каждое хранилище отказывало так, как отказывает его тип, и не более.

Внедрение у дилеров держалось. Когда виджет задаёт вопросы вместо того, чтобы показывать форму контактов, покупатели отвечают. Поток trade-in — спросить покупателя о его текущей машине, получить оценку TradePending, показать её прямо в диалоге — работал, не требуя участия персонала дилера.

Проект закрылся с 708 исходными файлами, полным набором покрытия на PHPUnit и Dusk и слоем данных, который собственная команда клиента расширяла после передачи. Новые типы карточек, новые коннекторы интеграций — они добавляли их без нас. Три базы данных делают три работы, и ни одна из них не делает чужую.

Outcome
Source files at handoff
708
Commits over active window
1,736
Years in production
2+
Post-handoff rewrites
0
NEXTКейс 05SW · 05 из 10
Hospitality2019

Консоль бронирований для пляжного оператора с несколькими площадками. Без бэкенда.