Skip to main content

ECI Client

1. Descripción general

eci-client es una librería cliente (JAR) que actúa como fachada HTTP declarativa (@HttpExchange) sobre la API del marketplace ECI (El Corte Inglés), según la description de su pom.xml: "ECI client".

El proyecto no es un servicio desplegable ni contiene lógica de negocio propia: es una dependencia interna publicada en el registro de artefactos Maven de Hawkers, consumida por los microservicios del ecosistema que necesitan integrar pedidos y catálogo con el marketplace de ECI. Encapsula:

  • Autenticación mediante un header Authorization estático configurado por el consumidor (sin flujo OAuth2 ni renovación de token).
  • Operaciones declarativas sobre pedidos (consulta filtrada por estado/fecha, aceptación de líneas, actualización de tracking, confirmación de envío, confirmación de entrega, descarga de documentos).
  • Operaciones declarativas sobre ofertas (consulta paginada, actualización masiva, importación de stock vía fichero multipart).
  • Modelos de datos (DTO) para los payloads de petición/respuesta de ECI, con doble anotación Gson/Jackson.

Dentro del ecosistema de microservicios de Hawkers, eci-client cumple el mismo rol que otros clientes de marketplace (p. ej. auro-client, dynamics-client): aislar a los microservicios de negocio de los detalles de transporte HTTP y serialización específicos de la API externa de ECI.

2. Información técnica

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

3. Arquitectura y diseño

Estructura de paquetes bajo com.hawkersco.eciclient:

com.hawkersco.eciclient
├── EciClientApplication.java # @SpringBootApplication (arranque para pruebas locales)
├── client/
│ └── EciClient.java # @HttpExchange — único punto de integración: pedidos y ofertas
├── config/
│ └── EciClientConfig.java # @AutoConfiguration — bean EciClient con header Authorization fijo
└── pojo/ # DTOs de request/response (Gson + Jackson)
├── EciAcceptOrder
├── EciOrderResponse # modelo más extenso: Order, Customer, Address, OrderLine, Cancelation, Refund...
├── OffersEciRequest
├── OffersEciResponse
├── OffersEciResponseAlt # variante alternativa del modelo de ofertas (más campos: fulfillment, logisticClass...)
├── UpdateTrackingRequest
└── ValidateDelivery

EciClientConfig se registra como auto-configuración Spring Boot en META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports, de modo que cualquier microservicio que añada eci-client como dependencia obtiene el bean EciClient automáticamente, condicionado (@ConditionalOnProperty) a que existan las propiedades eci.auth.client.url y eci.credentials.key.

A diferencia de dynamics-client o auro-client, no hay interceptor de autenticación dinámica: el header Authorization se fija una única vez al construir el RestClient, con el valor de eci.credentials.key tal cual (no se antepone prefijo Bearer/bearer en el código).

Flujo principal

sequenceDiagram
participant Consumidor as Microservicio consumidor
participant EciClient
participant ECI as API ECI

Consumidor->>EciClient: getOrdersWaiting() / acceptOrder() / updateOffers() ...
EciClient->>ECI: petición HTTP con header Authorization fijo
ECI-->>EciClient: respuesta (JSON tipado o String/byte[])
EciClient-->>Consumidor: ResponseEntity<T>

4. Dependencias principales

DependenciaPropósito
spring-boot-starterNúcleo de Spring Boot y auto-configuración.
spring-webRestClient, HttpServiceProxyFactory y anotaciones @HttpExchange.
org.projectlombok:lombokGeneración de getters/setters/constructores en los DTO (@Data, @Getter/@Setter...).
com.fasterxml.jackson.core:jackson-annotationsAnotaciones Jackson (@JsonProperty) en los DTO.
com.google.code.gson:gsonAnotaciones/serialización Gson (@SerializedName) en los DTO.
com.google.cloud.artifactregistry:artifactregistry-maven-wagon (extensión de build)Publicación del JAR en Google Artifact Registry (distributionManagement).

