Skip to main content

update-sfcloud

1. Descripción general

Según el pom.xml, el proyecto se describe como "Update Sfcc and Sfsc". Es un microservicio batch (runner) que sincroniza estados de envío y datos de pedido/producto desde el sistema de logística interno hacia Salesforce Commerce Cloud (SFCC) y Salesforce Service Cloud (SFSC), orquestando hasta 8 procesadores distintos en paralelo mediante CompletableFuture.

2. Información técnica

CampoValor
artifactIdupdate-sfcloud
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 un CommandLineRunner coordinador (UpdateSfcloudCoordinator) que orquesta en paralelo hasta 8 runners asíncronos, cada uno @Component con un método @Async runAsync(): CompletableFuture<Void>.

RunnerPropósito
LogisticsStatusProcessSfccRunnerEnvía a la API Shop de SFCC actualizaciones de estado de envío pendientes; gestiona pedidos multi-envío y pedidos de recogida en tienda con mapeos de estado por sitio de origen
LogisticsStatusProcessCheckShipmentSfccRunnerComprueba datos de seguimiento del envío y actualiza SFCC
LogisticsStatusProcessCheckShipmentSfccMxRunnerIgual que el anterior, específico para México
LogisticsStatusProcessCheckShipmentSfccAnotherRunnerVariante para proveedores logísticos específicos (Cubbo, Servientrega, Auro, Logsolutions, Sprint Logistics, 99minutos, Sarmed, Logiscore, NPF — según los modelos StatusOrder* del paquete .models)
UpdateDatabaseSfscProductsRunnerSincroniza datos de producto hacia SFSC
UpdateSfscOrderBatchRunnerSincroniza pedido + envío completo hacia SFSC vía API batch, con pausas entre pasos del lote
UpdateSfscStatusReptBatchRunnerActualización por lotes en SFSC del estado REPT (En Reparto)
UpdateSfscStatusResPrepConfBatchRunnerActualización por lotes en SFSC de los estados RES/PREP/CONF

UpdateSfcloudCoordinator lee la propiedad futures.async.runners ("All" o el nombre de una clase de runner concreta) para decidir qué runners ejecutar; los lanza todos como CompletableFuture async, espera a que todos terminen (CompletableFuture.allOf) y llama a System.exit. Los fallos de cualquier runner individual se registran (Level.SEVERE) sin interrumpir al resto.

  • .configDynamicsDbConfig (@Primary, datasource dynamics-pro), LogisticsDbConfig (datasource logistics), AsyncConfig, SfccApiProperties, UpdateSfcloudConfig (beans de servicios de logistics-commons).
  • .models — modelos de estado por transportista (StatusOrderCubbo, StatusOrderServientrega, StatusOrdersAuro, StatusOrderLogsolutions, StatusOrderSprintLogistics, StatusOrderList99min, StatusOrderSarmed, StatusOrderShippingLogiscore, StatusOrderNpf), CountriesLocale.
  • .utilsLogisticsStatusProcessCheckShipmentUtils, UpdateSfscStatusBatchUtils, excepciones propias (MyException, SfscAsyncTaskException).
flowchart TD
A[UpdateSfcloudCoordinator] -->|lee futures.async.runners| B{"All / runner concreto"}
B --> C[8 runners @Async CompletableFuture]
C -->|estados pendientes| D[(logistics · Order/Shipment/ShipmentStatusHistory)]
C -->|push estado| E[SFCC Shop API]
C -->|batch productos/pedidos/estados| F[SFSC Services API]
C -.->|error por runner| G[log SEVERE]

4. Dependencias principales

DependenciaPropósito
spring-boot-starterNúcleo de Spring Boot (sin web, es un runner CLI)
com.opencsv:opencsvParseo de datos auxiliares en CSV
com.hawkersco:logistics-commonsEntidades JPA y servicios (Order, Shipment, ShipmentStatusHistory, SfscProduct, etc.)
com.hawkersco:sfcc-clientCliente @HttpExchange para la API Shop de SFCC (SfccShopShipmentClient)
com.hawkersco:sfcc-services-clientCliente @HttpExchange para la API batch de Salesforce Services (SfccServicesBatchClient)
com.hawkersco:slack-clientCliente @HttpExchange para notificaciones de Slack
com.hawkersco:pi-function-commonsDateUtils y utilidades compartidas
Lombok (dependencia directa)Generación de código boilerplate

5. API / Endpoints

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

6. Integraciones externas

