Skip to content
04Caso de estudioSW · 04 de 10

Una plataforma de chatbot multi-tenant para concesionarios de coches, con tres bases de datos que se ganan su lugar.

Los concesionarios tenían los datos —inventario de vAuto, valoraciones de TradePending, especificaciones de ChromeData— pero ninguna forma de mostrarlos al comprador en el momento. Construimos un SaaS multi-tenant: un constructor visual de flujos para los concesionarios, un widget de chat para los compradores, tres bases de datos por debajo.

ClienteConfidencial
Año2017 — 2019
Duración3 yrs
StackPHP · Laravel · MongoDB · MySQL · Elasticsearch · Redis
Hero image for enterprise-conversational-data-platformFIG 01 · Hero

Los datos estaban ahí. El camino hacia ellos no.

Un concesionario de coches maneja muchos datos: inventario en vivo con precios y disponibilidad, especificaciones de vehículos vinculadas a los VIN, valoraciones de vehículos de intercambio que cambian a diario, opciones de financiación, citas de servicio. Esos datos estaban repartidos en vAuto para el inventario, TradePending para las cotizaciones de intercambio, ChromeData para las especificaciones de los vehículos y el propio CRM de cada concesionario. Nada de ello se mostraba al comprador en el momento en que decidía.

La conversación de compra —qué encaja en mi presupuesto, cuánto me darían por mi intercambio, podéis darle servicio la semana que viene— ocurría por teléfono o en el showroom, horas o días después. Los concesionarios perdían clientes potenciales que no conseguían una respuesta lo bastante rápido.

El encargo: poner una interfaz de chat en el sitio web de cada concesionario que pudiera responder a esas preguntas en tiempo real, conectada a los sistemas que ya tenían las respuestas.

Un constructor visual para los concesionarios, un widget de chat para los compradores.

La plataforma tenía dos superficies distintas. Los concesionarios usaban un constructor visual de flujos en la administración —un editor de grafo de tarjetas donde construían flujos de conversación conectando tarjetas de pregunta, ramas de respuesta y tarjetas de acción: mostrar inventario, obtener una cotización de intercambio, reservar una cita de servicio, capturar un lead—. Sin código requerido. Cada concesionario componía su propio bot; la plataforma se encargaba del renderizado y el enrutamiento.

Los compradores veían un widget de chat embebible en el sitio web del concesionario. El widget ejecutaba los flujos configurados, extraía inventario en vivo de vAuto, mostraba valoraciones de intercambio de TradePending en línea cuando un comprador describía su coche actual y capturaba los datos de contacto en formato ADF para el CRM del concesionario. La conversación se moldeaba en torno a lo que el concesionario había configurado y a lo que el comprador preguntaba.

La plataforma era multi-tenant desde el primer día. Cada concesionario tenía su propia configuración de bot, su propio grafo de flujos, su propia conexión de inventario y CRM. Una sola cuenta podía gestionar varios concesionarios. La autenticación, la facturación y la multitenencia vivían en MySQL; todo lo demás vivía en los almacenes que le encajaban.

F · 01Constructor visual de flujos
Los concesionarios construían flujos de conversación en un editor de grafo de tarjetas: preguntas, ramas de respuesta, consultas de inventario, cotizaciones de intercambio, captura de leads. Sin código requerido. Cada concesionario configuraba su propio bot.
F · 02Feed de inventario de vAuto
Un trabajo de cola respaldado por Redis parseaba las exportaciones FTP de vAuto, actualizaba los datos de producto en MongoDB y reindexaba Elasticsearch por concesionario. Los cambios del feed quedaban aislados en un solo trabajo.
F · 03Integración de intercambio con TradePending
El widget de chat obtenía valoraciones de intercambio de TradePending en línea, mostrando una cotización en la conversación cuando un comprador describía su vehículo actual.
F · 04Exportación de leads ADF
Los datos de contacto del comprador capturados en el chat se formateaban como XML ADF y se enrutaban al CRM del concesionario. El formato estándar del sector significaba que no había integración a medida por concesionario.
F · 05Backend de tres bases de datos
MongoDB para los esquemas en evolución de bot e inventario, MySQL para la autenticación y facturación multi-tenant, Elasticsearch para la búsqueda de inventario por concesionario. Cada almacén era dueño de un trabajo.
F · 06Suite de tests de automatización de navegador
Laravel Dusk cubría los flujos completos de conversación de extremo a extremo. Los cambios de tipo de tarjeta y esquema en MongoDB no rompían las rutas del widget; la suite de tests lo detectaba si lo hacían.

