Un catálogo que se construye solo: parsers, tarifas de proveedores e importaciones que se pueden deshacer
Miles de productos de varias fuentes significan copiar datos sin parar: modelos nuevos, características que cambian, fotos nuevas, tarifas en formatos distintos. El hub detrás de la tienda Ezeden se encarga de ese trabajo: lee las fuentes por sí mismo, enseña qué cambiaría y no deja que una importación estropee el catálogo.
El reto
Una tienda con miles de productos técnicos depende de datos que no escribe ella misma. Los fabricantes cambian modelos y características en sus webs, los proveedores mandan tarifas cada uno en su formato y una tienda antigua guarda años de trabajo de catálogo. Mantenerlo todo al día a mano es un trabajo a jornada completa, y un solo archivo erróneo puede borrar precios o descripciones de toda la gama.
El catálogo maestro de Ezeden tenía que traer los datos por sí mismo y de forma segura: enseñar qué cambiaría, pararse cuando algo no cuadra, no pisar nunca lo que una persona ha corregido y permitir deshacer cualquier importación.
Parsers de las webs de los fabricantes
Cuando la web de un fabricante es la mejor fuente, el hub la lee página a página, con permiso: nombre, descripción, características, fotos, fichas técnicas y planos en PDF, y los demás colores del modelo.
El parser es discreto por diseño: una página cada pocos segundos y solo dentro de una franja nocturna. La mayoría de las noches se lee solo lo que ha cambiado en la web; una vez por semana, una pasada completa lo revisa todo.
Una página sin referencia, nombre o precio se rechaza por incompleta: no es un producto con un campo vacío, así que se aparta como ilegible, con el motivo, y nunca se aplica. Si los rechazos superan el 5 %, la importación se retiene, porque cuando fallan tantas páginas casi siempre es que la web ha cambiado su diseño. No se aplica nada, el equipo recibe un correo y la importación retenida indica qué parte de la página ha desaparecido. El parser también se detiene cuando la web dice que no: tras cinco rechazos seguidos se para en lugar de insistir, y la siguiente ejecución continúa donde se quedó.
Un producto descatalogado deja de venderse: si una pasada completa ya no encuentra un modelo, el hub lo marca como descatalogado, se vende hasta agotar el stock y sale de los listados, pero su página se mantiene. Si el modelo vuelve, vuelve también el producto. La decisión de un responsable siempre prevalece.
Tarifas de proveedores sin programador
El hub incluye un mecanismo para archivos de proveedores en Excel, CSV y XML. Un responsable da de alta al proveedor en el panel, sube un archivo de muestra y monta una plantilla: el hub propone, a partir de las cabeceras, qué columna es la referencia, el precio o el stock, y el responsable lo corrige y guarda. Las transformaciones - separadores decimales, un multiplicador, un diccionario de valores, dividir una celda en una lista - son ajustes, no código.
Para cada proveedor se decide qué columna identifica el producto, si las filas desconocidas pueden crear productos (por defecto solo se informan) y, por columna, si actualiza siempre, solo rellena campos vacíos o escribe solo en productos nuevos.
Los archivos pueden llegar de cuatro formas: un enlace que el proveedor mantiene actualizado, una carpeta FTP o SFTP, o un buzón de correo, donde el mensaje se elige por remitente, asunto y nombre del adjunto. El hub comprueba cada pocos minutos y nunca mueve, renombra ni borra nada en el lado del proveedor. Cada archivo recibido se guarda, así que cualquier entrega se puede revisar o aplicar de nuevo.
Vista previa, anomalías y marcha atrás
Todas las fuentes pasan por el mismo proceso: lectura a una zona intermedia, validación, control de anomalías y aplicación. Nada toca el catálogo en vivo antes del último paso.
La vista previa muestra lo que haría la importación: productos que se crearían, cambiarían o quedarían igual, filas sin coincidencia y cada campo modificado como en una revisión de código, con las palabras eliminadas en rojo y las añadidas en verde. Desde ahí el responsable asigna una categoría desconocida, conserva el valor del catálogo o deja fuera una fila. El primer archivo de una plantilla nueva siempre se detiene aquí.
El detector de anomalías retiene la importación cuando la fuente devuelve de repente muchos menos productos que la vez anterior, cuando pone a cero precios o stock en una parte grande de la gama o cuando hay demasiadas páginas ilegibles. Un salto de precio por encima de un umbral queda retenido hasta que una persona la apruebe.
El trabajo manual lo protegen los modos de campo. Cada campo de un producto está sincronizado con su fuente, es local (editado a mano) o está bloqueado, y una importación solo actualiza los campos sincronizados. Una descripción que un responsable reescribió sigue reescrita, diga lo que diga el siguiente archivo.
Cada valor que escribe una importación queda en el historial, junto al anterior. Por eso se puede deshacer una importación entera - los productos nuevos se archivan y las ediciones manuales posteriores se respetan - o revertir un solo cambio.
Duplicados y características en orden
Con varias fuentes, un producto puede llegar dos veces. El hub busca duplicados por EAN, por la referencia del fabricante normalizada, por los códigos de modelo dentro del nombre y por similitud con IA. Nunca fusiona productos por su cuenta: presenta candidatos a un responsable.
Con las características pasa lo mismo. Una fuente dice “Color”, otra “Color del modelo”, otra lo escribe en otro idioma. El responsable fusiona dos nombres en uno y el antiguo se queda como alias, de modo que la siguiente importación cae en la característica correcta en lugar de crearla de nuevo. La fusión se puede deshacer. Una cola de candidatos sugiere qué pares pueden ser el mismo dato: por ejemplo, dos características que ningún producto tiene a la vez y que comparten muchos valores. Las unidades se convierten al entrar, así que “21,5 cm” llega a un campo en milímetros como 215.
Grupos de variantes y encuadre de fotos
Un grifo que se vende en seis acabados son seis productos, cada uno con su referencia, su precio y su stock. Un grupo de variantes los une en un único selector de color en la ficha. Los grupos salen de la fuente - una web de fabricante que enlaza los demás colores - o de una regla por marca que lee el acabado en la referencia. Si no, el hub propone productos con el mismo nombre que solo se diferencian en el color o el acabado. Qué características forman el selector se propone una vez; después, la elección es del responsable.
Las fotos se aceptan tal como las manda el fabricante, también en TIFF, PSD o HEIC, y se guardan como un archivo maestro de tamaño acotado. El encuadre - recorte, zoom, centrado, márgenes - se guarda como datos, no como edición del archivo, así que siempre se puede deshacer. El encuadre automático encuentra el objeto sobre un fondo liso y le da la misma proporción del marco en todas las fotos, así los colores de un modelo quedan alineados; una foto con un interior de fondo se deja como está. La tienda recibe los tamaños que necesita en WebP, con JPEG de respaldo.
Migración desde OpenCart
El primer catálogo vino de una tienda OpenCart existente. El hub lee su base de datos directamente y en modo solo lectura: productos, textos en los dos idiomas de la tienda, categorías, características, fotos, documentos enlazados en las descripciones, promociones y productos relacionados. Clientes y pedidos no se migran.
El tipo de cada característica se deduce de sus valores: las cifras con unidad pasan a campos numéricos en una unidad base, un conjunto corto de valores pasa a ser una lista y el resto queda como texto. Un texto guardado en el idioma equivocado - ruso en un campo ucraniano, detectado por letras que solo usa uno de los dos idiomas - se vacía para que la capa de traducción lo rellene bien. Los bloques de filtros de la tienda se trasladan a las categorías correspondientes, en el mismo orden, pero solo para características que los productos indican de verdad, y un filtro que un responsable quitó no vuelve a aparecer. La tienda se puede volver a leer cada noche, y una ejecución que cambiaría algo se detiene en su informe de cambios para un responsable.
Stack tecnológico
- Hub: Laravel 13 + Inertia + React 19 + Ant Design
- Parsers: Symfony HttpClient + DomCrawler
- Archivos: OpenSpout (xlsx, csv), XMLReader en streaming
- Entrega: Flysystem FTP/SFTP, webklex/php-imap
- Imágenes: Intervention Image + Imagick
- Segundo plano: Laravel Horizon sobre Redis 7; datos en MySQL 8.4Resultado
Añadir una marca o un proveedor es un ajuste y un mapeo, no un proyecto de desarrollo. El catálogo se actualiza solo desde las webs de los fabricantes, los archivos de proveedores y la tienda antigua, mientras cada cambio se ve antes de aplicarse, las importaciones sospechosas esperan a una persona, las ediciones manuales no se tocan y cualquier importación se puede deshacer.



