Skip to main content

showroom-flash-create-db

1. Descripción general

El pom.xml de este proyecto conserva la descripción genérica por defecto de Spring Initializr ("Demo project for Spring Boot"), que no refleja su propósito real (ver hallazgo en la sección 13). Según su CLAUDE.md y el código, es un microservicio batch (runner) ETL, hermano de showroom-create-db, que sincroniza pedidos del marketplace Showroom Flash (plataforma Mirakl) con la base de datos de logística: acepta automáticamente pedidos pendientes de aceptación con más de 1 hora de antigüedad, y persiste como nuevos pedidos internos los que ya están en estado de envío (SHIPPING).

2. Información técnica

CampoValor
artifactIdshowroom-flash-create-db
groupIdcom.hawkersco.showroomflashcreatedb
version1.0.25
Java25
Spring Boot4.0.6
Tipo de artefactojar (ejecutable, Spring Boot batch/CLI)
MódulosNo 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.

OrdenRunnerPropósito
1ShowroomFlashCreateDbWaitingRunnerPedidos WAITING_ACCEPTANCE con más de 1h → auto-aceptación en Mirakl
2ShowroomFlashCreateDbRunnerPedidos SHIPPING → transformación y persistencia en BD logistics
  • .configShowroomCreateDbConfig (beans de servicios de logistics-commons + PersistenceManagedTypes).
  • .utilsShowroomFlashCreateDbUtils (toda la lógica de creación de entidades: saveMarketplace, saveCustomer, saveOrder, saveOrderLine, saveShipment, saveOrderShipmentStatus).
flowchart TD
A["1. ShowroomFlashCreateDbWaitingRunner<br/>WAITING_ACCEPTANCE > 1h"] -->|acceptOrder| B[Mirakl Showroom Flash API]
A -.->|fallo al aceptar| C[Slack]
D["2. ShowroomFlashCreateDbRunner<br/>SHIPPING, paginado 100"] -->|getOrderListWithStatus| B
D -->|si no existe ya, fuente 72| E[(logistics · Order/OrderMarketplace)]

Flujo: el runner 1 pagina los pedidos en WAITING_ACCEPTANCE (esperando 10s entre páginas), calcula la antigüedad de cada uno y acepta (acceptOrder) los que superan 1 hora, notificando a Slack si la aceptación falla o si la API responde sin éxito. El runner 2 pagina los pedidos en SHIPPING desde hace 5 días, comprueba que no existan ya en BD (por SHOWROOM_SOURCE_ID=72 y cdOrderExternal), genera un nombre de pedido interno ("MKSHOF" + ceros de relleno + idOrder, 7 caracteres numéricos), y persiste cliente, pedido, líneas y envío. Ambos runners usan un cliente HTTP específico de Flash (ShowroomFlashClient), distinto del ShowroomClient genérico usado por showroom-create-db, aunque ambos provienen de la misma librería showroom-client.

4. Dependencias principales

DependenciaPropósito
spring-boot-starterNúcleo de Spring Boot (sin web, es un runner CLI)
spring-webRestClient/@HttpExchange
com.hawkersco:showroom-clientCliente @HttpExchange para la API de Mirakl Showroom Flash (ShowroomFlashClient), incluye tipos de request/response
com.hawkersco:logistics-commonsEntidades JPA (Order, OrderMarketplace, Customer, etc.) y servicios
com.hawkersco:pi-function-commonsDateUtils y utilidades compartidas
com.hawkersco:slack-clientCliente @HttpExchange para notificaciones (SlackClient)
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

SistemaProtocoloDirecciónDetalle
Mirakl Showroom Flash APIHTTP REST (ShowroomFlashClient)Entrante/SalienteLectura de pedidos por estado y aceptación de pedidos pendientes
SlackHTTP (SlackClient)SalienteAlertas de fallo de aceptación
PostgreSQL (logistics)JDBCSalientePersistencia de clientes, pedidos, líneas y envíos

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.

ClaveDescripción
spring.datasource.*Credenciales de la BD logistics (mismo host que showroom-create-db)
showroom-flash.credentials.url / .keyCredenciales de la API de Mirakl Showroom Flash
showroom.credentials.url / .keyPresentes pero vacías en ambos perfiles; sin uso aparente en este proyecto (ver sección 13)
slack.client.url / .auth.token / .channel.id / .channel-whs-not.idConfiguració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 showroom-create-db), clave de la API de Mirakl Showroom Flash (además de una clave comentada de un entorno de desarrollo de Mirakl), y token de bot de Slack (el mismo ya señalado en showroom-create-db). Ninguno de estos valores se ha reproducido en este documento. Se recomienda:

  1. Rotar la contraseña de BD, la clave de Mirakl Showroom Flash y el token de Slack.
  2. Sustituir los valores hardcodeados de application.properties por credenciales de un entorno de desarrollo aislado.
  3. Revisar el historial de control de versiones, ya que estas credenciales pueden seguir expuestas en commits anteriores.

