mirror of
https://git.imnavajas.es/jjimenez/erp-imprimelibros.git
synced 2026-01-13 08:58:48 +00:00
añadida validacion en el backend para datos generales
This commit is contained in:
@ -4,6 +4,7 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
|
||||
@Configuration
|
||||
public class SecurityConfig {
|
||||
@ -11,15 +12,24 @@ public class SecurityConfig {
|
||||
@Bean
|
||||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeHttpRequests(auth -> auth
|
||||
.requestMatchers("/", "/assets/**", "/css/**", "/js/**", "/images/**", "/public/**").permitAll()
|
||||
.anyRequest().authenticated()
|
||||
)
|
||||
.formLogin(login -> login
|
||||
//.loginPage("/login") añadir cuando se tenga login personalizado
|
||||
.permitAll()
|
||||
)
|
||||
.logout(logout -> logout.permitAll());
|
||||
.authorizeHttpRequests(auth -> auth
|
||||
.requestMatchers(
|
||||
"/",
|
||||
"/assets/**",
|
||||
"/css/**",
|
||||
"/js/**",
|
||||
"/images/**",
|
||||
"/public/**",
|
||||
"/error",
|
||||
"/presupuesto/validar/**")
|
||||
.permitAll()
|
||||
.anyRequest().authenticated())
|
||||
.csrf(csrf -> csrf
|
||||
.ignoringRequestMatchers("/presupuesto/validar/**"))
|
||||
.formLogin(login -> login
|
||||
// .loginPage("/login") añadir cuando se tenga login personalizado
|
||||
.permitAll())
|
||||
.logout(logout -> logout.permitAll());
|
||||
|
||||
return http.build();
|
||||
}
|
||||
|
||||
@ -0,0 +1,16 @@
|
||||
package com.imprimelibros.erp.config.validation;
|
||||
|
||||
import jakarta.validation.Constraint;
|
||||
import jakarta.validation.Payload;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Documented
|
||||
@Constraint(validatedBy = ConsistentTiradasValidator.class)
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ConsistentTiradas {
|
||||
String message() default "Las tiradas deben ser todas mayores o todas menores al valor POD";
|
||||
Class<?>[] groups() default {};
|
||||
Class<? extends Payload>[] payload() default {};
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
package com.imprimelibros.erp.config.validation;
|
||||
|
||||
import com.imprimelibros.erp.entity.Presupuesto;
|
||||
import com.imprimelibros.erp.service.VariableService;
|
||||
import jakarta.validation.ConstraintValidator;
|
||||
import jakarta.validation.ConstraintValidatorContext;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
|
||||
public class ConsistentTiradasValidator implements ConstraintValidator<ConsistentTiradas, Presupuesto> {
|
||||
|
||||
@Autowired
|
||||
private VariableService variableService;
|
||||
@Autowired
|
||||
private MessageSource messageSource;
|
||||
|
||||
@Override
|
||||
public boolean isValid(Presupuesto presupuesto, ConstraintValidatorContext context) {
|
||||
if (presupuesto == null)
|
||||
return true;
|
||||
|
||||
Integer[] tiradas = presupuesto.getTiradas();
|
||||
Integer podValue = variableService.getValorEntero("POD");
|
||||
|
||||
boolean allAbove = true;
|
||||
boolean allBelow = true;
|
||||
|
||||
for (Integer t : tiradas) {
|
||||
if (t == null)
|
||||
continue;
|
||||
if (t <= podValue)
|
||||
allAbove = false;
|
||||
if (t >= podValue)
|
||||
allBelow = false;
|
||||
}
|
||||
|
||||
if (!(allAbove || allBelow)) {
|
||||
|
||||
String mensajeInterpolado = messageSource.getMessage(
|
||||
"presupuesto.errores.tiradas.consistentes", // clave del mensaje
|
||||
new Object[] { podValue }, // parámetros para {0}
|
||||
LocaleContextHolder.getLocale() // respeta el idioma actual
|
||||
);
|
||||
context.disableDefaultConstraintViolation();
|
||||
context.buildConstraintViolationWithTemplate(mensajeInterpolado)
|
||||
.addConstraintViolation();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package com.imprimelibros.erp.config.validation;
|
||||
|
||||
import jakarta.validation.Constraint;
|
||||
import jakarta.validation.Payload;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Documented
|
||||
@Constraint(validatedBy = ParValidator.class)
|
||||
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Par {
|
||||
String message() default "El valor debe ser un número par";
|
||||
Class<?>[] groups() default {};
|
||||
Class<? extends Payload>[] payload() default {};
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
package com.imprimelibros.erp.config.validation;
|
||||
|
||||
import jakarta.validation.ConstraintValidator;
|
||||
import jakarta.validation.ConstraintValidatorContext;
|
||||
|
||||
public class ParValidator implements ConstraintValidator<Par, Integer> {
|
||||
|
||||
@Override
|
||||
public boolean isValid(Integer value, ConstraintValidatorContext context) {
|
||||
if (value == null) return true; // se permite null, usa @NotNull aparte si lo necesitas
|
||||
return value % 2 == 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
package com.imprimelibros.erp.config.validation;
|
||||
|
||||
public class PresupuestoValidationGroups {
|
||||
|
||||
public interface DatosGenerales {}
|
||||
public interface Interior {}
|
||||
public interface Cubierta {}
|
||||
|
||||
}
|
||||
@ -1,24 +1,46 @@
|
||||
package com.imprimelibros.erp.controller;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
import com.imprimelibros.erp.i18n.TranslationService;
|
||||
import com.imprimelibros.erp.service.VariableService;
|
||||
|
||||
import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
@Controller
|
||||
public class HomeController {
|
||||
|
||||
@Autowired
|
||||
private MessageSource messageSource;
|
||||
private TranslationService translationService;
|
||||
@Autowired
|
||||
private VariableService variableService;
|
||||
|
||||
@GetMapping("/")
|
||||
public String index(Model model, Locale locale) {
|
||||
//model.addAttribute("title", messageSource.getMessage("t-home", null, locale));
|
||||
model.addAttribute("title", "Inicio");
|
||||
return "imprimelibros/home";
|
||||
public String index(Model model, Authentication authentication, Locale locale) {
|
||||
|
||||
boolean isAuthenticated = authentication != null && authentication.isAuthenticated()
|
||||
&& !(authentication instanceof AnonymousAuthenticationToken);
|
||||
|
||||
if (!isAuthenticated) {
|
||||
|
||||
List<String> keys = List.of(
|
||||
"presupuesto.plantilla-cubierta",
|
||||
"presupuesto.plantilla-cubierta-text",
|
||||
"presupuesto.impresion-cubierta",
|
||||
"presupuesto.impresion-cubierta-help");
|
||||
|
||||
Map<String, String> translations = translationService.getTranslations(locale, keys);
|
||||
model.addAttribute("languageBundle", translations);
|
||||
model.addAttribute("pod", variableService.getValorEntero("POD"));
|
||||
}
|
||||
return "imprimelibros/home";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
package com.imprimelibros.erp.controller;
|
||||
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.imprimelibros.erp.service.PresupuestoService;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
|
||||
import jakarta.validation.Valid; // o javax.validation.Valid según tu versión
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.imprimelibros.erp.config.validation.PresupuestoValidationGroups;
|
||||
import com.imprimelibros.erp.entity.Presupuesto;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/presupuesto")
|
||||
public class PresupuestoController {
|
||||
|
||||
@Autowired
|
||||
protected PresupuestoService presupuestoService;
|
||||
|
||||
@PostMapping("/validar/datos-generales")
|
||||
public ResponseEntity<?> validarDatosGenerales(
|
||||
@Validated(PresupuestoValidationGroups.DatosGenerales.class) Presupuesto presupuesto,
|
||||
BindingResult result) {
|
||||
|
||||
Map<String, String> errores = new HashMap<>();
|
||||
|
||||
// errores de campos individuales
|
||||
result.getFieldErrors().forEach(error -> errores.put(error.getField(), error.getDefaultMessage()));
|
||||
|
||||
// errores globales (como tu @ConsistentTiradas)
|
||||
result.getGlobalErrors().forEach(error -> errores.put("global", error.getDefaultMessage()));
|
||||
|
||||
if (!errores.isEmpty()) {
|
||||
return ResponseEntity.badRequest().body(errores);
|
||||
}
|
||||
|
||||
return ResponseEntity.ok().build();
|
||||
}
|
||||
|
||||
}
|
||||
153
src/main/java/com/imprimelibros/erp/entity/Presupuesto.java
Normal file
153
src/main/java/com/imprimelibros/erp/entity/Presupuesto.java
Normal file
@ -0,0 +1,153 @@
|
||||
package com.imprimelibros.erp.entity;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.persistence.*;
|
||||
|
||||
import com.imprimelibros.erp.config.validation.PresupuestoValidationGroups;
|
||||
import com.imprimelibros.erp.config.validation.ConsistentTiradas;
|
||||
import com.imprimelibros.erp.config.validation.Par;
|
||||
|
||||
|
||||
@ConsistentTiradas(groups = PresupuestoValidationGroups.DatosGenerales.class)
|
||||
@Entity
|
||||
@Table(name = "presupuesto")
|
||||
public class Presupuesto {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
// Otros campos del presupuesto
|
||||
@NotBlank(message = "{presupuesto.errores.titulo}", groups = PresupuestoValidationGroups.DatosGenerales.class)
|
||||
@Column(name = "titulo")
|
||||
private String titulo;
|
||||
|
||||
@Column(name = "autor")
|
||||
private String autor;
|
||||
|
||||
@Column(name = "isbn")
|
||||
private String isbn;
|
||||
|
||||
@NotNull(message = "{presupuesto.errores.tirada1}", groups = PresupuestoValidationGroups.DatosGenerales.class)
|
||||
@Column(name = "tirada1")
|
||||
private Integer tirada1;
|
||||
|
||||
@Column(name = "tirada2")
|
||||
private Integer tirada2;
|
||||
|
||||
@Column(name = "tirada3")
|
||||
private Integer tirada3;
|
||||
|
||||
@Column(name = "tirada4")
|
||||
private Integer tirada4;
|
||||
|
||||
@Par(message = "{presupuesto.errores.paginasNegro.par}", groups = PresupuestoValidationGroups.DatosGenerales.class)
|
||||
@NotNull(message = "{presupuesto.errores.paginasNegro.required}", groups = PresupuestoValidationGroups.DatosGenerales.class)
|
||||
@Column(name = "paginas_negro")
|
||||
private Integer paginasNegro;
|
||||
|
||||
@Par(message = "{presupuesto.errores.paginasColor.par}", groups = PresupuestoValidationGroups.DatosGenerales.class)
|
||||
@NotNull(message = "{presupuesto.errores.paginasColor.required}", groups = PresupuestoValidationGroups.DatosGenerales.class)
|
||||
@Column(name = "paginas_color")
|
||||
private Integer paginasColor;
|
||||
|
||||
@NotNull(message = "El papel interior no puede estar vacío", groups = PresupuestoValidationGroups.Interior.class)
|
||||
@Column(name = "papel_interior")
|
||||
private Integer papelInterior;
|
||||
|
||||
|
||||
// Getters y Setters
|
||||
|
||||
public String getAutor() {
|
||||
return autor;
|
||||
}
|
||||
|
||||
public void setAutor(String autor) {
|
||||
this.autor = autor;
|
||||
}
|
||||
|
||||
public String getIsbn() {
|
||||
return isbn;
|
||||
}
|
||||
|
||||
public void setIsbn(String isbn) {
|
||||
this.isbn = isbn;
|
||||
}
|
||||
|
||||
public Integer getTirada1() {
|
||||
return tirada1;
|
||||
}
|
||||
|
||||
public void setTirada1(Integer tirada1) {
|
||||
this.tirada1 = tirada1;
|
||||
}
|
||||
|
||||
public Integer getTirada2() {
|
||||
return tirada2;
|
||||
}
|
||||
|
||||
public void setTirada2(Integer tirada2) {
|
||||
this.tirada2 = tirada2;
|
||||
}
|
||||
|
||||
public Integer getTirada3() {
|
||||
return tirada3;
|
||||
}
|
||||
|
||||
public void setTirada3(Integer tirada3) {
|
||||
this.tirada3 = tirada3;
|
||||
}
|
||||
|
||||
public Integer getTirada4() {
|
||||
return tirada4;
|
||||
}
|
||||
|
||||
public Integer[] getTiradas() {
|
||||
return new Integer[]{tirada1, tirada2, tirada3, tirada4};
|
||||
}
|
||||
|
||||
public void setTirada4(Integer tirada4) {
|
||||
this.tirada4 = tirada4;
|
||||
}
|
||||
|
||||
public String getTitulo() {
|
||||
return titulo;
|
||||
}
|
||||
|
||||
public void setTitulo(String titulo) {
|
||||
this.titulo = titulo;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Integer getPaginasNegro() {
|
||||
return paginasNegro;
|
||||
}
|
||||
|
||||
public void setPaginasNegro(Integer paginasNegro) {
|
||||
this.paginasNegro = paginasNegro;
|
||||
}
|
||||
|
||||
public Integer getPaginasColor() {
|
||||
return paginasColor;
|
||||
}
|
||||
|
||||
public void setPaginasColor(Integer paginasColor) {
|
||||
this.paginasColor = paginasColor;
|
||||
}
|
||||
|
||||
public Integer getPapelInterior() {
|
||||
return papelInterior;
|
||||
}
|
||||
|
||||
public void setPapelInterior(Integer papelInterior) {
|
||||
this.papelInterior = papelInterior;
|
||||
}
|
||||
}
|
||||
30
src/main/java/com/imprimelibros/erp/entity/Variable.java
Normal file
30
src/main/java/com/imprimelibros/erp/entity/Variable.java
Normal file
@ -0,0 +1,30 @@
|
||||
package com.imprimelibros.erp.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
|
||||
@Entity
|
||||
@Table(name = "variables")
|
||||
public class Variable {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
private String clave;
|
||||
|
||||
private String valor;
|
||||
|
||||
// Getters y setters
|
||||
|
||||
public Long getId() { return id; }
|
||||
|
||||
public void setId(Long id) { this.id = id; }
|
||||
|
||||
public String getClave() { return clave; }
|
||||
|
||||
public void setClave(String clave) { this.clave = clave; }
|
||||
|
||||
public String getValor() { return valor; }
|
||||
|
||||
public void setValor(String valor) { this.valor = valor; }
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
package com.imprimelibros.erp.i18n;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@Component
|
||||
public class TranslationService {
|
||||
|
||||
@Autowired
|
||||
private MessageSource messageSource;
|
||||
|
||||
public Map<String, String> getTranslations(Locale locale, List<String> keys) {
|
||||
Map<String, String> translations = new HashMap<>();
|
||||
for (String key : keys) {
|
||||
translations.put(key, messageSource.getMessage(key, null, locale));
|
||||
}
|
||||
return translations;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
package com.imprimelibros.erp.repository;
|
||||
|
||||
import com.imprimelibros.erp.entity.Variable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public interface VariableRepository extends JpaRepository<Variable, Long> {
|
||||
Optional<Variable> findByClave(String clave);
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package com.imprimelibros.erp.service;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class PresupuestoService {
|
||||
|
||||
public boolean validateDatosGenerales(int[] tiradas) {
|
||||
// Implement the logic to validate the tiradas
|
||||
// For example, check if all tiradas are positive integers
|
||||
for (int tirada : tiradas) {
|
||||
if (tirada <= 0) {
|
||||
return false; // Invalid tirada found
|
||||
}
|
||||
}
|
||||
return true; // All tiradas are valid
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package com.imprimelibros.erp.service;
|
||||
|
||||
import com.imprimelibros.erp.repository.VariableRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class VariableService {
|
||||
|
||||
@Autowired
|
||||
private VariableRepository variableRepository;
|
||||
|
||||
public Integer getValorEntero(String clave) {
|
||||
return variableRepository.findByClave(clave)
|
||||
.<Integer>map(v -> Integer.parseInt(v.getValor()))
|
||||
.orElseThrow(
|
||||
() -> new IllegalArgumentException("No se encontró la variable con clave '" + clave + "'"));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user