update-stock
1. Descripción general
Según el pom.xml, el proyecto se describe como "Update stock from dynamics" (descripción heredada, ver hallazgo en la sección 13: el proyecto no interactúa con Dynamics en absoluto). Es un microservicio batch (runner) que lee stock por marketplace desde una hoja de Google Sheets (dos pestañas, una por marca: Hawkers y Northweek) y sincroniza (upsert) los valores en la base de datos marketplaces, para los canales Decathlon, Miravia, Showroom y ECI.
2. Información técnica
| Campo | Valor |
|---|---|
artifactId | update-stock |
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 un único CommandLineRunner (MarketplacesRunner).
.config—UpdateStockConfig(beanMarketplaceStockService+PersistenceManagedTypesvíaPersistenceManagedTypesScannersobrecom.hawkersco.marketplacescommons.dao).
flowchart TD
A[MarketplacesRunner] -->|lee stock!A2:F| B[Google Sheets · pestaña HAWKERS]
A -->|lee NW - Decathlon!A2:F| C[Google Sheets · pestaña NORTHWEEK]
B --> D{existe MarketplaceStock<br/>por SKU+empresa?}
C --> D
D -->|sí| E[updateMarketplaceStock]
D -->|no| F[save nuevo MarketplaceStock]
E --> G[(marketplaces · MarketplaceStock)]
F --> G
Flujo: por cada una de las 2 pestañas (stock para Hawkers, NW - Decathlon para Northweek), lee el rango A2:F de la hoja de cálculo, y para cada fila con SKU no vacío comprueba si ya existe un MarketplaceStock para ese SKU y esa empresa (findByCdSkuAndDsCompany); si existe, actualiza los 4 campos de stock por marketplace (nmDecathlon, nmMiravia, nmShowroom, nmEci); si no existe, crea un nuevo registro. Un fallo de la API de Google Sheets al leer una pestaña se registra como warning y esa pestaña se omite, sin interrumpir el procesamiento de la otra.
4. Dependencias principales
| Dependencia | Propósito |
|---|---|
spring-boot-starter | Núcleo de Spring Boot (sin web, es un runner CLI) |
com.google.api-client:google-api-client | Cliente base de APIs de Google |
com.google.oauth-client:google-oauth-client-jetty | Autenticación OAuth de Google |
com.google.apis:google-api-services-sheets | Cliente de la API de Google Sheets v4 |
com.hawkersco:marketplaces-commons | Entidad MarketplaceStock y MarketplaceStockService |
com.hawkersco:pi-function-commons | SheetsServiceUtils (autenticación/acceso a Google Sheets) |
5. API / Endpoints
No aplica a este proyecto. Es un batch/runner sin capa REST.
6. Integraciones externas
| Sistema | Protocolo | Dirección | Detalle |
|---|---|---|---|
Google Sheets (hoja 1AFIE3V_eE58on_zyO4cpAhgItPUSuKBQVU4e1M2-vzQ) | API de Google v4 | Entrante | Lectura de stock por SKU y marketplace, 2 pestañas (Hawkers/Northweek) |
PostgreSQL (marketplaces) | JDBC | Saliente | Upsert de MarketplaceStock por SKU y empresa |
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.
| Clave | Descripción |
|---|---|
spring.datasource.* | Credenciales de la BD marketplaces |
GOOGLE_APPLICATION_CREDENTIALS (variable de entorno, no propiedad Spring) | Ruta al JSON de la cuenta de servicio de GCP para autenticar contra Google Sheets |
⚠️ Alerta de seguridad
El fichero src/main/resources/application.properties (perfil local) contiene actualmente la contraseña real en texto plano de la base de datos PostgreSQL marketplaces (la misma ya señalada como expuesta en otros proyectos de este ecosistema que comparten la instancia noctua-instance.hawkersco.net). No se ha reproducido en este documento. Se recomienda:
- Rotar la contraseña de BD.
- Sustituir el valor hardcodeado de
application.propertiespor credenciales de un entorno de desarrollo aislado. - Revisar el historial de control de versiones, ya que esta credencial puede seguir expuesta en commits anteriores.
8. Persistencia
Base de datos PostgreSQL marketplaces (spring.jpa.hibernate.ddl-auto=none). Entidad relevante: MarketplaceStock (paquete com.hawkersco.marketplacescommons.dao, escaneada vía PersistenceManagedTypesScanner). 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 * * * *", zona horaria Europe/Madrid, concurrencyPolicy: Forbid). Único runner, descrito en la sección 3.
10. Ejecución en local
Requisitos previos: JDK 25, Maven, acceso a la BD marketplaces y credenciales de aplicación por defecto de Google (Sheets).
# Compilar sin tests
./mvnw clean install -DskipTests
# Ejecutar la aplicación localmente
./mvnw spring-boot:run
No existen tests implementados (jenkins/scripts/test.sh es un placeholder vacío). Al ser un CommandLineRunner, no expone Actuator/health: la verificación se hace revisando el log de consola o los valores reflejados en la tabla MarketplaceStock.
11. Despliegue
- Imagen: construida con
jib-maven-plugin(baseeclipse-temurin:25-jre,containerizingMode=packaged), publicada eneurope-west3-docker.pkg.dev/pi-saldum/pi-repo/update-stock:<tag>. - Orquestación: Kubernetes
CronJoben el clúster GKEpi-cluster-hw, namespacepi, con credenciales de cuenta de servicio de GCP montadas por volumen (GOOGLE_APPLICATION_CREDENTIALS, necesarias en este caso para la autenticación real contra Google Sheets, a diferencia de otros proyectos de este lote donde el mismo montaje aparece sin uso aparente), ejecutándose cada hora. - CI/CD (Jenkins): pipeline real de 3 etapas —
Checkout→Build & Push→Deploy to GKE. ElCLAUDE.mddescribe un pipeline conKICS security scanySonarQubeque no existen en elJenkinsfileactual (mismo patrón detectado en varios proyectos hermanos de este lote).
Job de Jenkins: https://jenkins-pi.hawkersco.net/job/update-stock/
12. Manejo de errores y logging
No hay una estrategia de excepciones centralizada (no hay @ControllerAdvice, es un runner). processCompanySheet captura IOException por pestaña de hoja de cálculo, registrando Level.WARNING y continuando con la siguiente pestaña sin interrumpir el proceso. Logging mediante java.util.logging.Logger estándar (consola).
13. Notas y consideraciones
descriptiondelpom.xmldesactualizada: indica "Update stock from dynamics", pero el proyecto no lee ni escribe en Dynamics 365 en ningún punto del código — la única fuente de datos es Google Sheets. Es probable que la descripción sea un resto de una versión anterior del proyecto o de haberlo clonado de otro con un propósito distinto.- Fichero de recurso
aliexpress-sku.jsonsin ninguna referencia en el código: elCLAUDE.mdlo lista como parte de la arquitectura ("Static SKU mapping data"), pero no se ha encontrado ninguna referencia aaliexpressenMarketplacesRunnerni enUpdateStockConfig— el fichero está presente ensrc/main/resources/pero no se carga ni se usa en ningún punto del código actual. Probablemente un resto de una integración con AliExpress ya retirada o nunca completada. CLAUDE.mdafirma queapplication.propertiesestá en.gitignore, pero el fichero está presente y con la contraseña de BD real legible directamente en el repositorio de trabajo (mismo patrón detectado enshowroom-flash-create-dbytheiconic-create-db).- Pipeline de Jenkins más simple de lo documentado: ver hallazgo en la sección 11.
- El resto de la arquitectura descrita en
CLAUDE.md(flujo único de sincronización, las 2 pestañas de la hoja, los 4 campos de stock por marketplace) coincide con el código real, verificado directamente enMarketplacesRunner. - Ver alerta de seguridad en la sección 7 sobre la contraseña de BD expuesta en
application.properties.