logistics-status-process
1. Descripción general
Según el pom.xml, el proyecto se describe como "Process logistics states". Es un microservicio batch (runner) que sincroniza los estados de envío de pedidos entre múltiples proveedores logísticos externos y las bases de datos internas de Hawkers, y a continuación propaga esos estados actualizados a las APIs de los marketplaces correspondientes (Meli, Miravia, Showroom, TheBradery, El Corte Inglés, TheIconic, Decathlon). Orquesta hasta 17 procesadores asíncronos independientes.
2. Información técnica
| Campo | Valor |
|---|---|
artifactId | logistics-status-process |
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 un CommandLineRunner coordinador (LogisticsStatusProcessCoordinator) que orquesta en paralelo hasta 17 runners asíncronos (@Async, CompletableFuture<Void>), no los 8+9=17 descritos de forma inexacta en CLAUDE.md (ver hallazgo en la sección 13).
| Categoría | Runners (verificados en el código) |
|---|---|
| GCS → BD (9, no 8) | Auro, Cubbo, Logsolutions, NPF, Sarmed, Servientrega, SprintLogistics y SprintLogisticsGb (dos runners distintos, no uno solo), TimesLogistics |
| BD → Marketplace (8, no 9) | Auro, AuroTheBradery, Cubbo, Logsolutions, NPF, Servientrega, SprintLogistics, Times |
No existe un runner de tipo "BD → Marketplace" para Sarmed (solo GCS → BD) — Sarmed no propaga estados a ningún marketplace en el código actual.
LogisticsStatusProcessCoordinator lee futures.async.runners ("All" o el nombre de una clase concreta) para decidir qué runners ejecutar, los lanza todos como CompletableFuture async, espera con CompletableFuture.allOf, y llama a SpringApplication.exit() (con código de salida 1 si algún runner falló).
.config—DynamicsDbConfig(@Primary, BDdynamics-pro),DynamicsDbGoldConfig(BDdynamics-gold),LogisticsDbConfig(BDlogistics),LogisticsStatusProcessConfig..models— modelos de estado por transportista (StatusOrderCubbo,StatusOrderSarmed,StatusOrderServientrega,StatusOrderSprintLogistics,StatusOrdersAuro,StatusOrderNpf,StatusOrderLogiscore, etc.), másEbayShippingFulfillmentRequest(ver hallazgo en la sección 13)..utils—LogisticsStatusProcessGcPToDbUtils(operaciones GCS compartidas),UpdateDecathlonUtil,UpdateElCorteInglesUtils,UpdateMeliUtil,UpdateMiraviaUtil,UpdateShowroomUtil,UpdateTheBraderyUtils,UpdateTheIconicUtil(lógica de llamada a cada marketplace).
flowchart TD
A[LogisticsStatusProcessCoordinator] -->|futures.async.runners| B{"All / runner concreto"}
B --> C[9 runners GCS→BD]
B --> D[8 runners BD→Marketplace]
C -->|descarga y parsea| E[GCS pi-logistics-segment]
C -->|escribe estado| F[(dynamics-pro / dynamics-gold / logistics)]
D -->|lee estado pendiente| F
D -->|push estado| G[APIs de marketplace: Meli, Miravia, Showroom, TheBradery, ECI, TheIconic, Decathlon]
4. Dependencias principales
| Dependencia | Propósito |
|---|---|
spring-boot-starter, spring-boot-starter-data-jpa | Núcleo Spring Boot + JPA |
com.zaxxer:HikariCP | Pool de conexiones para el triple datasource |
org.apache.poi:poi / poi-ooxml | Parseo de ficheros Excel |
org.eclipse.angus:angus-mail | Envío de correo (Jakarta Mail) |
com.hawkersco:dynamics-commons / dynamics-client | Acceso a Dynamics 365 |
com.hawkersco:logistics-commons | Entidades JPA y servicios de logística |
com.hawkersco:logsolution-client, decathlon-client, theiconic-client, miravia-client, meli-client, liverpool-client, eci-client, showroom-client, bradery-client | Clientes @HttpExchange de cada marketplace/transportista |
com.miravia:miravia | SDK oficial de Miravia |
com.hawkersco:pi-generate-credentials-client | Cliente del servicio interno de credenciales |
com.hawkersco:slack-client | Notificaciones de error |
No existe dependencia tiktok-client en el pom.xml, pese a que CLAUDE.md la cita como dependencia interna y application.properties contiene credenciales reales de TikTok sin ningún uso en el código (ver hallazgo crítico en la sección 13 — mismo patrón ya detectado en pi-generate-credentials).
5. API / Endpoints
No aplica a este proyecto. Es un batch/runner sin capa REST.
6. Integraciones externas
| Sistema | Protocolo | Dirección | Detalle |
|---|---|---|---|
Google Cloud Storage (bucket pi-logistics-segment) | API de GCS | Entrante | Lectura de ficheros de estado por transportista |
| Meli, Miravia, Showroom, TheBradery, El Corte Inglés, TheIconic, Decathlon | HTTP REST (clientes @HttpExchange) | Saliente | Propagación de estados de envío actualizados |
| Slack | HTTP (SlackClient) | Saliente | Notificaciones de error |
PostgreSQL (dynamics-pro, dynamics-gold, logistics) | JDBC (triple datasource) | Entrante/Saliente | Lectura/escritura de estados de pedido |
| Correo electrónico (SMTP) | angus-mail | Saliente | Notificaciones relacionadas con TheBradery |
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.datasource.* / dynamicsgold.datasource.* / logistics.datasource.* | Credenciales de las tres BD |
futures.async.runners | Controla qué runners se ejecutan |
decathlon.credentials.key / decathlon-au.credentials.key | Credenciales de Decathlon (España/Australia) |
theiconic.api.key | Credencial de The Iconic |
miravia.client.appkey / .appsecret | Credenciales OAuth de Miravia |
meli.credentials.clientsecret | Credencial de Mercado Libre |
liverpool.credentials.key, qliverpool.api.key | Credenciales de Liverpool (con una clave adicional comentada) |
eci.credentials.key | Credencial de El Corte Inglés |
showroom.credentials.key, showroom-flash.credentials.key | Credenciales de Showroom Privé (estándar y Flash) |
ebay.credentials.granttype / .refresh.token | Credenciales OAuth de eBay |
aliexpress.app.key / .secret / .generated.secret | Credenciales de AliExpress |
cdiscount.credentials.token.* / .ocpaimsubkey | Credenciales OAuth de Cdiscount (Octopia) |
ninenineminutes.client.secret.prod | Credencial de 99minutos |
tiktok.app-key / .app-secret | Credenciales de TikTok — sin ningún uso en el código actual (ver hallazgo crítico) |
email.utils.bradery.password | Contraseña de la cuenta de correo de TheBradery |
slack.auth.token | Token de bot de Slack |
🛑 Alerta de seguridad — volumen muy elevado de credenciales reales, incluyendo un juego huérfano de TikTok
El fichero src/main/resources/application.properties (perfil local) contiene credenciales reales de al menos 13 sistemas externos distintos: tres bases de datos PostgreSQL (la misma contraseña compartida, ya señalada como expuesta en múltiples proyectos de este ecosistema), Decathlon (x2), The Iconic, Miravia, Mercado Libre, Liverpool (x2), El Corte Inglés, Showroom (x2), eBay (token de refresco OAuth), AliExpress, Cdiscount/Octopia, 99minutos, TikTok, y la contraseña de una cuenta de correo. Ninguna se ha reproducido en este documento.
En particular, tiktok.app-key/tiktok.app-secret no tienen ningún uso en el código de este proyecto (no hay dependencia tiktok-client en el pom.xml, ni ninguna referencia a "tiktok" en el código Java) — son credenciales reales, huérfanas, del mismo tipo de integración "TikTok Shop" ya señalada como ficticia/no implementada en el proyecto pi-generate-credentials de este mismo ecosistema. Es posible que ambos proyectos compartan el mismo origen de credenciales de una integración de TikTok que nunca llegó a completarse.
Se recomienda con prioridad alta:
- Rotar todas las credenciales listadas, dado el volumen y la antigüedad probable de exposición.
- Confirmar si la integración de TikTok Shop sigue teniendo sentido; si no, eliminar
tiktok.app-key/.app-secretde este fichero y del correspondienteSecretde Kubernetes (cruzar con el mismo hallazgo enpi-generate-credentials). - Sustituir los valores hardcodeados de
application.propertiespor credenciales de un entorno de desarrollo aislado.
8. Persistencia
Tres bases de datos PostgreSQL independientes (dynamics-pro @Primary, dynamics-gold, logistics), cada una con su propio EntityManagerFactory/TransactionManager (HikariCP, pool máx. 5 / mín. 2). 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 10 minutos (schedule: "0/10 * * * *", activeDeadlineSeconds: 43200 — 12 horas). En producción se ejecutan todos los runners (futures.async.runners=All) en paralelo.
10. Ejecución en local
Requisitos previos: JDK 25, Maven, acceso a las tres BD y credenciales válidas de los marketplaces/transportistas relevantes.
# Compilar
mvn clean install
# Ejecutar en desarrollo
mvn spring-boot:run
# Ejecutar solo un runner concreto
mvn spring-boot:run -Dfutures.async.runners=LogisticsStatusProcessAuroRunner
# Ejecutar tests
mvn test
# Ejecutar el JAR de producción
java -Xmx4g -jar target/logistics-status-process-1.0.25.jar
Al ser un CommandLineRunner, no expone Actuator/health: la verificación se hace revisando el log de consola o el estado reflejado en las 3 BD y en los paneles de cada marketplace.
11. Despliegue
- Imagen: construida con
jib-maven-plugin(baseeclipse-temurin:25-jre,containerizingMode=packaged), publicada eneurope-west3-docker.pkg.dev/pi-saldum/pi-repo/logistics-status-process:<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 10 minutos con un plazo de actividad de 12 horas. - CI/CD (Jenkins): pipeline real de 3 etapas —
Checkout→Build & Push→Deploy to GKE. ElCLAUDE.mddescribe un pipeline conKICS security scanySonarQubeque no aparecen en elJenkinsfileactual (mismo patrón detectado en varios proyectos hermanos de este lote).
Job de Jenkins: https://jenkins-pi.hawkersco.net/job/logistics-status-process/
12. Manejo de errores y logging
No hay una estrategia de excepciones centralizada (no hay @ControllerAdvice, es un runner). El coordinador recoge los resultados de todos los CompletableFuture y, si alguno falló, sale con código de estado 1 en lugar de 0. Cada runner individual gestiona sus propios errores de API/BD, típicamente notificando a Slack. Logging mediante java.util.logging.Logger/SLF4J según la clase.
13. Notas y consideraciones
CLAUDE.mdcuenta mal sus propios runners: afirma "GCP-to-DB Runners (8)" y los lista sin incluir la variante específica de Reino Unido de SprintLogistics (LogisticsStatusProcessSprintLogisticsGbGcpToDbRunner), que sí existe en el código — el número real es 9. Además, el propio encabezado "Marketplace Runners (9)" es inconsistente con su propia lista adjunta, que enumera solo 8 nombres — y el código confirma que son 8, no 9.- Credenciales de TikTok huérfanas: ver alerta de seguridad crítica en la sección 7 — mismo patrón que la integración ficticia de TikTok ya detectada en
pi-generate-credentialsen este ecosistema. EbayShippingFulfillmentRequestpresente en.modelssin runner ni utilidadUpdate*asociada visible: existe el modelo pero no se ha encontrado un runner o clase de utilidad dedicada a eBay entre los ficheros de este proyecto, pese a queapplication.propertiessí contiene credenciales OAuth completas de eBay — podría tratarse de una integración parcialmente implementada o en curso, pendiente de confirmar con el equipo.- Pipeline de Jenkins e imagen base más simples de lo documentado: ver hallazgo en la sección 11.
- El resto de la arquitectura descrita en
CLAUDE.md(patrón coordinador/runners asíncronos, triple datasource, filtrado porfutures.async.runners) coincide con el código real, verificado directamente enLogisticsStatusProcessCoordinator.