No se listan dependencias de test más allá de spring-boot-starter-test (scope test): el proyecto no contiene clases de test.

5. API / Endpoints

No aplica como API REST propia. eci-client no expone endpoints; es una librería consumida como dependencia. EciClientApplication (@SpringBootApplication) existe únicamente como contexto de arranque para desarrollo/pruebas locales.

En su lugar, la interfaz EciClient declara las operaciones disponibles contra la API externa de ECI:

Método JavaHTTPRutaDescripción
getOrdersWaiting()GET/api/orders?order_state_codes=WAITING_ACCEPTANCEPedidos pendientes de aceptación.
getOrderListByStateCode(...)GET/api/ordersPedidos filtrados por order_state_codes, start_date, max, offset (paginado).
getAllOrderList(...)GET/api/ordersTodos los pedidos desde start_date, paginado con max/offset.
acceptOrder(orderId, EciAcceptOrder)PUT/api/orders/{order_id}/acceptAcepta/rechaza líneas de un pedido (order_lines[].accepted).
updateTracking(orderId, UpdateTrackingRequest)PUT/api/orders/{order_id}/trackingActualiza transportista y número de seguimiento del pedido.
validateShipment(orderId)PUT/api/orders/{order_id}/shipMarca el pedido como enviado.
confirmDelivery(orderId, ValidateDelivery)PUT/api/orders/{order_id}/additional_fieldsConfirma la entrega mediante campos adicionales (p. ej. fecha de entrega).
downloadDocumentsByOrderList(orderIdList)GET/api/orders/documents/downloadDescarga documentos (etiquetas) de una lista de pedidos, devuelve byte[].
getOffers(max, offset)GET/api/offersOfertas paginadas, deserializadas a OffersEciResponse.
getOffersString(max, offset)GET/api/offersOfertas paginadas como JSON crudo (String).
updateOffers(json)POST/api/offersActualización masiva de ofertas mediante payload JSON en crudo.
importStockFile(file)POST/api/offers/stock/importsImporta niveles de stock desde un fichero (multipart/form-data).

Ejemplo de payload de aceptación de pedido (EciAcceptOrder):

{
"order_lines": [
{ "id": "12345", "accepted": true },
{ "id": "12346", "accepted": false }
]
}

Ejemplo de payload de actualización de tracking (UpdateTrackingRequest):

{
"carrier_code": "SEUR",
"carrier_name": "SEUR",
"carrier_url": "https://www.seur.com/tracking",
"tracking_number": "1234567890"
}

6. Integraciones externas