Tres bases de datos, cada una ganándose su lugar.

La decisión de ejecutar tres almacenes en paralelo fue deliberada y se defendió desde el primer día. La tentación en un proyecto como este es normalizarlo todo en un solo almacén y aceptar la fricción en los bordes. No lo hicimos.

MongoDB guardaba las configuraciones de bot y los flujos de conversación: tipos de tarjeta, lógica de ramificación, opciones de respuesta rápida, el esquema de visualización de inventario en evolución. Ese esquema cambiaba cada sprint a medida que crecía el conjunto de funciones. Una migración relacional en cada adición de tipo de tarjeta habría estrangulado la entrega. MongoDB absorbió esos cambios sin ceremonia.

MySQL gestionaba todo lo que necesitaba integridad transaccional: autenticación, facturación y fronteras de multitenencia de los concesionarios. No íbamos a dejar la consistencia eventual cerca del control de acceso ni del estado de las suscripciones. Elasticsearch indexaba cada producto de inventario activo por concesionario, enriquecido con los datos del feed de vAuto y las ofertas e interactivos que cada concesionario había configurado. Cuando un comprador preguntaba por un coche concreto en el chat, el widget consultaba Elasticsearch, no una tabla relacional. La calidad de recuperación se ajustaba a lo que el caso de uso necesitaba.

Tres bases de datos no es complejidad: es precisión. Un solo almacén intentando hacer los tres trabajos habría sido la elección compleja.

La integración con vAuto corría como un worker de cola dedicado. vAuto publicaba archivos de inventario por FTP; un trabajo de cola de Laravel respaldado por Redis los recogía, parseaba el feed, actualizaba MongoDB con los nuevos datos de producto y reindexaba en Elasticsearch el inventario afectado. Cada paso estaba aislado. Cuando vAuto cambiaba el formato de un archivo, cambiaba un trabajo, no todo el stack. La suite de tests de automatización de navegador en Laravel Dusk evitaba que los flujos completos de conversación regresaran a medida que evolucionaban los tipos de tarjeta y los esquemas. 1.736 commits a lo largo de aproximadamente dos años. La arquitectura aguantó.

Dos años en producción; cero reescrituras.

La plataforma se publicó para los primeros concesionarios a finales de 2017. El diseño multibase de datos —que había parecido complejidad en el diagrama de arquitectura— demostró su valor en operación. Los fallos quedaron contenidos en su capa. Un fallo de parseo del feed de vAuto no afectaba a la facturación. Una reindexación de Elasticsearch no bloqueaba una conversación de comprador. Cada almacén fallaba del modo en que falla su tipo, y nada más.

La adopción por parte de los concesionarios se mantuvo. Cuando el widget hace preguntas en lugar de mostrar un formulario de contacto, los compradores responden. El flujo de intercambio —preguntar al comprador por su coche actual, obtener una valoración de TradePending, mostrarla en línea— funcionaba sin requerir personal del concesionario.

El proyecto cerró con 708 archivos de código fuente, una suite completa de cobertura de PHPUnit y Dusk, y una capa de datos que el propio equipo del cliente extendió tras la entrega. Nuevos tipos de tarjeta, nuevos conectores de integración: los añadieron sin nosotros. Tres bases de datos haciendo tres trabajos, y ninguna haciendo el de otra.

Outcome
Source files at handoff
708
Commits over active window
1,736
Years in production
2+
Post-handoff rewrites
0
NEXTCaso de estudio 05SW · 05 de 10
Hospitality2019

Una consola de reservas para un operador de playas multilocal. Sin backend requerido.