Privalia Marketplace Client
1. Descripción general
privalia-marketplace-client es una librería cliente reutilizable (JAR) que encapsula la comunicación con la API Pink-Connect v4 de Privalia (canal marketplace, distinto del canal logístico cubierto por privalia-client). El proyecto no expone ningún endpoint REST propio; se publica en el registro de artefactos Maven interno y es consumido por otros microservicios del ecosistema Hawkers que necesiten consultar pedidos del marketplace Privalia y actualizar su estado (envío, cancelación parcial, etc.).
A diferencia de privalia-client, este cliente no gestiona el token internamente: cada método recibe la cabecera Authorization como parámetro explícito, siendo el consumidor responsable de obtener y anteponer el prefijo "Bearer " al token.
2. Información técnica
| Propiedad | Valor |
|---|---|
artifactId | privalia-marketplace-client |
groupId | com.hawkersco |
version | 1.0.25-SNAPSHOT |
| Java | 25 |
| Spring Boot | 4.0.6 |
| Tipo de artefacto | JAR (librería, no ejecutable) |
| Módulos | Proyecto único (no multi-módulo) |
3. Arquitectura y diseño
Estructura del proyecto:
com.hawkersco.privaliamarketplaceclient
├── PrivaliaMarketplaceClientApplication.java # Clase @SpringBootApplication (residual, sin lógica)
├── client/
│ └── PrivaliaMarketplaceClient.java # Interfaz @HttpExchange: getOrders, updateOrderStatus
├── config/
│ ├── PrivaliaMarketplaceClientAutoConfiguration.java # @AutoConfiguration principal (sin interceptor de auth)
│ ├── PrivaliaMarketplaceClientConfig.java # Clase vacía — placeholder heredado de una configuración Feign (ver sección 13)
│ ├── PrivaliaMarketplaceClientConst.java # Constantes de cabeceras y content-types (no referenciadas por el cliente actual)
│ └── CacheStore.java # Cache genérica en memoria (Guava), disponible para quien la necesite
└── models/
├── PrivaliaOrderRequest.java # Modelo de parámetros de consulta (no cableado a ningún método, ver sección 13)
├── PrivaliaOrderResponse.java # Modelo de respuesta de pedido (jerarquía completa)
└── PrivaliaUpdateOrderStatusRequest.java # Request de actualización de estado (contiene una clase anidada duplicada, ver sección 13)
Flujo principal
sequenceDiagram
participant Consumidor as Microservicio consumidor
participant Client as PrivaliaMarketplaceClient
participant API as API Pink-Connect v4 (Privalia)
Consumidor->>Consumidor: obtiene/renueva su propio Bearer token
Consumidor->>Client: getOrders("Bearer <token>") / updateOrderStatus("Bearer <token>", orderId, newStatus, body)
Client->>API: GET /orders | PUT /orders/{orderId}/status/{newStatus} + header Authorization
API-->>Client: ResponseEntity<PrivaliaOrderResponse[]> | ResponseEntity<Void>
Client-->>Consumidor: ResponseEntity<T>
La autoconfiguración (PrivaliaMarketplaceClientAutoConfiguration) se activa condicionalmente con @ConditionalOnProperty(prefix = "privaliacreatedb.v2.url", name = "staging"), registrando el bean PrivaliaMarketplaceClient con un RestClient simple (sin interceptores) apuntando a privaliacreatedb.v2.url.staging.
El registro de la autoconfiguración se realiza mediante el fichero estándar de Spring Boot:
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
4. Dependencias principales
| Dependencia | Versión | Propósito |
|---|---|---|
spring-boot-starter | (gestionada SB4) | Base de Spring Boot (contexto, autoconfiguración) |
spring-web | (gestionada SB4) | RestClient + @HttpExchange / HttpServiceProxyFactory |
com.google.guava:guava | 33.4.8-jre | Implementación de caché en CacheStore (CacheBuilder); no usada internamente por el cliente actual (ver sección 13) |
com.google.code.gson:gson | (gestionada SB4) | Anotaciones @SerializedName en los modelos (soporte dual con Jackson) |
com.fasterxml.jackson.core:jackson-annotations | (gestionada SB4) | Anotaciones @JsonProperty en los modelos |
org.projectlombok:lombok | 1.18.38 (dependencia; annotationProcessorPath del compilador usa 1.18.46) | Generación de boilerplate en los modelos (getters, setters, @Builder) |
spring-boot-starter-test | (gestionada SB4) | Testing (scope test) |
5. API / Endpoints
No aplica a este proyecto. privalia-marketplace-client es una librería cliente JAR que no expone endpoints REST propios. Las operaciones que encapsula sobre la API Pink-Connect v4 de Privalia se detallan en la sección 6.
6. Integraciones externas
API Pink-Connect v4 (marketplace Privalia)
| Método cliente | HTTP | Ruta remota | Descripción |
|---|---|---|---|
getOrders | GET | /orders | Lista los pedidos del marketplace (sin parámetros de consulta cableados, ver sección 13) |
updateOrderStatus | PUT | /orders/{orderId}/status/{newStatus} | Actualiza el estado de un pedido (envío, cancelación, envío parcial, etc.) |
Ejemplo de payload updateOrderStatus (PrivaliaUpdateOrderStatusRequest):
{
"trackingNumber": "1234567890",
"trackingUrl": "https://carrier.example/tracking/1234567890",
"carrierId": 12345,
"reason": null,
"order_line_ids": [111, 222]
}
order_line_ids solo es obligatorio cuando newStatus=PARTIALLY_SHIPPED; en cualquier otro caso se ignora (según comentario en el propio código).
Ejemplo de respuesta getOrders (PrivaliaOrderResponse[], un elemento resumido):
[
{
"orderId": 987654,
"marketplaceName": "Privalia",
"marketplaceCode": "PRV",
"marketplaceOrderCode": "PRV-000123",
"status": "PENDING",
"totalPrice": 59.90,
"currency": "EUR",
"shippingInformation": { "name": "Cliente Final", "city": "Madrid", "countryIsoCode": "ES" },
"orderLines": [
{
"id": 1,
"sku": "SKU-001",
"name": "Camiseta básica",
"quantity": 2,
"totalPrice": 39.98,
"status": { "In Stock": true, "Shipped": 0, "Pending": 2 }
}
]
}
]
Según el Javadoc del modelo PrivaliaOrderRequest (no cableado actualmente a ningún parámetro real del método getOrders, ver sección 13), el endpoint GET /orders del contrato de la API Pink-Connect v4 admitiría los siguientes parámetros de consulta: offset (paginación, >= 0), limit (<= 50), orderStatusCodes (lista de WAITING_ACCEPTANCE, PENDING, PROCESSING, SHIPPED, CANCELLED, PARTIALLY_SHIPPED), shopChannelId, marketplaceCode y marketplaceOrderCode.
Protocolo: HTTPS REST (JSON). Autenticación: Bearer token pasado explícitamente como cabecera Authorization en cada llamada (@RequestHeader); el cliente no obtiene ni renueva el token por sí mismo.
7. Configuración
No se incluye ningún application.properties/application.yml en la librería. La única propiedad requerida debe ser suministrada por la aplicación consumidora:
| Propiedad | Descripción | Ejemplo de valor |
|---|---|---|
privaliacreatedb.v2.url.staging | URL base de la API Pink-Connect v4 (activa la autoconfiguración) | ${PRIVALIA_MARKETPLACE_URL} |
El token OAuth/Bearer no se configura como propiedad Spring: el consumidor debe obtenerlo por su cuenta y pasarlo explícitamente (con el prefijo "Bearer ") en cada llamada.
Variables de entorno recomendadas
| Variable | Propiedad mapeada |
|---|---|
PRIVALIA_MARKETPLACE_URL | privaliacreatedb.v2.url.staging |
Importante: Si
privaliacreatedb.v2.url.stagingno está definida, el beanPrivaliaMarketplaceClientno se registra (condición@ConditionalOnProperty).Nota sobre el nombre de la propiedad: El nombre
privaliacreatedb.v2.url.stagingsugiere que fue copiado/heredado de otro proyecto relacionado (posiblementeprivalia-create-db) y que originalmente apuntaba a un entorno de staging específico; no sigue el patrónprivalia*.credentials.url/*.client.urlusado por el resto de clientes del ecosistema. Pendiente de verificar si es intencional o un remanente de copia.
8. Persistencia
No aplica a este proyecto. La librería no accede a ninguna base de datos. CacheStore está disponible como utilidad pero no se usa internamente por ningún componente de este cliente (ver sección 13).
9. Procesos programados y mensajería
No aplica a este proyecto. No existen jobs @Scheduled, listeners de colas/topics ni runners batch.
10. Ejecución en local
privalia-marketplace-client es una librería JAR, no una aplicación ejecutable. No tiene servidor embebido ni endpoint de health.
Requisitos previos
- Java 25
- Maven 3.x
- Acceso al registro de artefactos Maven interno (
europe-west3-maven.pkg.dev/pi-saldum/pi-repo-maven) para resolver/publicar dependencias.
Compilar e instalar en repositorio local
# Compilar sin tests
mvn clean install -DskipTests
# Compilar con tests
mvn clean install
# Ejecutar un test concreto
mvn test -Dtest=MyTestClass
mvn test -Dtest=MyTestClass#myMethod
Uso como dependencia en un microservicio consumidor
<dependency>
<groupId>com.hawkersco</groupId>
<artifactId>privalia-marketplace-client</artifactId>
<version>1.0.25-SNAPSHOT</version>
</dependency>
La autoconfiguración se activa automáticamente al declarar privaliacreatedb.v2.url.staging en la aplicación consumidora. El consumidor debe gestionar por su cuenta la obtención del token y pasarlo con el prefijo "Bearer " en cada llamada.
11. Despliegue
El pipeline de Jenkins (Jenkinsfile) consta de dos etapas:
- Checkout — descarga el código del repositorio.
- Publish to Artifact Registry — ejecuta
mvn deploy -DskipTestspara publicar el JAR en Google Artifact Registry.
CLAUDE.md documenta un pipeline de tres etapas (Build, SonarQube, Clean), que no se corresponde con el Jenkinsfile actual del repositorio (dos etapas: Checkout y Publish to Artifact Registry). Se documenta el Jenkinsfile realmente presente.
| Parámetro | Valor |
|---|---|
| JDK | JDK25 (tool Jenkins) |
| Maven | Maven3 (tool Jenkins) |
| Repositorio | europe-west3-maven.pkg.dev/pi-saldum/pi-repo-maven (Artifact Registry GCP) |
No existe Dockerfile ni despliegue como servicio independiente; el artefacto es un JAR publicado en el registro Maven.
Job de Jenkins:
https://jenkins-pi.hawkersco.net/job/privalia-marketplace-client/
12. Manejo de errores y logging
La librería no implementa ninguna estrategia propia de manejo de excepciones ni logging estructurado. Ningún método de PrivaliaMarketplaceClient declara throws explícito; las excepciones de red o HTTP propagadas por RestClient (como RestClientResponseException) son responsabilidad del servicio consumidor. No hay configuración de logback ni de niveles de log específicos en la librería.
13. Notas y consideraciones
-
PrivaliaMarketplaceClientConfigdocumentada explícitamente como placeholder muerto: El propio Javadoc de la clase indica que es un "Empty Feign configuration placeholder", conservada únicamente porque una antigua anotación@FeignClient(configuration = ...)la referenciaba, y que puede eliminarse una vez se retire esa referencia. Confirma que el proyecto migró de OpenFeign a@HttpExchange/RestClient(igual que otros clientes del ecosistema) dejando código residual documentado como tal. -
PrivaliaOrderRequestno cableado agetOrders: El métodogetOrdersdePrivaliaMarketplaceClientsolo recibe el token (@RequestHeader("Authorization")), sin ningún@RequestParamparaoffset,limit,orderStatusCodes,shopChannelId,marketplaceCodenimarketplaceOrderCode— pese a que el modeloPrivaliaOrderRequestdocumenta extensamente estos parámetros en su Javadoc como parte del contrato de la API. Esto significa que, tal como está implementado hoy, el cliente siempre solicita el conjunto completo de pedidos sin paginación ni filtro, yPrivaliaOrderRequestes un modelo huérfano no utilizado por ningún método. Pendiente de verificar si se trata de una funcionalidad incompleta o de una versión anterior del contrato de la API. -
Clase anidada
PrivaliaOrderResponseduplicada dentro dePrivaliaUpdateOrderStatusRequest:PrivaliaUpdateOrderStatusRequestcontiene una clase estática anidada también llamadaPrivaliaOrderResponse, con una estructura casi idéntica a la clase de nivel superiorcom.hawkersco.privaliamarketplaceclient.models.PrivaliaOrderResponse, pero con diferencias sutiles (p. ej.marketplaceOrderCodecomolongen la anidada vs.Stringen la de nivel superior;OrderLine.idcomoStringvs.Long;additionalInformationcomoStringvs.Map<String, Object>; ausencia del campocommentenContactInformation). Esta clase anidada no es utilizada por ningún método dePrivaliaMarketplaceClient— parece ser código copiado y pegado por error o un remanente de una refactorización, generando confusión sobre cuál es el modelo "correcto" de respuesta de pedido. -
CacheStoreyPrivaliaMarketplaceClientConstsin uso interno: Ambas clases están presentes en el paqueteconfig/pero ningún componente de este proyecto las utiliza —CacheStoreno se instancia en ningún punto y las constantes dePrivaliaMarketplaceClientConst(cabeceras, content-types) no se referencian, ya que la autoconfiguración no registra ningún interceptor. Podrían ser remanentes copiados deprivalia-client(que sí las usa activamente) durante la creación de este proyecto. -
Autenticación completamente delegada al consumidor: A diferencia de
privalia-client(que cachea el token 30 minutos vía interceptor), aquí el consumidor debe resolver el token en cada llamada; elCacheStoredisponible en el paquete podría haber sido pensado para este propósito pero no está integrado en el flujo actual. -
Nombre de propiedad
privaliacreatedb.v2.url.staginginconsistente con el resto del ecosistema: Ver detalle en sección 7. -
Sin tests implementados: No existe directorio
src/test/en el proyecto. -
PrivaliaMarketplaceClientApplication.java: Clase principal de Spring Boot en el paquete raíz, sin funcionalidad operativa. Artefacto residual de la generación inicial del proyecto con Spring Initializr, mismo patrón observado en otros clientes del ecosistema.