Automatizar la validación de datos de producto con Node.js: un pipeline de calidad básico

Un flujo técnico para validar completitud, consistencia y formato de los datos antes de que ingresen al PIM. Código reutilizable y adaptable.

En muchos proyectos, el problema no empieza cuando el dato ya está dentro del PIM. Empieza antes. Empieza cuando la información llega desde un ERP, una planilla, un proveedor, un feed o una API externa y nadie verifica seriamente si ese dato está listo para entrar.

Ahí aparece una confusión bastante común: creer que validar datos es lo mismo que comprobar si un campo viene vacío. En la práctica, la validación de datos de producto es bastante más que eso. Un registro puede venir completo y aun así estar mal. Puede tener todos los campos cargados, pero con formatos inconsistentes, valores fuera de vocabulario, unidades mezcladas o relaciones incorrectas entre atributos.

Antes de ingresar datos al PIM, no alcanza con que el archivo exista o la API responda. Lo importante es saber si el dato está realmente listo para entrar.

Por eso, antes de enviar información al PIM, conviene construir una capa técnica que haga tres cosas bien: leer, validar y decidir. Node.js encaja muy bien en ese trabajo porque permite automatizar flujos de entrada, procesar archivos o APIs y convertir reglas de calidad en código reutilizable. Node ofrece APIs estables para trabajar con sistema de archivos y también una API de streams pensada para manejar flujos de datos sin cargar todo en memoria, algo muy útil cuando el volumen crece.

Por qué conviene validar antes del PIM

Un PIM está pensado para centralizar, estructurar, enriquecer y distribuir información de producto. Eso no significa que deba absorber desorden sin control. En el ecosistema PIM, la calidad de datos se apoya en dimensiones como precisión, completitud, consistencia y conformidad, y esa lógica debería comenzar antes del alta, no después.

Akeneo insiste en ese punto cuando habla de calidad de datos: el trabajo serio empieza al recopilar, preparar y estandarizar la información que llega desde distintas fuentes, como ERP, proveedores o sistemas externos.

Eso tiene bastante sentido en proyectos reales. Si el dato entra mal al PIM, después hay que:

  • limpiarlo;
  • corregirlo manualmente;
  • revisar por qué se publicó mal;
  • volver a sincronizar;
  • y, en muchos casos, reparar también sus efectos aguas abajo en eCommerce o marketplaces.

Dicho de otro modo: cuanto más tarde se detecta un error, más caro suele ser corregirlo.

Qué debería validar un pipeline básico

Cuando hablo de un pipeline de calidad básico, no estoy pensando en una plataforma gigantesca ni en un framework complejo. Estoy pensando en un flujo técnico claro, con reglas concretas, que pueda reutilizarse y crecer con el tiempo.

Para un primer nivel, yo validaría al menos tres cosas:

1. Completitud

La pregunta más simple es: ¿están todos los campos mínimos que el producto necesita para existir o avanzar?

Eso puede incluir:

  • SKU;
  • nombre de producto;
  • marca;
  • categoría;
  • familia;
  • unidad de medida;
  • atributos mínimos de la familia;
  • identificadores técnicos.

La completitud sigue siendo una dimensión central de calidad dentro del mundo PIM, incluso en métricas nativas de plataformas como Akeneo.

2. Consistencia

Acá ya no importa solo si el campo existe, sino si tiene sentido en relación con otros campos.

Por ejemplo:

  • si el producto pertenece a una familia técnica, debería tener ciertos atributos y no otros;
  • si una variante tiene talle y color, debería heredar correctamente lo que corresponde del padre;
  • si el atributo dice “centímetros”, el valor debería poder interpretarse como tal;
  • si una categoría implica un conjunto de campos obligatorios, esa relación debería cumplirse.

3. Formato

Este nivel verifica que el valor respete una forma válida:

  • GTIN o EAN con largo correcto;
  • número donde debe haber número;
  • booleano donde debe haber booleano;
  • fecha en formato esperado;
  • texto sin caracteres de control;
  • listas cerradas donde no debería haber texto libre.

