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
| Campo | Valor |
|---|---|
artifactId | showroom-create-db |
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 2 CommandLineRunner, ambos activos.
| Orden | Runner | Propósito |
|---|---|---|
| 1 | ShowroomCreateDbWaitingRunner | Pedidos WAITING_ACCEPTANCE con más de 1h → auto-aceptación en Mirakl |
| 2 | ShowroomCreateDbRunner | Pedidos SHIPPING → transformación y persistencia en BD logistics |
.config—ShowroomCreateDbConfig(beans de servicios delogistics-commons+PersistenceManagedTypesvíaPersistenceManagedTypesScanner)..utils—ShowroomCreateDbUtils(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
| Dependencia | Propósito |
|---|---|
spring-boot-starter | Núcleo de Spring Boot (sin web, es un runner CLI) |
spring-web | RestClient/@HttpExchange |
com.hawkersco:showroom-client | Cliente @HttpExchange para la API de Mirakl Showroom (ShowroomClient), incluye tipos de request/response |
com.hawkersco:logistics-commons | Entidades JPA (Order, OrderMarketplace, Customer, etc.) y servicios |
com.hawkersco:pi-function-commons | ZipCodeUtils, DateUtils |
com.hawkersco:slack-client | Cliente @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
| Sistema | Protocolo | Dirección | Detalle |
|---|---|---|---|
| Mirakl Showroom API (Showroom Privé) | HTTP REST (ShowroomClient) | Entrante/Saliente | Lectura de pedidos por estado y aceptación de pedidos pendientes |
| Slack | HTTP (SlackClient) | Saliente | Alertas de fallo de aceptación y de pedidos con destino insular en Portugal |
PostgreSQL (logistics) | JDBC | Saliente | Persistencia 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).
| Clave | Descripción |
|---|---|
spring.datasource.* | Credenciales de la BD logistics |
showroom.credentials.url / .key | Credenciales de la API de Mirakl Showroom |
showroom-flash.credentials.url / .key | Presentes 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.id | Configuració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:
- Rotar la contraseña de BD, la clave de Mirakl Showroom y el token de Slack.
- Sustituir los valores hardcodeados de
application.propertiespor credenciales de un entorno de desarrollo aislado. - 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(baseeclipse-temurin:25-jre,containerizingMode=packaged), publicada eneurope-west3-docker.pkg.dev/pi-saldum/pi-repo/showroom-create-db:<tag>. ElCLAUDE.mdmenciona una imagen "multi-stage Eclipse Temurin 25 Alpine", que no coincide con la configuración real vía Jib delpom.xmlactual. - Orquestación: Kubernetes
CronJoben el clúster GKEpi-cluster-hw(zonaeurope-west3-a, proyectopi-saldum), namespacepi, contenedor no privilegiado (allowPrivilegeEscalation: false,capabilities: drop: ALL), ejecutándose cada hora. - CI/CD (Jenkins): pipeline real de 3 etapas —
Checkout→Build & Push(sustituyeapplication-pro.propertiesporapplication.properties,mvn clean package jib:build) →Deploy to GKE(kubectl delete cronjob+kubectl applydel manifiesto con sustitución de variables). ElCLAUDE.mddescribe un pipeline con etapasKICS scanySonarQubeque no existen en elJenkinsfileactual (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.mddescribe clases y paquetes que no existen en el código actual: mencionaclient/ShowroomHttpClient.java,client/SlackHttpClient.java,config/ShowroomClientAutoConfiguration.javayconfig/SlackClientAutoConfiguration.javacomo ficheros propios del proyecto, pero el árbol de código real solo contieneShowroomCreateDbApplication,ShowroomCreateDbRunner,ShowroomCreateDbWaitingRunner,config/ShowroomCreateDbConfigyutils/ShowroomCreateDbUtils— no existe ningún paqueteclientni clases de autoconfiguración locales.ShowroomClientySlackClientse inyectan directamente desde las librerías externasshowroom-clientyslack-client(autoconfiguración víaMETA-INF/spring/...AutoConfiguration.importsde cada JAR), no desde código local del proyecto.- Pipeline de Jenkins más simple de lo documentado: el
CLAUDE.mddescribeMaven build → KICS scan → SonarQube → Docker push → K8s deployment, pero elJenkinsfilereal 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: tantoapplication.propertiescomoapplication-pro.propertiesdeclaranshowroom-flash.credentials.url/.keyvací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 hermanoshowroom-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 pedidoMKSHO+ceros+ID, grupos de paísISO_GROUP_*, caso especial de Portugal insular, almacenamiento del JSON crudo de Mirakl) coincide con el código real, verificado directamente enShowroomCreateDbRunner,ShowroomCreateDbWaitingRunneryShowroomCreateDbUtils. - Ver alerta de seguridad en la sección 7 sobre credenciales reales expuestas en
application.properties.