terminado

This commit is contained in:
2026-02-08 18:50:48 +01:00
parent cc2d2ef193
commit fe4d180e2d
5 changed files with 72 additions and 575 deletions

View File

@ -398,13 +398,12 @@ public class skApiClient {
public Map<String, Object> checkPedidoEstado(Long presupuestoId, Locale locale) {
try {
String jsonResponse = performWithRetry(() -> {
String url = this.skApiUrl + "api/estado-pedido/" + presupuestoId;
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setBearerAuth(authService.getToken()); // token actualizado
headers.setBearerAuth(authService.getToken());
headers.setAccept(java.util.List.of(MediaType.APPLICATION_JSON));
HttpEntity<Void> entity = new HttpEntity<>(headers);
@ -420,19 +419,34 @@ public class skApiClient {
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(jsonResponse);
if (root.get("data") == null) {
throw new RuntimeException(
"Sin respuesta desde el servidor del proveedor");
// ✅ Si falta data, devolvemos mapa sin "estado" (o con estado=null pero con
// HashMap)
if (root == null || root.get("data") == null || root.get("data").isNull()) {
Map<String, Object> out = new HashMap<>();
out.put("message", "Respuesta sin campo 'data' desde el servidor del proveedor");
return out;
}
String estado = root.get("data").asText();
return Map.of(
"estado", estado);
return Map.of("estado", estado); // aquí NO es null, así que Map.of OK
} catch (HttpClientErrorException ex) {
if (ex.getStatusCode() == HttpStatus.NOT_FOUND) {
// ✅ 404: devolvemos mapa sin "estado" para evitar null en Map.of
Map<String, Object> out = new HashMap<>();
out.put("notFound", true);
out.put("message", "Orden de trabajo no encontrada para presupuestoId=" + presupuestoId);
return out;
}
throw ex;
} catch (JsonProcessingException e) {
// Fallback al 80% del ancho
return Map.of(
"estado", null);
// ✅ no parseable (HTML, debugbar, etc.)
Map<String, Object> out = new HashMap<>();
out.put("message", "Respuesta no-JSON o JSON inválido desde el proveedor");
return out;
}
}
@ -542,7 +556,7 @@ public class skApiClient {
}
public Boolean aceptarFerro(Long presupuestoId, Locale locale) {
String result = performWithRetry(() -> {
String url = this.skApiUrl + "api/aceptar-ferro/" + presupuestoId;
@ -576,9 +590,8 @@ public class skApiClient {
return Boolean.parseBoolean(result);
}
public Boolean cancelarPedido(Long pedidoId) {
String result = performWithRetry(() -> {
String url = this.skApiUrl + "api/cancelar-pedido/" + pedidoId;
@ -618,12 +631,21 @@ public class skApiClient {
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) {
// ✅ IMPORTANTe: si el segundo intento es 404, NO lo envuelvas
if (ex.getStatusCode() == HttpStatus.NOT_FOUND) {
throw ex;
}
// Si es otro 4xx/5xx, sí lo envolvemos
throw new RuntimeException("La autenticación ha fallado tras renovar el token.", ex);
}
}

View File

@ -3,6 +3,7 @@ package com.imprimelibros.erp.pedidos;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.stereotype.Service;
import java.util.List;
@ -25,18 +26,34 @@ public class PedidoEstadoService {
/**
* Ejecuta cada noche a las 4:00 AM
*/
@Transactional
// test @Scheduled(cron = "0 * * * * *")
@Scheduled(cron = "0 0 4 * * *")
public void actualizarEstadosPedidos() {
log.info("JOB actualizarEstadosPedidos iniciado");
List<PedidoLinea> pedidosLineas = pedidoLineaRepository.findPedidosLineasParaActualizarEstado();
log.info("Pedidos líneas a procesar: {}", pedidosLineas.size());
for (PedidoLinea linea : pedidosLineas) {
log.info("Actualizando estado pedidoLineaId={}", linea.getId());
try {
Map<String, Object> resultado = pedidoService.actualizarEstado(linea.getId(), Locale.getDefault());
if (!Boolean.TRUE.equals(resultado.get("success"))) {
log.error("Error al actualizar estado. pedidoLineaId={} message={}",
linea.getId(), resultado.get("message"));
} else {
String msg = String.valueOf(resultado.get("message"));
if (msg != null && msg.contains("Orden de trabajo no encontrada")) {
log.warn("OT no encontrada. pedidoLineaId={} message={}", linea.getId(), msg);
}
}
} catch (Exception ex) {
log.error("Excepción actualizando estado. pedidoLineaId={}", linea.getId(), ex);

View File

@ -24,10 +24,12 @@ import com.imprimelibros.erp.presupuesto.service.PresupuestoService;
import com.imprimelibros.erp.users.UserService;
import com.imprimelibros.erp.direcciones.DireccionService;
import com.imprimelibros.erp.externalApi.skApiClient;
import com.imprimelibros.erp.facturacion.FacturaDireccion;
import com.imprimelibros.erp.facturacion.dto.DireccionFacturacionDto;
import com.imprimelibros.erp.pedidos.PedidoLinea.Estado;
import org.springframework.http.HttpStatus;
import org.springframework.web.client.HttpClientErrorException;
@Service
public class PedidoService {
@ -341,14 +343,27 @@ public class PedidoService {
Map<String, Object> result = skApiClient.checkPedidoEstado(refExterna, locale);
if (result == null || result.get("estado") == null) {
if (result == null) {
return Map.of(
"success", false,
"message", messageSource.getMessage("pedido.errors.update-server-error", null, locale));
}
String estadoStr = String.valueOf(result.get("estado"));
if (Boolean.TRUE.equals(result.get("notFound"))) {
return Map.of(
"success", true,
"message", String.valueOf(result.getOrDefault("message", "OT no encontrada (404). Se omite.")));
}
Object estadoObj = result.get("estado");
if (estadoObj == null) {
return Map.of(
"success", false,
"message", messageSource.getMessage("pedido.errors.update-server-error", null, locale));
}
String estadoStr = String.valueOf(estadoObj);
PedidoLinea.Estado estadoSk;
try {
// si la API devuelve minúsculas tipo "produccion", esto funciona