mirror of
https://git.imnavajas.es/jjimenez/erp-imprimelibros.git
synced 2026-01-12 16:38:48 +00:00
784 lines
35 KiB
Java
784 lines
35 KiB
Java
package com.imprimelibros.erp.presupuesto;
|
|
|
|
import org.springframework.stereotype.Controller;
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
import org.springframework.ui.Model;
|
|
|
|
import java.security.Principal;
|
|
import java.time.Instant;
|
|
import java.util.HashMap;
|
|
import java.util.Locale;
|
|
import java.util.Map;
|
|
import java.util.Objects;
|
|
import java.util.Optional;
|
|
import java.util.List;
|
|
import java.util.Set;
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.context.MessageSource;
|
|
import org.springframework.http.ResponseEntity;
|
|
import org.springframework.security.core.Authentication;
|
|
import org.springframework.validation.BindingResult;
|
|
import org.springframework.validation.annotation.Validated;
|
|
import org.springframework.web.bind.annotation.RequestMapping;
|
|
import org.springframework.web.bind.annotation.RequestParam;
|
|
import org.springframework.web.bind.annotation.ResponseBody;
|
|
import org.springframework.web.context.request.RequestContextHolder;
|
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
|
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
|
import org.springframework.web.bind.annotation.DeleteMapping;
|
|
import org.springframework.web.bind.annotation.GetMapping;
|
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
|
import org.springframework.web.bind.annotation.PathVariable;
|
|
import org.springframework.web.bind.annotation.PostMapping;
|
|
import org.springframework.web.bind.annotation.RequestBody;
|
|
import org.springframework.http.HttpStatus;
|
|
import org.springframework.http.MediaType;
|
|
import jakarta.validation.Validator;
|
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
import com.fasterxml.jackson.core.type.TypeReference;
|
|
import com.imprimelibros.erp.configurationERP.VariableService;
|
|
import com.imprimelibros.erp.datatables.*;
|
|
import com.imprimelibros.erp.externalApi.skApiClient;
|
|
import com.imprimelibros.erp.i18n.TranslationService;
|
|
import com.imprimelibros.erp.presupuesto.classes.ImagenPresupuesto;
|
|
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.service.PresupuestoService;
|
|
import com.imprimelibros.erp.presupuesto.validation.PresupuestoValidationGroups;
|
|
import com.imprimelibros.erp.users.UserDao;
|
|
import com.imprimelibros.erp.users.UserDetailsImpl;
|
|
import com.imprimelibros.erp.presupuesto.service.PresupuestoFormDataMapper;
|
|
import com.imprimelibros.erp.presupuesto.service.PresupuestoFormDataMapper.PresupuestoFormDataDto;
|
|
import com.imprimelibros.erp.common.Utils;
|
|
import com.imprimelibros.erp.common.web.IpUtils;
|
|
|
|
import jakarta.servlet.http.HttpServletRequest;
|
|
import jakarta.validation.ConstraintViolation;
|
|
import jakarta.validation.Valid;
|
|
|
|
@Controller
|
|
@RequestMapping("/presupuesto")
|
|
public class PresupuestoController {
|
|
|
|
private final PresupuestoRepository presupuestoRepository;
|
|
|
|
@Autowired
|
|
protected PresupuestoService presupuestoService;
|
|
|
|
@Autowired
|
|
protected skApiClient apiClient;
|
|
|
|
@Autowired
|
|
protected MessageSource messageSource;
|
|
|
|
@Autowired
|
|
private Validator validator;
|
|
|
|
private final ObjectMapper objectMapper;
|
|
private final TranslationService translationService;
|
|
private final PresupuestoDatatableService dtService;
|
|
private final VariableService variableService;
|
|
private final PresupuestoFormDataMapper formDataMapper;
|
|
private final UserDao userRepo;
|
|
|
|
public PresupuestoController(ObjectMapper objectMapper, TranslationService translationService,
|
|
PresupuestoDatatableService dtService, PresupuestoRepository presupuestoRepository,
|
|
VariableService variableService, PresupuestoFormDataMapper formDataMapper, UserDao userRepo) {
|
|
this.objectMapper = objectMapper;
|
|
this.translationService = translationService;
|
|
this.dtService = dtService;
|
|
this.presupuestoRepository = presupuestoRepository;
|
|
this.variableService = variableService;
|
|
this.formDataMapper = formDataMapper;
|
|
this.userRepo = userRepo;
|
|
}
|
|
|
|
@PostMapping("/public/validar/datos-generales")
|
|
public ResponseEntity<?> validarDatosGenerales(
|
|
@Validated(PresupuestoValidationGroups.DatosGenerales.class) Presupuesto presupuesto,
|
|
BindingResult result, Locale locale) {
|
|
|
|
Map<String, String> errores = new HashMap<>();
|
|
|
|
result.getFieldErrors().forEach(error -> {
|
|
String code = Objects.requireNonNullElse(error.getDefaultMessage(), "").replace("{", "").replace("}", "");
|
|
String msg = messageSource.getMessage(code, null, locale);
|
|
errores.put(error.getField(), msg);
|
|
});
|
|
result.getGlobalErrors().forEach(error -> {
|
|
errores.put("global", error.getDefaultMessage());
|
|
});
|
|
if (!errores.isEmpty()) {
|
|
return ResponseEntity.badRequest().body(errores);
|
|
}
|
|
|
|
// opciones color
|
|
Map<String, Object> resultado = presupuestoService.obtenerOpcionesColor(presupuesto, locale);
|
|
|
|
// opciones papel interior
|
|
resultado.putAll(presupuestoService.obtenerOpcionesPapelInterior(presupuesto, locale));
|
|
|
|
// opciones gramaje interior
|
|
resultado.putAll(presupuestoService.obtenerOpcionesGramajeInterior(presupuesto));
|
|
return ResponseEntity.ok(resultado);
|
|
}
|
|
|
|
@PostMapping("/public/validar/interior")
|
|
public ResponseEntity<?> validarInterior(
|
|
@Validated(PresupuestoValidationGroups.Interior.class) Presupuesto presupuesto,
|
|
BindingResult result, Locale locale) {
|
|
|
|
Map<String, String> errores = new HashMap<>();
|
|
|
|
// errores de campos individuales
|
|
result.getFieldErrors().forEach(error -> {
|
|
String code = Objects.requireNonNullElse(error.getDefaultMessage(), "").replace("{", "").replace("}", "");
|
|
String msg = messageSource.getMessage(code, null, locale);
|
|
errores.put(error.getField(), msg);
|
|
});
|
|
|
|
// errores globales (@ConsistentTiradas...)
|
|
result.getGlobalErrors().forEach(error -> errores.put("global", error.getDefaultMessage()));
|
|
|
|
if (!errores.isEmpty()) {
|
|
return ResponseEntity.badRequest().body(errores);
|
|
}
|
|
Map<String, Object> resultado = new HashMap<>();
|
|
resultado.put("solapas", apiClient.getMaxSolapas(presupuestoService.toSkApiRequest(presupuesto), locale));
|
|
resultado.putAll(presupuestoService.obtenerOpcionesAcabadosCubierta(presupuesto, locale));
|
|
return ResponseEntity.ok(resultado);
|
|
}
|
|
|
|
@PostMapping("/public/validar/cubierta")
|
|
public ResponseEntity<?> validarCubierta(
|
|
@Validated(PresupuestoValidationGroups.Cubierta.class) Presupuesto presupuesto,
|
|
BindingResult result,
|
|
@RequestParam(name = "calcular", defaultValue = "true") boolean calcular,
|
|
Locale locale) {
|
|
|
|
Map<String, String> errores = new HashMap<>();
|
|
|
|
// errores de campos individuales
|
|
result.getFieldErrors().forEach(error -> {
|
|
String code = Objects.requireNonNullElse(error.getDefaultMessage(), "").replace("{", "").replace("}", "");
|
|
String msg = messageSource.getMessage(code, null, locale);
|
|
errores.put(error.getField(), msg);
|
|
});
|
|
|
|
// errores globales (@ConsistentTiradas...)
|
|
result.getGlobalErrors().forEach(error -> errores.put("global", error.getDefaultMessage()));
|
|
|
|
if (!errores.isEmpty()) {
|
|
return ResponseEntity.badRequest().body(errores);
|
|
}
|
|
|
|
if (calcular) {
|
|
|
|
HashMap<String, Object> price = presupuestoService.calcularPresupuesto(presupuesto, locale);
|
|
|
|
if (!price.containsKey("data")) {
|
|
return ResponseEntity.badRequest()
|
|
.body(messageSource.getMessage("presupuesto.error-obtener-precio", null, locale));
|
|
}
|
|
return ResponseEntity.ok(price.get("data"));
|
|
|
|
}
|
|
return ResponseEntity.ok().build();
|
|
}
|
|
|
|
@PostMapping("/public/validar/seleccion-tirada")
|
|
public ResponseEntity<?> validarSeleccionTirada(
|
|
Presupuesto presupuesto,
|
|
BindingResult result, Locale locale) {
|
|
|
|
Map<String, String> errores = new HashMap<>();
|
|
|
|
// errores de campos individuales
|
|
result.getFieldErrors().forEach(error -> {
|
|
String code = Objects.requireNonNullElse(error.getDefaultMessage(), "").replace("{", "").replace("}", "");
|
|
String msg = messageSource.getMessage(code, null, locale);
|
|
errores.put(error.getField(), msg);
|
|
});
|
|
|
|
// errores globales (@ConsistentTiradas...)
|
|
result.getGlobalErrors().forEach(error -> errores.put("global", error.getDefaultMessage()));
|
|
|
|
if (!errores.isEmpty()) {
|
|
return ResponseEntity.badRequest().body(errores);
|
|
}
|
|
|
|
Map<String, Object> resultado = new HashMap<>();
|
|
// servicios extra
|
|
resultado.putAll(presupuestoService.obtenerServiciosExtras(presupuesto, locale));
|
|
Map<String, String> language = new HashMap<>();
|
|
language.put("calcular", messageSource.getMessage("presupuesto.calcular", null, locale));
|
|
resultado.put("language", language);
|
|
|
|
return ResponseEntity.ok(resultado);
|
|
}
|
|
|
|
@PostMapping("/public/get-papel-interior")
|
|
public ResponseEntity<?> getPapelInterior(
|
|
@Validated(PresupuestoValidationGroups.Interior.class) Presupuesto presupuesto,
|
|
BindingResult result, Locale locale) {
|
|
|
|
Map<String, String> errores = new HashMap<>();
|
|
|
|
// errores de campos individuales
|
|
result.getFieldErrors().forEach(error -> {
|
|
String code = Objects.requireNonNullElse(error.getDefaultMessage(), "").replace("{", "").replace("}", "");
|
|
String msg = messageSource.getMessage(code, null, locale);
|
|
errores.put(error.getField(), msg);
|
|
});
|
|
|
|
if (!errores.isEmpty()) {
|
|
return ResponseEntity.badRequest().body(errores);
|
|
}
|
|
|
|
// opciones color
|
|
Map<String, Object> resultado = presupuestoService.obtenerOpcionesPapelInterior(presupuesto, locale);
|
|
|
|
// opciones gramaje interior
|
|
resultado.putAll(presupuestoService.obtenerOpcionesGramajeInterior(presupuesto));
|
|
|
|
List<ImagenPresupuesto> opciones_papel = new ObjectMapper().convertValue(
|
|
presupuestoService
|
|
.obtenerOpcionesPapelInterior(presupuesto, locale)
|
|
.get("opciones_papel_interior"),
|
|
new TypeReference<List<ImagenPresupuesto>>() {
|
|
});
|
|
|
|
if (opciones_papel != null && opciones_papel.stream().noneMatch(
|
|
o -> o.getExtra_data().get("sk-id").equals(String.valueOf(presupuesto.getPapelInteriorId())))) {
|
|
presupuesto.setPapelInteriorId(Integer.valueOf(opciones_papel.get(0).getExtra_data().get("sk-id")));
|
|
}
|
|
|
|
List<String> opciones = new ObjectMapper().convertValue(resultado.get("opciones_gramaje_interior"),
|
|
new TypeReference<List<String>>() {
|
|
});
|
|
|
|
if (opciones != null && !opciones.isEmpty()) {
|
|
String gramajeActual = presupuesto.getGramajeInterior().toString();
|
|
if (!opciones.contains(gramajeActual)) {
|
|
presupuesto.setGramajeInterior(Integer.parseInt(opciones.get(0))); // Asignar primera opción
|
|
}
|
|
}
|
|
|
|
resultado.put("solapas", apiClient.getMaxSolapas(presupuestoService.toSkApiRequest(presupuesto), locale));
|
|
return ResponseEntity.ok(resultado);
|
|
}
|
|
|
|
@PostMapping("/public/get-gramaje-interior")
|
|
public ResponseEntity<?> getGramajeInterior(
|
|
@Validated(PresupuestoValidationGroups.Interior.class) Presupuesto presupuesto,
|
|
BindingResult result, Locale locale) {
|
|
|
|
Map<String, String> errores = new HashMap<>();
|
|
|
|
// errores de campos individuales
|
|
result.getFieldErrors().forEach(error -> {
|
|
String code = Objects.requireNonNullElse(error.getDefaultMessage(), "").replace("{", "").replace("}", "");
|
|
String msg = messageSource.getMessage(code, null, locale);
|
|
errores.put(error.getField(), msg);
|
|
});
|
|
|
|
if (!errores.isEmpty()) {
|
|
return ResponseEntity.badRequest().body(errores);
|
|
}
|
|
|
|
Map<String, Object> resultado = presupuestoService.obtenerOpcionesGramajeInterior(presupuesto);
|
|
List<String> opciones = new ObjectMapper().convertValue(resultado.get("opciones_gramaje_interior"),
|
|
new TypeReference<List<String>>() {
|
|
});
|
|
|
|
if (opciones != null && !opciones.isEmpty()) {
|
|
String gramajeActual = presupuesto.getGramajeInterior().toString();
|
|
if (!opciones.contains(gramajeActual)) {
|
|
presupuesto.setGramajeInterior(Integer.parseInt(opciones.get(0))); // Asignar primera opción
|
|
}
|
|
}
|
|
resultado.put("solapas", apiClient.getMaxSolapas(presupuestoService.toSkApiRequest(presupuesto), locale));
|
|
return ResponseEntity.ok(resultado);
|
|
}
|
|
|
|
@PostMapping("/public/get-max-solapas")
|
|
public ResponseEntity<?> getMaxSolapas(
|
|
@Validated(PresupuestoValidationGroups.Interior.class) Presupuesto presupuesto,
|
|
BindingResult result, Locale locale) {
|
|
|
|
Map<String, String> errores = new HashMap<>();
|
|
|
|
// errores de campos individuales
|
|
result.getFieldErrors().forEach(error -> {
|
|
String code = Objects.requireNonNullElse(error.getDefaultMessage(), "").replace("{", "").replace("}", "");
|
|
String msg = messageSource.getMessage(code, null, locale);
|
|
errores.put(error.getField(), msg);
|
|
});
|
|
|
|
if (!errores.isEmpty()) {
|
|
return ResponseEntity.badRequest().body(errores);
|
|
}
|
|
|
|
Map<String, Object> resultado = new HashMap<>();
|
|
resultado.put("solapas", apiClient.getMaxSolapas(presupuestoService.toSkApiRequest(presupuesto), locale));
|
|
return ResponseEntity.ok(resultado);
|
|
}
|
|
|
|
@PostMapping("/public/get-papel-cubierta")
|
|
public ResponseEntity<?> getPapelCubierta(
|
|
Presupuesto presupuesto,
|
|
BindingResult result, Locale locale) {
|
|
|
|
Map<String, Object> resultado = new HashMap<>();
|
|
Map<String, Object> papelesCubierta = presupuestoService.obtenerOpcionesPapelCubierta(presupuesto, locale);
|
|
List<ImagenPresupuesto> opciones = new ObjectMapper().convertValue(
|
|
presupuestoService
|
|
.obtenerOpcionesPapelCubierta(presupuesto, locale)
|
|
.get("opciones_papel_cubierta"),
|
|
new TypeReference<List<ImagenPresupuesto>>() {
|
|
});
|
|
|
|
if (opciones != null && opciones.stream().noneMatch(
|
|
o -> o.getExtra_data().get("sk-id").equals(String.valueOf(presupuesto.getPapelCubiertaId())))) {
|
|
presupuesto.setPapelCubiertaId(Integer.valueOf(opciones.get(0).getExtra_data().get("sk-id")));
|
|
}
|
|
resultado.putAll(papelesCubierta);
|
|
|
|
resultado.putAll(presupuestoService.obtenerOpcionesGramajeCubierta(presupuesto));
|
|
List<String> gramajesCubierta = new ObjectMapper().convertValue(
|
|
resultado.get("opciones_gramaje_cubierta"),
|
|
new TypeReference<List<String>>() {
|
|
});
|
|
if (gramajesCubierta != null && !gramajesCubierta.isEmpty()) {
|
|
String gramajeActual = presupuesto.getGramajeCubierta().toString();
|
|
if (!gramajesCubierta.contains(gramajeActual)) {
|
|
presupuesto.setGramajeCubierta(Integer.parseInt(gramajesCubierta.get(0))); // Asignar primera opción
|
|
}
|
|
}
|
|
return ResponseEntity.ok(resultado);
|
|
}
|
|
|
|
@PostMapping("/public/get-gramaje-cubierta")
|
|
public ResponseEntity<?> getGramajeCubierta(
|
|
Presupuesto presupuesto,
|
|
BindingResult result) {
|
|
|
|
Map<String, Object> resultado = presupuestoService.obtenerOpcionesGramajeCubierta(presupuesto);
|
|
List<String> gramajesCubierta = (List<String>) resultado.get("opciones_gramaje_cubierta");
|
|
if (gramajesCubierta != null && !gramajesCubierta.isEmpty()) {
|
|
String gramajeActual = presupuesto.getGramajeCubierta().toString();
|
|
if (!gramajesCubierta.contains(gramajeActual)) {
|
|
presupuesto.setGramajeCubierta(Integer.parseInt(gramajesCubierta.get(0))); // Asignar primera opción
|
|
}
|
|
}
|
|
return ResponseEntity.ok(resultado);
|
|
}
|
|
|
|
@PostMapping("/public/get-acabados-cubierta")
|
|
public ResponseEntity<?> getAcabadosCubierta(
|
|
Presupuesto presupuesto,
|
|
BindingResult result, Locale locale) {
|
|
|
|
Map<String, Object> resultado = presupuestoService.obtenerOpcionesAcabadosCubierta(presupuesto, locale);
|
|
|
|
return ResponseEntity.ok(resultado);
|
|
}
|
|
|
|
@PostMapping("/public/get-price")
|
|
public ResponseEntity<?> getPrice(
|
|
Presupuesto presupuesto,
|
|
BindingResult result, Locale locale) {
|
|
|
|
Map<String, String> errores = new HashMap<>();
|
|
// errores de campos individuales
|
|
result.getFieldErrors().forEach(error -> errores.put(error.getField(), error.getDefaultMessage()));
|
|
// errores globales (@ConsistentTiradas...)
|
|
result.getGlobalErrors().forEach(error -> errores.put("global", error.getDefaultMessage()));
|
|
if (!errores.isEmpty()) {
|
|
return ResponseEntity.badRequest().body(errores);
|
|
}
|
|
String price = apiClient.getPrice(presupuestoService.toSkApiRequest(presupuesto),
|
|
presupuesto.getTipoEncuadernacion(), presupuesto.getTipoCubierta());
|
|
if (price == null || price.isEmpty()) {
|
|
return ResponseEntity.badRequest().body("No se pudo obtener el precio. Intente nuevamente.");
|
|
}
|
|
return ResponseEntity.ok(price);
|
|
|
|
}
|
|
|
|
@GetMapping(value = "/public/maquetacion/form", produces = MediaType.TEXT_HTML_VALUE)
|
|
public String getMaquetacionForm(Model model) {
|
|
model.addAttribute("presupuestoMaquetacion", new PresupuestoMaquetacion());
|
|
return "imprimelibros/presupuestos/presupuesto-maquetacion-form :: maquetacionForm";
|
|
}
|
|
|
|
@GetMapping("/public/maquetacion")
|
|
public ResponseEntity<?> getPresupuestoMaquetacion(
|
|
@Valid @ModelAttribute PresupuestoMaquetacion presupuestoMaquetacion,
|
|
BindingResult result,
|
|
Locale locale) {
|
|
|
|
if (result.hasErrors()) {
|
|
// Construimos un mapa field -> mensaje para tu AJAX
|
|
Map<String, String> errores = result.getFieldErrors().stream()
|
|
.collect(java.util.stream.Collectors.toMap(
|
|
fe -> fe.getField(),
|
|
fe -> fe.getDefaultMessage(),
|
|
(a, b) -> a));
|
|
return ResponseEntity.badRequest().body(errores);
|
|
}
|
|
|
|
Map<String, Object> resultado = presupuestoService.getPrecioMaquetacion(presupuestoMaquetacion, locale);
|
|
if ((Double) resultado.get("precio") == 0.0 && (Integer) resultado.get("numPaginasEstimadas") == 0
|
|
&& (Double) resultado.get("precioPaginaEstimado") == 0.0) {
|
|
return ResponseEntity.badRequest()
|
|
.body(messageSource.getMessage("presupuesto.errores.presupuesto-maquetacion", null, locale));
|
|
}
|
|
return ResponseEntity.ok(resultado);
|
|
}
|
|
|
|
@GetMapping(value = "/public/marcapaginas/form", produces = MediaType.TEXT_HTML_VALUE)
|
|
public String getMarcapaginasForm(Model model) {
|
|
model.addAttribute("presupuestoMarcapaginas", new PresupuestoMarcapaginas());
|
|
return "imprimelibros/presupuestos/presupuesto-marcapaginas-form :: marcapaginasForm";
|
|
}
|
|
|
|
@GetMapping("/public/marcapaginas")
|
|
public ResponseEntity<?> getPresupuestoMarcapaginas(
|
|
@Valid @ModelAttribute PresupuestoMarcapaginas presupuestoMarcapaginas,
|
|
BindingResult result,
|
|
Locale locale) {
|
|
|
|
if (result.hasErrors()) {
|
|
// Construimos un mapa field -> mensaje para tu AJAX
|
|
Map<String, String> errores = result.getFieldErrors().stream()
|
|
.collect(java.util.stream.Collectors.toMap(
|
|
fe -> fe.getField(),
|
|
fe -> fe.getDefaultMessage(),
|
|
(a, b) -> a));
|
|
return ResponseEntity.badRequest().body(errores);
|
|
}
|
|
|
|
Map<String, Object> resultado = presupuestoService.getPrecioMarcapaginas(presupuestoMarcapaginas, locale);
|
|
if ((Double) resultado.get("precio_total") == 0.0 && (Double) resultado.get("precio_unitario") == 0.0) {
|
|
return ResponseEntity.badRequest()
|
|
.body(messageSource.getMessage("presupuesto.errores.presupuesto-marcapaginas", null, locale));
|
|
}
|
|
return ResponseEntity.ok(resultado);
|
|
}
|
|
|
|
// Se hace un post para no tener problemas con la longitud de la URL
|
|
@PostMapping("/public/resumen")
|
|
public ResponseEntity<?> getResumen(
|
|
@RequestBody Map<String, Object> body,
|
|
Locale locale,
|
|
HttpServletRequest request) {
|
|
|
|
Presupuesto p = objectMapper.convertValue(body.get("presupuesto"), Presupuesto.class);
|
|
Boolean save = objectMapper.convertValue(body.get("save"), Boolean.class);
|
|
String mode = objectMapper.convertValue(body.get("mode"), String.class);
|
|
@SuppressWarnings("unchecked")
|
|
List<Map<String, Object>> serviciosList = (List<Map<String, Object>>) body.getOrDefault("servicios", List.of());
|
|
@SuppressWarnings("unchecked")
|
|
Map<String, Object> datosMaquetacion = (Map<String, Object>) objectMapper
|
|
.convertValue(body.get("datosMaquetacion"), Map.class);
|
|
@SuppressWarnings("unchecked")
|
|
Map<String, Object> datosMarcapaginas = (Map<String, Object>) objectMapper
|
|
.convertValue(body.get("datosMarcapaginas"), Map.class);
|
|
|
|
String sessionId = request.getSession(true).getId();
|
|
String ip = IpUtils.getClientIp(request);
|
|
|
|
var resumen = presupuestoService.getResumen(p, serviciosList, datosMaquetacion, datosMarcapaginas, save, mode, locale, sessionId, ip);
|
|
|
|
return ResponseEntity.ok(resumen);
|
|
}
|
|
|
|
// =============================================
|
|
// MÉTODOS PARA USUARIOS AUTENTICADOS
|
|
// =============================================
|
|
@GetMapping
|
|
public String getPresupuestoList(Model model, Authentication authentication, Locale locale) {
|
|
|
|
List<String> keys = List.of(
|
|
"presupuesto.delete.title",
|
|
"presupuesto.delete.text",
|
|
"presupuesto.eliminar",
|
|
"presupuesto.delete.button",
|
|
"app.yes",
|
|
"app.cancelar",
|
|
"presupuesto.delete.ok.title",
|
|
"presupuesto.delete.ok.text",
|
|
"presupuesto.add.tipo",
|
|
"presupuesto.add.anonimo",
|
|
"presupuesto.add.cliente",
|
|
"presupuesto.add.next",
|
|
"presupuesto.add.cancel",
|
|
"presupuesto.add.select-client",
|
|
"presupuesto.add.error.options",
|
|
"presupuesto.add.error.options-client");
|
|
|
|
Map<String, String> translations = translationService.getTranslations(locale, keys);
|
|
model.addAttribute("languageBundle", translations);
|
|
|
|
return "imprimelibros/presupuestos/presupuesto-list";
|
|
}
|
|
|
|
@GetMapping(value = { "/edit/{id}", "/view/{id}" })
|
|
public String getPresupuestoEditForm(
|
|
@PathVariable(name = "id", required = true) Long id,
|
|
RedirectAttributes redirectAttributes,
|
|
Model model,
|
|
Authentication authentication,
|
|
Locale locale) {
|
|
|
|
List<String> keys = List.of(
|
|
"presupuesto.plantilla-cubierta",
|
|
"presupuesto.plantilla-cubierta-text",
|
|
"presupuesto.impresion-cubierta",
|
|
"presupuesto.impresion-cubierta-help",
|
|
"presupuesto.exito.guardado",
|
|
"presupuesto.add.error.save.title",
|
|
"presupuesto.iva-reducido",
|
|
"presupuesto.iva-reducido-descripcion");
|
|
|
|
Map<String, String> translations = translationService.getTranslations(locale, keys);
|
|
model.addAttribute("languageBundle", translations);
|
|
model.addAttribute("pod", variableService.getValorEntero("POD"));
|
|
model.addAttribute("ancho_alto_min", variableService.getValorEntero("ancho_alto_min"));
|
|
model.addAttribute("ancho_alto_max", variableService.getValorEntero("ancho_alto_max"));
|
|
|
|
// Buscar el presupuesto
|
|
Optional<Presupuesto> presupuestoOpt = presupuestoRepository.findById(id);
|
|
|
|
if (presupuestoOpt.isEmpty()) {
|
|
// Añadir mensaje flash para mostrar alerta
|
|
redirectAttributes.addFlashAttribute("errorMessage",
|
|
messageSource.getMessage("presupuesto.errores.presupuesto-no-existe", new Object[] { id }, locale));
|
|
// Redirigir a la vista de lista
|
|
return "redirect:/presupuesto";
|
|
}
|
|
|
|
if(presupuestoOpt.get().getEstado() == Presupuesto.Estado.aceptado){
|
|
|
|
Map<String, Object> resumen = presupuestoService.getTextosResumen(
|
|
presupuestoOpt.get(),
|
|
Utils.decodeJsonList(presupuestoOpt.get().getServiciosJson()),
|
|
Utils.decodeJsonMap(presupuestoOpt.get().getDatosMaquetacionJson()),
|
|
Utils.decodeJsonMap(presupuestoOpt.get().getDatosMarcapaginasJson()),
|
|
locale);
|
|
|
|
model.addAttribute("resumen", resumen);
|
|
model.addAttribute("presupuesto", presupuestoOpt.get());
|
|
return "imprimelibros/presupuestos/presupuestador-view";
|
|
}
|
|
|
|
if (!presupuestoService.canAccessPresupuesto(presupuestoOpt.get(), authentication)) {
|
|
// Añadir mensaje flash para mostrar alerta
|
|
redirectAttributes.addFlashAttribute("errorMessage",
|
|
messageSource.getMessage("app.errors.403", null, locale));
|
|
// Redirigir a la vista de lista
|
|
return "redirect:/presupuesto";
|
|
}
|
|
|
|
model.addAttribute("presupuesto_id", presupuestoOpt.get().getId());
|
|
String path = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
|
|
.getRequest().getRequestURI();
|
|
String mode = path.contains("/view/") ? "view" : "edit";
|
|
if (mode.equals("view") || presupuestoOpt.get().getEstado() != Presupuesto.Estado.borrador) {
|
|
model.addAttribute("appMode", "view");
|
|
} else {
|
|
model.addAttribute("cliente_id", presupuestoOpt.get().getUser().getId());
|
|
model.addAttribute("appMode", "edit");
|
|
}
|
|
model.addAttribute("id", presupuestoOpt.get().getId());
|
|
return "imprimelibros/presupuestos/presupuesto-form";
|
|
}
|
|
|
|
@GetMapping(value = { "/add/{mode}", "/add/{mode}/{cliente_id}", "/add2/{cliente_id}" })
|
|
public String getPresupuestoEditForm(
|
|
@PathVariable(name = "mode", required = false) String mode,
|
|
@PathVariable(name = "cliente_id", required = false) Long clienteId,
|
|
RedirectAttributes redirectAttributes,
|
|
Model model,
|
|
Authentication authentication,
|
|
Locale locale) {
|
|
|
|
List<String> keys = List.of(
|
|
"presupuesto.plantilla-cubierta",
|
|
"presupuesto.plantilla-cubierta-text",
|
|
"presupuesto.impresion-cubierta",
|
|
"presupuesto.impresion-cubierta-help",
|
|
"presupuesto.exito.guardado",
|
|
"presupuesto.add.error.save.title",
|
|
"presupuesto.iva-reducido",
|
|
"presupuesto.iva-reducido-descripcion");
|
|
|
|
Map<String, String> translations = translationService.getTranslations(locale, keys);
|
|
model.addAttribute("languageBundle", translations);
|
|
model.addAttribute("pod", variableService.getValorEntero("POD"));
|
|
model.addAttribute("ancho_alto_min", variableService.getValorEntero("ancho_alto_min"));
|
|
model.addAttribute("ancho_alto_max", variableService.getValorEntero("ancho_alto_max"));
|
|
|
|
model.addAttribute("appMode", "add");
|
|
|
|
if (!mode.equals("public")) {
|
|
model.addAttribute("cliente_id", clienteId);
|
|
}
|
|
|
|
model.addAttribute("mode", mode);
|
|
return "imprimelibros/presupuestos/presupuesto-form";
|
|
}
|
|
|
|
@GetMapping(value = "/datatable/{tipo}", produces = "application/json")
|
|
@ResponseBody
|
|
public DataTablesResponse<Map<String, Object>> datatable(
|
|
HttpServletRequest request, Authentication auth, Locale locale,
|
|
@PathVariable("tipo") String tipo, Principal principal) {
|
|
|
|
DataTablesRequest dt = DataTablesParser.from(request);
|
|
|
|
if ("anonimos".equals(tipo)) {
|
|
return dtService.datatablePublicos(dt, locale, principal);
|
|
} else if ("clientes".equals(tipo)) {
|
|
return dtService.datatablePrivados(dt, locale, principal);
|
|
} else {
|
|
throw new IllegalArgumentException("Tipo de datatable no válido");
|
|
}
|
|
}
|
|
|
|
@DeleteMapping("/{id}")
|
|
@Transactional
|
|
public ResponseEntity<?> delete(@PathVariable Long id, Authentication auth, Locale locale) {
|
|
|
|
Presupuesto p = presupuestoRepository.findById(id).orElse(null);
|
|
if (p == null) {
|
|
return ResponseEntity.status(HttpStatus.NOT_FOUND)
|
|
.body(Map.of("message", messageSource.getMessage("presupuesto.error.not-found", null, locale)));
|
|
}
|
|
|
|
boolean isUser = auth != null && auth.getAuthorities().stream()
|
|
.anyMatch(a -> a.getAuthority().equals("ROLE_USER"));
|
|
|
|
Long ownerId = p.getUser() != null ? p.getUser().getId() : null;
|
|
Long currentUserId = null;
|
|
if (auth != null && auth.getPrincipal() instanceof UserDetailsImpl udi) {
|
|
currentUserId = udi.getId();
|
|
} else if (auth != null) {
|
|
currentUserId = userRepo.findIdByUserNameIgnoreCase(auth.getName()).orElse(null);
|
|
}
|
|
boolean isOwner = ownerId != null && ownerId.equals(currentUserId);
|
|
|
|
if (isUser && !isOwner) {
|
|
return ResponseEntity.status(HttpStatus.FORBIDDEN)
|
|
.body(Map.of("message",
|
|
messageSource.getMessage("presupuesto.error.delete-permission-denied", null, locale)));
|
|
}
|
|
|
|
if (p.getEstado() != null && !p.getEstado().equals(Presupuesto.Estado.borrador)) {
|
|
return ResponseEntity.status(HttpStatus.FORBIDDEN)
|
|
.body(Map.of("message",
|
|
messageSource.getMessage("presupuesto.error.delete-not-draft", null, locale)));
|
|
}
|
|
|
|
try {
|
|
p.setDeleted(true);
|
|
p.setDeletedAt(Instant.now());
|
|
|
|
if (auth != null && auth.getPrincipal() instanceof UserDetailsImpl udi) {
|
|
p.setDeletedBy(userRepo.getReferenceById(udi.getId()));
|
|
} else if (auth != null) {
|
|
userRepo.findByUserNameIgnoreCase(auth.getName()).ifPresent(p::setDeletedBy);
|
|
}
|
|
presupuestoRepository.saveAndFlush(p);
|
|
|
|
return ResponseEntity.ok(Map.of("message",
|
|
messageSource.getMessage("presupuesto.exito.eliminado", null, locale)));
|
|
|
|
} catch (Exception ex) {
|
|
// Devuelve SIEMPRE algo en el catch
|
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
|
.body(Map.of("message",
|
|
messageSource.getMessage("presupuesto.error.delete-internal-error", null, locale),
|
|
"detail",
|
|
ex.getClass().getSimpleName() + ": " + (ex.getMessage() != null ? ex.getMessage() : "")));
|
|
}
|
|
}
|
|
|
|
@GetMapping(value = "/api/get", produces = "application/json")
|
|
public ResponseEntity<PresupuestoFormDataDto> getPresupuesto(
|
|
@RequestParam("id") Long id, Authentication authentication) {
|
|
|
|
Optional<Presupuesto> presupuestoOpt = presupuestoRepository.findById(id);
|
|
|
|
if (!presupuestoService.canAccessPresupuesto(presupuestoOpt.get(), authentication)) {
|
|
return ResponseEntity.status(403).build();
|
|
}
|
|
|
|
if (presupuestoOpt.isPresent()) {
|
|
PresupuestoFormDataDto vm = formDataMapper.toFormData(presupuestoOpt.get());
|
|
return ResponseEntity.ok(vm);
|
|
} else {
|
|
return ResponseEntity.notFound().build();
|
|
}
|
|
}
|
|
|
|
@PostMapping(path = "/api/save")
|
|
public ResponseEntity<?> save(
|
|
@RequestBody Map<String, Object> body,
|
|
Locale locale, HttpServletRequest request) {
|
|
|
|
Presupuesto presupuesto = objectMapper.convertValue(body.get("presupuesto"), Presupuesto.class);
|
|
Long id = objectMapper.convertValue(body.get("id"), Long.class);
|
|
String mode = objectMapper.convertValue(body.get("mode"), String.class);
|
|
@SuppressWarnings("unchecked")
|
|
List<Map<String, Object>> serviciosList = (List<Map<String, Object>>) body.getOrDefault("servicios", List.of());
|
|
Long cliente_id = objectMapper.convertValue(body.get("cliente_id"), Long.class);
|
|
Map<String, Object> datosMaquetacion = (Map<String, Object>) objectMapper
|
|
.convertValue(body.get("datosMaquetacion"), Map.class);
|
|
Map<String, Object> datosMarcapaginas = (Map<String, Object>) objectMapper
|
|
.convertValue(body.get("datosMarcapaginas"), Map.class);
|
|
|
|
Set<ConstraintViolation<Presupuesto>> violations = validator.validate(presupuesto,
|
|
PresupuestoValidationGroups.All.class);
|
|
|
|
if (!violations.isEmpty()) {
|
|
Map<String, String> errores = new HashMap<>();
|
|
for (ConstraintViolation<Presupuesto> v : violations) {
|
|
String campo = v.getPropertyPath().toString();
|
|
String mensaje = messageSource.getMessage(v.getMessage().replace("{", "").replace("}", ""), null,
|
|
locale);
|
|
errores.put(campo, mensaje);
|
|
}
|
|
return ResponseEntity.badRequest().body(errores);
|
|
}
|
|
|
|
try {
|
|
|
|
Map<String, Object> saveResult = presupuestoService.guardarPresupuesto(
|
|
presupuesto,
|
|
serviciosList,
|
|
datosMaquetacion,
|
|
datosMarcapaginas,
|
|
mode,
|
|
cliente_id,
|
|
id,
|
|
request,
|
|
locale);
|
|
|
|
return ResponseEntity.ok(Map.of("id", saveResult.get("presupuesto_id"),
|
|
"message", messageSource.getMessage("presupuesto.exito.guardado", null, locale)));
|
|
} catch (Exception ex) {
|
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
|
.body(Map.of("message",
|
|
messageSource.getMessage("presupuesto.error.save-internal-error", null, locale),
|
|
"detail",
|
|
ex.getClass().getSimpleName() + ": " + (ex.getMessage() != null ? ex.getMessage() : "")));
|
|
}
|
|
}
|
|
|
|
}
|