orders-delayed
1. Descripción general
Según el pom.xml, el proyecto se describe como "Orders delayed". Es un microservicio batch (runner) que detecta pedidos cuyo tiempo de envío o entrega supera un umbral configurado por transportista/país, marca esos pedidos en Salesforce Commerce Cloud (SS_DeliveryDelay__c), y asigna cupones de compensación a los que, además de retrasados, ya fueron entregados (SS_DeliveryCoupon__c).
2. Información técnica
| Campo | Valor |
|---|---|
artifactId | orders-delayed |
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 4 CommandLineRunner, ejecutados en orden estricto, cada uno dependiente del estado dejado por el anterior (ficheros JSON en disco y registros en BD).
| Orden | Runner | Propósito |
|---|---|---|
| 1 | GenerateJsonDelayedRunner | Lee LogisticThreshold de BD → genera thresholds/thresholds-shipment-logistics.json y thresholds/thresholds-delivery-logistics.json |
| 2 | OrdersDelayedGetRunner | Detecta pedidos que superan el umbral de envío (en días laborables) → persiste OrderDelayed + resumen a Slack |
| 3 | OrdersDelayedSendMailRunner | Envía a SFCC los OrderDelayed no notificados aún (SS_DeliveryDelay__c=true) vía API batch CSV, sube el listado a Slack |
| 4 | OrdersDelayedProcessedRunner | Detecta pedidos retrasados ya entregados, asigna cupón desde inventario, actualiza SFCC (SS_DeliveryCoupon__c); llama a System.exit() al terminar |
.config—OrdersDelayedConfig..model—LogisticThresholds,LogisticThresholdsCsv,OrderDelayedEmail..utils—OrdersDelayedConst,OrdersDelayedUtil(incluyesendInfoToSfsc: construye CSV, envía a la API batch de SFCC, sondea el estado deljobIdhasta 5 veces con 10s de espera).
flowchart TD
A["1. GenerateJsonDelayedRunner"] -->|LogisticThreshold| B[thresholds/*.json]
C["2. OrdersDelayedGetRunner"] -->|lee| B
C -->|días laborables > umbral| D[(logistics · OrderDelayed)]
C -.->|resumen| E[Slack]
F["3. OrdersDelayedSendMailRunner"] -->|CSV batch| G[SFCC Services API]
F -.->|listado| E
H["4. OrdersDelayedProcessedRunner"] -->|entregados y retrasados| D
H -->|asigna cupón| G
Mapeo de fuente de pedido a transportista (según source-list): 8/36 → Auro, 10 → Servientrega, 11 → Cubbo, 57/71 → Sprint Logistics, 58 → Logsolutions, 61 → Sarmed. El retraso se calcula exclusivamente en días laborables (lunes a viernes).
4. Dependencias principales
| Dependencia | Propósito |
|---|---|
spring-boot-starter | Núcleo de Spring Boot (sin web, es un runner CLI) |
com.opencsv:opencsv | Construcción del CSV para la API batch de SFCC |
com.hawkersco:logistics-commons | Entidades JPA (Order, OrderDelayed, Shipment, LogisticThreshold, SfscJob) y servicios |
com.hawkersco:sfcc-services-client | Cliente de la API batch de Salesforce Services |
com.hawkersco:sfcc-marketing-client | Cliente de Salesforce Marketing Cloud |
com.hawkersco:sfcc-commons | Modelos SFCC compartidos |
com.hawkersco:slack-client | Notificaciones y subida de ficheros a Slack |
com.hawkersco:pi-function-commons | DateUtils, DirectoryUtils |
5. API / Endpoints
No aplica a este proyecto. Es un batch/runner sin capa REST.
6. Integraciones externas
| Sistema | Protocolo | Dirección | Detalle |
|---|---|---|---|
| Salesforce Service Cloud (Services API) | OAuth password grant + API batch CSV | Saliente | Marcado de retraso y asignación de cupón por pedido |
| Salesforce Marketing Cloud | OAuth2 client_credentials | Saliente | Declarada como dependencia; uso concreto no verificado en el código leído |
| Slack | HTTP (SlackClient) | Saliente | Resúmenes y listados de pedidos retrasados |
PostgreSQL (logistics) | JDBC | Entrante/Saliente | Lectura de umbrales/pedidos, escritura de OrderDelayed/OrderDelayedCoupon/SfscJob |
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), pese a que el CLAUDE.md afirma que este fichero está en .gitignore.
| Clave | Descripción |
|---|---|
orders.delayed.days-list | Umbrales de días separados por coma |
orders.delayed.source-list | IDs de fuente logística a procesar (actualmente solo 8, Auro) |
orders.delayed.plus-days | Días adicionales de margen sobre el umbral |
spring.datasource.* | Credenciales de la BD logistics |
sfccmarketing.credentials.* | Credenciales OAuth client_credentials de Salesforce Marketing Cloud |
sfccservices.credentials.token.* | Credenciales OAuth password grant de Salesforce Service Cloud |
slack.channel.id / .channel-atc.id | Canales de notificación |
⚠️ Alerta de seguridad
El fichero src/main/resources/application.properties (perfil local) contiene actualmente credenciales reales en texto plano: contraseña de la base de datos PostgreSQL logistics (la misma ya señalada como expuesta en múltiples proyectos de este ecosistema), credenciales OAuth completas de Salesforce Marketing Cloud, y credenciales OAuth completas de Salesforce Service Cloud (la misma cuenta developers@saldum.com ya señalada como expuesta en return-pi-dynamics, sfcc-abandoned-cart, sfsc-catalog-updater y update-sfcloud de este ecosistema), además del token de bot de Slack. Ninguna se ha reproducido en este documento. Se recomienda:
- Rotar de forma coordinada las credenciales de Salesforce (Service Cloud y Marketing Cloud), compartidas con varios proyectos de este ecosistema.
- Rotar la contraseña de BD y el token de Slack.
- Sustituir los valores hardcodeados de
application.propertiespor credenciales de un entorno de desarrollo aislado.
8. Persistencia
Base de datos PostgreSQL logistics (spring.jpa.hibernate.ddl-auto=none, esquema externo). Entidades relevantes: lectura de LogisticThreshold y tablas de logística; escritura en OrderDelayed, OrderDelayedCoupon y SfscJob. 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, que ejecuta el contenedor cada hora, de lunes a viernes (schedule: "0 * * * 1-5" — coherente con que el cálculo de retraso solo considera días laborables). Se ejecutan en orden estricto los 4 runners de la tabla de la sección 3.
10. Ejecución en local
Requisitos previos: JDK 25, Maven, acceso a la BD logistics y credenciales válidas de Salesforce (Service Cloud y Marketing Cloud).
# Compilar sin tests
mvn -B -DskipTests clean install
# Ejecutar tests
mvn test
# Ejecutar un test concreto
mvn test -Dtest=OrdersDelayedApplicationTests
# Build Docker
docker build -t orders-delayed .
Al ser un CommandLineRunner, no expone Actuator/health: la verificación se hace revisando el log de consola, los ficheros de umbral generados, o el estado en Salesforce.
11. Despliegue
- Imagen: construida con
jib-maven-plugin(baseeclipse-temurin:25-jre,containerizingMode=packaged), publicada eneurope-west3-docker.pkg.dev/pi-saldum/pi-repo/orders-delayed:<tag>. ElCLAUDE.mdmenciona una imagen baseeclipse-temurin:25-jdk-alpine, que no coincide con la configuración real vía Jib. - Orquestación: Kubernetes
CronJoben el clúster GKEpi-cluster-hw, namespacepi, ejecutándose cada hora de lunes a viernes. - CI/CD (Jenkins): pipeline real de 3 etapas —
Checkout→Build & Push→Deploy to GKE, consistente con la etapa de test vacía descrita en elCLAUDE.md.
Job de Jenkins: https://jenkins-pi.hawkersco.net/job/orders-delayed/
12. Manejo de errores y logging
No hay una estrategia de excepciones centralizada (no hay @ControllerAdvice, es un runner). El sondeo del jobId de la API batch de SFCC reintenta hasta 5 veces con 10 segundos de espera antes de darse por vencido. Logging vía SLF4J/java.util.logging según la clase.
13. Notas y consideraciones
CLAUDE.mdafirma queapplication.propertiesestá en.gitignore, pero el fichero está presente y con credenciales reales legibles directamente en el repositorio de trabajo (mismo patrón detectado enshowroom-flash-create-db,theiconic-create-db,update-stockylogistic-usa).CLAUDE.mdverificado y consistente en el resto de aspectos: el orden estricto de los 4 runners (verificado directamente mediante sus valores degetOrder()), la dependencia de estado entre ellos, el cálculo de retraso en días laborables, y el mapeo de fuente a transportista coinciden con el código real.- Ver alerta de seguridad en la sección 7 sobre credenciales de Salesforce y BD compartidas con otros proyectos de este ecosistema.