mirror of
https://git.imnavajas.es/jjimenez/erp-imprimelibros.git
synced 2026-01-13 00:48:49 +00:00
preparando el imprimir
This commit is contained in:
@ -41,6 +41,10 @@ import com.imprimelibros.erp.presupuesto.maquetacion.MaquetacionMatricesReposito
|
||||
import com.imprimelibros.erp.presupuesto.marcapaginas.MarcapaginasRepository;
|
||||
import com.imprimelibros.erp.users.UserDao;
|
||||
import com.imprimelibros.erp.users.UserDetailsImpl;
|
||||
|
||||
import jakarta.persistence.criteria.CriteriaBuilder.In;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.imprimelibros.erp.externalApi.skApiClient;
|
||||
|
||||
@Service
|
||||
@ -448,6 +452,16 @@ public class PresupuestoService {
|
||||
: "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<>();
|
||||
|
||||
@ -747,13 +761,20 @@ public class PresupuestoService {
|
||||
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;
|
||||
@ -824,7 +845,7 @@ public class PresupuestoService {
|
||||
if (mode.equals("public")) {
|
||||
|
||||
presupuesto = getDatosLocalizacion(presupuesto, sessionId, ip);
|
||||
|
||||
|
||||
} else
|
||||
presupuesto.setOrigen(Presupuesto.Origen.privado);
|
||||
|
||||
@ -847,7 +868,7 @@ public class PresupuestoService {
|
||||
|
||||
if (save != null && save) {
|
||||
// Si NO es para guardar (solo calcular resumen), devolver sin persistir
|
||||
this.guardarPresupuesto(presupuesto);
|
||||
presupuestoRepository.saveAndFlush(presupuesto);
|
||||
}
|
||||
|
||||
// Opcional: devolver el id guardado al frontend para que lo envíe en llamadas
|
||||
@ -865,24 +886,24 @@ public class PresupuestoService {
|
||||
}
|
||||
|
||||
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) {
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@ -892,84 +913,185 @@ public class PresupuestoService {
|
||||
Map<String, Object> resumen,
|
||||
Locale locale) {
|
||||
|
||||
// Genera los totalizadores (precio unitario, total tirada, etc.) sin guardar
|
||||
double precioUnit = 0.0;
|
||||
int cantidad = presupuesto.getSelectedTirada() != null ? presupuesto.getSelectedTirada() : 0;
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Double> precios = (List<Double>) ((Map<String, Object>) resumen.getOrDefault("precios", Map.of()))
|
||||
.getOrDefault("precios", List.of());
|
||||
if (precios.isEmpty()) {
|
||||
// si no venía en "resumen", recalcúlalo directamente
|
||||
var preciosCalc = this.calcularPresupuesto(presupuesto, locale);
|
||||
precios = (List<Double>) ((Map<String, Object>) preciosCalc.get("data")).get("precios");
|
||||
}
|
||||
precioUnit = precios.get(0);
|
||||
// guarda el snapshot completo de precios para auditoría
|
||||
presupuesto.setPreciosPorTiradaJson(new ObjectMapper().writeValueAsString(precios));
|
||||
} catch (Exception ignore) {
|
||||
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());
|
||||
if (precios.isEmpty()) {
|
||||
var preciosCalc = this.calcularPresupuesto(presupuesto, locale);
|
||||
precios = (List<Double>) ((Map<String, Object>) preciosCalc.get("data")).getOrDefault("precios", List.of());
|
||||
}
|
||||
|
||||
BigDecimal precioTotalTirada = BigDecimal.valueOf(precioUnit)
|
||||
.multiply(BigDecimal.valueOf(cantidad))
|
||||
.setScale(2, RoundingMode.HALF_UP);
|
||||
// iterate getTiradas with a foreach with not null
|
||||
for (Integer tirada : presupuesto.getTiradas()) {
|
||||
if (tirada == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// servicios_total
|
||||
BigDecimal serviciosTotal = BigDecimal.ZERO;
|
||||
if (servicios != null) {
|
||||
for (Map<String, Object> s : servicios) {
|
||||
// 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);
|
||||
|
||||
// servicios_total
|
||||
BigDecimal serviciosTotal = BigDecimal.ZERO;
|
||||
if (servicios != null) {
|
||||
for (Map<String, Object> s : servicios) {
|
||||
try {
|
||||
// retractilado o ejemplar-prueba: 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);
|
||||
}
|
||||
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 {
|
||||
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)));
|
||||
presupuesto.setServiciosJson(new ObjectMapper().writeValueAsString(servicios));
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
// base imponible, IVA y total (si tienes IVA configurable, úsalo; si no, 0)
|
||||
BigDecimal baseImponible = precioTotalTirada.add(serviciosTotal);
|
||||
BigDecimal ivaTipo = BigDecimal.ZERO;
|
||||
try {
|
||||
presupuesto.setServiciosJson(new ObjectMapper().writeValueAsString(servicios));
|
||||
double iva = 4.0; // 0..100
|
||||
ivaTipo = BigDecimal.valueOf(iva);
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
BigDecimal ivaImporte = baseImponible.multiply(ivaTipo).divide(BigDecimal.valueOf(100), 2,
|
||||
RoundingMode.HALF_UP);
|
||||
BigDecimal totalConIva = baseImponible.add(ivaImporte);
|
||||
|
||||
// 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.setIvaTipo(ivaTipo);
|
||||
presupuesto.setIvaImporte(ivaImporte);
|
||||
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_tipo", ivaTipo);
|
||||
snap.put("iva_importe", ivaImporte);
|
||||
snap.put("total_con_iva", totalConIva);
|
||||
snap.put("peso", (index >= 0 && index < pesos.size()) ? pesos.get(index) : 0.0);
|
||||
|
||||
pricing_snapshot.put(tirada, snap);
|
||||
|
||||
}
|
||||
|
||||
// base imponible, IVA y total (si tienes IVA configurable, úsalo; si no, 0)
|
||||
BigDecimal baseImponible = precioTotalTirada.add(serviciosTotal);
|
||||
BigDecimal ivaTipo = BigDecimal.ZERO;
|
||||
try {
|
||||
double iva = 4.0; // 0..100
|
||||
ivaTipo = BigDecimal.valueOf(iva);
|
||||
String json = new ObjectMapper()
|
||||
.writer()
|
||||
.withDefaultPrettyPrinter() // opcional
|
||||
.writeValueAsString(pricing_snapshot);
|
||||
presupuesto.setPricingSnapshotJson(pricing_snapshot.isEmpty() ? null : json);
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
BigDecimal ivaImporte = baseImponible.multiply(ivaTipo).divide(BigDecimal.valueOf(100), 2,
|
||||
RoundingMode.HALF_UP);
|
||||
BigDecimal totalConIva = baseImponible.add(ivaImporte);
|
||||
|
||||
// precios y totales
|
||||
presupuesto.setPrecioUnitario(BigDecimal.valueOf(precioUnit).setScale(6, RoundingMode.HALF_UP));
|
||||
presupuesto.setPrecioTotalTirada(precioTotalTirada);
|
||||
presupuesto.setServiciosTotal(serviciosTotal);
|
||||
presupuesto.setBaseImponible(baseImponible);
|
||||
presupuesto.setIvaTipo(ivaTipo);
|
||||
presupuesto.setIvaImporte(ivaImporte);
|
||||
presupuesto.setTotalConIva(totalConIva);
|
||||
|
||||
return presupuesto;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public HashMap<String, Object> guardarPresupuesto(Presupuesto presupuesto) {
|
||||
|
||||
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 p = presupuestoRepository.saveAndFlush(presupuesto);
|
||||
presupuesto.setDatosMaquetacionJson(
|
||||
datosMaquetacion != null ? new ObjectMapper().writeValueAsString(datosMaquetacion) : null);
|
||||
presupuesto.setDatosMarcapaginasJson(
|
||||
datosMarcapaginas != null ? new ObjectMapper().writeValueAsString(datosMarcapaginas) : null);
|
||||
var resumen = this.getTextosResumen(presupuesto, serviciosList, 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 = request.getRemoteAddr();
|
||||
|
||||
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", p.getId());
|
||||
|
||||
result.put("presupuesto_id", presupuesto.getId());
|
||||
|
||||
return result;
|
||||
|
||||
} catch (Exception e) {
|
||||
@ -1007,7 +1129,7 @@ public class PresupuestoService {
|
||||
if (isUser) {
|
||||
// Si es usuario, solo puede ver sus propios presupuestos
|
||||
String username = authentication.getName();
|
||||
if (!presupuesto.getUser().getUserName().equals(username)) {
|
||||
if (presupuesto.getUser() == null || !presupuesto.getUser().getUserName().equals(username)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user