Instalación
Requisitos
Magento 2.4.x — probado en 2.4.9, compatible con versiones 2.4.* anteriores. PHP 8.1–8.5. Compatible tanto con el tema Luma por defecto como con el tema Hyvä.
Pasos de instalación
- Añade las credenciales recibidas por correo electrónico a
auth.jsonen la raíz del proyecto Magento:{ "http-basic": { "repo.codingrow.com": { "username": "...", "password": "..." } } } composer config repositories.codingrow composer https://repo.codingrow.comcomposer require codingrow/module-mmisbin/magento module:enable Codingrow_Mmisbin/magento setup:upgrade && bin/magento setup:di:compile && bin/magento cache:flush- Pega la clave de licencia en Admin → Stores → Configuration → Codingrow Extensions → MMIS → License → License Key, guarda y luego ejecuta
bin/magento cache:flush.
Toda la interfaz de administración — cada etiqueta, tooltip y guía — está disponible en 7 idiomas, seleccionados automáticamente por usuario admin:
Configuración admin
Los ajustes compartidos entre perfiles están en Stores → Configuration → Codingrow Extensions → MMIS (Global Settings): on/off del módulo, visibilidad del menú, cola de imágenes/watchdog compartidos. Cada perfil de importación tiene sus propias pestañas Ajustes / Mapeo / Notificaciones / Log en la lista de perfiles MMIS.
Desinstalación
composer remove codingrow/module-mmis y luego
bin/magento setup:upgrade && bin/magento setup:di:compile && bin/magento cache:flush.
Los productos ya importados nunca se tocan automáticamente — usa primero la
herramienta de rollback si también quieres eliminarlos.
Guía de usuario
Perfiles de importación
Cada proveedor/feed desde el que importas es un Perfil independiente: feed propio, mapeo propio, planificación propia, ajustes propios — completamente independiente de cualquier otro perfil. Puedes ejecutar tantos perfiles como proveedores tengas, en paralelo, sobre el mismo catálogo, y cada uno toca solo los productos que él mismo ha creado (nunca un producto creado manualmente por un operador, aunque comparta el mismo prefijo de SKU).
Origen y formato del feed
Un perfil lee su propio feed desde uno de tres orígenes:
| Origen | Qué configuras |
|---|---|
| URL (por defecto) | Un enlace HTTP/HTTPS directo. Admite de forma transparente feeds comprimidos .zip (detectados por la firma del archivo, no por la extensión). |
| Sistema de archivos de Magento | Una ruta dentro de la instalación Magento (p. ej. var/import/feed.csv) — útil si el proveedor deposita archivos vía SFTP en una carpeta que controlas. |
| Servidor FTP | Host + usuario + contraseña (guardada cifrada) — el módulo se conecta y descarga el archivo por sí solo. |
Se admiten tres formatos de feed: CSV (delimitador configurable: coma, punto y coma o tabulación), XML (indicas qué elemento repetido representa un producto) y JSON (array de objetos).
https://codingrow.com/sample-feed.csvOpenAPI:
https://codingrow.com/sample-api.openapi.yamlMapeo de columnas
Seis campos son siempre obligatorios (Nombre del producto, Precio, Cantidad/Stock, Peso, EAN, Marca) — cada uno tiene su propia fila con columna de origen, valor por defecto y transformación. Además de estos seis, puedes añadir tantas filas de mapeo libres como quieras, hacia cualquier atributo real de Magento (no solo una lista fija de campos históricos) — incluidos atributos personalizados creados por ti.
precio_base
para el precio y peso_kg para el peso: mapea "Precio" → columna de origen
precio_base, "Peso" → columna de origen peso_kg. El nombre de la
columna nunca importa, solo importa a qué columna apunta cada fila.
Transformaciones y funciones de texto
Cada fila de mapeo tiene un tipo de "Transformación":
| Transformación | Qué hace |
|---|---|
| Ninguna | Copia directa del valor de la columna de origen. |
| Valor estático | Ignora la columna de origen, usa siempre el texto fijo escrito en "Valor". |
| Plantilla de texto | Texto libre con marcador de posición {NombreColumna} — ver funciones abajo. |
| Buscar y reemplazar | Búsqueda sin distinguir mayúsculas/minúsculas en el valor de la columna de origen, sustituido por tu texto (exactamente como lo escribas). |
| Strip HTML tags | Elimina las etiquetas HTML y decodifica las entidades del valor de la columna de origen. Solo para atributos de texto. |
| Fórmula matemática | Una expresión autónoma — ver Fórmulas matemáticas más abajo. |
Dentro de una Plantilla de texto, además del simple marcador de posición
{NombreColumna}, hay disponibles ocho funciones (solo para campos de texto):
| Función | Efecto | Ejemplo |
|---|---|---|
ucase{Columna} | TODO EN MAYÚSCULAS | ucase{Marca} → "ACME" |
lcase{Columna} | todo en minúsculas | lcase{Marca} → "acme" |
proper{Columna} | Inicial Mayúscula En Cada Palabra | proper{nombre} → "barra roja" → "Barra Roja" |
trim{Columna} | Elimina los espacios iniciales/finales | — |
left{Columna,N} | Primeros N caracteres | left{SKU,5} |
val{Columna} | Normaliza un número en formato europeo ("1.234,56") al formato estándar ("1234.56"), sin redondear los decimales | — |
replace{Columna,'buscar','nuevo'} | Busca/sustituye solo dentro de ese valor (búsqueda sin distinguir mayúsculas/minúsculas), utilizable dentro de una plantilla más amplia | replace{nombre,'Ref.','Referencia'} |
striphtml{Columna} | Elimina las etiquetas HTML y decodifica las entidades de ese valor, utilizable dentro de una plantilla más amplia | striphtml{descripcion} |
{ucase{Marca}} - {proper{nombre}}
en una fila donde Marca="acme" y nombre="barra roja" produce "ACME - Barra
Roja". Un nombre de función mal escrito permanece visible sin cambios en la
salida en lugar de desaparecer silenciosamente, de modo que un error de escritura
siempre se nota.
Fórmulas matemáticas
Solo para campos numéricos (Precio, Peso, Cantidad, o un atributo personalizado
numérico): una expresión autónoma con marcador de posición {NombreColumna},
los cuatro operadores básicos (+ - * /) y paréntesis — nada más (ninguna
función, ninguna comparación). El resultado siempre se redondea a un máximo de 2 decimales.
{Precio B2B} * 1.30
aplica un margen del 30% sobre el precio mayorista del proveedor.
({precio} + {coste_envio}) / 1.22 añade el envío y luego elimina el 22%
de IVA para obtener un precio neto.
Sustitución de texto en varios campos
Una regla de buscar y reemplazar que puede actuar sobre varias columnas en bruto del feed al mismo tiempo, ejecutada incluso antes de que empiece el mapeo. Limpiar una columna en el origen se propaga a cada fila de mapeo que la lee — en lugar de repetir la misma corrección en cada campo derivado por separado.
Filtros de importación (Grupos/Reglas)
Cada fila del feed pasa por tres filtros, siempre en este orden — un filtro posterior solo ve las filas que sobrevivieron al anterior:
- Categorías de feed permitidas — siempre en primer lugar. Una categoría que no esté en la lista descarta la fila aquí, incluso antes de que se considere un Grupo.
- Grupos/Reglas — opcional. Si no hay ningún Grupo configurado, cada fila que sobrevivió al paso 1 pasa sin cambios. Si existe al menos un Grupo, solo pasan las filas capturadas por un Grupo — las filas no capturadas por ningún Grupo se descartan (distinto de "ningún filtro").
- Categoría de destino del Grupo — si está configurada dentro del Grupo que capturó la fila, sustituye por completo la ruta de categoría; si se deja vacía, se usa la ruta de categoría del feed tal cual.
Categorías
El árbol de categorías se crea automáticamente a partir de la ruta de categoría de cada producto en el feed — no hace falta crear las categorías de antemano en Magento. El ajuste "Categoría padre" permite anidar todo el árbol de categorías de un perfil bajo una raíz compartida, útil cuando varios perfiles comparten el mismo catálogo y quieres mantener sus árboles de categorías visualmente separados. Las categorías que quedan vacías (p. ej. después de que un proveedor descontinúa toda una línea de producto) se limpian con un clic o desde la CLI.
Galería de imágenes
Mapea cualquier número de columnas del feed hacia los roles de imagen (base / small / thumbnail / gallery) — una sola columna puede servir a varios roles a la vez. Las imágenes descargadas se comprimen opcionalmente (redimensionadas si son más anchas de 1200px, recomprimidas en JPEG calidad 85, conservadas solo si el resultado es realmente más ligero) con concurrencia configurable y un watchdog de espacio en disco que suspende las descargas — nunca los datos del producto — si el espacio libre escasea.
Productos configurables (variantes)
Las filas del feed que comparten el mismo valor en una "columna de grupo/padre" se convierten en variantes de un único producto configurable. Cualquier número de atributos puede variar al mismo tiempo — talla, color y un tercer atributo juntos, por ejemplo — a cada uno le basta con su propia fila de mapeo con una columna que da un valor distinto para cada variante.
Productos agrupados
Conceptualmente distinto del configurable: ningún atributo de variante, ninguna columna de grupo — solo un enlace directo entre un "contenedor" padre y cualquier número de productos simples que permanecen completamente independientes (precio, stock y página navegable propios), útil cuando un proveedor vende tanto los componentes individuales por separado como un kit que los muestra juntos con un selector de cantidad para cada uno.
Gestión del stock
Las actualizaciones de stock pueden ser absolutas (sustituyen el valor) o relativas (suman/restan respecto a la cantidad actual) — útil para proveedores cuyo feed indica variaciones en lugar de totales. El backorder y "gestionar stock" siguen la configuración del perfil, no un único ajuste global.
Vista previa y archivo de salida
Dos formas de ver qué escribiría realmente una sincronización en el catálogo — solo los campos mapeados, nunca los filtros de categoría/disponibilidad/Grupo (la muestra es parcial a propósito):
| Vista previa | Refleja los valores actuales del formulario, incluso sin guardar — haz clic mientras editas para ver el efecto al instante, sin tocar el perfil. |
|---|---|
| Descargar archivo de salida | Usa la última configuración guardada y produce un archivo JSON descargable. |
Planificación y notificaciones
Cada perfil tiene su propia planificación cron (desde cada 15 minutos hasta una vez al día, o una expresión cron personalizada) tanto para la sincronización completa del catálogo como para una más ligera solo de stock/precios. Las notificaciones por correo electrónico (éxito/atención/error crítico) se configuran por perfil, de modo que distintos proveedores pueden tener políticas de aviso diferentes en la misma tienda.
Ciclo de vida del producto: nada desaparece por sorpresa
Un producto que desaparece del feed, o queda excluido por un filtro, siempre se desactiva primero — nunca se elimina — y se reactiva automáticamente por sí solo si reaparece en una sincronización posterior. La eliminación definitiva es un ajuste separado, opcional (desactivado por defecto): solo un producto que ha permanecido desactivado durante más de un número configurable de días se elimina realmente, y solo entonces.
Comandos CLI
Cada acción también está disponible desde la línea de comandos (útil para cron, o para una primera importación muy grande vía SSH): ejecutar la sincronización de un perfil, exportar/importar la configuración de un perfil, deshacer todo lo que un perfil haya importado alguna vez, limpiar categorías huérfanas y más — cada una con una vista previa dry-run por defecto cuando es destructiva.