Escenario · Configurador B2B · Fabricación a medida

De la oferta por email
al configurador en tiempo real.

Una empresa que fabrica componentes a medida y prepara cada oferta a mano, entre tarifas, hojas de cálculo y consultas a la oficina técnica. Un configurador web que calcula precio y referencia mientras el cliente elige.

Tipo de proyectoConfigurador B2B
SectorFabricación a medida
Plazos habituales10–14 semanas
●Escenario
aplicación web · configurador B2B
B2B
CONFIGURADOR DE PRODUCTOS
Usuario: oficina técnica
1
Tipo
2
Parámetros
3
Materiales
4
Oferta
Parámetros del producto
Diámetro nominal
DN 50
DN 80
DN 100
DN 150
Presión máx. (bar)
16 bar
25 bar
40 bar
Material del cuerpo
Acero inoxidable
Fundición
Bronce
Resumen de la configuración
CÓDIGO DE ARTÍCULO
VB-50-25-INOX-F
Base del cuerpo€ 2.100
Material inox ×1,8€ 1.680
Presión 25 bar€ 350
Descuento cliente (15%) − € 617
PRECIO NETO
€ 3.513
GENERAR PDF

Escenario web app — configurador de productos B2B

300 variantes de producto.
Cada presupuesto hecho a mano.

El escenario: un fabricante de válvulas y componentes hidráulicos industriales a medida que suministra a plantas de proceso, astilleros e industria alimentaria en toda Europa. Los productos son muy configurables: diámetro, presión nominal, material del cuerpo, tipo de conexión, revestimiento interior, certificaciones. Combinando las variables salen cientos de configuraciones posibles, cada una con un precio distinto.

Sin un configurador, cada petición de oferta sigue el mismo recorrido: el comercial recoge las especificaciones, las manda por email a la oficina técnica, que comprueba la viabilidad y pasa los datos a la oficina de precios, que prepara el presupuesto en Excel y se lo devuelve al comercial. Tiempo típico: 3–5 días laborables.

En un mercado en el que la competencia extranjera responde en menos de 24 horas, este proceso se convierte en una desventaja real: parte de las negociaciones se pierde solo por el tiempo de respuesta.

«Ya sabemos que el producto lo fabricamos. El problema es que el cliente no lo sabe, porque tardamos cuatro días en decírselo. Mientras tanto ya ha llamado a otro.»

— Lo que oigo a menudo en las empresas industriales
Escenario Configurador B2B con precios en tiempo real y generación de ofertas (ejemplo)
Stack Node.js + Express · React · PostgreSQL · Redis
Integraciones CRM (p. ej. HubSpot) · Puppeteer (PDF) · email con Nodemailer
Usuarios Comerciales internos · Agentes · Clientes directos (autoservicio)
Duración típica 9–10 semanas
Etiquetas
Node.js React motor de precios PostgreSQL Redis HubSpot API Puppeteer

Requisitos de un configurador industrial B2B

De días a minutos.
Sin errores de configuración.

Configurador guiado paso a paso con validación en tiempo real

El sistema tiene que guiar al usuario por los parámetros del producto mostrando solo las combinaciones técnicamente válidas. Si eliges DN 150 con presión de 40 bar, el material "bronce" tiene que desaparecer de la lista, porque esa combinación no está homologada. Las reglas de compatibilidad se gestionan en el servidor, no en el cliente.

Precios en tiempo real con tarifas diferenciadas por cliente

El precio tiene que actualizarse con cada cambio de parámetro, sin pulsar "calcular". Cada cliente B2B tiene una tarifa personalizada (descuentos, recargos por certificaciones, precios bloqueados en algunas familias). El motor de precios debe aplicar las reglas correctas según el usuario conectado, sin exponer nunca la tarifa base al frontend.

Generación de la oferta en PDF con la marca en un clic

El PDF de la oferta debe incluir: cabecera de la empresa, datos del cliente, descripción técnica completa del producto configurado, precio neto con desglose, condiciones de suministro, validez de la oferta y firma digital del comercial. Generación en menos de 5 segundos y envío automático por email al cliente.

Sincronización automática con el CRM HubSpot

Cada oferta generada debe crear automáticamente un deal en HubSpot con todos los detalles de la configuración, el importe de la oferta y el comercial asignado. Si el cliente ya existe en el CRM, el deal se vincula al contacto existente. Si es nuevo, se crea el contacto. Ninguna doble introducción manual.

