Files
erp-imprimelibros/src/main/java/com/imprimelibros/erp/externalApi/skApiClient.java
2025-10-12 21:42:04 +02:00

235 lines
9.6 KiB
Java

package com.imprimelibros.erp.externalApi;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.imprimelibros.erp.configuracion.margenes_presupuestos.MargenPresupuesto;
import com.imprimelibros.erp.configuracion.margenes_presupuestos.MargenPresupuestoDao;
import com.imprimelibros.erp.presupuesto.dto.Presupuesto.TipoCubierta;
import com.imprimelibros.erp.presupuesto.dto.Presupuesto.TipoEncuadernacion;
import java.util.Map;
import java.util.HashMap;
import java.util.List;
import java.util.function.Supplier;
@Service
public class skApiClient {
@Value("${safekat.api.url}")
private String skApiUrl;
private final AuthService authService;
private final RestTemplate restTemplate;
private final MargenPresupuestoDao margenPresupuestoDao;
public skApiClient(AuthService authService, MargenPresupuestoDao margenPresupuestoDao) {
this.authService = authService;
this.restTemplate = new RestTemplate();
this.margenPresupuestoDao = margenPresupuestoDao;
}
public String getPrice(Map<String, Object> requestBody, TipoEncuadernacion tipoEncuadernacion,
TipoCubierta tipoCubierta) {
return performWithRetry(() -> {
String url = this.skApiUrl + "api/calcular";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setBearerAuth(authService.getToken());
HttpEntity<Map<String, Object>> entity = new HttpEntity<>(requestBody, headers);
ResponseEntity<String> response = restTemplate.exchange(
url,
HttpMethod.POST,
entity,
String.class);
try {
Map<String, Object> responseBody = new ObjectMapper().readValue(
response.getBody(),
new TypeReference<Map<String, Object>>() {
});
ObjectMapper mapper = new ObjectMapper();
if (responseBody.get("error") == null) {
Object dataObj = responseBody.get("data");
if (dataObj instanceof Map) {
@SuppressWarnings("unchecked")
Map<String, Object> data = (Map<String, Object>) dataObj;
List<Integer> tiradas = mapper.convertValue(
data.get("tiradas"), new TypeReference<List<Integer>>() {
});
List<Double> precios = mapper.convertValue(
data.get("precios"), new TypeReference<List<Double>>() {
});
for (int i = 0; i < tiradas.size(); i++) {
int tirada = tiradas.get(i);
MargenPresupuesto margen = margenPresupuestoDao.findByTipoAndTirada(
tipoEncuadernacion, tipoCubierta, tirada);
if (margen != null) {
double margenValue = calcularMargen(
tirada,
margen.getTiradaMin(),
margen.getTiradaMax(),
margen.getMargenMax(),
margen.getMargenMin());
double nuevoPrecio = precios.get(i) * (1 + margenValue / 100.0);
precios.set(i, Math.round(nuevoPrecio * 10000.0) / 10000.0); // redondear a 2 decimales
} else {
System.out.println("No se encontró margen para tirada " + tirada);
}
}
// <-- Clave: sustituir la lista en el map que se devuelve
data.put("precios", precios);
// (tiradas no cambia, pero si la modificases: data.put("tiradas", tiradas);)
}
return mapper.writeValueAsString(Map.of("data", responseBody.get("data")));
} else {
return "{\"error\": 1}";
}
} catch (JsonProcessingException e) {
e.printStackTrace();
return "{\"error\": 1}";
}
});
}
public Integer getMaxSolapas(Map<String, Object> requestBody) {
try {
String jsonResponse = performWithRetry(() -> {
String url = this.skApiUrl + "api/calcular-solapas";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setBearerAuth(authService.getToken()); // token actualizado
Map<String, Object> data = new HashMap<>();
data.put("clienteId", requestBody.get("clienteId"));
data.put("tamanio", requestBody.get("tamanio"));
data.put("tirada", requestBody.get("tirada"));
data.put("paginas", requestBody.get("paginas"));
data.put("paginasColor", requestBody.get("paginasColor"));
data.put("papelInteriorDiferente", 0);
data.put("paginasCuadernillo", requestBody.get("paginasCuadernillo"));
data.put("tipo", requestBody.get("tipo"));
data.put("isColor", requestBody.get("isColor"));
data.put("isHq", requestBody.get("isHq"));
data.put("interior", requestBody.get("interior"));
HttpEntity<Map<String, Object>> entity = new HttpEntity<>(data, headers);
ResponseEntity<String> response = restTemplate.exchange(
url,
HttpMethod.POST,
entity,
String.class);
return response.getBody();
});
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(jsonResponse);
if (root.get("data") == null || !root.get("data").isInt()) {
throw new RuntimeException("Respuesta inesperada de calcular-solapas: " + jsonResponse);
}
return root.get("data").asInt();
} catch (JsonProcessingException e) {
// Fallback al 80% del ancho
Map<String, Object> tamanio = new ObjectMapper().convertValue(
requestBody.get("tamanio"),
new TypeReference<Map<String, Object>>() {
});
if (tamanio == null || tamanio.get("ancho") == null)
throw new RuntimeException("Tamaño no válido en la solicitud: " + requestBody);
else {
int ancho = (int) tamanio.get("ancho");
return (int) Math.floor(ancho * 0.8); // 80% del ancho
}
}
}
public Double getRetractilado(Map<String, Object> requestBody) {
String value = performWithRetry(() -> {
String url = this.skApiUrl + "api/calcular-retractilado";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setBearerAuth(authService.getToken());
HttpEntity<Map<String, Object>> entity = new HttpEntity<>(requestBody, headers);
ResponseEntity<String> response = restTemplate.exchange(
url,
HttpMethod.POST,
entity,
String.class);
try {
Map<String, Object> responseBody = new ObjectMapper().readValue(
response.getBody(),
new TypeReference<Map<String, Object>>() {
});
return responseBody.get("data").toString();
} catch (JsonProcessingException e) {
e.printStackTrace();
return "0.0"; // Fallback en caso de error
}
});
try {
return Double.parseDouble(value);
} catch (NumberFormatException e) {
throw new RuntimeException("Error al parsear el valor de retractilado: " + value, e);
}
}
/******************
* PRIVATE METHODS
******************/
private String performWithRetry(Supplier<String> request) {
try {
return request.get();
} catch (HttpClientErrorException.Unauthorized e) {
// Token expirado, renovar y reintentar
authService.invalidateToken();
try {
return request.get(); // segundo intento
} catch (HttpClientErrorException ex) {
throw new RuntimeException("La autenticación ha fallado tras renovar el token.", ex);
}
}
}
private static double calcularMargen(
int tirada, int tiradaMin, int tiradaMax,
double margenMax, double margenMin) {
if (tirada <= tiradaMin)
return margenMax;
if (tirada >= tiradaMax)
return margenMin;
return margenMax - ((double) (tirada - tiradaMin) / (tiradaMax - tiradaMin)) * (margenMax - margenMin);
}
}