Un registro puede venir completo y aun así estar mal. Validar calidad no es solo buscar campos vacíos.

La idea central: separar reglas de calidad del transporte del dato

Este punto me parece importante. Muchas integraciones empiezan resolviendo todo dentro del script que consume una API o lee un archivo. Eso funciona al principio, pero se degrada rápido.

Lo más sano es separar:

  • la lectura del dato;
  • la normalización inicial;
  • las reglas de validación;
  • y la salida del resultado.

Cuando esa separación existe, el pipeline se vuelve más mantenible. Si cambia la fuente, no necesariamente cambian las reglas. Si cambia una regla, no hace falta tocar el transporte completo. Y si el negocio quiere endurecer o flexibilizar validaciones, eso puede hacerse sin rehacer toda la integración.

Un pipeline básico en Node.js: cómo pensarlo

En términos simples, el flujo podría verse así:

  1. Entrada
    Recibir datos desde CSV, Excel convertido, JSON, API o feed.
  2. Normalización
    Traducir encabezados, unificar nombres de campos, limpiar tipos básicos.
  3. Validación de esquema
    Verificar si el registro cumple la estructura mínima esperada.
  4. Validación de reglas de negocio
    Verificar completitud, consistencia, vocabulario y formatos.
  5. Clasificación del resultado
    Marcar cada registro como válido, válido con warning o inválido.
  6. Salida
    Generar:
    • lote listo para el PIM;
    • archivo de errores;
    • resumen por lote;
    • o ambos.

Node.js ofrece bastante buen soporte para construir esta clase de pipeline. El módulo node:fs/promises permite trabajar con archivos desde promesas, y la API de streams es útil cuando no conviene cargar todo el dataset en memoria.

Qué herramientas encajan bien en este enfoque

No hace falta inventar todo desde cero. Para un pipeline básico en Node.js, una combinación razonable puede ser:

  • Node.js como runtime;
  • fs/promises para leer archivos o escribir reportes;
  • streams si el volumen es alto;
  • Ajv para validar estructuras con JSON Schema;
  • una capa propia de funciones para reglas de negocio.

Ajv encaja especialmente bien cuando querés separar validación estructural de validación semántica. Su documentación explica que permite implementar lógica de validación compleja a través de esquemas declarativos y compila los esquemas a JavaScript optimizado.

Eso lo vuelve útil para el primer filtro: confirmar si el objeto tiene la forma básica que el pipeline espera.

Un ejemplo simple de arquitectura

No lo plantearía como “un gran validador universal”, sino como módulos chicos y claros.

Podría organizarse así:

  • reader.js
    Lee la fuente.
  • normalize.js
    Traduce y limpia campos iniciales.
  • schema.js
    Define la estructura mínima esperada.
  • validators/required.js
    Reglas de completitud.
  • validators/consistency.js
    Reglas entre campos.
  • validators/format.js
    Reglas de formato.
  • pipeline.js
    Orquesta el flujo.
  • reporter.js
    Genera salida legible.

Ese tipo de separación tiene una ventaja práctica: el código se vuelve más reusable y más fácil de adaptar a otras familias, proveedores o canales.

Un ejemplo de código reutilizable y adaptable

A nivel conceptual, un pipeline básico podría empezar con una estructura como esta:

