trabajando con las lineas del resumen para la tabla

This commit is contained in:
2025-09-23 20:28:33 +02:00
parent c1df92b840
commit 0d205f9488
9 changed files with 131 additions and 88 deletions

View File

@ -28,7 +28,7 @@
<url />
</scm>
<properties>
<java.version>24</java.version>
<java.version>21</java.version>
</properties>
<dependencies>
<dependency>

View File

@ -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<String, Object> body, Locale locale) {
Presupuesto p = objectMapper.convertValue(body.get("presupuesto"), Presupuesto.class);
@SuppressWarnings("unchecked")
List<Map<String, Object>> serviciosList = (List<Map<String, Object>>) 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;
}
}
}

View File

@ -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<String, Object> getResumen(Presupuesto presupuesto, String[] servicios, Locale locale) {
Map<String, Object> resumen = new HashMap<>();
public Map<String, Object> getResumen(Presupuesto presupuesto, List<Map<String, Object>> servicios, Locale locale) {
Map<String, Object> 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<String, Object> precios = this.calcularPresupuesto(pressupuestoTemp, locale);
if(precios.containsKey("error")){
resumen.put("error", precios.get("error"));
return resumen;
}
HashMap<String, Object> 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<Double>) ((Map<String, Object>) 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;
}

View File

@ -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<Map<String, Object>> 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 += "<ul>";
@ -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);

View File

@ -171,6 +171,7 @@ presupuesto.resumen-texto-acabado-cubierta= <li>Acabado {0}. </li>
presupuesto.resumen-texto-end=</ul>
presupuesto.resumen-texto-sobrecubierta=<li>Sobrecubierta impresa en {0} {1} gr. <ul><li>Acabado {2}</li><li>Solapas: {3} mm.</li></ul></li>
presupuesto.resumen-texto-faja=<li>Faja impresa en {0} {1} gr. con un alto de {2} mm. <ul><li>Acabado {3}</li><li>Solapas: {4} mm.</li></ul></li>
presupuesto.resumen-deposito-legal=4 ejemplares para el Depósito Legal
presupuesto.volver-extras=Volver a extras
# Resumen del presupuesto

View File

@ -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
};

View File

@ -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 {

View File

@ -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 {

View File

@ -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)