From 6d8860861237327e324b6efd5024177f6569fef8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Jim=C3=A9nez?= Date: Fri, 19 Sep 2025 14:55:54 +0200 Subject: [PATCH 1/3] =?UTF-8?q?a=C3=B1adida=20carga=20de=20datos=20de=20ca?= =?UTF-8?q?che=20en=20formularios?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.properties | 41 ++++++++--- .../presupuestador/presupuestador.js | 44 ++++++++++-- .../presupuestador/presupuesto-maquetacion.js | 68 ++++++++++++++++--- .../presupuesto-marcapaginas.js | 40 +++++++++++ .../presupuesto-maquetacion-form.html | 22 +++--- .../presupuesto-marcapaginas-form.html | 12 ++-- 6 files changed, 187 insertions(+), 40 deletions(-) diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 6ffb606..cddf59d 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,26 +1,49 @@ spring.application.name=erp -logging.level.org.springframework.security=DEBUG +# +# Logging +# +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 - +# +# 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.username=imprimelibros_user spring.datasource.password=om91irrDctd spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver +spring.jpa.hibernate.ddl-auto=update +spring.jpa.show-sql=true + + +# +# Safekat API Configuration +# safekat.api.url=http://localhost:8000/ #safekat.api.url=https://erp-dev.safekat.es/ safekat.api.email=imnavajas@coit.es safekat.api.password=Safekat2024 -spring.jpa.hibernate.ddl-auto=update -spring.jpa.show-sql=true \ No newline at end of file + +# +# 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 + + +# +# Resource chain +# Activa el resource chain y versionado por contenido +# +spring.web.resources.chain.enabled=true +spring.web.resources.chain.strategy.content.enabled=true +spring.web.resources.chain.strategy.content.paths=/assets/** + 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 4a81990..f29014c 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 @@ -59,6 +59,38 @@ class PresupuestoCliente { acabado: 0 } }, + servicios: { + servicios: [], + datosMarcaPaginas: { + marcapaginas_tirada: 100, + tamanio_maquetacion: '_50x140_', + caras_impresion: 'una_cara', + papel_marcapaginas: 'cartulina_grafica', + gramaje_marcapaginas: 300, + acabado_marcapaginas: 'ninguno', + resultado: { + precio_unitario: 0, + precio_total: 0 + } + }, + datosMaquetacion: { + num_caracteres: 200000, + formato_maquetacion: 'A5', + cuerpo_texto: 'medium', + num_columnas: 1, + num_tablas: 0, + num_fotos: 0, + correccion_ortotipografica: false, + texto_mecanografiado: false, + disenio_portada: false, + epub: false, + resultado: { + num_paginas_estimadas: 0, + precio_pagina_estimado: 0, + precio: 0 + } + } + }, selectedTirada: null, } @@ -236,8 +268,9 @@ class PresupuestoCliente { contenedor.append(label); } + /****************************** - * END OF DATOS GENERALES + * DATOS GENERALES ******************************/ #initDatosGenerales() { @@ -1087,7 +1120,7 @@ class PresupuestoCliente { const tipoCubierta = $('.tapa-cubierta.selected').attr('id') || 'tapaBlanda'; const solapas = $('.solapas-cubierta.selected').id == 'sin-solapas' ? 0 : 1 || 0; - const tamanioSolapas = $('#tamanio-solapas-cubierta').val() || '80'; + const tamanioSolapasCubierta = $('#tamanio-solapas-cubierta').val() || '80'; const cubiertaCaras = parseInt(this.carasImpresionCubierta.val()) || 2; const guardasPapelId = parseInt($('#papel-guardas option:selected').data('papel-id')) || 3; const guardasGramaje = parseInt($('#papel-guardas option:selected').data('gramaje')) || 170; @@ -1111,7 +1144,7 @@ class PresupuestoCliente { return { tipoCubierta: tipoCubierta, solapas: solapas, - tamanioSolapas: tamanioSolapas, + tamanioSolapasCubierta: tamanioSolapasCubierta, cubiertaCaras: cubiertaCaras, guardasPapelId: guardasPapelId, guardasGramaje: guardasGramaje, @@ -1142,7 +1175,7 @@ class PresupuestoCliente { this.formData.cubierta.tipoCubierta = data.tipoCubierta; this.formData.cubierta.solapas = data.solapas; - this.formData.cubierta.tamanioSolapas = data.tamanioSolapas; + this.formData.cubierta.tamanioSolapasCubierta = data.tamanioSolapasCubierta; this.formData.cubierta.cubiertaCaras = data.cubiertaCaras; this.formData.cubierta.guardasPapelId = data.guardasPapelId; this.formData.cubierta.guardasGramaje = data.guardasGramaje; @@ -1219,7 +1252,7 @@ class PresupuestoCliente { $(`.solapas-cubierta#con-solapas`).addClass('selected'); this.divSolapasCubierta.removeClass('d-none'); this.carasImpresionCubierta.val(this.formData.cubierta.cubiertaCaras); - this.tamanioSolapasCubierta.val(this.formData.cubierta.tamanioSolapas); + this.tamanioSolapasCubierta.val(this.formData.cubierta.tamanioSolapasCubierta); } this.carasImpresionCubierta.val(this.formData.cubierta.cubiertaCaras); @@ -1361,6 +1394,7 @@ class PresupuestoCliente { // Eventos para el resumen $(document).on('change', '.service-checkbox', (e) => { Summary.updateExtras(); + }); } 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 91987d8..eaaa0da 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 @@ -3,10 +3,12 @@ import { formateaMoneda } from "../utils.js"; $(document).on('change', '#maquetacion', function (e) { + e.preventDefault(); if ($('#maquetacion').is(':checked')) { $.get("/presupuesto/public/maquetacion/form", function (data) { $("#maquetacionModalBody").html(data); + loadMaquetacionData(); $("#maquetacionModal").modal("show"); }); } else { @@ -18,7 +20,9 @@ $(document).on('change', '#maquetacion', function (e) { } }); + $(document).on("submit", "#maquetacionForm", function (e) { + e.preventDefault(); const $form = $(this); @@ -34,16 +38,15 @@ $(document).on("submit", "#maquetacionForm", function (e) { const modal = bootstrap.Modal.getInstance(modalEl) || new bootstrap.Modal(modalEl); modal.hide(); - const resumenHtml = ` -
-

