Skip to main content

sfcc-update-stock

1. Descripción general

Según el pom.xml, el proyecto se describe como "Sfcc update stock". Es un microservicio batch (runner) que calcula el stock neto disponible (stock de Dynamics menos pedidos pendientes de envío, forzando cero para SKUs en lista negra) y genera un fichero XML de inventario por región/tienda que sube por SFTP a Salesforce Commerce Cloud (SFCC). Es la contraparte de sincronización de stock hacia SFCC del ecosistema Hawkers/Northweek.

2. Información técnica

CampoValor
artifactIdsfcc-update-stock
groupIdcom.hawkersco
version1.0.25
Java25
Spring Boot4.0.6
Tipo de artefactojar (ejecutable, Spring Boot batch/CLI)
MódulosNo aplica (proyecto de módulo único)

3. Arquitectura y diseño

No es una API REST: es una aplicación Spring Boot CLI con 10 CommandLineRunner, todos activos, uno por región/tienda, siguiendo el mismo patrón.

OrdenRunnerRegión/tienda
1SfccHwEu2013UpdateStockRunner, SfccHwEuUpdateStockRunnerUE (dos variantes/catálogos)
2SfccNwEuUpdateStockRunnerUE (Northweek)
3SfccHwCoUpdateStockRunner, SfccHwMxUpdateStockRunnerColombia, México
4SfccHwNlUpdateStockRunnerPaíses Bajos
5SfccHwItUpdateStockRunnerItalia
6SfccHwGrUpdateStockRunnerGrecia
7SfccHwGbUpdateStockRunnerReino Unido
8SfccHwRetailUpdateStockRunnerRetail
  • .configDynamicsDbConfig (datasource dynamics-pro), LogisticsDbConfig (datasource logistics), SfccUpdateStockConfig.
flowchart TD
A[Runner por región] -->|excluye SKUs| B[Google Sheets]
A -->|findProductDynamicsByWharehouseAndDataAreaId, con reintento| C[(dynamics-pro · ProductDynamics)]
A -->|pedidos PENDING_STOCK últimos 2 meses| D[(logistics · Order/OrderLine)]
A -->|lista negra de stock forzado a cero| E[(logistics · SfscProductZero)]
A -->|calcula stock neto, formatea SKU| F[XML JAXB Inventory]
F -->|SFTP| G[SFCC]
A -.->|validaciones/errores| H[Slack]

Cada runner: obtiene la lista de SKUs a excluir desde una hoja de Google Sheets, consulta ProductDynamics por almacén/dataAreaId (con reintento hasta 10 veces, 5s de espera, si la consulta devuelve vacío), calcula el stock neto restando pedidos pendientes de los últimos 2 meses, fuerza a cero el stock de los SKUs en la lista negra (SfscProductZeroService) y de los productos ausentes del snapshot actual de Dynamics, formatea el SKU (ITEM, ITEM_COLORID o ITEM_COLORIDSIZE, con validaciones que generan alerta Slack y omiten el producto si tiene color sin talla, o si tiene styleId), genera el XML JAXB y lo sube por SFTP.

4. Dependencias principales

DependenciaPropósito
spring-boot-starterNúcleo de Spring Boot (sin web, es un runner CLI)
spring-webRestClient usado por el cliente Slack
com.hawkersco:dynamics-commonsProductDynamicsService, ProductDynamics
com.hawkersco:logistics-commonsOrderService, OrderLineService, SfscProductZeroService
com.hawkersco:sfcc-commonsModelo JAXB del inventario SFCC (Inventory, ComplexTypeInventoryList, ComplexTypeInventoryRecord)
com.hawkersco:slack-clientNotificaciones/validaciones vía Slack
com.hawkersco:pi-function-commonsDateUtils, DirectoryUtils, SftpUtils, SeveralUtils, SheetsServiceUtils
spring-boot-starter-test (test)JUnit 5 + Spring Test

5. API / Endpoints

No aplica a este proyecto. Es un batch/runner sin capa REST.

6. Integraciones externas

SistemaProtocoloDirecciónDetalle
Google Sheets (hoja 1HDdh5eHTxWx8YHJgp3O9mBm2qi9vtham_OwZk7vQXiY, rango skus!A2:A)API de Google (SheetsServiceUtils)EntranteLista de SKUs a excluir del envío de stock, por runner (no documentada en CLAUDE.md, ver sección 13)
Servidor SFTP (sftp.hawkersco.com)SFTP (SftpUtils)SalienteSubida del XML de inventario a SFCC
SlackHTTP (SlackClient)SalienteAlertas de validación de SKU (color sin talla, styleId presente) y errores de ejecución
PostgreSQL (dynamics-pro, logistics)JDBCEntranteLectura de stock, pedidos pendientes y lista negra de stock cero

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).