Acceso de autoservicio para clientes directos con área privada

Los clientes más grandes tienen que poder entrar al configurador directamente, sin pasar por un comercial. Ven solo su propia tarifa y el historial de ofertas anteriores, y pueden partir de una configuración guardada. La oficina comercial recibe un aviso por cada nueva oferta generada por un cliente por su cuenta.

Retos técnicos de un motor de precios en tiempo real

Un motor de precios
que nunca miente.

Un configurador que se equivoca es peor que no tener configurador: si da un precio erróneo o acepta una combinación imposible, la empresa tiene que renegociar una oferta ya aceptada. El reto principal no es técnico: es la corrección absoluta.

01

Modelar cientos de reglas de compatibilidad sin escribirlas en el código

Las reglas de compatibilidad entre parámetros (p. ej. "DN 150 + 40 bar → solo acero inoxidable") suelen estar repartidas entre años de documentos técnicos, emails y conocimiento en la cabeza de los técnicos. La solución es un motor de reglas sobre PostgreSQL: cada regla es una fila con condiciones y consecuencias, que la oficina técnica puede modificar sin tocar el código. El motor evalúa las reglas por prioridad y devuelve las opciones válidas del paso siguiente.

02

Motor de precios: varios niveles de tarifa, nada expuesto al navegador

El sistema gestiona varios tipos de tarifa (estándar, agente, cliente directo, acuerdo marco, promoción, precio bloqueado). El cálculo se hace solo en el servidor Node.js: el frontend recibe el precio final y el desglose que ese usuario puede ver. La tarifa base nunca sale de la API. Redis guarda las tarifas en caché 15 minutos y quita mucha carga a la base de datos en los picos.

03

Generación de PDF con Puppeteer: plantilla fiel a la marca

El PDF de la oferta tiene que ser idéntico al formato en papel que se usa desde hace años: cabecera precisa al milímetro, tablas técnicas complejas, la firma del comercial como imagen. Puppeteer convierte una plantilla HTML/CSS en PDF con márgenes calibrados. Se ejecuta en un proceso aparte para no bloquear el servidor, con un tiempo límite de 10 segundos y reintento automático.

04

Sincronización con HubSpot: gestionar duplicados y actualizaciones parciales

HubSpot no tiene un "crear o actualizar" atómico: si buscas un contacto por email y no está, hay que crearlo, pero mientras tanto otro proceso puede haberlo creado ya. La solución es la idempotencia basada en un ID único de oferta: cada sincronización comprueba primero si ya existe un negocio con ese ID en un campo personalizado y, si existe, lo actualiza en lugar de duplicarlo.

05

Sesión de configuración: recuperación tras recargar o perder la conexión

Una configuración compleja lleva varios minutos. Si el comercial recarga la página o pierde la conexión, tiene que poder seguir donde lo dejó. El estado se guarda automáticamente en PostgreSQL cada 30 segundos y se recupera al volver a abrir, incluso desde otro dispositivo.

Proceso de desarrollo del configurador B2B

9–10 semanas para convertir
el conocimiento tácito en software.

Semanas 1–2
Extracción del conocimiento técnico

Dos semanas con el responsable técnico y el comercial más experto para mapear cada regla de compatibilidad. Normalmente no están documentadas: viven en la cabeza de las personas y en algún Excel interno. El resultado es un documento estructurado con todas las reglas en la forma "SI [parámetro A] = X Y [parámetro B] = Y → ENTONCES [parámetro C] no puede ser Z", que se convierte en el modelo de datos del motor.

→ reglas mapeadas · estructura de la base de datos · revisión de completitud con la oficina técnica
Semanas 3–5
Backend Node.js: motor de reglas + motor de precios

El corazón del sistema: el motor de reglas en Node.js lee las reglas de PostgreSQL, las evalúa por prioridad y devuelve las opciones de cada paso. El motor de precios aplica la tarifa del usuario conectado —precio base × coeficiente de material × coeficiente de presión + opcionales— y luego el descuento contractual. Redis guarda las tarifas 15 minutos en caché. Pruebas de carga para comprobar que aguanta cientos de peticiones por segundo.

→ endpoints Express · motor de reglas · motor de precios · caché Redis · pruebas Jest
Semanas 6–7
Frontend React: configurador paso a paso + guardado automático

