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
| Campo | Valor |
|---|---|
artifactId | sfcc-update-stock |
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 10 CommandLineRunner, todos activos, uno por región/tienda, siguiendo el mismo patrón.
| Orden | Runner | Región/tienda |
|---|---|---|
| 1 | SfccHwEu2013UpdateStockRunner, SfccHwEuUpdateStockRunner | UE (dos variantes/catálogos) |
| 2 | SfccNwEuUpdateStockRunner | UE (Northweek) |
| 3 | SfccHwCoUpdateStockRunner, SfccHwMxUpdateStockRunner | Colombia, México |
| 4 | SfccHwNlUpdateStockRunner | Países Bajos |
| 5 | SfccHwItUpdateStockRunner | Italia |
| 6 | SfccHwGrUpdateStockRunner | Grecia |
| 7 | SfccHwGbUpdateStockRunner | Reino Unido |
| 8 | SfccHwRetailUpdateStockRunner | Retail |
.config—DynamicsDbConfig(datasourcedynamics-pro),LogisticsDbConfig(datasourcelogistics),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
| Dependencia | Propósito |
|---|---|
spring-boot-starter | Núcleo de Spring Boot (sin web, es un runner CLI) |
spring-web | RestClient usado por el cliente Slack |
com.hawkersco:dynamics-commons | ProductDynamicsService, ProductDynamics |
com.hawkersco:logistics-commons | OrderService, OrderLineService, SfscProductZeroService |
com.hawkersco:sfcc-commons | Modelo JAXB del inventario SFCC (Inventory, ComplexTypeInventoryList, ComplexTypeInventoryRecord) |
com.hawkersco:slack-client | Notificaciones/validaciones vía Slack |
com.hawkersco:pi-function-commons | DateUtils, 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
| Sistema | Protocolo | Dirección | Detalle |
|---|---|---|---|
Google Sheets (hoja 1HDdh5eHTxWx8YHJgp3O9mBm2qi9vtham_OwZk7vQXiY, rango skus!A2:A) | API de Google (SheetsServiceUtils) | Entrante | Lista 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) | Saliente | Subida del XML de inventario a SFCC |
| Slack | HTTP (SlackClient) | Saliente | Alertas de validación de SKU (color sin talla, styleId presente) y errores de ejecución |
PostgreSQL (dynamics-pro, logistics) | JDBC | Entrante | Lectura 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).
| Clave | Descripció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 / .dir | Credenciales SFTP hacia SFCC |
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: 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:
- Rotar las contraseñas de ambas BD, la contraseña SFTP y el token de Slack.
- 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
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(baseeclipse-temurin:25-jre,containerizingMode=packaged), publicada eneurope-west3-docker.pkg.dev/pi-saldum/pi-repo/sfcc-update-stock:<tag>. - Orquestación: Kubernetes
CronJoben el clúster GKEpi-cluster-hw, namespacepi, ejecutándose diariamente a las 07:45. - CI/CD (Jenkins): pipeline que sustituye
application-pro.propertiesporapplication.propertiesantes 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 elCLAUDE.mddel 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.mdverificado 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 enSfccHwEuUpdateStockRunnercomo por inspección del resto de clases.- Ver alerta de seguridad en la sección 7 sobre credenciales reales expuestas en
application.properties.