Skip to main content

QAT Client

1. Descripción general

qat-client es una librería cliente reutilizable (JAR) que encapsula la comunicación con la API de gestión de pedidos QAT. 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 listar pedidos, aceptar sus líneas y descargar la documentación asociada (etiquetas/albaranes) en formato ZIP.

2. Información técnica

PropiedadValor
artifactIdqat-client
groupIdcom.hawkersco
version1.0.25-SNAPSHOT
Java25
Spring Boot4.0.6
Tipo de artefactoJAR (librería, no ejecutable)
MódulosProyecto único (no multi-módulo)

3. Arquitectura y diseño

Estructura del proyecto:

com.hawkersco.qatclient
├── QatClientApplication.java # Clase @SpringBootApplication (residual, sin lógica)
├── client/
│ └── QatClient.java # Interfaz @HttpExchange con las 5 operaciones de negocio
├── config/
│ └── QatClientAutoConfiguration.java # @AutoConfiguration principal (cabecera apikey + Accept dinámico)
└── model/
├── AcceptOrderQtaRequest.java # Request de aceptación de líneas de pedido
└── OrdersQatResponse.java # Respuesta de listado de pedidos (jerarquía completa, ~490 líneas)

Flujo principal

sequenceDiagram
participant Consumidor as Microservicio consumidor
participant Client as QatClient
participant API as API QAT

Consumidor->>Client: getOrderList / acceptOrder / downloadDocumentsByOrderList / ...
Client->>API: GET/PUT + header apikey + Accept (dinámico según ruta)
API-->>Client: ResponseEntity<OrdersQatResponse | String | byte[]>
Client-->>Consumidor: ResponseEntity<T>

