mirror of
https://git.imnavajas.es/jjimenez/erp-imprimelibros.git
synced 2026-01-13 00:48:49 +00:00
1411 lines
65 KiB
Java
1411 lines
65 KiB
Java
package com.imprimelibros.erp.presupuesto.service;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Objects;
|
|
import java.util.stream.Collectors;
|
|
import java.util.Locale;
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.context.MessageSource;
|
|
import org.springframework.security.core.Authentication;
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
import com.fasterxml.jackson.core.type.TypeReference;
|
|
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;
|
|
import com.imprimelibros.erp.presupuesto.classes.ImagenPresupuesto;
|
|
import com.imprimelibros.erp.presupuesto.classes.PresupuestadorItems;
|
|
import com.imprimelibros.erp.presupuesto.classes.PresupuestoFormatter;
|
|
import com.imprimelibros.erp.presupuesto.maquetacion.MaquetacionPrecios;
|
|
import com.imprimelibros.erp.presupuesto.maquetacion.MaquetacionPreciosRepository;
|
|
import com.imprimelibros.erp.presupuesto.marcapaginas.Marcapaginas;
|
|
import com.imprimelibros.erp.presupuesto.classes.PresupuestoMaquetacion;
|
|
import com.imprimelibros.erp.presupuesto.classes.PresupuestoMarcapaginas;
|
|
import com.imprimelibros.erp.presupuesto.dto.Presupuesto;
|
|
import com.imprimelibros.erp.presupuesto.dto.Presupuesto.TipoCubierta;
|
|
import com.imprimelibros.erp.presupuesto.maquetacion.MaquetacionMatrices;
|
|
import com.imprimelibros.erp.presupuesto.maquetacion.MaquetacionMatricesRepository;
|
|
import com.imprimelibros.erp.presupuesto.marcapaginas.MarcapaginasRepository;
|
|
import com.imprimelibros.erp.users.UserDao;
|
|
|
|
import jakarta.servlet.http.HttpServletRequest;
|
|
|
|
import com.imprimelibros.erp.externalApi.skApiClient;
|
|
|
|
@Service
|
|
public class PresupuestoService {
|
|
|
|
@Autowired
|
|
protected VariableService variableService;
|
|
|
|
@Autowired
|
|
protected MessageSource messageSource;
|
|
|
|
@Autowired
|
|
protected MaquetacionPreciosRepository maquetacionPreciosRepository;
|
|
|
|
@Autowired
|
|
protected MaquetacionMatricesRepository maquetacionMatricesRepository;
|
|
|
|
@Autowired
|
|
protected MarcapaginasRepository marcapaginasRepository;
|
|
|
|
@Autowired
|
|
protected PresupuestoRepository presupuestoRepository;
|
|
|
|
private final PresupuestadorItems presupuestadorItems;
|
|
private final PresupuestoFormatter presupuestoFormatter;
|
|
private final skApiClient apiClient;
|
|
private final GeoIpService geoIpService;
|
|
private final UserDao userRepo;
|
|
|
|
public PresupuestoService(PresupuestadorItems presupuestadorItems, PresupuestoFormatter presupuestoFormatter,
|
|
skApiClient apiClient, GeoIpService geoIpService, UserDao userRepo) {
|
|
this.presupuestadorItems = presupuestadorItems;
|
|
this.presupuestoFormatter = presupuestoFormatter;
|
|
this.apiClient = apiClient;
|
|
this.geoIpService = geoIpService;
|
|
this.userRepo = userRepo;
|
|
}
|
|
|
|
public boolean validateDatosGenerales(int[] tiradas) {
|
|
for (int tirada : tiradas) {
|
|
if (tirada <= 0) {
|
|
return false; // Invalid tirada found
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public Boolean isPOD(Presupuesto presupuesto) {
|
|
int pod_value = variableService.getValorEntero("POD");
|
|
return (presupuesto.getTirada1() != null && presupuesto.getTirada1() <= pod_value) ||
|
|
(presupuesto.getTirada2() != null && presupuesto.getTirada2() <= pod_value) ||
|
|
(presupuesto.getTirada3() != null && presupuesto.getTirada3() <= pod_value) ||
|
|
(presupuesto.getTirada4() != null && presupuesto.getTirada4() <= pod_value);
|
|
}
|
|
|
|
public Map<String, Object> obtenerOpcionesColor(Presupuesto presupuesto, Locale locale) {
|
|
List<ImagenPresupuesto> opciones = new ArrayList<>();
|
|
|
|
if (presupuesto.getPaginasColor() > 0) {
|
|
if (!this.isPOD(presupuesto)) {
|
|
// POD solo color foto
|
|
ImagenPresupuesto opcionColor = this.presupuestadorItems.getImpresionColor(locale);
|
|
opcionColor.setSelected(Presupuesto.TipoImpresion.color.equals(presupuesto.getTipoImpresion()));
|
|
if (Presupuesto.TipoImpresion.color.equals(presupuesto.getTipoImpresion()))
|
|
opcionColor.setSelected(true);
|
|
opciones.add(opcionColor);
|
|
|
|
}
|
|
ImagenPresupuesto opcionColorHq = this.presupuestadorItems.getImpresionColorPremium(locale);
|
|
if (Presupuesto.TipoImpresion.colorhq.equals(presupuesto.getTipoImpresion()))
|
|
opcionColorHq.setSelected(true);
|
|
opciones.add(opcionColorHq);
|
|
} else {
|
|
ImagenPresupuesto opcionNegro = this.presupuestadorItems.getImpresionNegro(locale);
|
|
if (Presupuesto.TipoImpresion.negro.equals(presupuesto.getTipoImpresion()))
|
|
opcionNegro.setSelected(true);
|
|
opciones.add(opcionNegro);
|
|
|
|
ImagenPresupuesto opcionNegroHq = this.presupuestadorItems.getImpresionNegroPremium(locale);
|
|
if (Presupuesto.TipoImpresion.negrohq.equals(presupuesto.getTipoImpresion()))
|
|
opcionNegroHq.setSelected(true);
|
|
opciones.add(opcionNegroHq);
|
|
}
|
|
|
|
boolean opcionSeleccionada = opciones.stream().anyMatch(ImagenPresupuesto::isSelected);
|
|
if (!opcionSeleccionada) {
|
|
opciones.get(0).setSelected(true);
|
|
presupuesto.setTipoImpresion(Presupuesto.TipoImpresion.valueOf(opciones.get(0).getId()));
|
|
}
|
|
|
|
Map<String, Object> response = new HashMap<>();
|
|
response.put("opciones_color", opciones);
|
|
|
|
return response;
|
|
}
|
|
|
|
public Map<String, Object> obtenerOpcionesPapelInterior(Presupuesto presupuesto, Locale locale) {
|
|
List<ImagenPresupuesto> opciones = new ArrayList<>();
|
|
|
|
opciones.add(this.presupuestadorItems.getPapelOffsetBlanco(locale));
|
|
if ((presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.negro
|
|
&& !this.isPOD(presupuesto)) ||
|
|
presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.color) {
|
|
opciones.add(this.presupuestadorItems.getPapelOffsetBlancoVolumen(locale));
|
|
}
|
|
opciones.add(this.presupuestadorItems.getPapelOffsetAhuesado(locale));
|
|
if ((presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.negro
|
|
&& !this.isPOD(presupuesto)) ||
|
|
presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.color) {
|
|
opciones.add(this.presupuestadorItems.getPapelOffsetAhuesadoVolumen(locale));
|
|
}
|
|
opciones.add(this.presupuestadorItems.getPapelEstucadoMate(locale));
|
|
|
|
for (ImagenPresupuesto imagenPresupuesto : opciones) {
|
|
imagenPresupuesto.setSelected(
|
|
presupuesto.getPapelInteriorId() != null
|
|
&& imagenPresupuesto.getExtra_data().get("sk-id").equals(
|
|
String.valueOf(presupuesto.getPapelInteriorId())));
|
|
}
|
|
|
|
boolean yaSeleccionado = opciones.stream().anyMatch(ImagenPresupuesto::isSelected);
|
|
if (!yaSeleccionado && !opciones.isEmpty()) {
|
|
ImagenPresupuesto primeraOpcion = opciones.get(0);
|
|
primeraOpcion.setSelected(true);
|
|
presupuesto.setPapelInteriorId(Integer.parseInt(primeraOpcion.getExtra_data().get("sk-id")));
|
|
}
|
|
|
|
Map<String, Object> response = new HashMap<>();
|
|
response.put("opciones_papel_interior", opciones);
|
|
return response;
|
|
}
|
|
|
|
public Map<String, Object> obtenerOpcionesGramajeInterior(Presupuesto presupuesto) {
|
|
List<String> gramajes = new ArrayList<>();
|
|
|
|
final int BLANCO_OFFSET_ID = 3;
|
|
final int BLANCO_OFFSET_VOLUMEN_ID = 7;
|
|
final int AHUESADO_OFFSET_ID = 4;
|
|
final int AHUESADO_OFFSET_VOLUMEN_ID = 6;
|
|
final int ESTUCADO_MATE_ID = 2;
|
|
|
|
if (presupuesto.getPapelInteriorId() != null && presupuesto.getPapelInteriorId() == BLANCO_OFFSET_ID) {
|
|
gramajes.add("80");
|
|
gramajes.add("90");
|
|
if (presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.negrohq ||
|
|
presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.colorhq) {
|
|
gramajes.add("100");
|
|
gramajes.add("120");
|
|
gramajes.add("150");
|
|
gramajes.add("170");
|
|
}
|
|
} else if (presupuesto.getPapelInteriorId() != null
|
|
&& presupuesto.getPapelInteriorId() == BLANCO_OFFSET_VOLUMEN_ID) {
|
|
if (presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.negro ||
|
|
presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.color) {
|
|
gramajes.add("80");
|
|
}
|
|
} else if (presupuesto.getPapelInteriorId() != null && presupuesto.getPapelInteriorId() == AHUESADO_OFFSET_ID) {
|
|
gramajes.add("80");
|
|
gramajes.add("90");
|
|
if (presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.negrohq ||
|
|
presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.colorhq) {
|
|
gramajes.add("100");
|
|
}
|
|
} else if (presupuesto.getPapelInteriorId() != null
|
|
&& presupuesto.getPapelInteriorId() == AHUESADO_OFFSET_VOLUMEN_ID) {
|
|
if (presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.negro ||
|
|
presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.color) {
|
|
gramajes.add("70");
|
|
gramajes.add("80");
|
|
}
|
|
} else if (presupuesto.getPapelInteriorId() != null && presupuesto.getPapelInteriorId() == ESTUCADO_MATE_ID) {
|
|
if (presupuesto.getTipoImpresion() != Presupuesto.TipoImpresion.color) {
|
|
gramajes.add("90");
|
|
}
|
|
if (presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.negrohq ||
|
|
presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.colorhq) {
|
|
gramajes.add("100");
|
|
gramajes.add("115");
|
|
}
|
|
if ((presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.negro
|
|
&& !this.isPOD(presupuesto)) ||
|
|
presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.color) {
|
|
gramajes.add("120");
|
|
}
|
|
if (presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.negrohq ||
|
|
presupuesto.getTipoImpresion() == Presupuesto.TipoImpresion.colorhq) {
|
|
gramajes.add("125");
|
|
gramajes.add("135");
|
|
gramajes.add("150");
|
|
gramajes.add("170");
|
|
gramajes.add("200");
|
|
}
|
|
}
|
|
|
|
Map<String, Object> response = new HashMap<>();
|
|
response.put("opciones_gramaje_interior", gramajes);
|
|
return response;
|
|
}
|
|
|
|
public Map<String, Object> obtenerOpcionesPapelCubierta(Presupuesto presupuesto, Locale locale) {
|
|
List<ImagenPresupuesto> opciones = new ArrayList<>();
|
|
|
|
if (presupuesto.getTipoCubierta() == Presupuesto.TipoCubierta.tapaBlanda) {
|
|
opciones.add(this.presupuestadorItems.getCartulinaGraficaCubierta(locale));
|
|
}
|
|
opciones.add(this.presupuestadorItems.getEstucadoMateCubierta(locale));
|
|
|
|
for (ImagenPresupuesto imagenPresupuesto : opciones) {
|
|
imagenPresupuesto.setSelected(
|
|
presupuesto.getPapelCubiertaId() != null
|
|
&& imagenPresupuesto.getExtra_data().get("sk-id").equals(
|
|
String.valueOf(presupuesto.getPapelCubiertaId())));
|
|
}
|
|
|
|
Map<String, Object> response = new HashMap<>();
|
|
response.put("opciones_papel_cubierta", opciones);
|
|
return response;
|
|
}
|
|
|
|
public Map<String, Object> obtenerOpcionesGramajeCubierta(Presupuesto presupuesto) {
|
|
List<String> gramajes = new ArrayList<>();
|
|
|
|
final int CARTULINA_GRAFICA_ID = 5;
|
|
final int ESTUCADO_MATE_ID = 2;
|
|
|
|
if (presupuesto.getPapelCubiertaId() != null && presupuesto.getPapelCubiertaId() == CARTULINA_GRAFICA_ID) {
|
|
gramajes.add("240");
|
|
gramajes.add("270");
|
|
gramajes.add("300");
|
|
gramajes.add("350");
|
|
} else if (presupuesto.getPapelCubiertaId() != null && presupuesto.getPapelCubiertaId() == ESTUCADO_MATE_ID) {
|
|
if (presupuesto.getTipoCubierta() == Presupuesto.TipoCubierta.tapaBlanda) {
|
|
gramajes.add("250");
|
|
gramajes.add("300");
|
|
gramajes.add("350");
|
|
} else {
|
|
gramajes.add("170");
|
|
}
|
|
}
|
|
|
|
Map<String, Object> response = new HashMap<>();
|
|
response.put("opciones_gramaje_cubierta", gramajes);
|
|
return response;
|
|
}
|
|
|
|
public Map<String, Object> toSkApiRequest(Presupuesto presupuesto) {
|
|
return toSkApiRequest(presupuesto, false);
|
|
}
|
|
|
|
public Map<String, Object> toSkApiRequest(Presupuesto presupuesto, Boolean toSave) {
|
|
final int SK_CLIENTE_ID = 1284;
|
|
final int SK_PAGINAS_CUADERNILLO = 32;
|
|
|
|
Map<String, Object> tamanio = Map.of(
|
|
"ancho", presupuesto.getAncho(),
|
|
"alto", presupuesto.getAlto());
|
|
Map<String, Object> interior = Map.of(
|
|
"papelInterior", presupuesto.getPapelInteriorId(),
|
|
"gramajeInterior", presupuesto.getGramajeInterior());
|
|
Map<String, Object> cubierta = Map.of(
|
|
"tipoCubierta", presupuesto.getTipoCubierta().name(),
|
|
"papelCubierta", presupuesto.getPapelCubiertaId(),
|
|
"gramajeCubierta", presupuesto.getGramajeCubierta(),
|
|
"carasImpresion", presupuesto.getCubiertaCaras(),
|
|
"solapas", presupuesto.getSolapasCubierta() ? presupuesto.getTamanioSolapasCubierta() : 0,
|
|
"acabado", presupuesto.getAcabado(),
|
|
"cabezada", presupuesto.getCabezada(),
|
|
"lomoRedondo", presupuesto.getTipoCubierta() == TipoCubierta.tapaDuraLomoRedondo ? 1 : 0);
|
|
|
|
Map<String, Object> body = new HashMap<>();
|
|
body.put("tipo_impresion_id", this.getTipoImpresionId(presupuesto));
|
|
body.put("tirada", Arrays.stream(presupuesto.getTiradas())
|
|
.filter(Objects::nonNull)
|
|
.collect(Collectors.toList()));
|
|
body.put("tamanio", tamanio);
|
|
body.put("tipo", presupuesto.getTipoEncuadernacion());
|
|
body.put("clienteId", SK_CLIENTE_ID);
|
|
body.put("isColor", presupuesto.getTipoImpresion().name().contains("color") ? 1 : 0);
|
|
body.put("isHq", presupuesto.getTipoImpresion().name().contains("hq") ? 1 : 0);
|
|
body.put("paginas", presupuesto.getPaginasNegro() + presupuesto.getPaginasColor());
|
|
body.put("paginasColor", presupuesto.getPaginasColor());
|
|
body.put("paginasCuadernillo", SK_PAGINAS_CUADERNILLO);
|
|
body.put("interior", interior);
|
|
body.put("cubierta", cubierta);
|
|
body.put("guardas", null);
|
|
if (presupuesto.getSobrecubierta()) {
|
|
Map<String, Object> sobrecubierta = new HashMap<>();
|
|
sobrecubierta.put("papel", presupuesto.getPapelSobrecubiertaId());
|
|
sobrecubierta.put("gramaje", presupuesto.getGramajeSobrecubierta());
|
|
sobrecubierta.put("solapas", presupuesto.getTamanioSolapasSobrecubierta());
|
|
sobrecubierta.put("acabado", presupuesto.getAcabadoSobrecubierta());
|
|
body.put("sobrecubierta", sobrecubierta);
|
|
}
|
|
|
|
if (presupuesto.getFaja()) {
|
|
Map<String, Object> faja = new HashMap<>();
|
|
faja.put("papel", presupuesto.getPapelFajaId());
|
|
faja.put("gramaje", presupuesto.getGramajeFaja());
|
|
faja.put("solapas", presupuesto.getTamanioSolapasFaja());
|
|
faja.put("acabado", presupuesto.getAcabadoFaja());
|
|
faja.put("alto", presupuesto.getAltoFaja());
|
|
body.put("faja", faja);
|
|
}
|
|
|
|
if( toSave ){
|
|
Map<String, Object> data = new HashMap<>();
|
|
data.put("input_data", body);
|
|
data.put("ferroDigital", 1);
|
|
data.put("ferro", 0);
|
|
data.put("marcapaginas", 0);
|
|
data.put("retractilado5", 0);
|
|
if(presupuesto.getServiciosJson() != null && presupuesto.getServiciosJson().indexOf("ejemplar-prueba")>0){
|
|
data.put("prototipo", 1);
|
|
}
|
|
else{
|
|
data.put("prototipo", 0);
|
|
}
|
|
if(presupuesto.getServiciosJson() != null && presupuesto.getServiciosJson().indexOf("retractilado")>0){
|
|
data.put("retractilado", 1);
|
|
}
|
|
else{
|
|
data.put("retractilado", 0);
|
|
}
|
|
data.put("ivaReducido", presupuesto.getIvaReducido() ? 1 : 0);
|
|
data.put("confirmar", 1);
|
|
Map<String, Object> datosCabecera = new HashMap<>();
|
|
datosCabecera.put("titulo", presupuesto.getTitulo());
|
|
datosCabecera.put("autor", presupuesto.getAutor());
|
|
datosCabecera.put("isbn", presupuesto.getIsbn());
|
|
datosCabecera.put("coleccion", "");
|
|
datosCabecera.put("referenciaCliente", presupuesto.getId());
|
|
data.put("datosCabecera", datosCabecera);
|
|
return data;
|
|
|
|
}
|
|
return body;
|
|
|
|
|
|
}
|
|
|
|
public Integer getTipoImpresionId(Presupuesto presupuesto) {
|
|
if (presupuesto.getTipoEncuadernacion() == Presupuesto.TipoEncuadernacion.fresado) {
|
|
if (presupuesto.getTipoCubierta() == Presupuesto.TipoCubierta.tapaDura ||
|
|
presupuesto.getTipoCubierta() == Presupuesto.TipoCubierta.tapaDuraLomoRedondo) {
|
|
return 1; // Fresado tapa dura
|
|
} else {
|
|
return 2; // Fresado tapa blanda
|
|
}
|
|
} else if (presupuesto.getTipoEncuadernacion() == Presupuesto.TipoEncuadernacion.cosido) {
|
|
if (presupuesto.getTipoCubierta() == Presupuesto.TipoCubierta.tapaDura ||
|
|
presupuesto.getTipoCubierta() == Presupuesto.TipoCubierta.tapaDuraLomoRedondo) {
|
|
return 3; // Cosido tapa dura
|
|
} else {
|
|
return 4; // Cosido tapa blanda
|
|
}
|
|
} else if (presupuesto.getTipoEncuadernacion() == Presupuesto.TipoEncuadernacion.espiral) {
|
|
if (presupuesto.getTipoCubierta() == Presupuesto.TipoCubierta.tapaDura ||
|
|
presupuesto.getTipoCubierta() == Presupuesto.TipoCubierta.tapaDuraLomoRedondo) {
|
|
return 5; // Espiral tapa dura
|
|
} else {
|
|
return 6; // Espiral tapa blanda
|
|
}
|
|
} else if (presupuesto.getTipoEncuadernacion() == Presupuesto.TipoEncuadernacion.wireo) {
|
|
if (presupuesto.getTipoCubierta() == Presupuesto.TipoCubierta.tapaDura ||
|
|
presupuesto.getTipoCubierta() == Presupuesto.TipoCubierta.tapaDuraLomoRedondo) {
|
|
return 7; // Wireo tapa dura
|
|
} else {
|
|
return 8; // Wireo tapa blanda
|
|
}
|
|
} else if (presupuesto.getTipoEncuadernacion() == Presupuesto.TipoEncuadernacion.grapado) {
|
|
return 21; // Grapado
|
|
} else {
|
|
return 0; // Default case, no valid type
|
|
}
|
|
}
|
|
|
|
public Map<String, Object> obtenerOpcionesAcabadosCubierta(Presupuesto presupuesto, Locale locale) {
|
|
Map<String, Object> resultado = new HashMap<>();
|
|
List<Object> opciones = new ArrayList<>();
|
|
|
|
opciones.add(new HashMap<>() {
|
|
{
|
|
put("name", messageSource.getMessage("presupuesto.acabado-ninguno", null, locale));
|
|
put("sk-id", 0);
|
|
}
|
|
});
|
|
opciones.add(new HashMap<>() {
|
|
{
|
|
put("name", messageSource.getMessage("presupuesto.acabado-plastificado-brillo-1c", null, locale));
|
|
put("sk-id", 1);
|
|
}
|
|
});
|
|
opciones.add(new HashMap<>() {
|
|
{
|
|
put("name", messageSource.getMessage("presupuesto.acabado-plastificado-mate-1c", null, locale));
|
|
put("sk-id", 5);
|
|
}
|
|
});
|
|
opciones.add(new HashMap<>() {
|
|
{
|
|
put("name",
|
|
messageSource.getMessage("presupuesto.acabado-plastificado-mate-1c-antirrayado", null, locale));
|
|
put("sk-id", 8);
|
|
}
|
|
});
|
|
opciones.add(new HashMap<>() {
|
|
{
|
|
put("name", messageSource.getMessage("presupuesto.acabado-plastificado-mate-uvi", null, locale));
|
|
put("sk-id", 2);
|
|
}
|
|
});
|
|
opciones.add(new HashMap<>() {
|
|
{
|
|
put("name", messageSource.getMessage("presupuesto.acabado-plastificado-mate-uvi3d", null, locale));
|
|
put("sk-id", 3);
|
|
}
|
|
});
|
|
opciones.add(new HashMap<>() {
|
|
{
|
|
put("name", messageSource.getMessage("presupuesto.acabado-plastificado-mate-uvi-braile", null, locale));
|
|
put("sk-id", 4);
|
|
}
|
|
});
|
|
opciones.add(new HashMap<>() {
|
|
{
|
|
put("name", messageSource.getMessage("presupuesto.acabado-plastificado-sandy-1c", null, locale));
|
|
put("sk-id", 9);
|
|
}
|
|
});
|
|
|
|
resultado.put("opciones_acabados_cubierta", opciones);
|
|
return resultado;
|
|
}
|
|
|
|
public String obtenerPrecioRetractilado(Presupuesto presupuesto, Locale locale) {
|
|
Integer[] tiradas = presupuesto.getTiradas();
|
|
Integer tirada_min = Arrays.stream(tiradas)
|
|
.filter(Objects::nonNull)
|
|
.min(Integer::compareTo)
|
|
.orElse(0);
|
|
Map<String, Object> requestBody = new HashMap<>();
|
|
requestBody.put("tirada",
|
|
presupuesto.getSelectedTirada() != null ? presupuesto.getSelectedTirada() : tirada_min);
|
|
Double precio_retractilado = apiClient.getRetractilado(requestBody);
|
|
return precio_retractilado != null
|
|
? String.valueOf(Math.round(precio_retractilado * 100.0) / 100.0)
|
|
: "0.00";
|
|
}
|
|
|
|
private String obtenerPrecioRetractilado(Integer tirada) {
|
|
|
|
Map<String, Object> requestBody = new HashMap<>();
|
|
requestBody.put("tirada", tirada != null ? tirada : 0);
|
|
Double precio_retractilado = apiClient.getRetractilado(requestBody);
|
|
return precio_retractilado != null
|
|
? String.valueOf(Math.round(precio_retractilado * 100.0) / 100.0)
|
|
: "0.00";
|
|
}
|
|
|
|
public Map<String, Object> obtenerServiciosExtras(Presupuesto presupuesto, Locale locale) {
|
|
List<Object> opciones = new ArrayList<>();
|
|
|
|
Double price_prototipo = this.obtenerPrototipo(presupuesto);
|
|
|
|
opciones.add(new HashMap<String, String>() {
|
|
{
|
|
put("id", "retractilado");
|
|
put("title", messageSource.getMessage("presupuesto.extras-retractilado", null, locale));
|
|
put("description", "");
|
|
put("price", obtenerPrecioRetractilado(presupuesto, locale));
|
|
put("priceUnit", messageSource.getMessage("app.currency-symbol", null, locale));
|
|
}
|
|
});
|
|
opciones.add(new HashMap<String, String>() {
|
|
{
|
|
put("id", "service-isbn");
|
|
put("title", messageSource.getMessage("presupuesto.extras-isbn", null, locale));
|
|
put("description", "");
|
|
put("price", "30");
|
|
put("priceUnit", messageSource.getMessage("app.currency-symbol", null, locale));
|
|
}
|
|
});
|
|
opciones.add(new HashMap<String, String>() {
|
|
{
|
|
put("id", "deposito-legal");
|
|
put("title", messageSource.getMessage("presupuesto.extras-deposito-legal", null, locale));
|
|
put("description",
|
|
messageSource.getMessage("presupuesto.extras-deposito-legal-descripcion", null, locale));
|
|
put("price", "30");
|
|
put("priceUnit", messageSource.getMessage("app.currency-symbol", null, locale));
|
|
}
|
|
});
|
|
opciones.add(new HashMap<String, String>() {
|
|
{
|
|
put("id", "revision-archivos");
|
|
put("title", messageSource.getMessage("presupuesto.extras-revision-archivos", null, locale));
|
|
put("description", "");
|
|
put("price", "50");
|
|
put("priceUnit", messageSource.getMessage("app.currency-symbol", null, locale));
|
|
}
|
|
});
|
|
opciones.add(new HashMap<String, String>() {
|
|
{
|
|
put("id", "maquetacion-cubierta");
|
|
put("title", messageSource.getMessage("presupuesto.extras-maquetacion-cubierta", null, locale));
|
|
put("description", "");
|
|
put("price", "50");
|
|
put("priceUnit", messageSource.getMessage("app.currency-symbol", null, locale));
|
|
}
|
|
});
|
|
opciones.add(new HashMap<String, String>() {
|
|
{
|
|
put("id", "ferro-digital");
|
|
put("title", messageSource.getMessage("presupuesto.extras-ferro-digital", null, locale));
|
|
put("description", "");
|
|
put("price", "0");
|
|
put("priceUnit", messageSource.getMessage("app.currency-symbol", null, locale));
|
|
put("checked", "true");
|
|
put("allowChange", "false");
|
|
put("ribbonText", messageSource.getMessage("presupuesto.extras-ferro-digital-ribbon", null, locale));
|
|
}
|
|
});
|
|
opciones.add(new HashMap<String, String>() {
|
|
{
|
|
put("id", "ejemplar-prueba");
|
|
put("title", messageSource.getMessage("presupuesto.extras-ejemplar-prueba", null, locale));
|
|
put("description", "");
|
|
if (price_prototipo == 0.0) {
|
|
put("price", messageSource.getMessage("presupuesto.consultar-soporte", null, locale));
|
|
put("priceUnit", "");
|
|
} else {
|
|
put("price",
|
|
String.valueOf(Math.round(price_prototipo * 100.0) / 100.0));
|
|
put("priceUnit", messageSource.getMessage("app.currency-symbol", null, locale));
|
|
}
|
|
}
|
|
});
|
|
opciones.add(new HashMap<String, String>() {
|
|
{
|
|
put("id", "marcapaginas");
|
|
put("title", messageSource.getMessage("presupuesto.extras-marcapaginas", null, locale));
|
|
put("description", "");
|
|
put("price", messageSource.getMessage("presupuesto.extras-calcular", null, locale));
|
|
}
|
|
});
|
|
opciones.add(new HashMap<String, String>() {
|
|
{
|
|
put("id", "maquetacion");
|
|
put("title", messageSource.getMessage("presupuesto.extras-maquetacion", null, locale));
|
|
put("description", "");
|
|
put("price", messageSource.getMessage("presupuesto.extras-calcular", null, locale));
|
|
}
|
|
});
|
|
|
|
Map<String, Object> response = new HashMap<>();
|
|
response.put("servicios_extra", opciones);
|
|
return response;
|
|
}
|
|
|
|
public HashMap<String, Object> getPrecioMaquetacion(PresupuestoMaquetacion presupuestoMaquetacion, Locale locale) {
|
|
try {
|
|
List<MaquetacionPrecios> lista = maquetacionPreciosRepository.findAll();
|
|
|
|
java.util.function.Function<String, Double> price = key -> lista.stream()
|
|
.filter(p -> key.equals(p.getKey()))
|
|
.map(MaquetacionPrecios::getValue)
|
|
.findFirst()
|
|
.orElse(0.0);
|
|
|
|
BigDecimal precio = BigDecimal.ZERO;
|
|
|
|
BigDecimal millares = BigDecimal.valueOf(presupuestoMaquetacion.getNumCaracteres()).divide(
|
|
BigDecimal.valueOf(1000), 6, RoundingMode.HALF_UP);
|
|
precio = precio.add(millares.multiply(BigDecimal.valueOf(price.apply("millar_maquetacion"))));
|
|
|
|
int numPaginas = 0;
|
|
Integer matricesPorPagina = maquetacionMatricesRepository.findMatrices(
|
|
presupuestoMaquetacion.getFormato(),
|
|
presupuestoMaquetacion.getCuerpoTexto());
|
|
if (matricesPorPagina != null && matricesPorPagina > 0) {
|
|
numPaginas = presupuestoMaquetacion.getNumCaracteres() / matricesPorPagina;
|
|
}
|
|
|
|
BigDecimal precioRedondeado = precio.setScale(2, RoundingMode.HALF_UP);
|
|
double precioPaginaEstimado = 0.0;
|
|
if (numPaginas > 0) {
|
|
precioPaginaEstimado = precioRedondeado
|
|
.divide(BigDecimal.valueOf(numPaginas), 2, RoundingMode.HALF_UP)
|
|
.doubleValue();
|
|
}
|
|
|
|
// precio calculado por matrices * num. cols -1 * precio por columna
|
|
if (presupuestoMaquetacion.getNumColumnas() > 1) {
|
|
precio = precio.add(precio.multiply(
|
|
BigDecimal.valueOf(presupuestoMaquetacion.getNumColumnas() - 1))
|
|
.multiply(BigDecimal.valueOf(price.apply("columnas"))) );
|
|
}
|
|
|
|
precio = precio
|
|
.add(BigDecimal.valueOf(presupuestoMaquetacion.getNumTablas())
|
|
.multiply(BigDecimal.valueOf(price.apply("tabla"))));
|
|
|
|
precio = precio
|
|
.add(BigDecimal.valueOf(presupuestoMaquetacion.getNumFotos())
|
|
.multiply(BigDecimal.valueOf(price.apply("foto"))));
|
|
|
|
if (presupuestoMaquetacion.isCorreccionOrtotipografica()) {
|
|
precio = precio
|
|
.add(millares.multiply(BigDecimal.valueOf(price.apply("correccion_ortotipografica"))));
|
|
}
|
|
if (presupuestoMaquetacion.isTextoMecanografiado()) {
|
|
precio = precio.add(millares.multiply(BigDecimal.valueOf(price.apply("mecanoescritura_por_millar"))));
|
|
}
|
|
if (presupuestoMaquetacion.isDisenioPortada()) {
|
|
precio = precio.add(BigDecimal.valueOf(price.apply("disenio_portada")));
|
|
}
|
|
if (presupuestoMaquetacion.isEpub()) {
|
|
precio = precio.add(BigDecimal.valueOf(price.apply("epub")));
|
|
}
|
|
|
|
precioRedondeado = precio.setScale(2, RoundingMode.HALF_UP);
|
|
|
|
HashMap<String, Object> out = new HashMap<>();
|
|
out.put("precio", precioRedondeado.doubleValue());
|
|
out.put("numPaginasEstimadas", numPaginas);
|
|
out.put("precioPaginaEstimado", precioPaginaEstimado);
|
|
HashMap<String, String> language = new HashMap<>();
|
|
language.put("num_paginas_estimadas",
|
|
messageSource.getMessage("presupuesto.maquetacion.num-paginas-estimadas", null, locale));
|
|
language.put("precio_por_pagina_estimado",
|
|
messageSource.getMessage("presupuesto.maquetacion.precio-por-pagina-estimado", null, locale));
|
|
language.put("add_to_presupuesto",
|
|
messageSource.getMessage("presupuesto.add-to-presupuesto", null, locale));
|
|
language.put("cancel", messageSource.getMessage("app.cancelar", null, locale));
|
|
language.put("presupuesto_maquetacion", messageSource.getMessage("presupuesto.maquetacion", null, locale));
|
|
out.put("language", language);
|
|
return out;
|
|
|
|
} catch (
|
|
|
|
Exception e) {
|
|
System.out.println("Error procesando presupuesto maquetacion: " + e.getMessage());
|
|
}
|
|
|
|
HashMap<String, Object> out = new HashMap<>();
|
|
out.put("precio", 0.0);
|
|
out.put("numPaginasEstimadas", 0);
|
|
out.put("precioPaginaEstimado", 0.0);
|
|
return out;
|
|
}
|
|
|
|
public HashMap<String, Object> getPrecioMarcapaginas(PresupuestoMarcapaginas presupuestoMarcapaginas,
|
|
Locale locale) {
|
|
try {
|
|
List<Marcapaginas> m = marcapaginasRepository.findPrecios(presupuestoMarcapaginas);
|
|
if (m.isEmpty() || m.get(0) == null) {
|
|
HashMap<String, Object> out = new HashMap<>();
|
|
out.put("precio_unidad", 0.0);
|
|
out.put("precio_total", 0.0);
|
|
return out;
|
|
}
|
|
|
|
Marcapaginas marcapaginas = m.get(0);
|
|
|
|
Double precio = 0.0;
|
|
Double margen = 0.0;
|
|
Double pvp = 0.0;
|
|
BigDecimal data = BigDecimal.ZERO;
|
|
|
|
if (marcapaginas.getUnidades_max() >= presupuestoMarcapaginas.getUnidades()) {
|
|
|
|
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();
|
|
|
|
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();
|
|
|
|
pvp = precio + (precio * margen / 100);
|
|
|
|
data = new BigDecimal(pvp);
|
|
pvp = data.setScale(2, RoundingMode.HALF_UP).doubleValue();
|
|
|
|
} else {
|
|
|
|
// precio unidad para el máximo de unidades
|
|
precio = marcapaginas.getPrecio_unidades_max() / marcapaginas.getUnidades_max();
|
|
precio = precio * presupuestoMarcapaginas.getUnidades();
|
|
data = new BigDecimal(precio);
|
|
precio = data.setScale(2, RoundingMode.HALF_UP).doubleValue();
|
|
|
|
margen = 1.0 * marcapaginas.getMargen_unidades_max();
|
|
data = new BigDecimal(margen);
|
|
margen = data.setScale(2, RoundingMode.HALF_UP).doubleValue();
|
|
|
|
pvp = precio + (precio * margen / 100);
|
|
data = new BigDecimal(pvp);
|
|
pvp = data.setScale(2, RoundingMode.HALF_UP).doubleValue();
|
|
|
|
}
|
|
|
|
Double precio_unidad = pvp / presupuestoMarcapaginas.getUnidades();
|
|
data = new BigDecimal(precio_unidad);
|
|
precio_unidad = data.setScale(6, RoundingMode.HALF_UP).doubleValue();
|
|
|
|
HashMap<String, Object> resultado;
|
|
resultado = new HashMap<>();
|
|
resultado.put("precio_unitario", precio_unidad);
|
|
resultado.put("precio_total", pvp);
|
|
HashMap<String, String> language = new HashMap<>();
|
|
language.put("precio_unidad",
|
|
messageSource.getMessage("presupuesto.marcapaginas.precio-unidad", null, locale));
|
|
language.put("precio_total",
|
|
messageSource.getMessage("presupuesto.marcapaginas.precio-total", null, locale));
|
|
language.put("add_to_presupuesto",
|
|
messageSource.getMessage("presupuesto.add-to-presupuesto", null, locale));
|
|
language.put("cancel", messageSource.getMessage("app.cancelar", null, locale));
|
|
language.put("presupuesto_marcapaginas",
|
|
messageSource.getMessage("presupuesto.marcapaginas", null, locale));
|
|
resultado.put("language", language);
|
|
return resultado;
|
|
|
|
} catch (Exception e) {
|
|
System.out.println("Error procesando presupuesto marcapaginas: " + e.getMessage());
|
|
}
|
|
HashMap<String, Object> out = new HashMap<>();
|
|
out.put("precio_unidad", 0.0);
|
|
out.put("precio_total", 0.0);
|
|
return out;
|
|
}
|
|
|
|
/**
|
|
* Calcula el resumen (SIN persistir cambios de estado).
|
|
* Mantiene firma para no romper llamadas existentes.
|
|
*/
|
|
public Map<String, Object> getTextosResumen(Presupuesto presupuesto, List<Map<String, Object>> servicios,
|
|
Map<String, Object> datosMaquetacion, Map<String, Object> datosMarcapaginas, Locale locale) {
|
|
Map<String, Object> resumen = new HashMap<>();
|
|
resumen.put("titulo", presupuesto.getTitulo());
|
|
|
|
Presupuesto pressupuestoTemp = presupuesto.clone();
|
|
|
|
resumen.put("imagen",
|
|
"/assets/images/imprimelibros/presupuestador/" + presupuesto.getTipoEncuadernacion() + ".png");
|
|
resumen.put("imagen_alt",
|
|
messageSource.getMessage("presupuesto." + presupuesto.getTipoEncuadernacion(), null, locale));
|
|
|
|
boolean hayDepositoLegal = servicios != null && servicios.stream()
|
|
.map(m -> java.util.Objects.toString(m.get("id"), ""))
|
|
.map(String::trim)
|
|
.anyMatch("deposito-legal"::equals);
|
|
|
|
if (hayDepositoLegal) {
|
|
pressupuestoTemp.setSelectedTirada(
|
|
presupuesto.getSelectedTirada() != null ? presupuesto.getSelectedTirada() + 4 : 4);
|
|
for (Integer i = 0; i < pressupuestoTemp.getTiradas().length; i++) {
|
|
Integer tirada = pressupuestoTemp.getTiradas()[i];
|
|
if (tirada != null && tirada >= 4) {
|
|
tirada = tirada + 4;
|
|
}
|
|
pressupuestoTemp.getTiradas()[i] = tirada;
|
|
}
|
|
}
|
|
HashMap<String, Object> precios = this.calcularPresupuesto(pressupuestoTemp, locale);
|
|
if (precios.containsKey("error")) {
|
|
resumen.put("error", precios.get("error"));
|
|
return resumen;
|
|
}
|
|
resumen.put("precios", precios);
|
|
|
|
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() != null ? presupuesto.getSelectedTirada() : 0);
|
|
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++;
|
|
}
|
|
|
|
List<Map<String, Object>> serviciosExtras = new ArrayList<>();
|
|
if (servicios != null) {
|
|
for (Map<String, Object> servicio : servicios) {
|
|
HashMap<String, Object> servicioData = new HashMap<>();
|
|
servicioData.put("id", servicio.get("id"));
|
|
if (servicio.get("id").equals("marcapaginas")) {
|
|
String descripcion = servicio.get("label").toString();
|
|
descripcion += "<br><ul><li>";
|
|
descripcion += Marcapaginas.Tamanios.valueOf(datosMarcapaginas.get("tamanio").toString()).getLabel()
|
|
+ ", ";
|
|
descripcion += Marcapaginas.Caras_Impresion
|
|
.valueOf(datosMarcapaginas.get("carasImpresion").toString()).getMessageKey() + ", ";
|
|
descripcion += messageSource
|
|
.getMessage(Marcapaginas.Papeles.valueOf(datosMarcapaginas.get("papel").toString())
|
|
.getMessageKey(), null, locale)
|
|
+ " - " +
|
|
datosMarcapaginas.get("gramaje").toString() + " gr, ";
|
|
descripcion += messageSource.getMessage(
|
|
Marcapaginas.Acabado.valueOf(datosMarcapaginas.get("acabado").toString()).getMessageKey(),
|
|
null, locale);
|
|
descripcion += "</li></ul>";
|
|
servicioData.put("descripcion", descripcion);
|
|
|
|
} else if (servicio.get("id").equals("maquetacion")) {
|
|
String descripcion = servicio.get("label").toString();
|
|
descripcion += "<br><ul><li>";
|
|
descripcion += (datosMaquetacion.get("num_caracteres") + " "
|
|
+ messageSource.getMessage("presupuesto.maquetacion.caracteres", null, locale)) + ", ";
|
|
descripcion += MaquetacionMatrices.Formato
|
|
.valueOf(datosMaquetacion.get("formato_maquetacion").toString()).getLabel() + ", ";
|
|
descripcion += messageSource.getMessage(MaquetacionMatrices.FontSize
|
|
.valueOf(datosMaquetacion.get("cuerpo_texto").toString()).getMessageKey(), null, locale)
|
|
+ ", ";
|
|
descripcion += messageSource.getMessage("presupuesto.maquetacion.num-columnas", null, locale) + ": "
|
|
+ datosMaquetacion.get("num_columnas").toString() + ", ";
|
|
descripcion += messageSource.getMessage("presupuesto.maquetacion.num-tablas", null, locale) + ": "
|
|
+ datosMaquetacion.get("num_tablas").toString() + ", ";
|
|
descripcion += messageSource.getMessage("presupuesto.maquetacion.num-fotos", null, locale) + ": "
|
|
+ datosMaquetacion.get("num_fotos").toString();
|
|
if ((boolean) datosMaquetacion.get("correccion_ortotipografica")) {
|
|
descripcion += ", " + messageSource
|
|
.getMessage("presupuesto.maquetacion.correccion-ortotipografica", null, locale);
|
|
}
|
|
if ((boolean) datosMaquetacion.get("texto_mecanografiado")) {
|
|
descripcion += ", " + messageSource.getMessage("presupuesto.maquetacion.texto-mecanografiado",
|
|
null, locale);
|
|
}
|
|
if ((boolean) datosMaquetacion.get("disenio_portada")) {
|
|
descripcion += ", "
|
|
+ messageSource.getMessage("presupuesto.maquetacion.diseno-portada", null, locale);
|
|
}
|
|
if ((boolean) datosMaquetacion.get("epub")) {
|
|
descripcion += ", " + messageSource.getMessage("presupuesto.maquetacion.epub", null, locale);
|
|
}
|
|
descripcion += "</li></ul>";
|
|
servicioData.put("descripcion", descripcion);
|
|
} else {
|
|
servicioData.put("descripcion", servicio.get("label"));
|
|
}
|
|
|
|
servicioData.put("precio", servicio.get("id").equals("marcapaginas")
|
|
? Double.parseDouble(servicio.get("price").toString())
|
|
/ Double.parseDouble(servicio.get("units").toString())
|
|
: servicio.get("price"));
|
|
servicioData.put("unidades", servicio.get("units"));
|
|
serviciosExtras.add(servicioData);
|
|
}
|
|
}
|
|
resumen.put("servicios", serviciosExtras);
|
|
|
|
return resumen;
|
|
}
|
|
|
|
/**
|
|
* PÚBLICO: calcula el resumen y GUARDA el presupuesto completo como BORRADOR.
|
|
* Se invoca al entrar en la pestaña "Resumen" del presupuestador público.
|
|
*/
|
|
// PresupuestoService.java
|
|
public Map<String, Object> getResumen(
|
|
Presupuesto presupuesto,
|
|
List<Map<String, Object>> servicios,
|
|
Map<String, Object> datosMaquetacion,
|
|
Map<String, Object> datosMarcapaginas,
|
|
Boolean save,
|
|
String mode,
|
|
Locale locale,
|
|
String sessionId,
|
|
String ip) {
|
|
|
|
// 1) Calcula el resumen (como ya haces)
|
|
try {
|
|
presupuesto.setDatosMaquetacionJson(
|
|
datosMaquetacion != null ? new ObjectMapper().writeValueAsString(datosMaquetacion) : null);
|
|
presupuesto.setDatosMarcapaginasJson(
|
|
datosMarcapaginas != null ? new ObjectMapper().writeValueAsString(datosMarcapaginas) : null);
|
|
} catch (Exception e) {
|
|
System.out.println("Error guardando datos adicionales: " + e.getMessage());
|
|
}
|
|
|
|
Map<String, Object> resumen = getTextosResumen(presupuesto, servicios, datosMaquetacion, datosMarcapaginas,
|
|
locale);
|
|
if (resumen.containsKey("error"))
|
|
return resumen;
|
|
|
|
presupuesto = generateTotalizadores(presupuesto, servicios, resumen, locale);
|
|
|
|
// 3) Enriquecer el Presupuesto a persistir
|
|
presupuesto.setEstado(Presupuesto.Estado.borrador);
|
|
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);
|
|
|
|
// 4) UPSERT: si viene id -> actualiza; si no, reusa el último borrador de la
|
|
// sesión
|
|
Presupuesto entidad;
|
|
if (presupuesto.getId() != null) {
|
|
entidad = presupuestoRepository.findById(presupuesto.getId()).orElse(presupuesto);
|
|
} else {
|
|
entidad = presupuestoRepository
|
|
.findTopBySessionIdAndEstadoOrderByCreatedAtDesc(sessionId, Presupuesto.Estado.borrador)
|
|
.orElse(presupuesto);
|
|
// Si se reutiliza un borrador existente, copia el ID a nuestro objeto para
|
|
// hacer merge
|
|
presupuesto.setId(entidad.getId());
|
|
}
|
|
|
|
// 5) Guardar/actualizar
|
|
entidad = mergePresupuesto(entidad, presupuesto);
|
|
|
|
if (save != null && save) {
|
|
|
|
// Si NO es para guardar (solo calcular resumen), devolver sin persistir
|
|
presupuestoRepository.saveAndFlush(presupuesto);
|
|
}
|
|
|
|
// Opcional: devolver el id guardado al frontend para que lo envíe en llamadas
|
|
// siguientes
|
|
resumen.put("presupuesto_id", entidad.getId());
|
|
resumen.put("precio_unitario", presupuesto.getPrecioUnitario());
|
|
resumen.put("precio_total_tirada", presupuesto.getPrecioTotalTirada());
|
|
resumen.put("servicios_total", presupuesto.getServiciosTotal());
|
|
resumen.put("base_imponible", presupuesto.getBaseImponible());
|
|
resumen.put("iva_importe_4", presupuesto.getIvaImporte4());
|
|
resumen.put("iva_importe_21", presupuesto.getIvaImporte21());
|
|
resumen.put("total_con_iva", presupuesto.getTotalConIva());
|
|
|
|
return resumen;
|
|
}
|
|
|
|
public Presupuesto getDatosLocalizacion(Presupuesto presupuesto, String sessionId, String ip) {
|
|
|
|
presupuesto.setOrigen(Presupuesto.Origen.publico);
|
|
presupuesto.setSessionId(sessionId);
|
|
// IP: guarda hash y trunc (si tienes campos). Si no, guarda tal cual en
|
|
// ip_trunc/ip_hash según tu modelo.
|
|
String ipTrunc = anonymizeIp(ip);
|
|
presupuesto.setIpTrunc(ipTrunc);
|
|
presupuesto.setIpHash(Integer.toHexString(ip.hashCode()));
|
|
|
|
// ubicación (si tienes un servicio GeoIP disponible; si no, omite estas tres
|
|
// líneas)
|
|
try {
|
|
GeoIpService.GeoData geo = geoIpService.lookup(ip).orElse(null);
|
|
presupuesto.setPais(geo.getPais());
|
|
presupuesto.setRegion(geo.getRegion());
|
|
presupuesto.setCiudad(geo.getCiudad());
|
|
} catch (Exception ignore) {
|
|
}
|
|
return presupuesto;
|
|
}
|
|
|
|
public Presupuesto generateTotalizadores(
|
|
Presupuesto presupuesto,
|
|
List<Map<String, Object>> servicios,
|
|
Map<String, Object> resumen,
|
|
Locale locale) {
|
|
|
|
Map<Integer, Map<String, Object>> pricing_snapshot = new HashMap<>();
|
|
|
|
@SuppressWarnings("unchecked")
|
|
Map<String, Object> preciosNode = (Map<String, Object>) resumen.getOrDefault("precios", Map.of());
|
|
@SuppressWarnings("unchecked")
|
|
Map<String, Object> data = (Map<String, Object>) preciosNode.getOrDefault("data", Map.of());
|
|
@SuppressWarnings("unchecked")
|
|
List<Integer> tiradas = (List<Integer>) data.getOrDefault("tiradas", List.of());
|
|
@SuppressWarnings("unchecked")
|
|
List<Double> precios = (List<Double>) data.getOrDefault("precios", List.of());
|
|
@SuppressWarnings("unchecked")
|
|
List<Double> pesos = (List<Double>) data.getOrDefault("peso", List.of());
|
|
|
|
boolean hayDepositoLegal = servicios != null && servicios.stream()
|
|
.map(m -> java.util.Objects.toString(m.get("id"), ""))
|
|
.map(String::trim)
|
|
.anyMatch("deposito-legal"::equals);
|
|
|
|
if (precios.isEmpty()) {
|
|
var preciosCalc = this.calcularPresupuesto(presupuesto, locale);
|
|
precios = (List<Double>) ((Map<String, Object>) preciosCalc.get("data")).getOrDefault("precios", List.of());
|
|
}
|
|
|
|
// iterate getTiradas with a foreach with not null
|
|
for (Integer tirada : presupuesto.getTiradas()) {
|
|
if (tirada == null) {
|
|
continue;
|
|
}
|
|
|
|
// Genera los totalizadores (precio unitario, total tirada, etc.) sin guardar
|
|
double precioUnit = 0.0;
|
|
int cantidad = tirada != null ? tirada : 0;
|
|
int index = tiradas.indexOf(tirada);
|
|
try {
|
|
|
|
if (index >= 0 && index < precios.size()) {
|
|
precioUnit = precios.get(index);
|
|
} else if (!precios.isEmpty()) {
|
|
precioUnit = precios.get(0); // fallback al primero
|
|
}
|
|
// guarda el snapshot completo de precios para auditoría
|
|
presupuesto.setPreciosPorTiradaJson(new ObjectMapper().writeValueAsString(precios));
|
|
} catch (Exception ignore) {
|
|
precioUnit = 0.0;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
// servicios_total
|
|
BigDecimal serviciosIva4 = BigDecimal.ZERO;
|
|
BigDecimal serviciosTotal = BigDecimal.ZERO;
|
|
if (servicios != null) {
|
|
for (Map<String, Object> s : servicios) {
|
|
try {
|
|
// retractilado: recalcular precio
|
|
if (s.get("id").equals("retractilado")) {
|
|
double precio_retractilado = obtenerPrecioRetractilado(cantidad) != null
|
|
? Double.parseDouble(obtenerPrecioRetractilado(cantidad))
|
|
: 0.0;
|
|
s.put("price", precio_retractilado);
|
|
}
|
|
// si tiene protitipo, guardamos el valor para el IVA al 4%
|
|
else if (s.get("id").equals("ejemplar-prueba")) {
|
|
serviciosIva4 = BigDecimal.valueOf(
|
|
s.get("price") != null ? Double.parseDouble(String.valueOf(s.get("price"))) : 0.0);
|
|
}
|
|
double unidades = Double.parseDouble(String.valueOf(s.getOrDefault("units", 0)));
|
|
double precio = Double.parseDouble(String.valueOf(
|
|
s.get("id").equals("marcapaginas")
|
|
? (Double.parseDouble(String.valueOf(s.get("price"))) / unidades) // unidad
|
|
: s.getOrDefault("price", 0)));
|
|
serviciosTotal = serviciosTotal.add(
|
|
BigDecimal.valueOf(precio).multiply(BigDecimal.valueOf(unidades)));
|
|
} catch (Exception ignore) {
|
|
}
|
|
}
|
|
try {
|
|
presupuesto.setServiciosJson(new ObjectMapper().writeValueAsString(servicios));
|
|
} catch (Exception ignore) {
|
|
}
|
|
}
|
|
|
|
BigDecimal baseImponible = precioTotalTirada;
|
|
BigDecimal ivaImporte4 = BigDecimal.ZERO;
|
|
BigDecimal ivaImporte21 = BigDecimal.ZERO;
|
|
|
|
// 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) {
|
|
// Si el iva es reducido, el precio de la tirada y el del prototipo llevan IVA
|
|
// 4%
|
|
if (presupuesto.getIvaReducido()) {
|
|
ivaImporte4 = baseImponible.add(serviciosIva4).multiply(BigDecimal.valueOf(4)).divide(
|
|
BigDecimal.valueOf(100), 2,
|
|
RoundingMode.HALF_UP);
|
|
ivaImporte21 = serviciosTotal.subtract(serviciosIva4).multiply(BigDecimal.valueOf(21)).divide(
|
|
BigDecimal.valueOf(100), 2,
|
|
RoundingMode.HALF_UP);
|
|
} else {
|
|
ivaImporte21 = baseImponible.add(serviciosTotal).multiply(BigDecimal.valueOf(21)).divide(
|
|
BigDecimal.valueOf(100), 2,
|
|
RoundingMode.HALF_UP);
|
|
}
|
|
}
|
|
baseImponible = baseImponible.add(serviciosTotal);
|
|
BigDecimal totalConIva = baseImponible.add(ivaImporte21).add(ivaImporte4);
|
|
|
|
// precios y totales
|
|
if (tirada == (presupuesto.getSelectedTirada() != null ? presupuesto.getSelectedTirada() : 0)) {
|
|
presupuesto.setPrecioUnitario(BigDecimal.valueOf(precioUnit).setScale(6, RoundingMode.HALF_UP));
|
|
presupuesto.setPrecioTotalTirada(precioTotalTirada);
|
|
presupuesto.setServiciosTotal(serviciosTotal);
|
|
presupuesto.setBaseImponible(baseImponible);
|
|
presupuesto.setIvaImporte4(ivaImporte4);
|
|
presupuesto.setIvaImporte21(ivaImporte21);
|
|
presupuesto.setTotalConIva(totalConIva);
|
|
}
|
|
Map<String, Object> snap = new HashMap<>();
|
|
snap.put("precio_unitario", BigDecimal.valueOf(precioUnit).setScale(6, RoundingMode.HALF_UP));
|
|
snap.put("precio_total_tirada", precioTotalTirada);
|
|
snap.put("servicios_total", serviciosTotal);
|
|
snap.put("base_imponible", baseImponible);
|
|
snap.put("iva_importe_4", ivaImporte4);
|
|
snap.put("iva_importe_21", ivaImporte21);
|
|
snap.put("total_con_iva", totalConIva);
|
|
snap.put("peso", (index >= 0 && index < pesos.size()) ? pesos.get(index) : 0.0);
|
|
|
|
pricing_snapshot.put(tirada, snap);
|
|
|
|
}
|
|
|
|
try {
|
|
String json = new ObjectMapper()
|
|
.writer()
|
|
.withDefaultPrettyPrinter() // opcional
|
|
.writeValueAsString(pricing_snapshot);
|
|
presupuesto.setPricingSnapshotJson(pricing_snapshot.isEmpty() ? null : json);
|
|
} catch (Exception ignore) {
|
|
}
|
|
|
|
return presupuesto;
|
|
}
|
|
|
|
@Transactional
|
|
public HashMap<String, Object> guardarPresupuesto(
|
|
Presupuesto presupuesto,
|
|
List<Map<String, Object>> serviciosList,
|
|
Map<String, Object> datosMaquetacion,
|
|
Map<String, Object> datosMarcapaginas,
|
|
String mode,
|
|
Long cliente_id,
|
|
Long id,
|
|
HttpServletRequest request,
|
|
Locale locale) {
|
|
|
|
HashMap<String, Object> result = new HashMap<>();
|
|
try {
|
|
|
|
presupuesto.setDatosMaquetacionJson(
|
|
datosMaquetacion != null ? new ObjectMapper().writeValueAsString(datosMaquetacion) : null);
|
|
presupuesto.setDatosMarcapaginasJson(
|
|
datosMarcapaginas != null ? new ObjectMapper().writeValueAsString(datosMarcapaginas) : null);
|
|
var resumen = this.getTextosResumen(presupuesto, serviciosList, datosMaquetacion, datosMarcapaginas,
|
|
locale);
|
|
|
|
Object serviciosObj = resumen.get("servicios");
|
|
|
|
if (serviciosObj instanceof List<?> servicios && !servicios.isEmpty()) {
|
|
// serializa a JSON válido
|
|
ObjectMapper objectMapper = new ObjectMapper();
|
|
String json = objectMapper.writeValueAsString(servicios);
|
|
presupuesto.setServiciosJson(json);
|
|
} else {
|
|
// decide tu política: null o "[]"
|
|
presupuesto.setServiciosJson(null); // o presupuesto.setServiciosJson("[]");
|
|
}
|
|
|
|
if (cliente_id != null && !mode.equals("public")) {
|
|
|
|
presupuesto.setUser(userRepo.findById(cliente_id).orElse(null));
|
|
presupuesto.setOrigen(Presupuesto.Origen.privado);
|
|
if (id != null) {
|
|
presupuesto.setId(id);
|
|
}
|
|
}
|
|
|
|
if (mode.equals("public")) {
|
|
presupuesto.setOrigen(Presupuesto.Origen.publico);
|
|
String sessionId = request.getSession(true).getId();
|
|
String ip = IpUtils.getClientIp(request);
|
|
|
|
presupuesto = this.getDatosLocalizacion(presupuesto, sessionId, ip);
|
|
if (id != null) {
|
|
presupuesto.setId(id); // para que actualice, no cree uno nuevo
|
|
}
|
|
}
|
|
presupuesto = this.generateTotalizadores(presupuesto, serviciosList, resumen, locale);
|
|
|
|
presupuestoRepository.saveAndFlush(presupuesto);
|
|
|
|
result.put("success", true);
|
|
result.put("presupuesto_id", presupuesto.getId());
|
|
|
|
return result;
|
|
|
|
} catch (Exception e) {
|
|
System.out.println("Error guardando presupuesto: " + e.getMessage());
|
|
result.put("success", false);
|
|
return result;
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* PRIVADO (futuro botón "Guardar"): persiste el presupuesto como borrador.
|
|
*/
|
|
|
|
public HashMap<String, Object> calcularPresupuesto(Presupuesto presupuesto, Locale locale) {
|
|
HashMap<String, Object> price = new HashMap<>();
|
|
String priceStr = apiClient.getPrice(this.toSkApiRequest(presupuesto), presupuesto.getTipoEncuadernacion(),
|
|
presupuesto.getTipoCubierta());
|
|
|
|
try {
|
|
price = new ObjectMapper().readValue(priceStr, new TypeReference<>() {
|
|
});
|
|
} catch (JsonProcessingException e) {
|
|
price = new HashMap<>();
|
|
price.put("error", messageSource.getMessage("presupuesto.error-obtener-precio", null, locale));
|
|
}
|
|
return price;
|
|
}
|
|
|
|
public Boolean canAccessPresupuesto(Presupuesto presupuesto, Authentication authentication) {
|
|
|
|
boolean isUser = authentication.getAuthorities().stream()
|
|
.anyMatch(a -> a.getAuthority().equals("ROLE_USER"));
|
|
|
|
if (isUser) {
|
|
// Si es usuario, solo puede ver sus propios presupuestos
|
|
String username = authentication.getName();
|
|
if (presupuesto.getUser() == null || !presupuesto.getUser().getUserName().equals(username)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// =======================================================================
|
|
// Métodos privados
|
|
// =======================================================================
|
|
/**
|
|
* Copia de campos "actualizables" para no machacar otros (created_at, etc.)
|
|
*/
|
|
private Presupuesto mergePresupuesto(Presupuesto target, Presupuesto src) {
|
|
// Campos funcionales
|
|
target.setTitulo(src.getTitulo());
|
|
target.setTipoEncuadernacion(src.getTipoEncuadernacion());
|
|
target.setTipoCubierta(src.getTipoCubierta());
|
|
target.setTipoImpresion(src.getTipoImpresion());
|
|
target.setPaginasNegro(src.getPaginasNegro());
|
|
target.setPaginasColor(src.getPaginasColor());
|
|
target.setPaginasColorTotal(src.getPaginasColorTotal());
|
|
target.setPosicionPaginasColor(src.getPosicionPaginasColor());
|
|
target.setAncho(src.getAncho());
|
|
target.setAlto(src.getAlto());
|
|
target.setPapelInteriorId(src.getPapelInteriorId());
|
|
target.setGramajeInterior(src.getGramajeInterior());
|
|
target.setPapelCubiertaId(src.getPapelCubiertaId());
|
|
target.setGramajeCubierta(src.getGramajeCubierta());
|
|
target.setCubiertaCaras(src.getCubiertaCaras());
|
|
target.setSolapasCubierta(src.getSolapasCubierta());
|
|
target.setTamanioSolapasCubierta(src.getTamanioSolapasCubierta());
|
|
target.setSobrecubierta(src.getSobrecubierta());
|
|
target.setPapelSobrecubiertaId(src.getPapelSobrecubiertaId());
|
|
target.setGramajeSobrecubierta(src.getGramajeSobrecubierta());
|
|
target.setTamanioSolapasSobrecubierta(src.getTamanioSolapasSobrecubierta());
|
|
target.setAcabado(src.getAcabado());
|
|
target.setCabezada(src.getCabezada());
|
|
target.setTipoCubierta(src.getTipoCubierta());
|
|
target.setSelectedTirada(src.getSelectedTirada());
|
|
target.setTirada1(src.getTirada1());
|
|
target.setTirada2(src.getTirada2());
|
|
target.setTirada3(src.getTirada3());
|
|
target.setTirada4(src.getTirada4());
|
|
|
|
// Metadatos y totales
|
|
target.setEstado(Presupuesto.Estado.borrador);
|
|
target.setOrigen(src.getOrigen());
|
|
target.setSessionId(src.getSessionId());
|
|
target.setIpHash(src.getIpHash());
|
|
target.setIpTrunc(src.getIpTrunc());
|
|
target.setPais(src.getPais());
|
|
target.setRegion(src.getRegion());
|
|
target.setCiudad(src.getCiudad());
|
|
target.setServiciosJson(src.getServiciosJson());
|
|
target.setPreciosPorTiradaJson(src.getPreciosPorTiradaJson());
|
|
target.setPrecioUnitario(src.getPrecioUnitario());
|
|
target.setPrecioTotalTirada(src.getPrecioTotalTirada());
|
|
target.setServiciosTotal(src.getServiciosTotal());
|
|
target.setBaseImponible(src.getBaseImponible());
|
|
target.setIvaReducido(src.getIvaReducido());
|
|
target.setEntregaTipo(src.getEntregaTipo());
|
|
target.setIvaImporte4(src.getIvaImporte4());
|
|
target.setIvaImporte21(src.getIvaImporte21());
|
|
target.setTotalConIva(src.getTotalConIva());
|
|
target.setCreatedBy(target.getCreatedBy() == null ? src.getCreatedBy() : target.getCreatedBy()); // no pisar si
|
|
// ya existe
|
|
|
|
return target;
|
|
}
|
|
|
|
private Double obtenerPrototipo(Presupuesto presupuesto) {
|
|
// Obtenemos el precio de 1 unidad para el ejemplar de prueba
|
|
HashMap<String, Object> price = new HashMap<>();
|
|
Presupuesto presupuestoTemp = presupuesto.clone();
|
|
presupuestoTemp.setTirada1(1);
|
|
presupuestoTemp.setTirada2(null);
|
|
presupuestoTemp.setTirada3(null);
|
|
presupuestoTemp.setTirada4(null);
|
|
if (presupuestoTemp.getTipoImpresion() == Presupuesto.TipoImpresion.color) {
|
|
presupuestoTemp.setTipoImpresion(Presupuesto.TipoImpresion.colorhq);
|
|
} else if (presupuestoTemp.getTipoImpresion() == Presupuesto.TipoImpresion.negro) {
|
|
presupuestoTemp.setTipoImpresion(Presupuesto.TipoImpresion.negrohq);
|
|
}
|
|
String priceStr = apiClient.getPrice(this.toSkApiRequest(presupuestoTemp),
|
|
presupuestoTemp.getTipoEncuadernacion(), presupuestoTemp.getTipoCubierta());
|
|
Double price_prototipo = 0.0;
|
|
try {
|
|
price = new ObjectMapper().readValue(priceStr, new TypeReference<>() {
|
|
});
|
|
price_prototipo = ((List<Double>) ((Map<String, Object>) price.get("data")).get("precios")).get(0);
|
|
if (price_prototipo < 25) {
|
|
price_prototipo = 25.0;
|
|
}
|
|
} catch (JsonProcessingException e) {
|
|
} catch (Exception exception) {
|
|
}
|
|
return price_prototipo;
|
|
}
|
|
|
|
// Utilidad local (puedes moverla a una clase Utils si quieres)
|
|
private static String anonymizeIp(String ip) {
|
|
if (ip == null)
|
|
return null;
|
|
// IPv4
|
|
if (ip.contains(".") && !ip.contains(":")) {
|
|
String[] p = ip.split("\\.");
|
|
if (p.length == 4) {
|
|
return p[0] + "." + p[1] + "." + p[2] + ".0";
|
|
}
|
|
}
|
|
// IPv6: quedarnos con /64 -> primera mitad y rellenar
|
|
if (ip.contains(":")) {
|
|
String[] parts = ip.split(":", -1);
|
|
// expand no estricta, nos quedamos con primeros 4 bloques y completamos
|
|
int blocks = Math.min(parts.length, 4);
|
|
StringBuilder sb = new StringBuilder();
|
|
for (int i = 0; i < blocks; i++) {
|
|
if (i > 0)
|
|
sb.append(":");
|
|
sb.append(parts[i].isEmpty() ? "0" : parts[i]);
|
|
}
|
|
// completar a /64 con ceros
|
|
for (int i = blocks; i < 8; i++)
|
|
sb.append(":0");
|
|
return sb.toString();
|
|
}
|
|
return ip;
|
|
}
|
|
|
|
}
|