Interfaz en React por pasos: cada elección pide al backend las opciones válidas del paso siguiente. El precio se actualiza en tiempo real con un debounce de 300 ms en la llamada. El estado se guarda en PostgreSQL cada 30 segundos: al cerrar y volver a abrir el navegador todo sigue igual. Además, un "historial de ofertas" para los clientes con acceso directo.

→ React + debounce 300 ms · autoguardado 30 s · historial de ofertas · responsive para tablet
Semana 8
Generación de PDF con Puppeteer + integración con HubSpot

La plantilla del PDF está hecha en HTML/CSS y reproduce fielmente la de papel. Puppeteer la convierte en PDF en pocos segundos en un proceso dedicado. El archivo va a S3 y se envía por email al cliente y al comercial. En paralelo, la misma oferta llega al CRM por API: contacto creado o actualizado, negocio con todos los campos de la configuración, asignado al comercial.

→ Worker Puppeteer · subida a S3 · Nodemailer · HubSpot API v3 · upsert idempotente
Semanas 9–10
UAT con los comerciales y go-live

Dos semanas de pruebas con algunos comerciales y agentes externos. Es normal que aparezcan un par de reglas que faltaban (casos rarísimos que nadie mencionó en las entrevistas) o un descuento mal aplicado en una familia de productos: con el motor de reglas configurable se corrigen sin una nueva versión. Puesta en marcha gradual: primero la red comercial interna, luego los agentes y por último los clientes en autoservicio tras unas semanas de estabilidad.

→ pruebas con comerciales y agentes · reglas completadas · lanzamiento en 3 fases · sin cortes

Solución: motor de reglas y precios en Node.js

El motor de reglas:
cientos de restricciones, ninguna en el código.

La decisión de arquitectura más importante es separar las reglas de negocio del código. Cada vez que la oficina técnica añade una variante o cambia una compatibilidad, modifica una fila en la base de datos, sin nuevas versiones.

Solución 01 / 03

Motor de reglas configurable: editable sin código

Cada regla es una fila de PostgreSQL con cuatro campos: param_key, param_value, excluded_key, excluded_values y una priority para gestionar los conflictos. El motor en Node.js carga las reglas relevantes para la configuración actual, las evalúa en orden y devuelve un array de opciones válidas para el paso siguiente. La oficina técnica gestiona las reglas desde un panel de administración construido con React Table: el desarrollador no tiene que intervenir para añadir o modificar restricciones.

// pricing-engine.js — cálculo del precio con caché Redis async function calculatePrice( config, userId ) { const cacheKey = `listino:${userId}`; let listino = await redis.get( cacheKey ); if ( !listino ) { listino = await db.query( 'SELECT * FROM listini WHERE cliente_id = $1 AND attivo = true', [userId] ); await redis.setEx( cacheKey, 900, JSON.stringify(listino) ); // TTL 15 min } else { listino = JSON.parse( listino ); } const basePrice = getBasePrice( config.tipologia, config.diametro ); const coefMat = listino.find( r => r.param === config.materiale )?.coef ?? 1; const coefPress = listino.find( r => r.param === config.pressione )?.coef ?? 1; const sconto = listino.sconto_cliente ?? 0; const lordo = basePrice * coefMat * coefPress; return { netto: lordo * (1 - sconto), lordo, sconto, breakdown: { basePrice, coefMat, coefPress } }; }
Solución 02 / 03

PDF en segundos, idéntico al modelo en papel

Puppeteer convierte una plantilla HTML/CSS con los datos de la oferta insertados en el servidor. La plantilla reproduce el formato en papel de la empresa: cabecera con el logo vectorial, tabla de parámetros técnicos con unidades, desglose del precio, condiciones de suministro, validez y firma del comercial. El proceso de Puppeteer va separado del servidor principal, con límite de 10 segundos y reintento automático. Objetivo: oferta lista en menos de 5 segundos.

Oferta_VB-50-25-INOX.pdf
OFERTA N.º 0847 (ejemplo)
Fecha: 15/11
Válvula de bola VB · DN 50 · 25 bar · Acero inoxidable
Diámetro
DN 50
Presión
25 bar
Precio neto (descuento 15%)
€ 3.513,00
Enviado al cliente · HubSpot actualizado
Solución 03 / 03

Un CRM siempre al día, sin tocar HubSpot