La autoconfiguración (QatClientAutoConfiguration) se activa condicionalmente con @ConditionalOnProperty(prefix = "qat.credentials", name = {"url", "key"}), registrando un único bean QatClient cuyo RestClient:

  • Fija la cabecera apikey por defecto (defaultHeader) con el valor de qat.credentials.key.
  • Incorpora un requestInterceptor que decide dinámicamente el valor de la cabecera Accept según la URL de la petición: */* para las rutas que contienen documentmanagement/documents/entities/ORDER/download o /accept, y application/vnd.private.api.v1+json para el resto.

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

DependenciaVersiónPropósito
spring-boot-starter(gestionada SB4)Base de Spring Boot (contexto, autoconfiguración)
spring-web(gestionada SB4)RestClient + @HttpExchange / HttpServiceProxyFactory
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:lombok1.18.42 (dependencia; annotationProcessorPath del compilador usa 1.18.46)Generación de boilerplate en los modelos
spring-boot-starter-test(gestionada SB4)Testing (scope test)

5. API / Endpoints

No aplica a este proyecto. qat-client es una librería cliente JAR que no expone endpoints REST propios. Las operaciones que encapsula sobre la API de QAT se detallan en la sección 6.

6. Integraciones externas

API de gestión de pedidos QAT

Método clienteHTTPRuta remotaDescripción
acceptOrderPUT/api/ordermanagement/orders/{orderId}/accept?shop_id=Acepta/rechaza las líneas de un pedido (accepted por ítem)
getOrderListByStateCodeGET/api/ordermanagement/orders?order_state_codes&shop_id&start_date&max&offsetLista pedidos paginados filtrados por código de estado
getOrderListGET/api/ordermanagement/orders?shop_id&start_date&max&offsetLista todos los pedidos de una tienda, paginados, sin filtro de estado
downloadDocumentsByOrderListGET/api/documentmanagement/documents/entities/ORDER/download?order_ids&shop_idDescarga un ZIP de documentos asociados a una lista de pedidos, devuelve byte[]
getOrderListByIdGET/api/ordermanagement/orders?order_ids&shop_idConsulta pedidos por una lista concreta de identificadores

Ejemplo de payload acceptOrder (AcceptOrderQtaRequest):

{
"items": [
{ "id": "ORDLINE-001", "accepted": true },
{ "id": "ORDLINE-002", "accepted": false }
]
}

Ejemplo de respuesta getOrderList (OrdersQatResponse, resumida — misma forma general que otras integraciones de marketplace del ecosistema, con pedido, canal, cliente, líneas y direcciones anidadas):

{
"total_count": 12,
"orders": [
{
"commercial_id": "ORD-000123",
"created_date": "2026-07-01T10:00:00Z",
"currency_iso_code": "EUR",
"can_cancel": true,
"can_evaluate": false,
"channel": { "code": "MP", "label": "Marketplace" },
"customer": { "firstname": "Nombre", "lastname": "Apellido" }
}
]
}

Protocolo: HTTPS REST (JSON para las operaciones de pedido; binario byte[] para la descarga de documentos). Autenticación: cabecera estática apikey, inyectada como valor por defecto en el RestClient a partir de qat.credentials.key.

7. Configuración

No se incluye ningún application.properties/application.yml en la librería. Las propiedades deben ser inyectadas por la aplicación consumidora.

Propiedades requeridas (prefijo qat.credentials)

PropiedadDescripciónEjemplo de valor
qat.credentials.urlURL base de la API QAT (activa la autoconfiguración)${QAT_CLIENT_URL}
qat.credentials.keyValor de la cabecera apikey${QAT_CLIENT_API_KEY}

Importante: Si falta qat.credentials.url o qat.credentials.key, el bean QatClient no se registra (condición @ConditionalOnProperty con ambas claves).

Variables de entorno recomendadas

VariablePropiedad mapeada
QAT_CLIENT_URLqat.credentials.url
QAT_CLIENT_API_KEYqat.credentials.key

8. Persistencia

No aplica a este proyecto. La librería no accede a ninguna base de datos ni mantiene estado en memoria.

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

qat-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
./mvnw -B -DskipTests clean install

# Compilar con tests
./mvnw clean install

# Ejecutar tests
./mvnw test

Uso como dependencia en un microservicio consumidor

<dependency>
<groupId>com.hawkersco</groupId>
<artifactId>qat-client</artifactId>
<version>1.0.25-SNAPSHOT</version>
</dependency>

La autoconfiguración se activa automáticamente al declarar qat.credentials.url y qat.credentials.key en la aplicación consumidora.

11. Despliegue

El pipeline de Jenkins (Jenkinsfile) consta de dos etapas:

  1. Checkout — descarga el código del repositorio.
  2. Publish to Artifact Registry — ejecuta mvn deploy -DskipTests para publicar el JAR en Google Artifact Registry.
ParámetroValor
JDKJDK25 (tool Jenkins)
MavenMaven3 (tool Jenkins)
Repositorioeurope-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/qat-client/

12. Manejo de errores y logging

La librería no implementa ninguna estrategia propia de manejo de excepciones ni logging estructurado. Las excepciones de red o HTTP propagadas por RestClient (como RestClientResponseException) son responsabilidad del servicio consumidor, ya que ningún método de QatClient declara throws explícito. No hay configuración de logback ni de niveles de log específicos en la librería.

13. Notas y consideraciones

  • Cabecera Accept dinámica basada en substring de la URL: El interceptor de QatClientAutoConfiguration decide el valor de Accept comprobando si la URL contiene las cadenas documentmanagement/documents/entities/ORDER/download o /accept. Esta lógica basada en coincidencia de texto es frágil ante cambios futuros en las rutas (p. ej. si se añadiera un nuevo endpoint cuya ruta contuviera casualmente /accept), en lugar de una asociación explícita por método o por constante de ruta completa.

  • getOrderListByStateCode, getOrderList y getOrderListById comparten la misma ruta base: Los tres métodos apuntan a GET /api/ordermanagement/orders, diferenciándose únicamente en los parámetros de query enviados (order_state_codes+paginación, solo paginación, o order_ids). Refleja un único endpoint remoto con múltiples modos de uso, modelados como métodos Java distintos por claridad de la API del cliente.

  • AcceptOrderQtaRequest.Item.accepted vs. nombre del método acceptOrder: El campo se llama accepted (no accept), pese a que la clase se llama AcceptOrderQtaRequest — nomenclatura menor a tener en cuenta al construir el payload.

  • Estructura de OrdersQatResponse muy similar a otras integraciones del ecosistema: La jerarquía de campos (acceptance_decision_date, can_cancel, channel, commercial_id, currency_iso_code, customer...) coincide en gran medida con la de OrdersLiverpoolResponse (liverpool-client), sugiriendo que ambas integraciones comparten un formato de pedido subyacente similar (posible plataforma de marketplace común o plantilla de generación compartida entre clientes del ecosistema).

  • Sin tests implementados: El directorio src/test/java/com/hawkersco/ existe pero está vacío, sin ninguna clase de test. CLAUDE.md señala que no hay etapa de test en CI.

  • QatClientApplication.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.