return-pi-dynamics
1. Descripción general
Según el pom.xml, el proyecto se describe como "Return PI Dynamics". Es un microservicio batch (runner) que sincroniza las devoluciones (Return) registradas en la base de datos de logística con Dynamics 365 (creación, recepción y pago de la devolución), gestiona el caso de devoluciones con origen cancelado, y finalmente dispara el email transaccional de reembolso al cliente vía Salesforce Marketing Cloud.
2. Información técnica
| Campo | Valor |
|---|---|
artifactId | return-pi-dynamics |
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, todos activos, ejecutados en orden.
| Orden | Runner | Estado de entrada | Acción |
|---|---|---|---|
| 1 | ReturnApprovedPiDynamicsRunner | APPROVED | Crea y recibe la devolución en Dynamics; omite (y notifica por Slack) las que tienen origen cancelado (idReturnOrigin == 8) |
| 2 | ReturnPaymentPiDynamicsRunner | REFUNDED pendiente de pago | Crea → recibe → paga la devolución en Dynamics |
| 3 | ReturnCancelledPiDynamicsRunner | REFUNDED con origen cancelado | Envía la cancelación a Dynamics |
| 4 | ReturnSendEmailPiDynamicsRunner | Post-Dynamics | Envía el email de reembolso vía SFCC Marketing Cloud, y cierra la JVM |
.util—ReturnPiDynamicsUtil(mapeo SKU→dimensiones de inventario de Dynamics, con caché local en BD),ReturnPiSendDynamicsUtil(lógica central de envío:sendCreateReturn,sendReceiveReturn,sendPaymentReturn,sendCancelledReturn)..config—LogisticsDbConfig(datasource primariologistics),DynamicsDbConfig(datasource secundariodynamics-pro).
flowchart TD
A["1. ReturnApprovedPiDynamicsRunner"] -->|crea + recibe| B[Dynamics 365]
C["2. ReturnPaymentPiDynamicsRunner"] -->|crea + recibe + paga| B
D["3. ReturnCancelledPiDynamicsRunner"] -->|cancela| B
E["4. ReturnSendEmailPiDynamicsRunner"] -->|email reembolso| F[SFCC Marketing Cloud]
E -->|System.exit| G[Fin del proceso]
A -.->|origen cancelado| H[Slack]
Doble datasource
LogisticsDbConfig (primario, BD logistics: Order, Return, ReturnLine, ReturnStatus) y DynamicsDbConfig (secundario, BD dynamics-pro: InventDimensionsCombinations, PiCustomerSetup).
4. Dependencias principales
| Dependencia | Propósito |
|---|---|
spring-boot-starter | Núcleo de Spring Boot (sin web, es un runner CLI) |
com.hawkersco:logistics-commons | Entidades/servicios de devoluciones y pedidos |
com.hawkersco:dynamics-commons | Entidades de dimensiones de inventario y configuración de cliente PI en Dynamics |
com.hawkersco:dynamics-client | Cliente @HttpExchange (DynamicsDataClient) para crear/cancelar/recibir devoluciones y consultar dimensiones de inventario |
com.hawkersco:slack-client | Notificaciones de error/escalado a Slack |
com.hawkersco:sfcc-marketing-client | Cliente para Salesforce Marketing Cloud (envío del email de reembolso) |
com.hawkersco:sfcc-commons | Utilidades SFCC compartidas |
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 |
|---|---|---|---|
Dynamics 365 (scul072xsfj99233501-rs.su.retail.dynamics.com) | HTTP OAuth client_credentials (DynamicsDataClient) | Saliente | Crear/recibir/pagar/cancelar devoluciones, consultar dimensiones de inventario |
PI Customer Setup (hawkers.operations.dynamics.com) | HTTP OAuth client_credentials | Saliente | Configuración de cliente PI en Dynamics F&O |
| Salesforce Marketing Cloud | HTTP OAuth client_credentials | Saliente | Envío del email transaccional de reembolso |
| Slack | HTTP (SlackClient) | Saliente | Escalado de errores y aviso de devoluciones con origen cancelado |
PostgreSQL (logistics, dynamics-pro) | JDBC | Entrante/Saliente | Lectura de devoluciones pendientes y persistencia de contadores de reintento |
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) |
dynamics.login.* | OAuth client_credentials para Dynamics 365 Commerce — mismas credenciales ya señaladas como expuestas en otros proyectos del ecosistema |
dynamics.picustomersetup.* | OAuth client_credentials para Dynamics F&O (PI Customer Setup) |
slack.client.url / .auth.token / .channel.id | Configuración de Slack |
sfccmarketing.credentials.* | Credenciales OAuth y configuración de Salesforce Marketing Cloud (incluye eventdefinitionkey, account-id) |
⚠️ Alerta de seguridad (severidad alta)
El fichero src/main/resources/application.properties (perfil local) contiene actualmente credenciales OAuth reales de Dynamics 365 (las mismas ya señaladas como expuestas en gio-pos-sync-service, infranete-api, products-dynamics-pi), las contraseñas de ambas bases de datos PostgreSQL, un token de bot de Slack, y credenciales OAuth reales de Salesforce Marketing Cloud (client-id/client-secret, no señaladas hasta ahora en el resto del ecosistema documentado). Ninguno de estos valores se ha reproducido en este documento. Se recomienda:
- Rotar el
client-secretde las aplicaciones Azure AD de Dynamics (coordinando con los demás proyectos que las comparten). - Rotar las credenciales de Salesforce Marketing Cloud y el token de Slack.
- Rotar las contraseñas de ambas bases de datos.
- 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: logistics (Order, Return, ReturnLine, ReturnStatus) y dynamics-pro (InventDimensionsCombinations, PiCustomerSetup), ambas con ddl-auto=none. El progreso de sincronización se rastrea mediante columnas contador (nmReturnCreateDynamics, nmReturnReceiveDynamics, etc.) en la entidad Return, con un máximo de 5 reintentos antes de escalar por Slack. ReturnPiDynamicsUtil cachea en BD el mapeo SKU→dimensiones de inventario de Dynamics para reducir llamadas a la API. 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 cada 15 minutos (schedule: "*/15 * * * *"). Cada uno de los 4 runners verifica el resultado del paso anterior antes de continuar (p. ej. ReturnApprovedPiDynamicsRunner solo llama a sendReceiveReturn si la devolución ya estaba creada o si sendCreateReturn tuvo éxito en esta misma ejecución). Las devoluciones con origen cancelado se omiten explícitamente en el flujo de aprobadas y se notifican por Slack como posible anomalía (una devolución con origen cancelado no debería llegar a estado APPROVED).
10. Ejecución en local
Requisitos previos: JDK 25, Maven, acceso a ambas BD y credenciales OAuth válidas de Dynamics 365 y Salesforce Marketing Cloud.
# Compilar
mvn clean package
# Ejecutar (perfil dev)
mvn spring-boot:run
# Ejecutar (perfil pro)
mvn spring-boot:run -Dspring.profiles.active=pro
# Ejecutar tests
mvn test
mvn test -Dtest=ClassName
# Build de imagen OCI
mvn spring-boot:build-image
Al ser un CommandLineRunner, no expone Actuator/health: la verificación se hace revisando el log de consola o el estado de las devoluciones (ReturnStatus) tras la ejecución.
11. Despliegue
- Imagen: construida con
jib-maven-plugin(baseeclipse-temurin:25-jre,containerizingMode=packaged), publicada eneurope-west3-docker.pkg.dev/pi-saldum/pi-repo/return-pi-dynamics:<tag>. - Orquestación: Kubernetes
CronJoben el clúster GKEpi-cluster-hw, namespacepi, ejecutándose cada 15 minutos. - CI/CD (Jenkins): pipeline que sustituye
application-pro.propertiesporapplication.propertiesantes de construir.
Job de Jenkins: https://jenkins-pi.hawkersco.net/job/return-pi-dynamics/
12. Manejo de errores y logging
No hay una estrategia de excepciones centralizada (no hay @ControllerAdvice, es un runner). Cada paso del flujo comprueba el éxito del anterior antes de continuar (patrón de "cortocircuito" por devolución individual, no a nivel de todo el runner). Notificación a Slack específica cuando una devolución con origen cancelado llega al flujo de aprobadas, y escalado tras superar el máximo de reintentos por operación. Logging mediante SLF4J (consola).
13. Notas y consideraciones
CLAUDE.mdverificado y consistente con el código: la secuencia de 4 runners, sus órdenes de ejecución, el doble datasource y las integraciones externas descritas coinciden con lo observado directamente en el código (ReturnApprovedPiDynamicsRunner, órdenes 1–4 confirmados por grep). No se han encontrado discrepancias relevantes en este proyecto, a diferencia de la mayoría de los documentados en este lote.- Ver alerta de seguridad en la sección 7 sobre credenciales OAuth reales de Dynamics 365 y de Salesforce Marketing Cloud expuestas en
application.properties.