Skip to main content

showroom-create-db

1. Descripción general

Según el pom.xml, el proyecto se describe como "Showroom create DB". Es un microservicio batch (runner) ETL que sincroniza pedidos del marketplace Showroom Privé (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-create-db
groupIdcom.hawkersco
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
1ShowroomCreateDbWaitingRunnerPedidos WAITING_ACCEPTANCE con más de 1h → auto-aceptación en Mirakl
2ShowroomCreateDbRunnerPedidos SHIPPING → transformación y persistencia en BD logistics
  • .configShowroomCreateDbConfig (beans de servicios de logistics-commons + PersistenceManagedTypes vía PersistenceManagedTypesScanner).
  • .utilsShowroomCreateDbUtils (toda la lógica de creación de entidades: saveMarketplace, saveCustomer, saveOrder, saveOrderLine, saveShipment, saveOrderShipmentStatus).
flowchart TD
A["1. ShowroomCreateDbWaitingRunner<br/>WAITING_ACCEPTANCE > 1h"] -->|acceptOrder| B[Mirakl Showroom API]
A -.->|fallo al aceptar| C[Slack]
D["2. ShowroomCreateDbRunner<br/>SHIPPING, paginado 100"] -->|getOrderListWithStatus| B
D -->|si no existe ya| E[(logistics · Order/OrderMarketplace)]
D -->|isIslandPtPostalCode| F[NO_SEND_PT_ISLAND + alerta Slack]

Flujo: el runner 1 pagina los pedidos en WAITING_ACCEPTANCE, 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 con error. El runner 2 pagina los pedidos en SHIPPING desde hace 5 días, comprueba que no existan ya en BD (por SOURCE_ID=66 y cdOrderExternal), genera un nombre de pedido interno ("MKSHO" + ceros de relleno + idOrder, 7 caracteres numéricos), y persiste cliente, pedido, líneas y envío; direcciones en Portugal insular reciben el estado especial NO_SEND_PT_ISLAND con alerta a Slack.

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 (ShowroomClient), incluye tipos de request/response
com.hawkersco:logistics-commonsEntidades JPA (Order, OrderMarketplace, Customer, etc.) y servicios
com.hawkersco:pi-function-commonsZipCodeUtils, DateUtils
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 API (Showroom Privé)HTTP REST (ShowroomClient)Entrante/SalienteLectura de pedidos por estado y aceptación de pedidos pendientes
SlackHTTP (SlackClient)SalienteAlertas de fallo de aceptación y de pedidos con destino insular en Portugal
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).

ClaveDescripción
spring.datasource.*Credenciales de la BD logistics
showroom.credentials.url / .keyCredenciales de la API de Mirakl Showroom
showroom-flash.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 (canal general y canal de alertas de almacén)

⚠️ 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, clave de la API de Mirakl Showroom, y token de bot de Slack. Ninguno de estos valores se ha reproducido en este documento. Se recomienda:

  1. Rotar la contraseña de BD, la clave de Mirakl Showroom 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 sobre com.hawkersco.logisticscommons.dao): 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.

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

# Compilar con tests
./mvnw clean install

# Ejecutar el JAR
java -jar target/showroom-create-db-1.0.25.jar

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. No existe suite de tests (jenkins/scripts/test.sh está vacío).

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-create-db:<tag>. El CLAUDE.md menciona una imagen "multi-stage Eclipse Temurin 25 Alpine", que no coincide con la configuración real vía Jib del pom.xml actual.
  • Orquestación: Kubernetes CronJob en el clúster GKE pi-cluster-hw (zona europe-west3-a, proyecto pi-saldum), namespace pi, contenedor no privilegiado (allowPrivilegeEscalation: false, capabilities: drop: ALL), ejecutándose cada hora.
  • CI/CD (Jenkins): pipeline real 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 del manifiesto con sustitución de variables). El CLAUDE.md describe un pipeline con etapas KICS scan y SonarQube que no existen en el Jenkinsfile actual (ver hallazgo en la sección 13).

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

12. Manejo de errores y logging

No hay una estrategia de excepciones centralizada (no hay @ControllerAdvice, es un runner). ShowroomCreateDbRunner captura ParseException por pedido, registrando un warning sin interrumpir el resto del lote. ShowroomCreateDbWaitingRunner captura RestClientResponseException al aceptar un pedido, notificando a Slack y registrando Level.SEVERE; si la API responde correctamente pero 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

  • CLAUDE.md describe clases y paquetes que no existen en el código actual: menciona client/ShowroomHttpClient.java, client/SlackHttpClient.java, config/ShowroomClientAutoConfiguration.java y config/SlackClientAutoConfiguration.java como ficheros propios del proyecto, pero el árbol de código real solo contiene ShowroomCreateDbApplication, ShowroomCreateDbRunner, ShowroomCreateDbWaitingRunner, config/ShowroomCreateDbConfig y utils/ShowroomCreateDbUtils — no existe ningún paquete client ni clases de autoconfiguración locales. ShowroomClient y SlackClient se inyectan directamente desde las librerías externas showroom-client y slack-client (autoconfiguración vía META-INF/spring/...AutoConfiguration.imports de cada JAR), no desde código local del proyecto.
  • Pipeline de Jenkins más simple de lo documentado: el CLAUDE.md describe Maven build → KICS scan → SonarQube → Docker push → K8s deployment, pero el Jenkinsfile real solo tiene 3 etapas (Checkout, Build & Push, Deploy to GKE), sin escaneo KICS ni análisis SonarQube.
  • Propiedades showroom-flash.* vacías y sin uso aparente: tanto application.properties como application-pro.properties declaran showroom-flash.credentials.url/.key vacíos; no se ha encontrado ninguna referencia a ellas en el código de este proyecto — probablemente un resto de copia/pegado desde el proyecto hermano showroom-flash-create-db (pendiente de verificar al documentar ese proyecto).
  • El resto de la arquitectura descrita en CLAUDE.md (flujo de los 2 runners, generación del nombre de pedido MKSHO+ceros+ID, grupos de país ISO_GROUP_*, caso especial de Portugal insular, almacenamiento del JSON crudo de Mirakl) coincide con el código real, verificado directamente en ShowroomCreateDbRunner, ShowroomCreateDbWaitingRunner y ShowroomCreateDbUtils.
  • Ver alerta de seguridad en la sección 7 sobre credenciales reales expuestas en application.properties.