diff --git a/src/main/java/com/imprimelibros/erp/common/web/IpUtils.java b/src/main/java/com/imprimelibros/erp/common/web/IpUtils.java index 41068c8..e1930bb 100644 --- a/src/main/java/com/imprimelibros/erp/common/web/IpUtils.java +++ b/src/main/java/com/imprimelibros/erp/common/web/IpUtils.java @@ -2,32 +2,36 @@ package com.imprimelibros.erp.common.web; import jakarta.servlet.http.HttpServletRequest; -import java.util.Arrays; -import java.util.List; - -public final class IpUtils { - private IpUtils() {} - - private static final List HEADERS = Arrays.asList( - "X-Forwarded-For", - "X-Real-IP", - "CF-Connecting-IP", - "True-Client-IP", - "X-Client-IP", - "X-Forwarded", - "Forwarded-For", - "Forwarded" - ); +public class IpUtils { public static String getClientIp(HttpServletRequest request) { - for (String h : HEADERS) { - String v = request.getHeader(h); - if (v != null && !v.isBlank() && !"unknown".equalsIgnoreCase(v)) { - // X-Forwarded-For puede traer lista: "client, proxy1, proxy2" - String first = v.split(",")[0].trim(); - if (!first.isBlank()) return first; + String[] headers = { + "X-Forwarded-For", + "Proxy-Client-IP", + "WL-Proxy-Client-IP", + "HTTP_X_FORWARDED_FOR", + "HTTP_X_FORWARDED", + "HTTP_X_CLUSTER_CLIENT_IP", + "HTTP_CLIENT_IP", + "HTTP_FORWARDED_FOR", + "HTTP_FORWARDED", + "HTTP_VIA", + "REMOTE_ADDR" + }; + + for (String header : headers) { + String ip = request.getHeader(header); + if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) { + // Si hay varios (X-Forwarded-For), toma el primero + return ip.split(",")[0]; } } - return request.getRemoteAddr(); + + // Fallback + String ip = request.getRemoteAddr(); + if ("0:0:0:0:0:0:0:1".equals(ip) || "::1".equals(ip)) { + return "127.0.0.1"; + } + return ip; } } diff --git a/src/main/java/com/imprimelibros/erp/presupuesto/PresupuestoController.java b/src/main/java/com/imprimelibros/erp/presupuesto/PresupuestoController.java index e4f34be..81564fc 100644 --- a/src/main/java/com/imprimelibros/erp/presupuesto/PresupuestoController.java +++ b/src/main/java/com/imprimelibros/erp/presupuesto/PresupuestoController.java @@ -51,6 +51,7 @@ import com.imprimelibros.erp.users.UserDao; import com.imprimelibros.erp.users.UserDetailsImpl; import com.imprimelibros.erp.presupuesto.service.PresupuestoFormDataMapper; import com.imprimelibros.erp.presupuesto.service.PresupuestoFormDataMapper.PresupuestoFormDataDto; +import com.imprimelibros.erp.common.web.IpUtils; import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.ConstraintViolation; @@ -482,7 +483,7 @@ public class PresupuestoController { List> serviciosList = (List>) body.getOrDefault("servicios", List.of()); String sessionId = request.getSession(true).getId(); - String ip = request.getRemoteAddr(); + String ip = IpUtils.getClientIp(request); var resumen = presupuestoService.getResumen(p, serviciosList, save, mode, locale, sessionId, ip); diff --git a/src/main/java/com/imprimelibros/erp/presupuesto/dto/Presupuesto.java b/src/main/java/com/imprimelibros/erp/presupuesto/dto/Presupuesto.java index da150ba..06d2a8e 100644 --- a/src/main/java/com/imprimelibros/erp/presupuesto/dto/Presupuesto.java +++ b/src/main/java/com/imprimelibros/erp/presupuesto/dto/Presupuesto.java @@ -4,6 +4,7 @@ import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import com.imprimelibros.erp.presupuesto.validation.ConsistentTiradas; +import com.imprimelibros.erp.presupuesto.validation.PaginasCosido; import com.imprimelibros.erp.presupuesto.validation.Par; import com.imprimelibros.erp.presupuesto.validation.PresupuestoValidationGroups; import com.imprimelibros.erp.presupuesto.validation.Tamanio; @@ -22,6 +23,7 @@ import java.math.BigDecimal; import com.imprimelibros.erp.users.User; @ConsistentTiradas(groups = PresupuestoValidationGroups.DatosGenerales.class) +@PaginasCosido(groups = PresupuestoValidationGroups.DatosGenerales.class) @Tamanio(groups = PresupuestoValidationGroups.DatosGenerales.class) @EntityListeners(AuditingEntityListener.class) @Entity diff --git a/src/main/java/com/imprimelibros/erp/presupuesto/service/PresupuestoService.java b/src/main/java/com/imprimelibros/erp/presupuesto/service/PresupuestoService.java index cb297c2..35b9b2c 100644 --- a/src/main/java/com/imprimelibros/erp/presupuesto/service/PresupuestoService.java +++ b/src/main/java/com/imprimelibros/erp/presupuesto/service/PresupuestoService.java @@ -24,6 +24,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import java.math.BigDecimal; import java.math.RoundingMode; +import com.imprimelibros.erp.common.web.IpUtils; import com.imprimelibros.erp.configurationERP.VariableService; import com.imprimelibros.erp.presupuesto.GeoIpService; import com.imprimelibros.erp.presupuesto.PresupuestoRepository; @@ -845,6 +846,8 @@ public class PresupuestoService { if (mode.equals("public")) { presupuesto = getDatosLocalizacion(presupuesto, sessionId, ip); + presupuesto.setOrigen(Presupuesto.Origen.publico); + presupuesto = this.getDatosLocalizacion(presupuesto, sessionId, ip); } else presupuesto.setOrigen(Presupuesto.Origen.privado); @@ -962,8 +965,10 @@ public class PresupuestoService { BigDecimal precioTotalTirada = BigDecimal.valueOf(precioUnit) .multiply(BigDecimal.valueOf(cantidad)) .setScale(2, RoundingMode.HALF_UP); - if( hayDepositoLegal ){ - precioTotalTirada = precioTotalTirada.add(BigDecimal.valueOf(precioUnit).multiply(BigDecimal.valueOf(4))).setScale(6, RoundingMode.HALF_UP); + if (hayDepositoLegal) { + precioTotalTirada = precioTotalTirada + .add(BigDecimal.valueOf(precioUnit).multiply(BigDecimal.valueOf(4))) + .setScale(6, RoundingMode.HALF_UP); } // servicios_total @@ -1020,7 +1025,7 @@ public class PresupuestoService { // Si la entrega es en peninsula, se mira el valor del iva // Canarias y paises UE no llevan IVA - if (presupuesto.getEntregaTipo() == Presupuesto.Entrega.peninsula){ + if (presupuesto.getEntregaTipo() == Presupuesto.Entrega.peninsula) { // Si el iva es reducido, el precio de la tirada y el del prototipo llevan IVA // 4% if (presupuesto.getIvaReducido()) { @@ -1035,7 +1040,7 @@ public class PresupuestoService { BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP); } - } + } baseImponible = baseImponible.add(serviciosTotal); BigDecimal totalConIva = baseImponible.add(ivaImporte21).add(ivaImporte4); @@ -1120,7 +1125,7 @@ public class PresupuestoService { if (mode.equals("public")) { presupuesto.setOrigen(Presupuesto.Origen.publico); String sessionId = request.getSession(true).getId(); - String ip = request.getRemoteAddr(); + String ip = IpUtils.getClientIp(request); presupuesto = this.getDatosLocalizacion(presupuesto, sessionId, ip); if (id != null) { @@ -1178,6 +1183,7 @@ public class PresupuestoService { return true; } + // ======================================================================= // Métodos privados // ======================================================================= diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 35978a9..66f623c 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -11,8 +11,8 @@ logging.level.org.springframework=ERROR # # Database Configuration # -#spring.datasource.url=jdbc:mysql://localhost:3309/imprimelibros -spring.datasource.url=jdbc:mysql://127.0.0.1:3309/imprimelibros?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Europe/Madrid&characterEncoding=utf8 +spring.datasource.url=jdbc:mysql://localhost:3309/imprimelibros +#spring.datasource.url=jdbc:mysql://127.0.0.1:3309/imprimelibros?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Europe/Madrid&characterEncoding=utf8 spring.datasource.username=imprimelibros_user spring.datasource.password=om91irrDctd spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver @@ -24,8 +24,8 @@ spring.jpa.show-sql=false # # Safekat API Configuration # -#safekat.api.url=http://localhost:8000/ -safekat.api.url=https://erp-dev.safekat.es/ +safekat.api.url=http://localhost:8000/ +#safekat.api.url=https://erp-dev.safekat.es/ safekat.api.email=imnavajas@coit.es safekat.api.password=Safekat2024 diff --git a/src/main/resources/i18n/presupuesto_es.properties b/src/main/resources/i18n/presupuesto_es.properties index bf7f2c8..8d69eaf 100644 --- a/src/main/resources/i18n/presupuesto_es.properties +++ b/src/main/resources/i18n/presupuesto_es.properties @@ -312,6 +312,7 @@ presupuesto.errores.paginasNegro.required=El número de páginas en negro es obl presupuesto.errores.paginasNegro.par=El número de páginas en negro debe ser par presupuesto.errores.paginasColor.required=El número de páginas en color es obligatorio presupuesto.errores.paginasColor.par=El número de páginas en color debe ser par +presupuesto.errores.tipo-paginas-cosido=Para encuadernación cosido, sólo se pueden seleccionar o bien páginas a color o páginas en blanco y negro. No se pueden mezclar. presupuesto.errores.tipo-encuadernacion=Seleccione el tipo de libro presupuesto.errores.ancho=El ancho no puede estar vacío presupuesto.errores.ancho.min_max=El ancho tiene que estar en el rango [{0}, {1}] mm;