diff --git a/src/main/java/com/imprimelibros/erp/presupuesto/classes/PresupuestoMarcapaginas.java b/src/main/java/com/imprimelibros/erp/presupuesto/classes/PresupuestoMarcapaginas.java new file mode 100644 index 0000000..28fa75c --- /dev/null +++ b/src/main/java/com/imprimelibros/erp/presupuesto/classes/PresupuestoMarcapaginas.java @@ -0,0 +1,57 @@ +package com.imprimelibros.erp.presupuesto.classes; + +import static com.imprimelibros.erp.presupuesto.marcapaginas.Marcapaginas.Papeles; +import static com.imprimelibros.erp.presupuesto.marcapaginas.Marcapaginas.Acabado; +import static com.imprimelibros.erp.presupuesto.marcapaginas.Marcapaginas.Tamanios; +import static com.imprimelibros.erp.presupuesto.marcapaginas.Marcapaginas.Caras_Impresion; + +import jakarta.validation.constraints.Min; + +public class PresupuestoMarcapaginas { + + @Min(value = 100, message = "{validation.min}") + private Integer unidades = 100; + private Tamanios tamanio = Tamanios._50x140_; + private Caras_Impresion carasImpresion = Caras_Impresion.una_cara; + private Papeles papel = Papeles.cartulina_grafica; + private Integer gramaje = 300; + private Acabado acabado = Acabado.ninguno; + + + public Integer getUnidades() { + return unidades; + } + public void setUnidades(Integer unidades) { + this.unidades = unidades; + } + public Tamanios getTamanio() { + return tamanio; + } + public void setTamanio(Tamanios tamanio) { + this.tamanio = tamanio; + } + public Caras_Impresion getCarasImpresion() { + return carasImpresion; + } + public void setCarasImpresion(Caras_Impresion carasImpresion) { + this.carasImpresion = carasImpresion; + } + public Papeles getPapel() { + return papel; + } + public void setPapel(Papeles papel) { + this.papel = papel; + } + public Integer getGramaje() { + return gramaje; + } + public void setGramaje(Integer gramaje) { + this.gramaje = gramaje; + } + public Acabado getAcabado() { + return acabado; + } + public void setAcabado(Acabado acabado) { + this.acabado = acabado; + } +} diff --git a/src/main/java/com/imprimelibros/erp/presupuesto/marcapaginas/Marcapaginas.java b/src/main/java/com/imprimelibros/erp/presupuesto/marcapaginas/Marcapaginas.java new file mode 100644 index 0000000..4eaef57 --- /dev/null +++ b/src/main/java/com/imprimelibros/erp/presupuesto/marcapaginas/Marcapaginas.java @@ -0,0 +1,154 @@ +package com.imprimelibros.erp.presupuesto.marcapaginas; + +import jakarta.validation.constraints.NotNull; +import jakarta.persistence.*; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; + +@Entity +@Table(name = "marcapaginas") +public class Marcapaginas { + + public enum Acabado{ + ninguno, + plastificado_brillo_1c, + plastificado_brillo_2c, + plastificado_mate_1c, + plastificado_mate_2c + }; + + public enum Tamanios{ + _50x140_, _50x170_, _50x210_ + }; + + public enum Papeles{ + cartulina_grafica, estucado_mate + }; + + public enum Caras_Impresion{ + una_cara, dos_caras + }; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @NotNull(message = "{validation.required}") + @Enumerated(EnumType.STRING) + private Caras_Impresion carasImpresion = Caras_Impresion.una_cara; + + @NotNull(message = "{validation.required}") + @Enumerated(EnumType.STRING) + private Tamanios tamanio = Tamanios._50x140_; + + @NotNull(message = "{validation.required}") + @Enumerated(EnumType.STRING) + private Papeles papel = Papeles.cartulina_grafica; + + @NotNull(message = "{validation.required}") + private Integer gramaje = 300; + + @NotNull(message = "{validation.required}") + @Enumerated(EnumType.STRING) + private Acabado acabado = Acabado.ninguno; + + @Min(value = 100, message = "{validation.min}") + @NotNull(message = "{validation.required}") + private Integer unidades_min = 100; + + @Min(value = 101, message = "{validation.min}") + @NotNull(message = "{validation.required}") + private Integer unidades_max = 5000; + + @NotNull(message = "{validation.required}") + private Double precio_unidades_min; + + @NotNull(message = "{validation.required}") + private Double precio_unidades_max; + + @NotNull(message = "{validation.required}") + @Min(value = 0, message = "{validation.min}") + @Max(value = 300, message = "{validation.max}") + + private Integer margen_unidades_min = 0; + + @NotNull(message = "{validation.required}") + @Min(value = 0, message = "{validation.min}") + @Max(value = 300, message = "{validation.max}") + private Integer margen_unidades_max = 0; + + /* Getters and Setters */ + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + public Caras_Impresion getCarasImpresion() { + return carasImpresion; + } + public void setCarasImpresion(Caras_Impresion carasImpresion) { + this.carasImpresion = carasImpresion; + } + public Tamanios getTamanio() { + return tamanio; + } + public void setTamanio(Tamanios tamanio) { + this.tamanio = tamanio; + } + public Papeles getPapel() { + return papel; + } + public void setPapel(Papeles papel) { + this.papel = papel; + } + public Integer getGramaje() { + return gramaje; + } + public void setGramaje(Integer gramaje) { + this.gramaje = gramaje; + } + public Acabado getAcabado() { + return acabado; + } + public void setAcabado(Acabado acabado) { + this.acabado = acabado; + } + public Integer getUnidades_min() { + return unidades_min; + } + public void setUnidades_min(Integer unidades_min) { + this.unidades_min = unidades_min; + } + public Integer getUnidades_max() { + return unidades_max; + } + public void setUnidades_max(Integer unidades_max) { + this.unidades_max = unidades_max; + } + public Double getPrecio_unidades_min() { + return precio_unidades_min; + } + public void setPrecio_unidades_min(Double precio_unidades_min) { + this.precio_unidades_min = precio_unidades_min; + } + public Double getPrecio_unidades_max() { + return precio_unidades_max; + } + public void setPrecio_unidades_max(Double precio_unidades_max) { + this.precio_unidades_max = precio_unidades_max; + } + public Integer getMargen_unidades_min() { + return margen_unidades_min; + } + public void setMargen_unidades_min(Integer margen_unidades_min) { + this.margen_unidades_min = margen_unidades_min; + } + public Integer getMargen_unidades_max() { + return margen_unidades_max; + } + public void setMargen_unidades_max(Integer margen_unidades_max) { + this.margen_unidades_max = margen_unidades_max; + } + +} diff --git a/src/main/java/com/imprimelibros/erp/presupuesto/marcapaginas/MarcapaginasRepository.java b/src/main/java/com/imprimelibros/erp/presupuesto/marcapaginas/MarcapaginasRepository.java new file mode 100644 index 0000000..33a6482 --- /dev/null +++ b/src/main/java/com/imprimelibros/erp/presupuesto/marcapaginas/MarcapaginasRepository.java @@ -0,0 +1,32 @@ +package com.imprimelibros.erp.presupuesto.marcapaginas; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import com.imprimelibros.erp.presupuesto.classes.PresupuestoMarcapaginas; + +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import java.util.List; + +@Repository +public interface MarcapaginasRepository extends JpaRepository { + + @Query(""" + SELECT m + FROM Marcapaginas m + WHERE m.tamanio = :#{#p.tamanio} + AND m.carasImpresion = :#{#p.carasImpresion} + AND m.papel = :#{#p.papel} + AND m.gramaje = :#{#p.gramaje} + AND m.acabado = :#{#p.acabado} + AND m.unidades_min <= :#{#p.unidades} + ORDER BY + CASE + WHEN :#{#p.unidades} BETWEEN m.unidades_min AND m.unidades_max THEN 0 + ELSE 1 + END, + m.unidades_max DESC + """) + List findPrecios(@Param("p") PresupuestoMarcapaginas p); +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 8ace703..6ffb606 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -4,6 +4,13 @@ logging.level.org.springframework.security=DEBUG logging.level.root=WARN logging.level.org.springframework=ERROR +#debug JPA / Hibernate +#spring.jpa.show-sql=true +#logging.level.org.hibernate.SQL=DEBUG +#logging.level.org.hibernate.orm.jdbc.bind=TRACE +#spring.jpa.properties.hibernate.format_sql=true + + 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 diff --git a/src/main/resources/i18n/presupuesto_es.properties b/src/main/resources/i18n/presupuesto_es.properties index 1e34b44..1fd2a74 100644 --- a/src/main/resources/i18n/presupuesto_es.properties +++ b/src/main/resources/i18n/presupuesto_es.properties @@ -88,6 +88,7 @@ presupuesto.cabezada-roja-amarilla=Roja-Amarilla presupuesto.papel-cubierta=Papel cubierta presupuesto.papel-cubierta-descripcion=Seleccione el papel para la cubierta presupuesto.cartulina-grafica-cubierta=Cartulina gráfica estucada a una cara +presupuesto.cartulina-grafica=Cartulina gráfica presupuesto.estucado-mate-cubierta=Estucado mate presupuesto.gramaje-cubierta=Gramaje cubierta presupuesto.gramaje-cubierta-descripcion=Seleccione el gramaje para la cubierta @@ -103,7 +104,9 @@ presupuesto.acabado-cubierta-descripcion=Seleccione el acabado para la cubierta presupuesto.acabado-cubierta-aviso=La falta de plastificado en la cubierta puede comprometer su calidad, ya que aumenta el riesgo de agrietamiento en los pliegues o hendidos, afectando su apariencia y resistencia. presupuesto.acabado-ninguno=Sin acabado presupuesto.acabado-plastificado-brillo-1c=Plastificado Brillo 1/C +presupuesto.acabado-plastificado-brillo-2c=Plastificado Brillo 2/C presupuesto.acabado-plastificado-mate-1c=Plastificado Mate 1/C +presupuesto.acabado-plastificado-mate-2c=Plastificado Mate 2/C presupuesto.acabado-plastificado-mate-1c-antirrayado=Plastificado Mate 1/C Antirrayado presupuesto.acabado-plastificado-mate-uvi=Plastificado Mate 1/C + Reserva UVI presupuesto.acabado-plastificado-mate-uvi3d=Plastificado Mate 1/C + Reserva UVI 3D diff --git a/src/test/java/com/imprimelibros/erp/presupuestoMarcapaginasTest.java b/src/test/java/com/imprimelibros/erp/presupuestoMarcapaginasTest.java new file mode 100644 index 0000000..f3c2ad4 --- /dev/null +++ b/src/test/java/com/imprimelibros/erp/presupuestoMarcapaginasTest.java @@ -0,0 +1,136 @@ +package com.imprimelibros.erp; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.Map; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import java.util.Locale; + +import com.imprimelibros.erp.presupuesto.PresupuestoService; +import com.imprimelibros.erp.presupuesto.classes.PresupuestoMarcapaginas; +import com.imprimelibros.erp.presupuesto.marcapaginas.Marcapaginas; + +import com.imprimelibros.erp.presupuesto.marcapaginas.MarcapaginasRepository; + +@SpringBootTest +class presupuestoMarcapaginasTest { + + @Autowired + protected PresupuestoService presupuestoService; + + @Autowired + protected MarcapaginasRepository marcapaginasRepository; + + private static final Logger log = LoggerFactory.getLogger(presupuestoMarcapaginasTest.class); + + @Test + void testCalculoMaquetacion() { + Map resultado = this.test(); + + System.out.println("Resultado:"); + System.out.println(resultado); + log.info("📦 Resultado: {}", resultado); + + assertNotNull(resultado, "El resultado no debe ser null"); + assertFalse(resultado.containsKey("error"), "El resultado no debe contener error"); + // assertFalse((Double)resultado.get("precio") == 0.0, "El precio debe ser mayor + // que 0"); + } + + public Map test() { + + PresupuestoMarcapaginas presupuestoMarcapaginas = new PresupuestoMarcapaginas(); + presupuestoMarcapaginas.setUnidades(10000); + presupuestoMarcapaginas.setTamanio(Marcapaginas.Tamanios._50x140_); + presupuestoMarcapaginas.setAcabado(Marcapaginas.Acabado.ninguno); + presupuestoMarcapaginas.setCarasImpresion(Marcapaginas.Caras_Impresion.una_cara); + presupuestoMarcapaginas.setPapel(Marcapaginas.Papeles.cartulina_grafica); + presupuestoMarcapaginas.setGramaje(300); + + Locale locale = Locale.getDefault(); + + List m = marcapaginasRepository.findPrecios(presupuestoMarcapaginas); + if (m.isEmpty() || m.get(0) == null) { + System.out.println( + "⚠️ No se han encontrado precios para el presupuesto de marcapáginas: " + presupuestoMarcapaginas); + return Map.of("error", "No se han encontrado precios para el presupuesto de marcapáginas"); + } + + Marcapaginas marcapaginas = m.get(0); + + if (marcapaginas.getUnidades_max() >= presupuestoMarcapaginas.getUnidades()) { + + BigDecimal data = BigDecimal.ZERO; + Double precio = marcapaginas.getPrecio_unidades_min() + + (presupuestoMarcapaginas.getUnidades() - marcapaginas.getUnidades_min()) + * (marcapaginas.getPrecio_unidades_max() - marcapaginas.getPrecio_unidades_min()) + / (marcapaginas.getUnidades_max() - marcapaginas.getUnidades_min()); + + data = new BigDecimal(precio); + precio = data.setScale(2, RoundingMode.HALF_UP).doubleValue(); + + Double margen = 1.0 * marcapaginas.getMargen_unidades_min() + + (1.0 * presupuestoMarcapaginas.getUnidades() - 1.0 * marcapaginas.getUnidades_min()) + * (1.0 * marcapaginas.getMargen_unidades_max() + - 1.0 * marcapaginas.getMargen_unidades_min()) + / (1.0 * marcapaginas.getUnidades_max() - 1.0 * marcapaginas.getUnidades_min()); + + data = new BigDecimal(margen); + margen = data.setScale(2, RoundingMode.HALF_UP).doubleValue(); + + Double pvp = precio + (precio * margen / 100); + + data = new BigDecimal(pvp); + pvp = data.setScale(2, RoundingMode.HALF_UP).doubleValue(); + + System.out.println("📦 Precio interpolado para " + presupuestoMarcapaginas.getUnidades() + " unidades: " + + precio + " + " + margen + "% = " + pvp + " (" + marcapaginas.getPrecio_unidades_min() + " - " + + marcapaginas.getPrecio_unidades_max() + ")"); + Map resultado; + resultado = Map.of( + "precio", precio, + "margen", margen, + "pvp", pvp); + return resultado; + } + else { + + BigDecimal data = BigDecimal.ZERO; + + // precio unidad para el máximo de unidades + Double precio = marcapaginas.getPrecio_unidades_max() / marcapaginas.getUnidades_max(); + precio = precio * presupuestoMarcapaginas.getUnidades(); + data = new BigDecimal(precio); + precio = data.setScale(2, RoundingMode.HALF_UP).doubleValue(); + + Double margen = 1.0 * marcapaginas.getMargen_unidades_max(); + data = new BigDecimal(margen); + margen = data.setScale(2, RoundingMode.HALF_UP).doubleValue(); + + Double pvp = precio + (precio * margen / 100); + data = new BigDecimal(pvp); + pvp = data.setScale(2, RoundingMode.HALF_UP).doubleValue(); + + System.out.println("📦 Precio interpolado para " + presupuestoMarcapaginas.getUnidades() + " unidades: " + + precio + " + " + margen + "% = " + pvp + " (" + marcapaginas.getPrecio_unidades_min() + " - " + + marcapaginas.getPrecio_unidades_max() + ")"); + Map resultado; + resultado = Map.of( + "precio", precio, + "margen", margen, + "pvp", pvp); + return resultado; + } + } + +}