${json.language.num_paginas_estimadas || 'Páginas calculadas'}: ${json.numPaginasEstimadas ?? "-"}

-

${json.language.precio_por_pagina_estimado || 'Precio por página estimado'}: ${formateaMoneda(json.precioPaginaEstimado) || "-"}

-
- ${json.precio ? - `

Precio: ${formateaMoneda(json.precio)}

` : ""} -
- `; +
+

${json.language.num_paginas_estimadas || 'Páginas calculadas'}: ${json.numPaginasEstimadas ?? "-"}

+

${json.language.precio_por_pagina_estimado || 'Precio por página estimado'}: ${formateaMoneda(json.precioPaginaEstimado) || "-"}

+
+ ${json.precio ? + `

Precio: ${formateaMoneda(json.precio)}

` : ""} +
+ `; Swal.fire({ title: json.language.presupuesto_maquetacion || 'Presupuesto Maquetación', @@ -66,6 +69,13 @@ $(document).on("submit", "#maquetacionForm", function (e) { $('label[for="maquetacion"] .service-price') .text(formateaMoneda(json.precio)); Summary.updateExtras(); + + // guardamos los datos del formulario en sessionStorage + const stored = JSON.parse(sessionStorage.getItem("formData")); + 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; + sessionStorage.setItem("formData", JSON.stringify(stored)); } else { const calcularStr = $('#div-extras').data('language-calcular'); @@ -108,3 +118,43 @@ $(document).on('hidden.bs.modal', '#maquetacionModal', function () { $('label[for="maquetacion"] .service-price').text(calcularStr); }); + +$(document).on('change', '.maquetacion-item', () => { + + saveMaquetacionData(); +}); + + +function loadMaquetacionData() { + + const stored = JSON.parse(sessionStorage.getItem("formData")).servicios.datosMaquetacion; + $('#num-caracteres').val(stored.num_caracteres); + $('#formato-maquetacion').val(stored.formato_maquetacion); + $('#cuerpo-texto').val(stored.cuerpo_texto); + $('#num-columnas').val(stored.num_columnas); + $('#num-tablas').val(stored.num_tablas); + $('#num-fotos').val(stored.num_fotos); + $('#correccion-ortotipografica').prop('checked', stored.correccion_ortotipografica); + $('#texto-mecanografiado').prop('checked', stored.texto_mecanografiado); + $('#disenio-portada').prop('checked', stored.disenio_portada); + $('#epub').prop('checked', stored.epub); +} + + +function saveMaquetacionData() { + + const stored = JSON.parse(sessionStorage.getItem("formData")); + stored.servicios.datosMaquetacion.num_caracteres = parseInt($('#num-caracteres').val()) || 0; + stored.servicios.datosMaquetacion.formato_maquetacion = $('#formato-maquetacion').val() || 'A5'; + stored.servicios.datosMaquetacion.cuerpo_texto = $('#cuerpo-texto').val() || 'medium'; + stored.servicios.datosMaquetacion.num_columnas = parseInt($('#num-columnas').val()) || 1; + stored.servicios.datosMaquetacion.num_tablas = parseInt($('#num-tablas').val()) || 0; + stored.servicios.datosMaquetacion.num_fotos = parseInt($('#num-fotos').val()) || 0; + stored.servicios.datosMaquetacion.correccion_ortotipografica = $('#correccion-ortotipografica').is(':checked'); + stored.servicios + .datosMaquetacion.texto_mecanografiado = $('#texto-mecanografiado').is(':checked'); + stored.servicios.datosMaquetacion.disenio_portada = $('#disenio-portada').is(':checked'); + stored.servicios.datosMaquetacion.epub = $('#epub').is(':checked'); + sessionStorage.setItem("formData", JSON.stringify(stored)); +} + 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 94349f5..6c2f932 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 @@ -7,6 +7,8 @@ $(document).on('change', '#marcapaginas', function (e) { $.get("/presupuesto/public/marcapaginas/form", function (data) { $("#marcapaginasModalBody").html(data); + loadMarcapaginasData(); + // init marcapaginas form filtrarAcabados(); $("#marcapaginasModal").modal("show"); @@ -65,6 +67,12 @@ $(document).on("submit", "#marcapaginasForm", function (e) { $('label[for="marcapaginas"] .service-price') .text(formateaMoneda(json.precio_total)); Summary.updateExtras(); + + // guardamos los datos del formulario en sessionStorage + const stored = JSON.parse(sessionStorage.getItem("formData")); + stored.servicios.datosMarcapaginas.resultado.precio_unitario = json.precio_unidad; + stored.servicios.datosMarcapaginas.resultado.precio_total = json.precio_total; + sessionStorage.setItem("formData", JSON.stringify(stored)); } else { const calcularStr = $('#div-extras').data('language-calcular'); @@ -139,5 +147,37 @@ function filtrarAcabados() { } +$(document).on('change', '.marcapaginas-item', () => { + + saveMarcapaginasData(); +}); + + +function loadMarcapaginasData() { + + const stored = JSON.parse(sessionStorage.getItem("formData")).servicios.datosMarcapaginas; + $('#marcapaginas-tirada').val(stored.marcapaginas_tirada); + $('#tamanio-maquetacion').val(stored.tamanio_maquetacion); + $('#caras-impresion').val(stored.caras_impresion); + $('#papel-marcapaginas').val(stored.papel_marcapaginas); + $('#gramaje-marcapaginas').val(stored.gramaje_marcapaginas); + $('#num-fotos').val(stored.num_fotos); + $('#acabado-marcapaginas').prop('checked', stored.acabado_marcapaginas); +} + + +function saveMarcapaginasData() { + + const stored = JSON.parse(sessionStorage.getItem("formData")); + stored.servicios.datosMarcapaginas.marcapaginas_tirada = parseInt($('#marcapaginas-tirada').val()) || 100; + stored.servicios.datosMarcapaginas.tamanio_maquetacion = $('#tamanio-maquetacion').val() || '_50x140_'; + stored.servicios.datosMarcapaginas.caras_impresion = $('#caras-impresion').val() || 'una_cara'; + stored.servicios.datosMarcapaginas.papel_marcapaginas = $('#papel-marcapaginas').val() || 'cartulina_grafica'; + stored.servicios.datosMarcapaginas.gramaje_marcapaginas = parseInt($('#gramaje-marcapaginas').val()) || 300; + stored.servicios.datosMarcapaginas.num_fotos = parseInt($('#num-fotos').val()) || 0; + stored.servicios.datosMarcapaginas.acabado_marcapaginas = $('#acabado-marcapaginas').val() || 'ninguno'; + sessionStorage.setItem("formData", JSON.stringify(stored)); +} + diff --git a/src/main/resources/templates/imprimelibros/presupuestos/presupuesto-maquetacion-form.html b/src/main/resources/templates/imprimelibros/presupuestos/presupuesto-maquetacion-form.html index 43715a7..47c1160 100644 --- a/src/main/resources/templates/imprimelibros/presupuestos/presupuesto-maquetacion-form.html +++ b/src/main/resources/templates/imprimelibros/presupuestos/presupuesto-maquetacion-form.html @@ -2,13 +2,13 @@
- +
- @@ -17,52 +17,52 @@
- - +
- +
- +
- +
-
-
-
-
diff --git a/src/main/resources/templates/imprimelibros/presupuestos/presupuesto-marcapaginas-form.html b/src/main/resources/templates/imprimelibros/presupuestos/presupuesto-marcapaginas-form.html index 1b806fd..b8440ee 100644 --- a/src/main/resources/templates/imprimelibros/presupuestos/presupuesto-marcapaginas-form.html +++ b/src/main/resources/templates/imprimelibros/presupuestos/presupuesto-marcapaginas-form.html @@ -2,12 +2,12 @@
- +
- @@ -15,28 +15,28 @@
-
-
-
- From b5275f89f7d2b2a3a7072054a747626fe92d24ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Jim=C3=A9nez?= Date: Fri, 19 Sep 2025 15:16:28 +0200 Subject: [PATCH 2/3] corregidas algunas erratas --- .../imprimelibros/presupuestador/presupuestador.js | 6 +++--- .../presupuestador/presupuesto-marcapaginas.js | 11 +++++------ .../presupuestos/presupuesto-marcapaginas-form.html | 4 ++-- 3 files changed, 10 insertions(+), 11 deletions(-) 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 f29014c..6748a20 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 @@ -61,9 +61,9 @@ class PresupuestoCliente { }, servicios: { servicios: [], - datosMarcaPaginas: { + datosMarcapaginas: { marcapaginas_tirada: 100, - tamanio_maquetacion: '_50x140_', + tamanio_marcapaginas: '_50x140_', caras_impresion: 'una_cara', papel_marcapaginas: 'cartulina_grafica', gramaje_marcapaginas: 300, @@ -1394,7 +1394,7 @@ class PresupuestoCliente { // Eventos para el resumen $(document).on('change', '.service-checkbox', (e) => { Summary.updateExtras(); - + }); } 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 6c2f932..458f393 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 @@ -11,6 +11,7 @@ $(document).on('change', '#marcapaginas', function (e) { // init marcapaginas form filtrarAcabados(); + $("#marcapaginasModal").modal("show"); }); } else { @@ -70,7 +71,7 @@ $(document).on("submit", "#marcapaginasForm", function (e) { // guardamos los datos del formulario en sessionStorage const stored = JSON.parse(sessionStorage.getItem("formData")); - stored.servicios.datosMarcapaginas.resultado.precio_unitario = json.precio_unidad; + stored.servicios.datosMarcapaginas.resultado.precio_unitario = json.precio_unitario; stored.servicios.datosMarcapaginas.resultado.precio_total = json.precio_total; sessionStorage.setItem("formData", JSON.stringify(stored)); } @@ -157,12 +158,11 @@ function loadMarcapaginasData() { const stored = JSON.parse(sessionStorage.getItem("formData")).servicios.datosMarcapaginas; $('#marcapaginas-tirada').val(stored.marcapaginas_tirada); - $('#tamanio-maquetacion').val(stored.tamanio_maquetacion); + $('#tamanio-marcapaginas').val(stored.tamanio_marcapaginas); $('#caras-impresion').val(stored.caras_impresion); $('#papel-marcapaginas').val(stored.papel_marcapaginas); $('#gramaje-marcapaginas').val(stored.gramaje_marcapaginas); - $('#num-fotos').val(stored.num_fotos); - $('#acabado-marcapaginas').prop('checked', stored.acabado_marcapaginas); + $('#acabado-marcapaginas').val(stored.acabado_marcapaginas); } @@ -170,11 +170,10 @@ function saveMarcapaginasData() { const stored = JSON.parse(sessionStorage.getItem("formData")); stored.servicios.datosMarcapaginas.marcapaginas_tirada = parseInt($('#marcapaginas-tirada').val()) || 100; - stored.servicios.datosMarcapaginas.tamanio_maquetacion = $('#tamanio-maquetacion').val() || '_50x140_'; + stored.servicios.datosMarcapaginas.tamanio_marcapaginas = $('#tamanio-marcapaginas').val() || '_50x140_'; stored.servicios.datosMarcapaginas.caras_impresion = $('#caras-impresion').val() || 'una_cara'; stored.servicios.datosMarcapaginas.papel_marcapaginas = $('#papel-marcapaginas').val() || 'cartulina_grafica'; stored.servicios.datosMarcapaginas.gramaje_marcapaginas = parseInt($('#gramaje-marcapaginas').val()) || 300; - stored.servicios.datosMarcapaginas.num_fotos = parseInt($('#num-fotos').val()) || 0; stored.servicios.datosMarcapaginas.acabado_marcapaginas = $('#acabado-marcapaginas').val() || 'ninguno'; sessionStorage.setItem("formData", JSON.stringify(stored)); } diff --git a/src/main/resources/templates/imprimelibros/presupuestos/presupuesto-marcapaginas-form.html b/src/main/resources/templates/imprimelibros/presupuestos/presupuesto-marcapaginas-form.html index b8440ee..054cdeb 100644 --- a/src/main/resources/templates/imprimelibros/presupuestos/presupuesto-marcapaginas-form.html +++ b/src/main/resources/templates/imprimelibros/presupuestos/presupuesto-marcapaginas-form.html @@ -6,8 +6,8 @@
- - From 42fa3478295f1814f6a74057e73aae3a73b07066 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaime=20Jim=C3=A9nez?= Date: Sun, 21 Sep 2025 14:16:00 +0200 Subject: [PATCH 3/3] terminado --- pom.xml | 6 +++ .../erp/common/HtmlStripConverter.java | 20 ++++++++ .../erp/presupuesto/Presupuesto.java | 5 ++ .../resources/i18n/presupuesto_es.properties | 8 +++- .../presupuestador/presupuestador.js | 48 +++++++++++++++++-- .../presupuestador/presupuesto-maquetacion.js | 6 ++- .../presupuesto-marcapaginas.js | 11 +++-- .../presupuestador/service-option-card.js | 4 +- .../presupuestador/tirada-price-card.js | 17 +++---- .../assets/js/pages/imprimelibros/utils.js | 46 +++++++++++------- .../_datos-generales.html | 6 +-- .../presupuestador-items/_extras.html | 4 +- .../presupuestador-items/_resumen.html | 24 ++++++++++ .../presupuestos/presupuestador.html | 16 +++++++ 14 files changed, 177 insertions(+), 44 deletions(-) create mode 100644 src/main/java/com/imprimelibros/erp/common/HtmlStripConverter.java create mode 100644 src/main/resources/templates/imprimelibros/presupuestos/presupuestador-items/_resumen.html diff --git a/pom.xml b/pom.xml index 5f641c6..2463cb2 100644 --- a/pom.xml +++ b/pom.xml @@ -92,6 +92,12 @@ test + + org.jsoup + jsoup + 1.17.2 + + diff --git a/src/main/java/com/imprimelibros/erp/common/HtmlStripConverter.java b/src/main/java/com/imprimelibros/erp/common/HtmlStripConverter.java new file mode 100644 index 0000000..b7b364b --- /dev/null +++ b/src/main/java/com/imprimelibros/erp/common/HtmlStripConverter.java @@ -0,0 +1,20 @@ +package com.imprimelibros.erp.common; + +import jakarta.persistence.AttributeConverter; +import jakarta.persistence.Converter; +import org.jsoup.Jsoup; +import org.jsoup.safety.Safelist; + +@Converter(autoApply = false) +public class HtmlStripConverter implements AttributeConverter { + + @Override + public String convertToDatabaseColumn(String attribute) { + return attribute == null ? null : Jsoup.clean(attribute, Safelist.none()); + } + + @Override + public String convertToEntityAttribute(String dbData) { + return dbData; // tal cual + } +} diff --git a/src/main/java/com/imprimelibros/erp/presupuesto/Presupuesto.java b/src/main/java/com/imprimelibros/erp/presupuesto/Presupuesto.java index 83cb397..d768ab2 100644 --- a/src/main/java/com/imprimelibros/erp/presupuesto/Presupuesto.java +++ b/src/main/java/com/imprimelibros/erp/presupuesto/Presupuesto.java @@ -8,6 +8,8 @@ import com.imprimelibros.erp.presupuesto.validation.Par; import com.imprimelibros.erp.presupuesto.validation.PresupuestoValidationGroups; import com.imprimelibros.erp.presupuesto.validation.Tamanio; +import com.imprimelibros.erp.common.HtmlStripConverter; + import jakarta.persistence.*; @ConsistentTiradas(groups = PresupuestoValidationGroups.DatosGenerales.class) @@ -45,13 +47,16 @@ public class Presupuesto implements Cloneable{ @Column(name = "tipo_encuadernacion") private TipoEncuadernacion tipoEncuadernacion = TipoEncuadernacion.fresado; + @Convert(converter = HtmlStripConverter.class) @NotBlank(message = "{presupuesto.errores.titulo}", groups = PresupuestoValidationGroups.DatosGenerales.class) @Column(name = "titulo") private String titulo; + @Convert(converter = HtmlStripConverter.class) @Column(name = "autor") private String autor; + @Convert(converter = HtmlStripConverter.class) @Column(name = "isbn") private String isbn; diff --git a/src/main/resources/i18n/presupuesto_es.properties b/src/main/resources/i18n/presupuesto_es.properties index 222b3c6..13a8e98 100644 --- a/src/main/resources/i18n/presupuesto_es.properties +++ b/src/main/resources/i18n/presupuesto_es.properties @@ -1,9 +1,11 @@ presupuesto.datos-generales=Datos Generales presupuesto.interior=Interior presupuesto.cubierta=Cubierta -presupuesto.seleccion-tirada=Seleccion de tirada +presupuesto.seleccion-tirada=Selección tirada presupuesto.extras=Extras +presupuesto.resumen=Resumen presupuesto.add-to-presupuesto=Añadir al presupuesto +presupuesto.calcular=Calcular # Pestaña datos generales de presupuesto presupuesto.informacion-libro=Información del libro @@ -153,7 +155,9 @@ presupuesto.volver-cubierta=Volver a diseño cubierta presupuesto.finalizar=Finalizar presupuesto presupuesto.calcular-presupuesto=Calcular presupuesto presupuesto.consultar-soporte=Consultar con soporte -presupuesto.calcular=Calcular + +# Pestaña resumen del presupuesto +presupuesto.volver-extras=Volver a extras # Resumen del presupuesto presupuesto.resumen-presupuesto=Resumen 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 6748a20..303654b 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 @@ -70,7 +70,7 @@ class PresupuestoCliente { acabado_marcapaginas: 'ninguno', resultado: { precio_unitario: 0, - precio_total: 0 + precio: 0 } }, datosMaquetacion: { @@ -184,6 +184,7 @@ class PresupuestoCliente { this.#initInterior(); this.#initSeleccionTirada(); this.#initExtras(); + this.#initResumen(); $(document).on('change', 'input[min][max]', function () { const $input = $(this); @@ -1387,14 +1388,25 @@ class PresupuestoCliente { this.#changeTab('pills-seleccion-tirada'); this.summaryTableExtras.addClass('d-none'); } else { - //this.#changeTab('pills-finalizar'); + this.#changeTab('pills-resumen'); } }); // Eventos para el resumen $(document).on('change', '.service-checkbox', (e) => { - Summary.updateExtras(); + const $target = $(e.currentTarget); + + if ($target.prop('checked')) { + this.formData.servicios.servicios.push($target.val()); + } else { + const index = this.formData.servicios.servicios.indexOf($target.val()); + if (index > -1) { + this.formData.servicios.servicios.splice(index, 1); + } + } + Summary.updateExtras(); + this.#cacheFormData(); }); } @@ -1406,14 +1418,44 @@ class PresupuestoCliente { this.divExtras.addClass('animate-fadeInUpBounce'); for (const extra of servicios) { + if (this.formData.servicios.servicios.includes(extra.id) && !extra.checked) { + extra.checked = true; + if (extra.id === "marcapaginas" || extra.id === "maquetacion") { + extra.price = extra.id === "marcapaginas" ? + this.formData.servicios.datosMarcapaginas.resultado.precio : + this.formData.servicios.datosMaquetacion.resultado.precio; + extra.priceUnit = this.divExtras.data('currency'); + } + } const item = new ServiceOptionCard(extra); this.divExtras.append(item.render()); + if (item.checked) { + if (!this.formData.servicios.servicios.includes(extra.id)) { + this.formData.servicios.servicios.push(extra.id); + } + } } + this.#cacheFormData(); Summary.updateExtras(); } + /****************************** + * END EXTRAS + ******************************/ + + /****************************** + * EXTRAS + ******************************/ + #initResumen() { + $(document).on('click', '.btn-change-tab-resumen', (e) => { + const id = e.currentTarget.id; + if (id === 'btn-prev-resumen') { + this.#changeTab('pills-extras'); + } + }); + } /****************************** * END EXTRAS ******************************/ 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 eaaa0da..6b7e8db 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 @@ -113,9 +113,11 @@ $(document).on("submit", "#maquetacionForm", function (e) { $(document).on('hidden.bs.modal', '#maquetacionModal', function () { const calcularStr = $('#div-extras').data('language-calcular'); - $('#maquetacion').prop('checked', false); $('#maquetacion').data('price', calcularStr); $('label[for="maquetacion"] .service-price').text(calcularStr); + $('#maquetacion').prop('checked', false).trigger('change'); + + Summary.updateExtras(); }); @@ -138,6 +140,8 @@ function loadMaquetacionData() { $('#texto-mecanografiado').prop('checked', stored.texto_mecanografiado); $('#disenio-portada').prop('checked', stored.disenio_portada); $('#epub').prop('checked', stored.epub); + + Summary.updateExtras(); } 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 458f393..34e4a3b 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 @@ -1,5 +1,5 @@ import * as Summary from "./summary.js"; -import { formateaMoneda, formateaMoneda6Decimales } from "../utils.js"; +import { formateaMoneda } from "../utils.js"; $(document).on('change', '#marcapaginas', function (e) { e.preventDefault(); @@ -10,7 +10,7 @@ $(document).on('change', '#marcapaginas', function (e) { loadMarcapaginasData(); // init marcapaginas form - filtrarAcabados(); + filtrarAcabados(); $("#marcapaginasModal").modal("show"); }); @@ -42,7 +42,7 @@ $(document).on("submit", "#marcapaginasForm", function (e) { const resumenHtml = `
-

${json.language.precio_unidad || 'Precio por unidad'}: ${formateaMoneda6Decimales(json.precio_unitario) || "-"}

+

${json.language.precio_unidad || 'Precio por unidad'}: ${formateaMoneda(json.precio_unitario, 6) || "-"}

${json.language.precio_total || 'Precio total'}: ${formateaMoneda(json.precio_total) || "-"}

`; @@ -72,7 +72,7 @@ $(document).on("submit", "#marcapaginasForm", function (e) { // guardamos los datos del formulario en sessionStorage const stored = JSON.parse(sessionStorage.getItem("formData")); stored.servicios.datosMarcapaginas.resultado.precio_unitario = json.precio_unitario; - stored.servicios.datosMarcapaginas.resultado.precio_total = json.precio_total; + stored.servicios.datosMarcapaginas.resultado.precio = json.precio_total; sessionStorage.setItem("formData", JSON.stringify(stored)); } else { @@ -117,9 +117,10 @@ $(document).on("change", "#caras-impresion", function (e) { $(document).on('hidden.bs.modal', '#marcapaginasModal', function () { const calcularStr = $('#div-extras').data('language-calcular'); - $('#marcapaginas').prop('checked', false); $('#marcapaginas').data('price', calcularStr); $('label[for="marcapaginas"] .service-price').text(calcularStr); + $('#marcapaginas').prop('checked', false).trigger('change'); + Summary.updateExtras(); }); diff --git a/src/main/resources/static/assets/js/pages/imprimelibros/presupuestador/service-option-card.js b/src/main/resources/static/assets/js/pages/imprimelibros/presupuestador/service-option-card.js index d9416f0..2e0835f 100644 --- a/src/main/resources/static/assets/js/pages/imprimelibros/presupuestador/service-option-card.js +++ b/src/main/resources/static/assets/js/pages/imprimelibros/presupuestador/service-option-card.js @@ -1,3 +1,5 @@ +import {formateaMoneda, isNumber} from '../utils.js'; + class ServiceOptionCard { constructor({ id, title, description = '', price = '', priceUnit = '', checked = false, allowChange = true, ribbonText }) { @@ -23,7 +25,7 @@ class ServiceOptionCard { ${ribbonHtml}
${this.title}

${this.description}

-

${this.price} ${this.priceUnit}

+

${isNumber(this.price) ? formateaMoneda(this.price, 2, this.locale) : this.price}

`); diff --git a/src/main/resources/static/assets/js/pages/imprimelibros/presupuestador/tirada-price-card.js b/src/main/resources/static/assets/js/pages/imprimelibros/presupuestador/tirada-price-card.js index 0acf65f..7acc726 100644 --- a/src/main/resources/static/assets/js/pages/imprimelibros/presupuestador/tirada-price-card.js +++ b/src/main/resources/static/assets/js/pages/imprimelibros/presupuestador/tirada-price-card.js @@ -1,6 +1,8 @@ +import { formateaMoneda, formateaNumero } from "../utils.js"; + // ===== Clase ===== class TiradaCard { - constructor({ id, titulo, unidades, precioUnidad, precioTotal, selected = false, moneda = '€', name = 'tirada', + constructor({ id, titulo, unidades, precioUnidad, precioTotal, selected = false, name = 'tirada', labels = {}, locale = (document.documentElement.lang || navigator.language || 'es-ES') }) { this.id = id; @@ -9,7 +11,6 @@ class TiradaCard { this.precioUnidad = precioUnidad; this.precioTotal = precioTotal; this.selected = selected; - this.moneda = moneda; this.name = name; this.locale = locale; this.labels = Object.assign({ @@ -22,16 +23,10 @@ class TiradaCard { this.$container = null; // se establece al renderizar } - #formatMoneyES(value, decimals = 2) { - return new Intl.NumberFormat(this.locale, { - minimumFractionDigits: decimals, - maximumFractionDigits: decimals - }).format(Number(value)); - } #title() { if (this.titulo) return this.titulo; - if (this.unidades != null) return `${this.unidades} ${this.labels.units}`; + if (this.unidades != null) return `${formateaNumero({valor: this.unidades, locale: this.locale, digits: 0})} ${this.labels.units}`; return ''; } @@ -46,11 +41,11 @@ class TiradaCard {
${this.#title()}
${this.labels.perUnit}
-
${this.#formatMoneyES(this.precioUnidad, 4)} ${this.moneda}
+
${formateaMoneda(this.precioUnidad, 4, this.locale)}
${this.labels.total}
-
${this.#formatMoneyES(this.precioTotal, 2)} ${this.moneda}
+
${formateaMoneda(this.precioTotal, 2, this.locale)}
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 4872496..15a4a3a 100644 --- a/src/main/resources/static/assets/js/pages/imprimelibros/utils.js +++ b/src/main/resources/static/assets/js/pages/imprimelibros/utils.js @@ -1,26 +1,40 @@ -function formateaMoneda(valor) { +function formateaMoneda(valor, digits = 2, locale = 'es-ES', currency = 'EUR') { try { - return new Intl.NumberFormat('es-ES', { style: 'currency', currency: 'EUR' }).format(valor); + return new Intl.NumberFormat(locale, { style: 'currency', currency, minimumFractionDigits: digits, useGrouping: true }).format(valor); } catch { return valor; } } export { formateaMoneda }; -function formateaMoneda4Decimales(valor) { - try { - return new Intl.NumberFormat('es-ES', { style: 'currency', currency: 'EUR', minimumFractionDigits: 4 }).format(valor); - } catch { - return valor; - } -} -export { formateaMoneda4Decimales }; -function formateaMoneda6Decimales(valor) { - try { - return new Intl.NumberFormat('es-ES', { style: 'currency', currency: 'EUR', minimumFractionDigits: 6 }).format(valor); - } catch { - return valor; +function formateaNumero({ + valor, + digits = 2, + style = 'decimal', + locale = 'es-ES', + currency = 'EUR' +}) { + const n = Number(valor); + if (!Number.isFinite(n)) return valor; + + const opts = { + useGrouping: true, + minimumFractionDigits: digits, + maximumFractionDigits: digits, + }; + + if (style === 'currency') { + opts.style = 'currency'; + opts.currency = currency; } + + return new Intl.NumberFormat(locale, opts).format(n); } -export { formateaMoneda6Decimales }; \ No newline at end of file +export { formateaNumero }; + + +function isNumber(value) { + return !isNaN(Number(value)) && value.trim() !== ''; +} +export { isNumber }; \ No newline at end of file diff --git a/src/main/resources/templates/imprimelibros/presupuestos/presupuestador-items/_datos-generales.html b/src/main/resources/templates/imprimelibros/presupuestos/presupuestador-items/_datos-generales.html index f0b25e0..a8666b6 100644 --- a/src/main/resources/templates/imprimelibros/presupuestos/presupuestador-items/_datos-generales.html +++ b/src/main/resources/templates/imprimelibros/presupuestos/presupuestador-items/_datos-generales.html @@ -24,7 +24,7 @@ + th:value="${presupuesto?.titulo} ?: ''"> @@ -33,13 +33,13 @@
- +
- +
diff --git a/src/main/resources/templates/imprimelibros/presupuestos/presupuestador-items/_extras.html b/src/main/resources/templates/imprimelibros/presupuestos/presupuestador-items/_extras.html index c16830e..ecb6a86 100644 --- a/src/main/resources/templates/imprimelibros/presupuestos/presupuestador-items/_extras.html +++ b/src/main/resources/templates/imprimelibros/presupuestos/presupuestador-items/_extras.html @@ -10,7 +10,7 @@
-
+
@@ -24,7 +24,7 @@ diff --git a/src/main/resources/templates/imprimelibros/presupuestos/presupuestador-items/_resumen.html b/src/main/resources/templates/imprimelibros/presupuestos/presupuestador-items/_resumen.html new file mode 100644 index 0000000..50330b6 --- /dev/null +++ b/src/main/resources/templates/imprimelibros/presupuestos/presupuestador-items/_resumen.html @@ -0,0 +1,24 @@ +
+ + +
+
+
Resumen +
+
+ +
+
+
+
+
+ + +
+ +
+
\ No newline at end of file diff --git a/src/main/resources/templates/imprimelibros/presupuestos/presupuestador.html b/src/main/resources/templates/imprimelibros/presupuestos/presupuestador.html index 5f2e48b..07f0245 100644 --- a/src/main/resources/templates/imprimelibros/presupuestos/presupuestador.html +++ b/src/main/resources/templates/imprimelibros/presupuestos/presupuestador.html @@ -61,6 +61,15 @@ + @@ -106,6 +115,13 @@ +
+ +
+
+ +