update-pim-web
1. Descripción general
Según el pom.xml, el proyecto se describe como "Update PIM Web". Es un microservicio batch (runner) que descarga el catálogo de producto desde SalesLayer (en formato ZIP con 3 CSV), lo transforma en bullets de atributos multilingües (10 idiomas) y actualiza el PIM web mediante peticiones por lotes a la API de SalesLayer PIM.
2. Información técnica
| Campo | Valor |
|---|---|
artifactId | update-pim-web |
groupId | com.hawkersco |
version | 1.0.25 |
| Java | 25 |
| Spring Boot | 4.0.6 |
| Tipo de artefacto | jar (ejecutable, Spring Boot batch/CLI) |
| Módulos | No aplica (proyecto de módulo único) |
3. Arquitectura y diseño
No es una API REST: es una aplicación Spring Boot CLI con un único CommandLineRunner (UpdatePimWebRunner).
.client—PimHttpClient,SlackHttpClient(interfaces@HttpExchangelocales al proyecto)..config—PimHttpClientConfiguration,SlackHttpClientConfiguration(wiring de losRestClient)..model— 18 clases modelo (PimProductcon 71 campos vía OpenCSV,PimBullets,PimFrames, y modelos de atributo:PimGender,PimLensColor,PimFrameMaterial, etc.)..utils—UpdatePimWebUtil(transforma filas CSV de bullets en texto multilingüe formateado).
flowchart TD
A[UpdatePimWebRunner] -->|descarga pim.zip| B[SalesLayer API]
A -->|descomprime y parsea 3 CSV| C[Products / Bullets / Frames]
A -->|construye bullets por 10 idiomas| D[Producto PIM multilingüe]
D -->|lotes de 500, PUT| E[PimHttpClient → SalesLayer PIM API]
A -.->|error de descarga o de lote| F[Slack]
Flujo: borra y recrea el directorio de trabajo local, descarga pim.zip desde un endpoint de conector de SalesLayer (URL con un ID de conector hardcodeado en el código fuente, ver hallazgo en la sección 13) y lo descomprime; parsea los 3 CSV (Products, Bullets, Frames) con OpenCSV; construye 14 mapas de bullets multilingües (color de montura, material de montura, género, apariencia/categoría/color/material de lente, polarizado, color de correa, grupo objetivo, color de patilla, blue blocking, talla, monturas); para cada producto y cada uno de los 10 idiomas (en, de, es, es_CL, es_CO, es_MX, fr, el, it, pt) genera 4 bloques de texto (bullets generales, de lente, de montura y de grupo objetivo); agrupa los productos en lotes de 500 y los envía por PUT a la API de PIM; notifica a Slack si un lote falla o si la descarga inicial falla (en este último caso, además, termina el proceso inmediatamente).
4. Dependencias principales
| Dependencia | Propósito |
|---|---|
spring-boot-starter | Núcleo de Spring Boot (sin web, es un runner CLI) |
spring-web | RestClient/@HttpExchange |
com.opencsv:opencsv | Parseo de los 3 ficheros CSV a modelos Java |
com.hawkersco:pim-client | Modelos de request/response de la API de SalesLayer PIM (PIMBulletProductRequest) |
com.hawkersco:slack-client | Modelos de notificación de Slack |
com.hawkersco:pi-function-commons | DirectoryUtils |
| Lombok | Generación de código boilerplate en los modelos |
5. API / Endpoints
No aplica a este proyecto. Es un batch/runner sin capa REST.
6. Integraciones externas
| Sistema | Protocolo | Dirección | Detalle |
|---|---|---|---|
| SalesLayer (descarga de catálogo) | HTTP (descarga directa de ZIP) | Entrante | Descarga de pim.zip (Products/Bullets/Frames) mediante un conector configurado |
| SalesLayer PIM API | HTTP PUT (PimHttpClient) | Saliente | Actualización por lotes (500) de los bullets multilingües de producto |
| Slack | HTTP (SlackHttpClient) | Saliente | Notificación de error de descarga o de lote fallido |
7. Configuración
En producción (application-pro.properties) las credenciales llegan por variables de entorno inyectadas como Secret de Kubernetes; en local (application.properties) el repositorio contiene actualmente valores reales hardcodeados (ver alerta de seguridad).
| Clave | Descripción |
|---|---|
pim.client.url | URL de la API de SalesLayer PIM |
pim.client.code / .secretKey | Credenciales de autenticación de la API de PIM |
slack.client.url / .auth.token / .channel.id | Configuración de Slack |
⚠️ Alerta de seguridad
El fichero src/main/resources/application.properties (perfil local) contiene actualmente credenciales reales en texto plano: la clave secreta (secretKey) de la API de SalesLayer PIM, y el token de bot de Slack (el mismo ya señalado en otros proyectos de este ecosistema). Además, el ID del conector de descarga de SalesLayer está hardcodeado directamente en el código fuente Java (UpdatePimWebRunner.URL_DOWNLOAD), no en un fichero de propiedades — no se ha reproducido en este documento. Ninguno de estos valores se ha reproducido. Se recomienda:
- Rotar la clave secreta de la API de PIM y el token de Slack.
- Mover el ID del conector de SalesLayer de
URL_DOWNLOADa una propiedad de configuración inyectada por variable de entorno, para poder rotarlo sin necesidad de un redeploy de código. - Sustituir los valores hardcodeados de
application.propertiespor credenciales de un entorno de desarrollo aislado. - Revisar el historial de control de versiones, ya que estas credenciales pueden seguir expuestas en commits anteriores.
8. Persistencia
No aplica a este proyecto. No usa base de datos: el catálogo se obtiene íntegramente de los CSV descargados de SalesLayer en cada ejecución, sin persistencia local salvo los ficheros temporales de trabajo.
9. Procesos programados y mensajería
No hay @Scheduled ni listeners de colas: la periodicidad la impone el CronJob de Kubernetes (k8s/cronjob.yaml), que ejecuta el contenedor cada 6 horas (schedule: "0 */6 * * *", zona horaria Europe/Madrid, concurrencyPolicy: Forbid, activeDeadlineSeconds: 3600). Único runner, descrito en la sección 3.
10. Ejecución en local
Requisitos previos: JDK 25, Maven, credenciales válidas de SalesLayer PIM y de Slack en application.properties.
# Compilar sin tests
./mvnw clean package -DskipTests
# Compilar con tests
./mvnw clean install
# Ejecutar un test concreto
./mvnw test -Dtest=UpdatePimWebApplicationTests
# Ejecutar la aplicación localmente
./mvnw spring-boot:run
# Build Docker
docker build -t update-pim-web .
Al ser un CommandLineRunner, no expone Actuator/health: la verificación se hace revisando el log de consola o el catálogo reflejado en el panel de SalesLayer PIM.
11. Despliegue
- Imagen: construida con
jib-maven-plugin(baseeclipse-temurin:25-jre,containerizingMode=packaged), publicada eneurope-west3-docker.pkg.dev/pi-saldum/pi-repo/update-pim-web:<tag>. - Orquestación: Kubernetes
CronJoben el clúster GKEpi-cluster-hw, namespacepi, con credenciales de cuenta de servicio de GCP montadas por volumen (GOOGLE_APPLICATION_CREDENTIALS), ejecutándose cada 6 horas. No se ha encontrado uso de APIs de Google en el código de este proyecto (mismo patrón detectado enshowroom-update-stockytheiconic-create-db). - CI/CD (Jenkins): pipeline real de 3 etapas —
Checkout→Build & Push→Deploy to GKE, consistente con lo descrito en elCLAUDE.md.
Job de Jenkins: https://jenkins-pi.hawkersco.net/job/update-pim-web/
12. Manejo de errores y logging
No hay una estrategia de excepciones centralizada (no hay @ControllerAdvice, es un runner). Un fallo al descargar el ZIP inicial se notifica a Slack y termina el proceso inmediatamente (System.exit), sin intentar procesar el resto del flujo. Un fallo al enviar un lote a la API de PIM se notifica a Slack pero no interrumpe el envío de los lotes restantes. Logging mediante java.util.logging.Logger estándar (consola).
13. Notas y consideraciones
- ID de conector de SalesLayer hardcodeado en código fuente Java: la constante
URL_DOWNLOADenUpdatePimWebRunnerincluye el ID del conector de descarga directamente en el código, no enapplication.properties. A diferencia de una credencial en fichero de configuración, este valor no puede rotarse sin modificar el código y volver a desplegar — mismo patrón de severidad detectado enpi-generate-credentialsylogistic-erpen este ecosistema. CLAUDE.mdverificado y consistente con el código: el flujo completo (descarga → descompresión → parseo de 3 CSV → construcción de bullets en 10 idiomas → envío en lotes de 500 → notificación Slack), las clases clave y las dependencias externas coinciden con el código real, verificado directamente enUpdatePimWebRunner.- Ver alerta de seguridad en la sección 7 sobre credenciales reales y el ID de conector expuestos en el proyecto.