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. Checkout — checkout scm.
  2. Publish to Artifact Registry — mvn 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.