ClaveDescripción
spring.datasource.*Credenciales de la BD logistics (datasource primario)
dynamics.datasource.*Credenciales de la BD dynamics-pro (datasource secundario)
pro.ftp.server / .port / .user / .pass / .dirCredenciales SFTP hacia SFCC
slack.client.url / .auth.token / .channel.idConfiguración de Slack

⚠️ Alerta de seguridad

El fichero src/main/resources/application.properties (perfil local) contiene actualmente credenciales reales en texto plano: contraseñas de ambas bases de datos PostgreSQL, contraseña del servidor SFTP hacia SFCC, y token de bot de Slack (xoxb-...). Ninguno de estos valores se ha reproducido en este documento. Se recomienda:

  1. Rotar las contraseñas de ambas BD, la contraseña SFTP y el token de Slack.
  2. Sustituir los valores hardcodeados de application.properties por credenciales de un entorno de desarrollo aislado.
  3. Revisar el historial de control de versiones, ya que estas credenciales pueden seguir expuestas en commits anteriores.

8. Persistencia

Dos bases de datos PostgreSQL: dynamics-pro (ProductDynamics) y logistics (Order, OrderLine, SfscProductZero), ambas con ddl-auto=none. No hay Flyway/Liquibase en este repositorio.

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 una vez al día a las 07:45 (schedule: "45 7 * * *", zona horaria Europe/Madrid). Se ejecutan en orden los 10 runners de la tabla de la sección 3.

10. Ejecución en local

Requisitos previos: JDK 25, Maven, acceso a ambas BD, credenciales SFTP y credenciales de aplicación por defecto de Google (para el acceso a Sheets).

# Compilar sin tests
mvn -B -DskipTests clean install

# Ejecutar tests
mvn test

# Ejecutar un test concreto
mvn test -Dtest=SfccUpdateStockApplicationTests

# Ejecutar el JAR tras compilar
java -jar target/sfcc-update-stock-*.jar

Al ser un CommandLineRunner, no expone Actuator/health: la verificación se hace revisando el log de consola o los ficheros subidos por SFTP.

11. Despliegue

  • Imagen: construida con jib-maven-plugin (base eclipse-temurin:25-jre, containerizingMode=packaged), publicada en europe-west3-docker.pkg.dev/pi-saldum/pi-repo/sfcc-update-stock:<tag>.
  • Orquestación: Kubernetes CronJob en el clúster GKE pi-cluster-hw, namespace pi, ejecutándose diariamente a las 07:45.
  • CI/CD (Jenkins): pipeline que sustituye application-pro.properties por application.properties antes de construir.

Job de Jenkins: https://jenkins-pi.hawkersco.net/job/sfcc-update-stock/

12. Manejo de errores y logging

No hay una estrategia de excepciones centralizada (no hay @ControllerAdvice, es un runner). Cada runner envuelve su ejecución completa en un try/catch genérico que notifica a Slack y registra Level.WARNING ante cualquier error, sin interrumpir el resto de runners de la secuencia. Validaciones de SKU (color sin talla, styleId presente) generan una notificación Slack específica y omiten ese producto del inventario en lugar de fallar toda la ejecución. Logging mediante java.util.logging.Logger estándar (consola).

13. Notas y consideraciones

  • Dependencia de Google Sheets no documentada en CLAUDE.md: cada runner consulta una hoja de Google Sheets (fetchExcludedSkusFromSheets) para obtener una lista de SKUs a excluir del envío de stock, pero el CLAUDE.md del proyecto no menciona esta integración en absoluto — su diagrama de flujo de datos solo describe Dynamics → Logistics → lista negra → XML → SFTP. Es una fuente de datos externa adicional y no trivial (afecta a qué productos se reportan) que debería reflejarse en la documentación.
  • CLAUDE.md verificado en el resto de aspectos: los 10 runners, sus órdenes de ejecución exactos, el patrón de reintento (MAX_ATTEMPTS=10, 5s de espera), las reglas de validación de SKU y el doble datasource coinciden con el código real, verificado tanto en SfccHwEuUpdateStockRunner como por inspección del resto de clases.
  • Ver alerta de seguridad en la sección 7 sobre credenciales reales expuestas en application.properties.