From 0d205f948837bbed440407c020d614e167a4d9f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Jim=C3=A9nez?= Date: Tue, 23 Sep 2025 20:28:33 +0200 Subject: [PATCH] trabajando con las lineas del resumen para la tabla --- pom.xml | 2 +- .../presupuesto/PresupuestoController.java | 39 +++---- .../erp/presupuesto/PresupuestoService.java | 51 ++++++++- .../classes/PresupuestoFormatter.java | 106 +++++++++--------- .../resources/i18n/presupuesto_es.properties | 1 + .../presupuestador/presupuestador.js | 8 +- .../presupuestador/presupuesto-maquetacion.js | 3 + .../presupuesto-marcapaginas.js | 3 + .../assets/js/pages/imprimelibros/utils.js | 6 +- 9 files changed, 131 insertions(+), 88 deletions(-) diff --git a/pom.xml b/pom.xml index 2463cb2..a6602d9 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ - 24 + 21 diff --git a/src/main/java/com/imprimelibros/erp/presupuesto/PresupuestoController.java b/src/main/java/com/imprimelibros/erp/presupuesto/PresupuestoController.java index f568b86..4f4883e 100644 --- a/src/main/java/com/imprimelibros/erp/presupuesto/PresupuestoController.java +++ b/src/main/java/com/imprimelibros/erp/presupuesto/PresupuestoController.java @@ -3,6 +3,7 @@ package com.imprimelibros.erp.presupuesto; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; +import java.math.BigDecimal; import java.util.HashMap; import java.util.Locale; import java.util.Map; @@ -21,6 +22,7 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.http.MediaType; +import com.fasterxml.jackson.databind.ObjectMapper; import com.imprimelibros.erp.externalApi.skApiClient; import com.imprimelibros.erp.presupuesto.classes.ImagenPresupuesto; import com.imprimelibros.erp.presupuesto.classes.PresupuestoMaquetacion; @@ -42,6 +44,12 @@ public class PresupuestoController { @Autowired protected MessageSource messageSource; + private final ObjectMapper objectMapper; + + public PresupuestoController(ObjectMapper objectMapper){ + this.objectMapper = objectMapper; + } + @PostMapping("/public/validar/datos-generales") public ResponseEntity validarDatosGenerales( @Validated(PresupuestoValidationGroups.DatosGenerales.class) Presupuesto presupuesto, @@ -368,30 +376,13 @@ public class PresupuestoController { // Se hace un post para no tener problemas con la longitud de la URL @PostMapping("/public/resumen") - public ResponseEntity getResumen(@RequestBody PresupuestoRequest req, Locale locale) { - Presupuesto p = req.getPresupuesto(); - String[] servicios = req.getServicios() != null ? req.getServicios() : new String[0]; - return ResponseEntity.ok(presupuestoService.getResumen(p, servicios, locale)); + public ResponseEntity getResumen(@RequestBody Map body, Locale locale) { + Presupuesto p = objectMapper.convertValue(body.get("presupuesto"), Presupuesto.class); + + @SuppressWarnings("unchecked") + List> serviciosList = (List>) body.getOrDefault("servicios", List.of()); + + return ResponseEntity.ok(presupuestoService.getResumen(p, serviciosList, locale)); } - public static class PresupuestoRequest { - private Presupuesto presupuesto; - private String[] servicios; - - public Presupuesto getPresupuesto() { - return presupuesto; - } - - public void setPresupuesto(Presupuesto p) { - this.presupuesto = p; - } - - public String[] getServicios() { - return servicios; - } - - public void setServicios(String[] servicios) { - this.servicios = servicios; - } - } } diff --git a/src/main/java/com/imprimelibros/erp/presupuesto/PresupuestoService.java b/src/main/java/com/imprimelibros/erp/presupuesto/PresupuestoService.java index 985343b..1046fe0 100644 --- a/src/main/java/com/imprimelibros/erp/presupuesto/PresupuestoService.java +++ b/src/main/java/com/imprimelibros/erp/presupuesto/PresupuestoService.java @@ -6,12 +6,14 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.function.BiFunction; import java.util.stream.Collectors; import java.util.Locale; import java.text.NumberFormat; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.MessageSource; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import com.fasterxml.jackson.core.JsonProcessingException; @@ -774,13 +776,52 @@ public class PresupuestoService { return out; } - public Map getResumen(Presupuesto presupuesto, String[] servicios, Locale locale) { - Map resumen = new HashMap<>(); - + public Map getResumen(Presupuesto presupuesto, List> servicios, Locale locale) { - + Map resumen = new HashMap<>(); resumen.put("titulo", presupuesto.getTitulo()); - resumen.put("texto", presupuestoFormatter.resumen(presupuesto, servicios, locale)); + + Presupuesto pressupuestoTemp = presupuesto.clone(); + + boolean hayDepositoLegal = servicios != null && servicios.stream() + .map(m -> java.util.Objects.toString(m.get("id"), "")) // null-safe -> String + .map(String::trim) + .anyMatch("deposito-legal"::equals); + + if(hayDepositoLegal){ + pressupuestoTemp.setSelectedTirada(presupuesto.getSelectedTirada()+4); + } + + HashMap precios = this.calcularPresupuesto(pressupuestoTemp, locale); + if(precios.containsKey("error")){ + resumen.put("error", precios.get("error")); + return resumen; + } + + HashMap linea = new HashMap<>(); + Double precio_unitario = 0.0; + Double precio_total = 0.0; + Integer counter = 0; + linea.put("descripcion", presupuestoFormatter.resumen(presupuesto, servicios, locale)); + linea.put("cantidad", presupuesto.getSelectedTirada() != null ? presupuesto.getSelectedTirada() : 0); + precio_unitario = ((List) ((Map) precios.get("data")).get("precios")) + .get(0); + precio_total = precio_unitario * presupuesto.getSelectedTirada(); + linea.put("precio_unitario", precio_unitario); + linea.put("precio_total", BigDecimal.valueOf(precio_total).setScale(2, RoundingMode.HALF_UP)); + resumen.put("linea" + counter, linea); + counter++; + + if(hayDepositoLegal) { + + linea = new HashMap<>(); + linea.put("descripcion", messageSource.getMessage("presupuesto.resumen-deposito-legal", null, locale)); + linea.put("cantidad", 4); + linea.put("precio_unitario", precio_unitario); + linea.put("precio_total", BigDecimal.valueOf(precio_unitario * 4).setScale(2, RoundingMode.HALF_UP)); + resumen.put("linea" + counter, linea); + counter++; + } return resumen; } diff --git a/src/main/java/com/imprimelibros/erp/presupuesto/classes/PresupuestoFormatter.java b/src/main/java/com/imprimelibros/erp/presupuesto/classes/PresupuestoFormatter.java index e278786..c3e6980 100644 --- a/src/main/java/com/imprimelibros/erp/presupuesto/classes/PresupuestoFormatter.java +++ b/src/main/java/com/imprimelibros/erp/presupuesto/classes/PresupuestoFormatter.java @@ -8,6 +8,8 @@ import org.springframework.context.MessageSource; import java.util.Arrays; import java.util.Locale; +import java.util.List; +import java.util.Map; @Component public class PresupuestoFormatter { @@ -28,20 +30,22 @@ public class PresupuestoFormatter { this.acabados = acabados; } - public String resumen(Presupuesto p, String[] servicios, Locale locale) { + public String resumen(Presupuesto p, List> servicios, Locale locale) { String encuadernacion = translationService.label(p.getTipoEncuadernacion(), locale); String tipoImpresion = translationService.label(p.getTipoImpresion(), locale); String tapaCubierta = translationService.label(p.getTipoCubierta(), locale); Object[] args = { - Arrays.asList(servicios).contains("deposito-legal") ? p.getSelectedTirada() + 4 : p.getSelectedTirada(), - encuadernacion, - tipoImpresion, - (p.getPaginasColorTotal() != null ? p.getPaginasColorTotal() : p.getPaginasColor()) + p.getPaginasNegro(), - p.getAncho(), p.getAlto(), - papeles.labelPapel(p.getPapelInteriorId(), locale), p.getGramajeInterior(), - tapaCubierta, - papeles.labelPapel(p.getPapelCubiertaId(), locale), p.getGramajeCubierta(), + + p.getSelectedTirada(), + encuadernacion, + tipoImpresion, + (p.getPaginasColorTotal() != null ? p.getPaginasColorTotal() : p.getPaginasColor()) + + p.getPaginasNegro(), + p.getAncho(), p.getAlto(), + papeles.labelPapel(p.getPapelInteriorId(), locale), p.getGramajeInterior(), + tapaCubierta, + papeles.labelPapel(p.getPapelCubiertaId(), locale), p.getGramajeCubierta(), }; String textoResumen = ms.getMessage("presupuesto.resumen-texto", args, locale); textoResumen += "
    "; @@ -49,27 +53,25 @@ public class PresupuestoFormatter { // tapa blanda if (p.getTipoCubierta() == Presupuesto.TipoCubierta.tapaBlanda) { String impresionCubierta = ms.getMessage( - "presupuesto.resumen-texto-impresion-caras-cubierta", - new Object[] { - p.getCubiertaCaras() == 2 - ? ms.getMessage("presupuesto.una-cara", null, locale) - : ms.getMessage("presupuesto.dos-caras", null, locale) - }, - locale - ); + "presupuesto.resumen-texto-impresion-caras-cubierta", + new Object[] { + p.getCubiertaCaras() == 2 + ? ms.getMessage("presupuesto.una-cara", null, locale) + : ms.getMessage("presupuesto.dos-caras", null, locale) + }, + locale); textoResumen += impresionCubierta; if (p.getSolapasCubierta()) { textoResumen += ms.getMessage( - "presupuesto.resumen-texto-solapas-cubierta", - new Object[] { p.getTamanioSolapasCubierta() }, - locale - ); + "presupuesto.resumen-texto-solapas-cubierta", + new Object[] { p.getTamanioSolapasCubierta() }, + locale); } } // tapa dura else if (p.getTipoCubierta() == Presupuesto.TipoCubierta.tapaDura - || p.getTipoCubierta() == Presupuesto.TipoCubierta.tapaDuraLomoRedondo) { + || p.getTipoCubierta() == Presupuesto.TipoCubierta.tapaDuraLomoRedondo) { String textImpresionGuardas = ""; if (p.getGuardasImpresas() == 0) { @@ -81,52 +83,48 @@ public class PresupuestoFormatter { } textoResumen += ms.getMessage( - "presupuesto.resumen-texto-guardas-cabezada", - new Object[] { - textImpresionGuardas, - papeles.labelPapel(p.getPapelGuardasId(), locale), - p.getGramajeGuardas(), - papeles.labelCabezada(p.getCabezada(), locale), - }, - locale - ); + "presupuesto.resumen-texto-guardas-cabezada", + new Object[] { + textImpresionGuardas, + papeles.labelPapel(p.getPapelGuardasId(), locale), + p.getGramajeGuardas(), + papeles.labelCabezada(p.getCabezada(), locale), + }, + locale); } if (p.getAcabado() != null) { textoResumen += ms.getMessage( - "presupuesto.resumen-texto-acabado-cubierta", - new Object[] { acabados.labelAcabado(p.getAcabado(), locale) }, - locale - ); + "presupuesto.resumen-texto-acabado-cubierta", + new Object[] { acabados.labelAcabado(p.getAcabado(), locale) }, + locale); } textoResumen += ms.getMessage("presupuesto.resumen-texto-end", null, locale); if (Boolean.TRUE.equals(p.getSobrecubierta())) { textoResumen += ms.getMessage( - "presupuesto.resumen-texto-sobrecubierta", - new Object[] { - papeles.labelPapel(p.getPapelSobrecubiertaId(), locale), - p.getGramajeSobrecubierta(), - acabados.labelAcabado(p.getAcabadoSobrecubierta(), locale), - p.getTamanioSolapasSobrecubierta() - }, - locale - ); + "presupuesto.resumen-texto-sobrecubierta", + new Object[] { + papeles.labelPapel(p.getPapelSobrecubiertaId(), locale), + p.getGramajeSobrecubierta(), + acabados.labelAcabado(p.getAcabadoSobrecubierta(), locale), + p.getTamanioSolapasSobrecubierta() + }, + locale); } if (Boolean.TRUE.equals(p.getFaja())) { textoResumen += ms.getMessage( - "presupuesto.resumen-texto-faja", - new Object[] { - papeles.labelPapel(p.getPapelFajaId(), locale), - p.getGramajeFaja(), - p.getAltoFaja(), - acabados.labelAcabado(p.getAcabadoFaja(), locale), - p.getTamanioSolapasFaja() - }, - locale - ); + "presupuesto.resumen-texto-faja", + new Object[] { + papeles.labelPapel(p.getPapelFajaId(), locale), + p.getGramajeFaja(), + p.getAltoFaja(), + acabados.labelAcabado(p.getAcabadoFaja(), locale), + p.getTamanioSolapasFaja() + }, + locale); } textoResumen += ms.getMessage("presupuesto.resumen-texto-end", null, locale); diff --git a/src/main/resources/i18n/presupuesto_es.properties b/src/main/resources/i18n/presupuesto_es.properties index d3b5ce4..6f67f94 100644 --- a/src/main/resources/i18n/presupuesto_es.properties +++ b/src/main/resources/i18n/presupuesto_es.properties @@ -171,6 +171,7 @@ presupuesto.resumen-texto-acabado-cubierta=
  • Acabado {0}.
  • presupuesto.resumen-texto-end=
presupuesto.resumen-texto-sobrecubierta=
  • Sobrecubierta impresa en {0} {1} gr.
    • Acabado {2}
    • Solapas: {3} mm.
  • presupuesto.resumen-texto-faja=
  • Faja impresa en {0} {1} gr. con un alto de {2} mm.
    • Acabado {3}
    • Solapas: {4} mm.
  • +presupuesto.resumen-deposito-legal=4 ejemplares para el Depósito Legal presupuesto.volver-extras=Volver a extras # Resumen del presupuesto diff --git a/src/main/resources/static/assets/js/pages/imprimelibros/presupuestador/presupuestador.js b/src/main/resources/static/assets/js/pages/imprimelibros/presupuestador/presupuestador.js index 0acae88..b765fd9 100644 --- a/src/main/resources/static/assets/js/pages/imprimelibros/presupuestador/presupuestador.js +++ b/src/main/resources/static/assets/js/pages/imprimelibros/presupuestador/presupuestador.js @@ -1381,6 +1381,8 @@ class PresupuestoCliente { ******************************/ #initExtras() { + const self = this; + $(document).on('click', '.btn-change-tab-extras', (e) => { const id = e.currentTarget.id; @@ -1394,13 +1396,13 @@ class PresupuestoCliente { $('.service-checkbox:checked').each(function () { const $servicio = $(this); servicios.push({ - id: $(`label[for="${$servicio.attr('id')}"] .service-title`).text().trim() || $servicio.attr('id'), - price: $(`label[for="${$servicio.attr('id')}"] .service-price`).text().trim() || $servicio.attr('price') + id: $servicio.attr('id') ?? $(`label[for="${$servicio.attr('id')}"] .service-title`).text().trim(), + price: $servicio.data('price') ?? $(`label[for="${$servicio.attr('id')}"] .service-price`).text().trim().replace(" " + self.divExtras.data('currency'), ''), }); }); const body = { - presupuesto: this.#getPresupuestoData(), // objeto JS con campos que coincidan con la entidad + presupuesto: this.#getPresupuestoData(), servicios: servicios }; diff --git a/src/main/resources/static/assets/js/pages/imprimelibros/presupuestador/presupuesto-maquetacion.js b/src/main/resources/static/assets/js/pages/imprimelibros/presupuestador/presupuesto-maquetacion.js index 6b7e8db..cbe874e 100644 --- a/src/main/resources/static/assets/js/pages/imprimelibros/presupuestador/presupuesto-maquetacion.js +++ b/src/main/resources/static/assets/js/pages/imprimelibros/presupuestador/presupuesto-maquetacion.js @@ -75,6 +75,9 @@ $(document).on("submit", "#maquetacionForm", function (e) { stored.servicios.datosMaquetacion.resultado.num_paginas_estimadas = json.numPaginasEstimadas; stored.servicios.datosMaquetacion.resultado.precio_pagina_estimado = json.precioPaginaEstimado; stored.servicios.datosMaquetacion.resultado.precio = json.precio; + if(stored.servicios.servicios.includes("maquetacion") === false) { + stored.servicios.servicios.push("maquetacion"); + } sessionStorage.setItem("formData", JSON.stringify(stored)); } else { diff --git a/src/main/resources/static/assets/js/pages/imprimelibros/presupuestador/presupuesto-marcapaginas.js b/src/main/resources/static/assets/js/pages/imprimelibros/presupuestador/presupuesto-marcapaginas.js index 34e4a3b..58654ee 100644 --- a/src/main/resources/static/assets/js/pages/imprimelibros/presupuestador/presupuesto-marcapaginas.js +++ b/src/main/resources/static/assets/js/pages/imprimelibros/presupuestador/presupuesto-marcapaginas.js @@ -73,6 +73,9 @@ $(document).on("submit", "#marcapaginasForm", function (e) { const stored = JSON.parse(sessionStorage.getItem("formData")); stored.servicios.datosMarcapaginas.resultado.precio_unitario = json.precio_unitario; stored.servicios.datosMarcapaginas.resultado.precio = json.precio_total; + if(stored.servicios.servicios.includes("marcapaginas") === false) { + stored.servicios.servicios.push("marcapaginas"); + } sessionStorage.setItem("formData", JSON.stringify(stored)); } else { diff --git a/src/main/resources/static/assets/js/pages/imprimelibros/utils.js b/src/main/resources/static/assets/js/pages/imprimelibros/utils.js index 2723cdc..01ace58 100644 --- a/src/main/resources/static/assets/js/pages/imprimelibros/utils.js +++ b/src/main/resources/static/assets/js/pages/imprimelibros/utils.js @@ -33,7 +33,11 @@ export function formateaNumero({ export function isNumber(value) { - return !isNaN(Number(value)) && value.trim() !== ''; + + if(typeof value === 'string') { + if(value.trim() === '') return false; + } + return !isNaN(Number(value)); } // Aplana un objeto a "prefijo.clave" (sin arrays)