Skip to main content

miravia-update-stock

1. Descripción general

Según el pom.xml, el proyecto se describe como "Miravia update stock". Es un microservicio batch (runner) que sincroniza el stock disponible en Dynamics 365 con las ofertas activas del marketplace Miravia, actualizando la cantidad de cada SKU vía la API de Miravia (firmada con SHA-256).

2. Información técnica

CampoValor
artifactIdmiravia-update-stock
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 un único CommandLineRunner (MiraviaUpdateStockRunner).

  • .configMiraviaUpdateStockConfig, DynamicsDbConfig (único datasource, dynamics-pro).
flowchart TD
A[MiraviaUpdateStockRunner] -->|token vía pi-generate-credentials| B[Miravia API]
A -->|findProductDynamicsByWharehouseAndDataAreaId<br/>AU03 / dataAreaId 10| C[(dynamics-pro · ProductDynamics)]
A -->|pagina productos, 40/página| B
A -->|"stock = floor(cantidad Dynamics)"| D[updateProductPriceQuantity]
D --> B
A -->|SKU no encontrado| E["cantidad = 0"]

Flujo: obtiene un token OAuth de Miravia vía el servicio interno pi-generate-credentials; carga el stock disponible del almacén AU03/dataAreaId 10 desde Dynamics; pagina el catálogo completo de ofertas de Miravia (40 por página); para cada SKU de Miravia presente en Dynamics, actualiza su cantidad a floor(cantidad disponible en Dynamics) —sin ningún ajuste porcentual—; para los SKUs de Miravia no encontrados en Dynamics, fija la cantidad a 0. Entre llamadas a la API se espera 3 segundos por límite de tasa.

4. Dependencias principales

DependenciaPropósito
spring-boot-starterNúcleo de Spring Boot (sin web, es un runner CLI)
spring-webRestClient/@HttpExchange
com.hawkersco:miravia-clientCliente @HttpExchange + utilidades de firma SHA-256 para la API de Miravia
com.hawkersco:dynamics-commonsProductDynamicsService, entidad ProductDynamics
com.hawkersco:pi-generate-credentials-clientObtención de token OAuth de Miravia

No existe dependencia marketplaces-commons en el pom.xml, pese a que CLAUDE.md describe un segundo datasource hacia una BD de "Marketplaces" con porcentajes de asignación por SKU (ver hallazgo crítico en la sección 13).

5. API / Endpoints

No aplica a este proyecto. Es un batch/runner sin capa REST.

6. Integraciones externas

SistemaProtocoloDirecciónDetalle
Miravia API (api.miravia.es)HTTP REST firmado SHA-256 (MiraviaClient)Entrante/SalienteLectura paginada del catálogo y actualización de cantidad por SKU
Servicio interno pi-generate-credentialsHTTPEntranteObtención de token OAuth de Miravia
PostgreSQL (dynamics-pro)JDBCEntranteLectura de stock disponible por almacén/dataAreaId

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
miravia.client.url / .appkey / .appsecretCredenciales de la API de Miravia
spring.datasource.*Credenciales de la BD dynamics-pro (único datasource)
credentials-client.api.hostURL del servicio interno pi-generate-credentials

⚠️ Alerta de seguridad

El fichero src/main/resources/application.properties (perfil local) contiene actualmente credenciales reales en texto plano: la clave/secreto de aplicación de Miravia (la misma ya señalada como expuesta en miravia-create-db y logistics-status-process) y la contraseña de la base de datos PostgreSQL dynamics-pro (la misma ya señalada como expuesta en múltiples proyectos de este ecosistema). Ninguna se ha reproducido en este documento. Se recomienda rotar ambas credenciales y sustituir los valores hardcodeados por credenciales de un entorno de desarrollo aislado.

8. Persistencia

Base de datos PostgreSQL dynamics-pro, único datasource (DynamicsDbConfig), acceso vía dynamics-commons (ddl-auto=none). Entidad relevante: ProductDynamics. 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 15 minutos (schedule: "*/15 * * * *"). Único runner, descrito en la sección 3.

10. Ejecución en local

Requisitos previos: JDK 25, Maven, acceso a la BD dynamics-pro y credenciales válidas de Miravia.

# Compilar
./mvnw clean install

# Compilar sin tests (producción)
./mvnw -B -DskipTests clean install

# Ejecutar tests
./mvnw test

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

# 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 las ofertas en el panel de Miravia.

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/miravia-update-stock:<tag>.
  • Orquestación: Kubernetes CronJob en el clúster GKE pi-cluster-hw, namespace pi, ejecutándose cada 15 minutos.
  • CI/CD (Jenkins): pipeline real de 3 etapas — CheckoutBuild & PushDeploy to GKE. El CLAUDE.md describe un pipeline de 5 etapas (Build → Test → Push → Deployment → Clean) que no coincide con el Jenkinsfile actual.

Job de Jenkins: https://jenkins-pi.hawkersco.net/job/miravia-update-stock/

12. Manejo de errores y logging

No hay una estrategia de excepciones centralizada (no hay @ControllerAdvice, es un runner). Todo el run() está envuelto en un único try/catch genérico que registra Level.WARNING sin interrumpir la finalización normal del proceso. Un fallo HTTP al actualizar un SKU concreto se registra pero no interrumpe el resto del lote. Logging mediante java.util.logging.Logger estándar (consola).

13. Notas y consideraciones

  • CLAUDE.md describe una arquitectura de doble datasource y ajuste de stock por porcentaje que no existe en el código actual: afirma que el runner consulta un segundo datasource ("Marketplaces DB", vía una clase MarketplacesDbConfig y un MarketplaceStockService de la librería marketplaces-commons) para obtener un porcentaje de asignación por SKU y calcular stock = floor(dynamicsQty * allocation / 100). En el código real solo existe un datasource (dynamics-pro), no hay clase MarketplacesDbConfig, la librería marketplaces-commons ni siquiera es una dependencia del pom.xml, y el cálculo de stock es una copia directa del valor de Dynamics redondeado hacia abajo, sin ningún ajuste porcentual. Es exactamente el mismo patrón de desviación ya detectado en el proyecto hermano showroom-update-stock de este mismo ecosistema — probablemente ambos CLAUDE.md se generaron a partir de una plantilla común o se copiaron entre sí sin ajustarse al código real de cada proyecto.
  • Retardo entre llamadas distinto del documentado: CLAUDE.md indica una espera de 10 segundos entre llamadas a la API; el código real usa RATE_LIMIT_DELAY_MS = 3_000L (3 segundos).
  • Pipeline de Jenkins más simple de lo documentado: ver hallazgo en la sección 11.
  • Ver alerta de seguridad en la sección 7 sobre credenciales reales expuestas en application.properties.