order-pi-dynamics
1. Descripción general
Según el pom.xml, el proyecto se describe como "Send orders pi to dynamics". Es el microservicio orquestador central que envía pedidos desde numerosas plataformas de e-commerce/marketplace (SFCC en sus variantes ES/MX/CO/NW/EU2013, Mercado Libre, Mercado Libre Colombia, Miravia, Decathlon, El Corte Inglés, Falabella, Privalia, Privalia Marketplace, Coppel, Liverpool, Showroom, Showroom Flash, TheBradery) hacia Microsoft Dynamics 365, además de sincronizar estados de pedido de vuelta y realizar actualizaciones de datos y pagos.
2. Información técnica
| Campo | Valor |
|---|---|
artifactId | order-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 24 CommandLineRunner, cada uno activado por un perfil de Spring (@Profile("NombreDelRunner")) con el mismo nombre que la clase, salvo una excepción notable (ver hallazgo en la sección 13). En producción se activan todos los perfiles simultáneamente; en desarrollo solo se activa uno.
| Runner | Perfil (@Profile) | Ámbito |
|---|---|---|
OrderMeliPiDynamicsRunner | Activo | Mercado Libre |
OrderMeliCoPiDynamicsRunner | Activo | Mercado Libre Colombia |
OrderSfccPiDynamicsRunner, OrderSfccMxPiDynamicsRunner, OrderSfccCoPiDynamicsRunner, OrderSfccNwPiDynamicsRunner, OrderSfccEu2013PiDynamicsRunner | Activos | Variantes de Salesforce Commerce Cloud |
OrderSfccMxPaidZeroPiDynamicsRunner, OrderSfccCoPaidZeroPiDynamicsRunner | Activos | Pedidos SFCC con importe pagado cero (MX/CO) |
OrderMiraviaPiDynamicsRunner | Activo | Miravia |
OrderDecathlonPiDynamicsRunner | Activo | Decathlon |
OrderECIPiDynamicsRunner | Activo | El Corte Inglés |
OrderFalabellaPiDynamicsRunner | Activo | Falabella |
OrderPrivaliaPiDynamicsRunner, OrderPrivaliaMarketplacePiDynamicsRunner | Activos | Privalia (directo y marketplace) |
OrderCoppelPiDynamicsRunner | Activo | Coppel |
OrderLiverpoolPiDynamicsRunner | Activo | Liverpool |
OrderShowroomPiDynamicsRunner | Activo | Showroom Privé |
OrderShowroomFlashPiDynamicsRunner | @Profile comentado — sin restricción de perfil (ver hallazgo crítico en la sección 13) | Showroom Flash |
OrderTheBraderyPiDynamicsRunner | Activo | TheBradery |
OrderBrandingPiDynamicsRunner | Activo | Pedidos de branding/personalización |
StatusOrderPiDynamicsRunner | Activo | Sincronización de estados de pedido de vuelta a Dynamics |
OrderDetectorLimboRunner | Activo | Detección de pedidos atascados/en limbo |
UpdateDataDynamicsRunner | Activo | Actualizaciones masivas de datos |
UpdatePaymentDynamicsRunner | Activo | Actualizaciones de pago |
.config—DynamicsDbConfig(@Primary, BDdynamics-pro),LogisticsDbConfig(BDlogistics)..utils—OrderPiDynamicsUtils(transformación compartida),OrderPiDynamicsCons(constantes: SKUs, tipos de tender,DATA_AREA_IDpor país),OrderVerifyPiDynamicsUtils(validación previa al envío),OrderPiDynamicsErrorUtils(formato de error + Slack),OrderSfccPiDynamicsUtils/OrderSfccMxPiDynamicsUtils/OrderSfccCoPiDynamicsUtils(lógica específica por canal SFCC),StatusOrderPiDynamicsUtils,UpdateDataDynamicsUtils.
flowchart TD
A[24 runners activados por perfil] -->|pedidos pendientes| B[(logistics · Order)]
A -->|obtiene pedido| C[API de la plataforma correspondiente]
A -->|valida y transforma| D[OrderPiDynamicsUtils]
D -->|envía| E[Dynamics 365 REST API]
A -.->|error| F[Slack]
4. Dependencias principales
| Dependencia | Propósito |
|---|---|
spring-boot-starter | Núcleo de Spring Boot (sin web, es un runner CLI) |
org.apache.poi:poi / poi-ooxml | Soporte de ficheros Excel |
com.hawkersco:dynamics-client / dynamics-commons | Cliente y entidades de Dynamics 365 |
com.hawkersco:sfcc-commons | Modelos de pedido de Salesforce Commerce Cloud |
com.hawkersco:meli-client, miravia-client, decathlon-client, eci-client, falabella-client, privalia-client, privalia-marketplace-client, coppel-client, qat-client (Liverpool), showroom-client, bradery-client | Clientes @HttpExchange por plataforma |
com.hawkersco:recharge-client | Suscripciones Recharge (lentillas) |
com.hawkersco.posclient:pos-client | Punto de venta |
com.hawkersco:stripe-client | Pagos Stripe |
com.hawkersco:slack-client | Notificaciones de error |
No existen dependencias shein-client ni tiktok-client en el pom.xml, pese a que CLAUDE.md las cita explícitamente como integraciones activas, incluyendo un runner OrderSheinPiDynamicsRunner que no existe en el árbol de código actual (ver hallazgo crítico en la sección 13).
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 REST API | HTTP REST, OAuth2 (2 client secrets: login general y picustomersetup) | Saliente | Creación/actualización de pedidos y datos |
| Mercado Libre, Mercado Libre Colombia, Miravia, Decathlon, El Corte Inglés, Falabella, Privalia (x2), Coppel, Liverpool, Showroom (x2), TheBradery | HTTP REST (clientes @HttpExchange) | Entrante | Lectura de pedidos por plataforma |
| Recharge | HTTP, con tokens por país (ES/DE/FR/IT/PT/UK) | Saliente | Gestión de suscripciones de lentillas |
| Stripe | HTTP | Saliente | Verificación/gestión de pagos |
| SprintLogistics | HTTP | Saliente | Datos logísticos asociados a pedidos |
| Slack | HTTP (SlackClient) | Saliente | Notificaciones de error |
PostgreSQL (dynamics-pro, logistics) | JDBC (doble datasource) | Entrante/Saliente | Lectura de pedidos pendientes y escritura en Dynamics |
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 una cantidad muy elevada de valores reales hardcodeados (ver alerta de seguridad).
| Clave | Descripción |
|---|---|
spring.profiles.active | Determina qué runner se ejecuta en local — actualmente StatusOrderPiDynamicsRunner (ver hallazgo en la sección 13) |
spring.datasource.* / logistics.datasource.* | Credenciales de las BD dynamics-pro y logistics |
dynamics.login.client-secret / dynamics.picustomersetup.login.client-secret | Dos secretos OAuth distintos de Dynamics 365 |
slack.auth.token | Token de bot de Slack |
lenses.recharge.token | Tokens de Recharge por país (ES/DE/FR/IT/PT/UK) |
sprintlogistics.api.password | Credencial de SprintLogistics |
meli.credentials.clientsecret | Credencial OAuth de Mercado Libre |
stripe.client.password | Credencial de Stripe |
🛑 Alerta de seguridad — volumen muy elevado de credenciales reales de múltiples sistemas
El fichero src/main/resources/application.properties (perfil local) contiene credenciales reales de al menos 8 sistemas distintos: ambas bases de datos PostgreSQL (contraseña compartida ya señalada como expuesta en múltiples proyectos), dos secretos OAuth de Dynamics 365, el token de bot de Slack, seis tokens de Recharge (uno por país), la contraseña de la API de SprintLogistics, el client secret de Mercado Libre, y la contraseña del cliente de Stripe. Ninguna se ha reproducido en este documento. Dada la centralidad de este proyecto (orquestador de pedidos hacia el ERP), se recomienda rotar todas estas credenciales con prioridad alta y sustituir los valores hardcodeados de application.properties por credenciales de un entorno de desarrollo aislado.
8. Persistencia
Dos bases de datos PostgreSQL independientes: dynamics-pro (@Primary, vía dynamics-commons) y logistics (vía logistics-commons), cada una con su propio EntityManagerFactory/TransactionManager. 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. En producción se activan todos los perfiles de runner simultáneamente (application-pro.properties), ejecutándose los 24 runners en cada invocación.
10. Ejecución en local
Requisitos previos: JDK 25, Maven, acceso a ambas BD y credenciales válidas de la plataforma/runner que se quiera probar.
# Compilar
./mvnw clean package
# Ejecutar (usa el perfil activo en application.properties)
./mvnw spring-boot:run
# Ejecutar tests
./mvnw test
# Ejecutar un test concreto
./mvnw test -Dtest=OrderPiDynamicsApplicationTests
# Build Docker
docker build -t order-pi-dynamics .
Al ser un conjunto de CommandLineRunner, no expone Actuator/health: la verificación se hace revisando el log de consola o el estado de los pedidos en Dynamics/BD.
11. Despliegue
- Imagen: construida con
jib-maven-plugin(baseeclipse-temurin:25-jre,containerizingMode=packaged), publicada eneurope-west3-docker.pkg.dev/pi-saldum/pi-repo/order-pi-dynamics:<tag>. ElCLAUDE.mdmenciona una imagen baseeclipse-temurin:25-jdkcon heap-Xmx2G, que no coincide con la configuración real vía Jib. - Orquestación: Kubernetes
CronJoben el clúster GKEpi-cluster-hw, namespacepi. - CI/CD (Jenkins): pipeline real de 3 etapas —
Checkout→Build & Push→Deploy to GKE.
Job de Jenkins: https://jenkins-pi.hawkersco.net/job/order-pi-dynamics/
12. Manejo de errores y logging
No hay una estrategia de excepciones centralizada (no hay @ControllerAdvice, es un conjunto de runners). OrderPiDynamicsErrorUtils centraliza el formato de error y la notificación a Slack, usada de forma consistente por los distintos runners de plataforma. Logging mediante java.util.logging.Logger/SLF4J según la clase.
13. Notas y consideraciones
⚠️ Hallazgo: OrderShowroomFlashPiDynamicsRunner no tiene restricción de perfil activa
A diferencia de los otros 23 runners, cuya anotación @Profile("NombreDelRunner") limita su ejecución al perfil correspondiente, OrderShowroomFlashPiDynamicsRunner tiene esta anotación comentada (//@Profile("OrderShowroomFlashPiDynamicsRunner")). Esto significa que este runner en concreto se ejecuta siempre, independientemente del perfil de Spring activo — incluido en el entorno local, donde el perfil activo es actualmente StatusOrderPiDynamicsRunner (ver más abajo), lo que provocaría que ambos runners se ejecuten simultáneamente en desarrollo aunque solo se pretendiera probar uno. En producción, donde todos los perfiles ya están activos a la vez, el efecto práctico es menor, pero conviene restaurar la anotación para mantener el comportamiento consistente y predecible entre entornos.
Otros hallazgos
CLAUDE.mdcita un runner y clientes de Shein/TikTok que no existen en el código actual: el documento existente mencionaOrderSheinPiDynamicsRunnercomo uno de los "key runners" y lista clientes internos desheinytiktokentre las integraciones REST — ninguno de los dos existe: no hay ningún ficheroOrderSheinPiDynamicsRunner.javaen el árbol de código, y elpom.xmlno declara nishein-clientnitiktok-client. Es el mismo patrón de integración ficticia/huérfana de TikTok ya detectado enpi-generate-credentialsylogistics-status-processen este ecosistema, y aquí se extiende también a una integración de Shein igualmente inexistente.- El perfil activo por defecto en
application.propertiesno coincide conCLAUDE.md: el documento existente afirma que en desarrollo soloOrderMeliPiDynamicsRunnerestá activo por defecto; el fichero real de configuración tienespring.profiles.active=StatusOrderPiDynamicsRunner. - Imagen base y heap no coinciden con la configuración real: ver hallazgo en la sección 11.
- El resto de la arquitectura descrita en
CLAUDE.md(patrón de runner por perfil, doble datasource, utilidades compartidas) coincide con el código real, verificado mediante inspección de las anotaciones@Profilede los 24 runners. - Ver alerta de seguridad en la sección 7 sobre el elevado volumen de credenciales reales expuestas en
application.properties.