logistic-mx
1. Descripción general
Según el pom.xml, el proyecto se describe como "Logistic from Mexico". Es un microservicio batch (runner) que procesa pedidos pendientes con destino México (estándar y de marketplace) y los envía al operador logístico Cubbo, validando disponibilidad de stock e inventario de marketplace antes del envío.
2. Información técnica
| Campo | Valor |
|---|---|
artifactId | logistic-mx |
groupId | com.hawkersco |
version | 1.0.25 |
| Java | 25 |
| Spring Boot | 4.0.6 |
| Tipo de artefacto | jar (ejecutable, Spring Boot batch/CLI, spring.main.web-application-type=none) |
| 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 2 CommandLineRunner, ambos activos.
| Orden | Runner | Propósito |
|---|---|---|
| 1 | LogisticMxRunner | Procesa pedidos estándar (no marketplace): construye OrderCubboRequest y los envía a Cubbo |
| 2 | LogisticMxMpRunner | Procesa pedidos de marketplace: además valida stock/inventario en Cubbo antes de enviar; llama a System.exit() al terminar |
.client—GroupLogisticsClient(@HttpExchangehacia un endpoint de pruebas de "Group Logistics", ver hallazgo en la sección 13 — no invocado desde ningún punto del código actual)..config—GroupLogisticsAutoConfiguration(wiring del cliente anterior),LogisticMxConfiguration(beans delogistics-commons),LogisticMxUtils..utils—LogisticMxConst(constantes: mapas de código postal por transportista, IDs de transportista).
flowchart TD
A["1. LogisticMxRunner<br/>pedidos estándar"] -->|OrderCubboRequest| B[Cubbo API]
C["2. LogisticMxMpRunner<br/>pedidos marketplace"] -->|valida stock/inventario| B
C -->|envía| B
B -->|éxito/error| D[GCS pi-logistics-segment]
A -.->|≥4 fallos| E[Slack]
C -.->|≥4 fallos, stock, duplicados| E
C -->|System.exit al terminar| F[Fin del proceso]
Ambos runners incrementan un contador de reintentos (nmSendLogistic) por pedido tras un fallo HTTP (RestClientResponseException), archivan cada petición/respuesta en GCS, y notifican a Slack tras 4 fallos, ante escasez de stock, o ante pedidos duplicados.
4. Dependencias principales
| Dependencia | Propósito |
|---|---|
spring-boot-starter | Núcleo de Spring Boot (sin web, es un runner CLI) |
spring-web | RestClient/@HttpExchange |
com.hawkersco:cubbo-client | Cliente @HttpExchange para la API de Cubbo |
com.hawkersco:logistics-commons | Entidades JPA (Order, OrderLine, Shipment) y servicios |
com.hawkersco:slack-client | Notificaciones de error |
com.hawkersco:pi-function-commons | DateUtils y utilidades compartidas |
No existe dependencia logisfashion-client en el pom.xml, pese a que CLAUDE.md la cita como dependencia interna y application.properties contiene credenciales de LogisFashion sin ningún uso en el código (ver hallazgo 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 |
|---|---|---|---|
| Cubbo API | HTTP REST (CubboClient) | Saliente | Envío de pedidos estándar y de marketplace, consulta de stock/inventario |
Google Cloud Storage (bucket pi-logistics-segment) | API de GCS | Saliente | Archivado de peticiones/respuestas |
| Slack | HTTP (SlackClient) | Saliente | Alertas de stock, duplicados y fallos repetidos |
PostgreSQL (logistics) | JDBC | Entrante/Saliente | Lectura de pedidos pendientes y actualización de 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).
| Clave | Descripción |
|---|---|
spring.datasource.* | Credenciales de la BD logistics |
gcs.bucket.name | Bucket de GCS para archivado |
cubbo.client.url / .clientid.prod / .clientsecret.prod / .storeid.prod | Credenciales OAuth de la API de Cubbo (con un bloque de credenciales de test comentado adicional) |
logisfashion.api.url / .key / .password | Credenciales de LogisFashion — sin ningún uso en el código actual (ver hallazgo en la sección 13) |
logisticmx.carrier*.cp | Extensos listados de códigos postales por transportista para enrutamiento |
logisticmx.shipping.country / .iso2 / .iso3 / .isoid | Datos fijos de país (México) |
slack.client.url / .auth.token / .channel.id / .channel-atc-mx.id | Configuración de Slack |
⚠️ 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), dos juegos de credenciales OAuth de Cubbo (uno de test comentado, uno de producción activo), las credenciales de LogisFashion (huérfanas, sin uso), y el token de bot de Slack. Adicionalmente, el fichero GroupLogisticsClient.java contiene un token de autenticación hardcodeado directamente en la URL de la anotación @HttpExchange en código fuente Java (ver hallazgo en la sección 13). Ninguna credencial se ha reproducido en este documento. Se recomienda:
- Rotar la contraseña de BD, las credenciales de Cubbo y el token de Slack.
- Decidir si las credenciales de LogisFashion siguen siendo necesarias; si no, eliminarlas del fichero de configuración.
- Eliminar o mover a configuración el token hardcodeado en
GroupLogisticsClient, y valorar si esa clase debe eliminarse por completo al no usarse.
8. Persistencia
Base de datos PostgreSQL logistics (spring.jpa.hibernate.ddl-auto=none). Entidades relevantes: Order, OrderLine, Shipment. 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 5 minutos (schedule: "0/5 * * * *", concurrencyPolicy: Forbid). Se ejecutan en orden los 2 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 la API de Cubbo.
# Compilar sin tests
./mvnw clean install -DskipTests
# Compilar con tests
./mvnw clean install
# Ejecutar tests
./mvnw test
# Ejecutar un test concreto
./mvnw test -Dtest=ClassName#methodName
# Ejecutar la aplicación localmente
./mvnw spring-boot:run
Al ser un CommandLineRunner, no expone Actuator/health: la verificación se hace revisando el log de consola o el estado de los pedidos en la BD logistics.
11. Despliegue
- Imagen: construida con
jib-maven-plugin(baseeclipse-temurin:25-jre,containerizingMode=packaged), publicada eneurope-west3-docker.pkg.dev/pi-saldum/pi-repo/logistic-mx:<tag>. - Orquestación: Kubernetes
CronJoben el clúster GKEpi-cluster-hw, namespacepi, ejecutándose cada 5 minutos. - CI/CD (Jenkins): pipeline real de 3 etapas —
Checkout→Build & Push→Deploy to GKE. ElCLAUDE.mdmenciona escaneo KICS y análisis SonarQube que no aparecen en elJenkinsfileactual (mismo patrón detectado en varios proyectos hermanos de este lote).
Job de Jenkins: https://jenkins-pi.hawkersco.net/job/logistic-mx/
12. Manejo de errores y logging
No hay una estrategia de excepciones centralizada (no hay @ControllerAdvice, es un runner). Las llamadas HTTP a Cubbo se envuelven en try/catch sobre RestClientResponseException; ante fallo se incrementa el contador de reintentos del pedido y se archiva el error en GCS. Tras 4 fallos se notifica a Slack. Logging mediante java.util.logging.Logger estándar (consola).
13. Notas y consideraciones
GroupLogisticsClientapunta a un endpoint de pruebas con un token hardcodeado, y no se usa en ningún punto del código: la interfaz@HttpExchangedeclara la URL basehttps://wms-api-test.grupo-logistics.com(obsérvese "test" en el propio host) y una ruta con un token de autenticación embebido como parámetro de consulta (tokenData=...) directamente en la anotación Java. No hay ninguna referencia a esta clase desdeLogisticMxRunnerniLogisticMxMpRunner— es código muerto, aparentemente un cliente experimental o abandonado, con un secreto de entorno de pruebas expuesto en el código fuente. Se recomienda eliminarlo si no tiene uso previsto, o moverlo a configuración si se planea retomar.- Credenciales de LogisFashion huérfanas:
application.propertiesdefinelogisfashion.api.url/.key/.password, yCLAUDE.mdcitalogisfashion-clientcomo dependencia interna, pero elpom.xmlno la declara y no hay ninguna referencia a "logisfashion" en el código Java de este proyecto — mismo patrón de credenciales huérfanas (aunque de menor escala) detectado enlogistic-lensescon Shopify. - Doble juego de credenciales de Cubbo en el mismo fichero:
application.propertiesmantiene un bloque de credenciales de test comentado junto al bloque de producción activo — práctica común en este ecosistema, pero que aumenta la superficie de credenciales a rotar si se limpia el fichero en el futuro. - El resto de la arquitectura descrita en
CLAUDE.md(dos runners, orden de ejecución, patrón de reintento con contadornmSendLogistic, archivado en GCS, alertas Slack) coincide con el código real, verificado directamente enLogisticMxRunneryLogisticMxMpRunner. - Ver alerta de seguridad en la sección 7 sobre credenciales reales expuestas en
application.propertiesy sobre el token hardcodeado enGroupLogisticsClient.