// validate-product.js
export function validateProduct(product) {
const errors = [];
const warnings = [];

// Completitud
if (!product.sku) errors.push({ field: 'sku', code: 'REQUIRED', message: 'SKU obligatorio' });
if (!product.name) errors.push({ field: 'name', code: 'REQUIRED', message: 'Nombre obligatorio' });
if (!product.category) errors.push({ field: 'category', code: 'REQUIRED', message: 'Categoría obligatoria' });

// Formato
if (product.ean && !/^\d{13}$/.test(product.ean)) {
errors.push({ field: 'ean', code: 'INVALID_FORMAT', message: 'EAN debe tener 13 dígitos' });
}

if (product.weight && Number.isNaN(Number(product.weight))) {
errors.push({ field: 'weight', code: 'INVALID_NUMBER', message: 'Peso debe ser numérico' });
}

// Consistencia
if (product.family === 'calzado' && !product.size) {
errors.push({ field: 'size', code: 'REQUIRED_BY_FAMILY', message: 'Talle obligatorio para calzado' });
}

if (product.unit === 'cm' && product.length && Number(product.length) <= 0) {
errors.push({ field: 'length', code: 'INVALID_RANGE', message: 'Largo debe ser mayor a cero' });
}

// Warning de vocabulario
const allowedColors = ['Negro', 'Blanco', 'Azul', 'Rojo', 'Gris'];
if (product.color && !allowedColors.includes(product.color)) {
warnings.push({ field: 'color', code: 'NON_STANDARD_VALUE', message: 'Color fuera de vocabulario controlado' });
}

return {
valid: errors.length === 0,
errors,
warnings
};
}

No es un sistema completo, pero ya muestra algo importante: las reglas pueden escribirse como unidades pequeñas, legibles y reusables.

Cómo sumar validación de esquema con Ajv

La validación de reglas de negocio conviene separarla de la validación estructural. Para esto, Ajv puede cumplir muy bien el rol de primera barrera.

// schema.js
export const productSchema = {
type: 'object',
required: ['sku', 'name', 'category'],
properties: {
sku: { type: 'string', minLength: 1 },
name: { type: 'string', minLength: 1 },
category: { type: 'string', minLength: 1 },
ean: { type: 'string' },
weight: { type: ['string', 'number'] },
family: { type: 'string' },
size: { type: 'string' },
unit: { type: 'string' },
length: { type: ['string', 'number'] },
color: { type: 'string' }
},
additionalProperties: true
};
// pipeline.js
import Ajv from 'ajv';
import { productSchema } from './schema.js';
import { validateProduct } from './validate-product.js';

const ajv = new Ajv({ allErrors: true });
const validateSchema = ajv.compile(productSchema);

export function runValidation(product) {
const schemaOk = validateSchema(product);

if (!schemaOk) {
return {
valid: false,
errors: validateSchema.errors || [],
warnings: []
};
}

return validateProduct(product);
}

Ajv está pensado justamente para validar datos JSON con esquemas declarativos y reutilizables, lo que ayuda mucho cuando el flujo recibe objetos desde archivos transformados o desde APIs.

Conviene separar la validación de esquema de la validación de negocio. La estructura y la lógica del dato no son exactamente el mismo problema.

Qué salida debería generar el pipeline

Una validación útil no termina en un true o false. Tiene que devolver información accionable.

Como mínimo, el resultado debería distinguir entre:

  • válido, puede avanzar;
  • válido con warning, puede avanzar con observación;
  • inválido, debe detenerse o ir a revisión.

Además, conviene devolver:

  • campo afectado;
  • código de error;
  • mensaje;
  • severidad;
  • identificador de producto;
  • lote o fuente.

Eso permite hacer algo bastante más útil que “el archivo tiene errores”. Permite saber qué falló, en qué fila, bajo qué regla y con qué impacto.

Qué tipo de reglas conviene modelar primero

Si el pipeline está arrancando, no intentaría cubrir cien casos el primer día. Empezaría por reglas de alto impacto y baja ambigüedad.

Un primer paquete razonable podría incluir:

Reglas de completitud

  • SKU obligatorio;
  • nombre obligatorio;
  • categoría obligatoria;
  • marca obligatoria;
  • familia obligatoria según tipo de carga.

Reglas de formato

  • EAN de 13 dígitos;
  • números positivos en peso, alto, ancho y largo;
  • booleanos convertibles;
  • fechas con formato válido.

Reglas de consistencia

  • atributos mínimos por familia;
  • unidad compatible con atributo;
  • relaciones padre-hijo válidas;
  • categoría compatible con familia;
  • vocabulario controlado para color, material o marca.

Ese conjunto ya alcanza para reducir muchos errores antes del ingreso.

Cómo hacerlo adaptable de verdad