Cada oferta lanza una secuencia en segundo plano: primero el PDF va a S3 y después arranca la sincronización con el CRM. El contacto se busca por email: si existe se actualiza y si no se crea. Luego se crea o actualiza el negocio con un campo offerta_id como clave de idempotencia: si el job se ejecuta dos veces, no crea un duplicado. Los comerciales encuentran cada oferta en el CRM ya ligada al contacto correcto, con el PDF adjunto, el importe y la fase "Oferta enviada". Objetivo: cero introducción manual.

Por qué importa: el responsable comercial deja de hacer la "ronda de la tarde" para actualizar el CRM a mano, y los datos se mantienen limpios, sin duplicados.

Stack tecnológico Node.js React PostgreSQL

Node.js en el centro.
Cada herramienta en su sitio.

Node.js + Express
React
PostgreSQL
Redis
Puppeteer
API del CRM (p. ej. HubSpot)
AWS S3
Nodemailer + SES
Jest + Supertest
Vite
React Table
Zod (validación)

¿Por qué Node.js y no PHP/Laravel?

El motor de precios evalúa decenas de reglas seguidas en cada petición: un trabajo rápido pero muy frecuente. Node.js gestiona bien la concurrencia típica de una API que hace muchas consultas a Redis y PostgreSQL en paralelo. Usar TypeScript tanto en el frontend como en el backend reduce los cambios de contexto y los errores de interfaz entre las dos capas.

¿Por qué Puppeteer y no una librería de PDF?

Librerías como PDFKit o jsPDF obligan a construir el layout por programación: cada línea, cada tabla, cada margen definidos en código. Una plantilla HTML/CSS es infinitamente más fácil de mantener: un diseñador puede cambiar el aspecto de la oferta tocando el CSS, sin tocar JavaScript. El precio es un proceso algo más pesado, resuelto con el worker aislado y el precalentamiento de Puppeteer al arrancar el servidor.

Objetivos de ejemplo — configurador B2B

De días a minutos.
Cada oferta registrada.

Cifras de ejemplo, no resultados de un cliente: objetivos realistas para un escenario como este, a medir en los primeros meses tras el lanzamiento frente al mismo periodo anterior.

−90%
Ciclo de oferta
objetivo: de días a minutos
100%
Ofertas generadas
todas en el CRM, sin errores de precio
−90%
Errores de configuración
objetivo de menos correcciones
+20%
Tasa de cierre
objetivo de más ofertas aceptadas
<5s
Generación de PDF
objetivo de tiempo de generación
0
Duplicados en HubSpot
objetivo con la sincronización idempotente

«Un cliente envía un pedido desde el acceso directo un viernes a las 22:30. Antes habría esperado al lunes.» Ese es el escenario al que apuntar: una empresa que responde aunque la oficina esté cerrada.

— El objetivo concreto del autoservicio

Aprendizajes del desarrollo del configurador de productos

Lo que aplico
en cada proyecto así.

→

Separar las reglas de negocio del código se amortiza enseguida. Tras el lanzamiento siempre llegan nuevas variantes y compatibilidades: con el motor de reglas las gestiona la oficina técnica desde el panel, sin desarrollo.

→

El precio se calcula siempre y solo en el servidor. Calcularlo en el navegador ahorraría llamadas, pero dejaría los coeficientes de la tarifa a la vista de cualquiera que abra las herramientas de desarrollo: sería regalar la estructura de precios a la competencia. Con un debounce de 300 ms la experiencia sigue siendo en tiempo real.

→

El guardado automático siempre compensa su coste. Basta una recarga accidental para perder diez minutos de configuración: en cualquier web app con formularios complejos es un requisito innegociable.

→

La idempotencia de los jobs de sincronización no es un detalle. En producción a veces un job se ejecuta dos veces (tiempo límite + reintento). Sin una comprobación por ID único, el CRM se llena de duplicados justo los primeros días tras el lanzamiento, cuando más importa la calidad de los datos.

→

El acceso directo para clientes B2B cambia la relación más que cualquier función. Parte de las ofertas llega fuera del horario de oficina, y un proceso transparente y rápido crea una confianza distinta a la de una llamada con el comercial.

¿Tienes un proceso de venta que merece automatizarse?

Configuradores, presupuestos, catálogos complejos: si la lógica ya existe, se puede programar.

¿Tienes en mente un proyecto parecido?

Cuéntamelo: partimos de objetivos y prioridades, y la primera llamada es gratuita.