SistemaProtocoloDirecciónDetalle
Marketplace ECI — API de pedidos y ofertasHTTPS, JSON (y multipart/form-data para importación de stock)SalienteÚnico sistema externo integrado: consulta/gestión de pedidos (/api/orders/*) y ofertas (/api/offers/*).

No hay otras integraciones (colas, SFTP, Dynamics 365, etc.) en este proyecto.

7. Configuración

El proyecto no incluye application.properties/application.yml propio (es una librería); las propiedades deben ser definidas por el microservicio consumidor:

ClaveDescripciónEjemplo de valor
eci.auth.client.urlURL base de la API de ECI.https://api.eci-marketplace.com
eci.credentials.keyValor completo enviado en el header Authorization (token/API key).********

Si falta alguna de las dos propiedades, el bean EciClient no se registra (@ConditionalOnProperty), sin error de arranque explícito.

8. Persistencia

No aplica. El proyecto no gestiona base de datos ni realiza persistencia propia; todos los DTO son objetos de transporte para las llamadas HTTP a la API de ECI.

9. Procesos programados y mensajería

No aplica. No existen @Scheduled, @KafkaListener ni @RabbitListener en el código. La ejecución de las operaciones (consulta/actualización de pedidos y ofertas) es responsabilidad del microservicio consumidor, que decide cuándo invocarlas.

10. Ejecución en local

Requisitos previos:

  • JDK 25.
  • Maven Wrapper (./mvnw, incluido en el repositorio).
  • Credenciales válidas del marketplace ECI (proporcionadas por el consumidor vía las propiedades de la sección 7).

Comandos:

# Build e instalación en repositorio Maven local
./mvnw clean install

# Empaquetado sin instalar
./mvnw clean package

# Build sin tests (equivalente al comportamiento de CI)
./mvnw clean install -DskipTests

# Análisis SonarQube
./mvnw sonar:sonar

Al ser una librería, no se "levanta" como servicio independiente ni expone actuator/health. Para probarla en local es necesario:

  1. Instalarla en el repositorio Maven local (./mvnw clean install) o consumir la versión publicada en Artifact Registry.
  2. Añadirla como dependencia en un microservicio consumidor que defina eci.auth.client.url y eci.credentials.key.
  3. Verificar el correcto arranque comprobando que el bean EciClient se inyecta sin error en el microservicio consumidor.

11. Despliegue

El proyecto se publica como artefacto Maven en Google Artifact Registry (artifactregistry://europe-west3-maven.pkg.dev/pi-saldum/pi-repo-maven), no se despliega como contenedor ni servicio.

El Jenkinsfile define un pipeline de dos etapas:

  1. Checkoutcheckout scm.
  2. Publish to Artifact Registrymvn deploy -DskipTests.

Job de Jenkins del proyecto: https://jenkins-pi.hawkersco.net/job/eci-client/

12. Manejo de errores y logging

  • No hay manejo de excepciones propio: los métodos de EciClient devuelven ResponseEntity<T> directamente (con String, byte[] o DTOs tipados), por lo que los errores HTTP de ECI se propagan tal cual al consumidor a través del código de estado y el cuerpo de la respuesta.
  • No se implementa lógica de reintento ni circuit breaker: es responsabilidad del microservicio consumidor.
  • No hay un @ControllerAdvice ni códigos de error propios, al no exponer API REST propia.
  • No hay configuración de logging específica en el proyecto (ni SLF4J ni java.util.logging configurados); hereda la configuración de logs del consumidor.

13. Notas y consideraciones

  • El header Authorization se construye con el valor íntegro de eci.credentials.key sin prefijo (Bearer /bearer ) añadido en código; el prefijo, si es necesario, debe incluirse ya en el valor de la propiedad configurada por el consumidor.
  • Existen dos modelos distintos para la respuesta de ofertas (OffersEciResponse y OffersEciResponseAlt), con estructuras de campos diferentes (p. ej. OffersEciResponseAlt añade fulfillment, logisticClass, allPrices, channels...). El método getOffers usa OffersEciResponse; OffersEciResponseAlt no está referenciado desde ningún método de EciClient en este repositorio — su propósito exacto (¿versión de API distinta? ¿modelo legado?) queda pendiente de verificar.
  • Todos los DTO llevan simultáneamente anotaciones Gson (@SerializedName) y Jackson (@JsonProperty); al añadir campos nuevos hay que mantener ambas anotaciones sincronizadas, como indica el propio CLAUDE.md del proyecto.
  • EciOrderResponse es el DTO más extenso del proyecto, con múltiples clases anidadas (Order, Customer, Address, OrderLine, Cancelation, Refund, Promotions...) que reflejan fielmente el modelo de datos de pedidos de ECI.
  • ValidateDelivery.OrderAdditionalFields.value es de tipo java.util.Date; a diferencia del resto de campos de fecha del proyecto, que se modelan como String. Comportamiento a tener en cuenta si se depuran problemas de formato de fecha en la confirmación de entrega.
  • No existen tests unitarios en el repositorio (solo la dependencia spring-boot-starter-test, sin uso); el flag -DskipTests en Jenkins refleja esto directamente, no es una omisión de CI.