Si el objetivo es que el código sea reutilizable, el pipeline no debería depender de una única familia, un único proveedor o una única fuente.

Hay varias formas de volverlo más adaptable:

  1. Configurar reglas por familia
    Por ejemplo, requiredFieldsByFamily.
  2. Configurar vocabularios externos
    Colores, materiales, marcas, unidades.
  3. Usar archivos JSON de reglas
    En vez de hardcodear todo.
  4. Separar normalización y validación
    Para que las reglas operen sobre nombres internos estables.
  5. Agregar severidades configurables
    No todo warning tiene que bloquear.

Eso permite que el pipeline crezca sin convertirse en un bloque rígido.

Un ejemplo de configuración por familia

export const requiredFieldsByFamily = {
calzado: ['sku', 'name', 'category', 'size', 'color'],
indumentaria: ['sku', 'name', 'category', 'size', 'material'],
ferreteria: ['sku', 'name', 'category', 'brand']
};
export function validateRequiredByFamily(product) {
const errors = [];
const required = requiredFieldsByFamily[product.family] || [];

for (const field of required) {
if (!product[field]) {
errors.push({
field,
code: 'REQUIRED_BY_FAMILY',
message: `${field} es obligatorio para la familia ${product.family}`
});
}
}

return errors;
}

Este tipo de enfoque se alinea bastante con la lógica del mundo PIM, donde familias de atributos, completitud y reglas por tipo de producto forman parte del diseño del modelo de datos.

Qué pasa cuando el volumen crece

Cuando el volumen de datos empieza a subir, el pipeline debería adaptarse. No siempre conviene leer todo en memoria y procesar al final. Ahí Node.js tiene una ventaja concreta: su modelo de streams permite trabajar con datos en flujo y controlar mejor el uso de memoria. La propia documentación de Node remarca ese punto como uno de los beneficios principales del modelo.

Eso no obliga a empezar con streams desde el día uno. Pero sí conviene diseñar el pipeline de manera que pueda evolucionar hacia un procesamiento más incremental si el catálogo lo necesita.

Qué errores resuelve este enfoque antes de que lleguen al PIM

Un pipeline básico bien planteado puede evitar cosas como estas:

  • productos sin identificador técnico;
  • categorías vacías o incompatibles;
  • medidas con formato imposible;
  • unidades mezcladas;
  • variantes sin atributos mínimos;
  • valores fuera de vocabulario controlado;
  • identificadores mal formados;
  • lotes con registros parciales marcados como correctos.

No elimina todos los problemas del ecosistema, pero sí reduce mucho la cantidad de basura que entra al maestro de producto.

Un buen pipeline no reemplaza al PIM. Lo protege de recibir datos que todavía no están listos para formar parte del catálogo.

Dónde está el valor real

Desde afuera, esto puede parecer una decisión puramente técnica. Pero en realidad tiene bastante impacto operativo.

Cuando una empresa valida datos antes del PIM:

  • reduce correcciones manuales;
  • mejora la calidad del catálogo desde el ingreso;
  • acelera onboarding de productos;
  • baja errores repetitivos;
  • y le da al equipo una base más ordenada para enriquecer.

Eso coincide con algo que el ecosistema PIM viene repitiendo bastante: la calidad del dato no se resuelve solo al publicar, sino al preparar y estandarizar lo que entra desde origen.

Automatizar la validación de datos de producto con Node.js no consiste solo en escribir unas cuantas reglas para rechazar registros. Consiste en crear una capa técnica intermedia que ayude a decidir qué dato está listo para entrar al PIM y cuál todavía necesita corrección. Ahí está el verdadero valor del pipeline: no en bloquear por bloquear, sino en convertir calidad de datos en una práctica operativa, repetible y escalable antes de que el catálogo absorba errores que luego salen mucho más caros de corregir.

Foto del avatar

Desarrollador Node.js Senior en CRITERIA Smart Cataloging. Responsable de las integraciones API REST entre plataformas PIM y sistemas de eCommerce, ERP, marketplaces y puntos de venta. Construye los puentes técnicos que conectan el dato de producto con cada canal de distribución.