8. Persistencia

Base de datos PostgreSQL logistics (esquema externo, no gestionado por este proyecto: spring.jpa.hibernate.ddl-auto=none). Entidades relevantes (definidas en logistics-commons, escaneadas vía PersistenceManagedTypesScanner): Order, OrderMarketplace, Customer, CustomerSource, OrderLine, Shipment, ShipmentLine, OrderShipmentStatus. 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 hora (schedule: "0 * * * *", concurrencyPolicy: Forbid, activeDeadlineSeconds: 3600). 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 Mirakl Showroom Flash.

# Compilar sin tests
./mvnw -B -DskipTests clean install

# Ejecutar tests
./mvnw test

# Ejecutar la aplicación localmente
./mvnw spring-boot:run

# Ejecutar un test concreto
./mvnw test -Dtest=ShowroomFlashCreateDbApplicationTests

Al ser un CommandLineRunner, no expone Actuator/health: la verificación se hace revisando el log de consola o los pedidos reflejados en la BD logistics.

11. Despliegue

  • Imagen: construida con jib-maven-plugin (base eclipse-temurin:25-jre, containerizingMode=packaged), publicada en europe-west3-docker.pkg.dev/pi-saldum/pi-repo/showroom-flash-create-db:<tag>. El CLAUDE.md menciona una imagen base eclipse-temurin:25-jdk-alpine, que no coincide con la configuración real vía Jib del pom.xml actual (mismo patrón detectado en showroom-create-db).
  • Orquestación: Kubernetes CronJob en el clúster GKE pi-cluster-hw, namespace pi, contenedor no privilegiado (allowPrivilegeEscalation: false, capabilities: drop: ALL), ejecutándose cada hora.
  • CI/CD (Jenkins): pipeline de 3 etapas — CheckoutBuild & Push (sustituye application-pro.properties por application.properties, mvn clean package jib:build) → Deploy to GKE (kubectl delete cronjob + kubectl apply).

Job de Jenkins: https://jenkins-pi.hawkersco.net/job/showroom-flash-create-db/

12. Manejo de errores y logging

No hay una estrategia de excepciones centralizada (no hay @ControllerAdvice, es un runner). ShowroomFlashCreateDbRunner captura ParseException por pedido, registrando un warning sin interrumpir el resto del lote. ShowroomFlashCreateDbWaitingRunner captura RestClientResponseException al aceptar un pedido, notificando a Slack y registrando Level.SEVERE; si la API responde sin éxito 2xx, también notifica a Slack sin lanzar excepción. Logging mediante java.util.logging.Logger estándar (consola).

13. Notas y consideraciones

  • description del pom.xml no actualizada: conserva el texto genérico de Spring Initializr ("Demo project for Spring Boot") en lugar de una descripción real del propósito del proyecto, a diferencia de la mayoría de proyectos hermanos de este ecosistema.
  • Propiedades showroom.* vacías y sin uso aparente: tanto application.properties como application-pro.properties declaran showroom.credentials.url/.key vacíos (además de una URL/clave de Mirakl de desarrollo comentada); no se ha encontrado ninguna referencia a showroom.credentials.* en el código de este proyecto. Es el mismo patrón de restos de copia/pegado detectado de forma recíproca en showroom-create-db (que a su vez tiene showroom-flash.* vacías sin uso) — ambos proyectos comparten un origen común y probablemente se clonó uno a partir del otro sin limpiar las propiedades del marketplace contrario.
  • CLAUDE.md afirma que application.properties está en .gitignore ("Dev: application.properties (gitignored — contains real credentials)"), pero el fichero está presente y con credenciales reales legibles directamente en el repositorio de trabajo — no se ha podido confirmar si existe una entrada de .gitignore que simplemente no se está respetando, o si la afirmación es incorrecta.
  • El resto de la arquitectura descrita en CLAUDE.md (flujo de los 2 runners, SHOWROOM_SOURCE_ID=72, prefijo de nombre MKSHOF, grupos de país, uso de ShowroomFlashClient) coincide con el código real, verificado directamente en ShowroomFlashCreateDbRunner y ShowroomFlashCreateDbWaitingRunner.
  • Ver alerta de seguridad en la sección 7 sobre credenciales reales expuestas en application.properties, compartidas parcialmente con showroom-create-db.