SistemaProtocoloDirecciónDetalle
SFCC Shop APIHTTP REST (sfcc-client)SalienteActualización del estado de envío por pedido
Salesforce Service Cloud (SFSC) Services APIOAuth password grant + HTTP batch (sfcc-services-client)SalienteSincronización batch de productos, pedidos y estados
SlackHTTP (slack-client)SalienteNotificación de errores por runner
PostgreSQL (dynamics-pro, logistics)JDBC (doble datasource)Entrante/SalienteLectura de pedidos/envíos pendientes y actualización de su estado

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
futures.async.runnersControla qué runners se ejecutan ("All" o el nombre de una clase concreta; en local está fijado a un único runner para pruebas dirigidas)
spring.datasource.*Credenciales de la BD dynamics-pro (datasource primario)
logistics.datasource.*Credenciales de la BD logistics
sfcc.client.url / .staging.client.url / .shop.client.url / .auth.client.urlURLs de los distintos entornos/módulos de SFCC
sfcc.api.siteid / .sitemxid / .sitecoid / .version / .clientidIdentificadores de sitio y credenciales de API de SFCC
sfcc.auth.basicCredencial HTTP Basic (Base64) para la API de SFCC
sfccservices.credentials.token.*Credenciales OAuth password grant de Salesforce Service Cloud
sfccservices.credentials.urlURL base de la API de Salesforce Service Cloud
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 (las mismas ya señaladas como expuestas en múltiples proyectos de este ecosistema), la credencial HTTP Basic de la API de SFCC, las credenciales OAuth completas de Salesforce Service Cloud (las mismas ya señaladas como expuestas en return-pi-dynamics, sfcc-abandoned-cart y sfsc-catalog-updater), y el token de bot de Slack. Ninguno de estos valores se ha reproducido en este documento. Se recomienda:

  1. Rotar de forma coordinada las credenciales de Salesforce (Service Cloud y SFCC), compartidas con otros proyectos del ecosistema.
  2. Rotar las contraseñas de ambas BD y el token de Slack.
  3. Sustituir los valores hardcodeados de application.properties por credenciales de un entorno de desarrollo aislado.
  4. Revisar el historial de control de versiones, ya que estas credenciales pueden seguir expuestas en commits anteriores.

8. Persistencia

Dos bases de datos PostgreSQL con datasources JPA independientes (ddl-auto=none en ambas):

  • dynamics-pro (DynamicsDbConfig, @Primary).
  • logistics (LogisticsDbConfig): entidades Order, Shipment, ShipmentStatusHistory, OrderLine, SfscProduct, más un SfscProductBatchRepository construido directamente sobre JdbcTemplate (no un repositorio Spring Data estándar).

No hay Flyway/Liquibase en este repositorio.

9. Procesos programados y mensajería

No hay @Scheduled interno: la periodicidad la impone el CronJob de Kubernetes (k8s/cronjob.yaml), que ejecuta el contenedor cada 5 minutos (schedule: "0/5 * * * *", concurrencyPolicy: Forbid, activeDeadlineSeconds: 7200). En producción se ejecutan todos los runners (futures.async.runners=All) en paralelo, según la tabla de la sección 3.

10. Ejecución en local

Requisitos previos: JDK 25, Maven, acceso a ambas BD y credenciales válidas de SFCC/Salesforce Service Cloud.

# Compilar sin tests
./mvnw -B -DskipTests clean install

# Ejecutar tests
./mvnw test

# Ejecutar un test concreto
./mvnw test -Dtest=UpdateSfcloudApplicationTests

# Build Docker
docker build -t update-sfcloud .

En local, futures.async.runners está fijado a un único runner (UpdateSfscStatusReptBatchRunner) para facilitar pruebas dirigidas, en lugar de "All". Al ser un CommandLineRunner, no expone Actuator/health: la verificación se hace revisando el log de consola o el estado reflejado en SFCC/SFSC.

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/update-sfcloud:<tag>.
  • Orquestación: Kubernetes CronJob en el clúster GKE pi-cluster-hw, namespace pi, con credenciales de cuenta de servicio de GCP montadas por volumen (GOOGLE_APPLICATION_CREDENTIALS, sin uso aparente de APIs de Google en el código — mismo patrón detectado en otros proyectos de este lote), ejecutándose cada 5 minutos.
  • CI/CD (Jenkins): pipeline real de 3 etapas — CheckoutBuild & PushDeploy to GKE.

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

12. Manejo de errores y logging

No hay una estrategia de excepciones centralizada (no hay @ControllerAdvice, es un runner). El coordinador envuelve cada CompletableFuture con un manejador (whenComplete) que registra Level.SEVERE con el nombre del runner si falla, sin interrumpir al resto de runners en curso. Las excepciones checked lanzadas al invocar runAsync() (InterruptedException, ParseException, IOException) se capturan y se relanzan envueltas en la excepción propia SfscAsyncTaskException. Logging mediante java.util.logging.Logger estándar (consola).

13. Notas y consideraciones

  • CLAUDE.md describe los clientes de sfcc-client, sfcc-services-client y slack-client como "Feign client", terminología obsoleta: el código real (LogisticsStatusProcessSfccRunner y el resto de runners) importa clientes @HttpExchange (SfccShopShipmentClient, SlackClient) desde esas mismas librerías, sin ninguna dependencia de Spring Cloud OpenFeign en el pom.xml — coherente con el patrón de migración a @HttpExchange/RestClient ya observado en el resto de proyectos de este ecosistema (Spring Boot 4 eliminó el soporte nativo de Feign).
  • SfscProductBatchRepository construido manualmente sobre JdbcTemplate: a diferencia del resto de repositorios de logistics-commons (Spring Data JPA), este se instancia como un @Bean explícito que envuelve un JdbcTemplate, sugiriendo que la operación batch subyacente no encaja bien en el modelo estándar de Spring Data (probablemente por el volumen de filas o el tipo de sentencia SQL usada).
  • CLAUDE.md verificado y consistente en el resto de aspectos: los 8 runners, el patrón de orquestación asíncrona vía CompletableFuture, el filtrado por futures.async.runners, el doble datasource, y los mapeos de idSource/estado de envío a SFCC coinciden con el código real, verificado directamente en UpdateSfcloudCoordinator.
  • Ver alerta de seguridad en la sección 7 sobre credenciales reales expuestas en application.properties, compartidas con otros proyectos del ecosistema.