mirror of
https://git.imnavajas.es/jjimenez/erp-imprimelibros.git
synced 2026-01-13 00:48:49 +00:00
guardando presupuestos anonimos
This commit is contained in:
@ -5,13 +5,13 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.ui.Model;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
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;
|
||||
@ -33,7 +33,7 @@ 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 org.springframework.web.server.ResponseStatusException;
|
||||
import jakarta.validation.Validator;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
@ -48,12 +48,12 @@ 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.User;
|
||||
import com.imprimelibros.erp.users.UserDetailsImpl;
|
||||
import com.imprimelibros.erp.presupuesto.service.PresupuestoFormDataMapper;
|
||||
import com.imprimelibros.erp.presupuesto.service.PresupuestoFormDataMapper.PresupuestoFormDataDto;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.validation.ConstraintViolation;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
@Controller
|
||||
@ -71,6 +71,9 @@ public class PresupuestoController {
|
||||
@Autowired
|
||||
protected MessageSource messageSource;
|
||||
|
||||
@Autowired
|
||||
private Validator validator;
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
private final TranslationService translationService;
|
||||
private final PresupuestoDatatableService dtService;
|
||||
@ -472,6 +475,8 @@ public class PresupuestoController {
|
||||
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());
|
||||
@ -479,7 +484,7 @@ public class PresupuestoController {
|
||||
String sessionId = request.getSession(true).getId();
|
||||
String ip = request.getRemoteAddr();
|
||||
|
||||
var resumen = presupuestoService.getResumenPublico(p, serviciosList, locale, sessionId, ip);
|
||||
var resumen = presupuestoService.getResumen(p, serviciosList, save, mode, locale, sessionId, ip);
|
||||
|
||||
return ResponseEntity.ok(resumen);
|
||||
}
|
||||
@ -498,7 +503,15 @@ public class PresupuestoController {
|
||||
"app.yes",
|
||||
"app.cancelar",
|
||||
"presupuesto.delete.ok.title",
|
||||
"presupuesto.delete.ok.text");
|
||||
"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);
|
||||
@ -557,6 +570,35 @@ public class PresupuestoController {
|
||||
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");
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return "imprimelibros/presupuestos/presupuesto-form";
|
||||
}
|
||||
|
||||
@GetMapping(value = "/api/get", produces = "application/json")
|
||||
public ResponseEntity<PresupuestoFormDataDto> getPresupuesto(
|
||||
@RequestParam("id") Long id, Authentication authentication) {
|
||||
@ -588,51 +630,102 @@ public class PresupuestoController {
|
||||
@Transactional
|
||||
public ResponseEntity<?> delete(@PathVariable Long id, Authentication auth, Locale locale) {
|
||||
|
||||
Presupuesto p = presupuestoRepository.findById(id)
|
||||
.orElseThrow(() -> new ResponseStatusException(
|
||||
HttpStatus.NOT_FOUND,
|
||||
messageSource.getMessage("presupuesto.error.not-found", null, 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"));
|
||||
|
||||
// compara por IDs (no uses equals entre tipos distintos)
|
||||
Long ownerId = p.getUser() != null ? p.getUser().getId() : null;
|
||||
|
||||
User currentUser = null;
|
||||
Long currentUserId = null;
|
||||
if (auth != null && auth.getPrincipal() instanceof UserDetailsImpl udi) {
|
||||
currentUserId = udi.getId();
|
||||
currentUser = userRepo.findById(currentUserId).orElse(null);
|
||||
} else if (auth != null) {
|
||||
currentUserId = userRepo.findIdByUserNameIgnoreCase(auth.getName()).orElse(null); // fallback
|
||||
currentUser = userRepo.findById(currentUserId).orElse(null);
|
||||
currentUserId = userRepo.findIdByUserNameIgnoreCase(auth.getName()).orElse(null);
|
||||
}
|
||||
|
||||
boolean isOwner = ownerId != null && ownerId.equals(currentUserId);
|
||||
|
||||
if (isUser && !isOwner) {
|
||||
throw new ResponseStatusException(
|
||||
HttpStatus.FORBIDDEN,
|
||||
messageSource.getMessage("presupuesto.error.delete-permission-denied", null, locale));
|
||||
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)) {
|
||||
throw new ResponseStatusException(
|
||||
HttpStatus.FORBIDDEN,
|
||||
messageSource.getMessage("presupuesto.error.delete-not-draft", null, locale));
|
||||
return ResponseEntity.status(HttpStatus.FORBIDDEN)
|
||||
.body(Map.of("message",
|
||||
messageSource.getMessage("presupuesto.error.delete-not-draft", null, locale)));
|
||||
}
|
||||
|
||||
// SOFT DELETE (no uses deleteById)
|
||||
p.setDeleted(true);
|
||||
p.setDeletedAt(Instant.now());
|
||||
p.setDeletedBy(currentUser);
|
||||
try {
|
||||
p.setDeleted(true);
|
||||
p.setDeletedAt(Instant.now());
|
||||
|
||||
presupuestoRepository.save(p);
|
||||
return ResponseEntity.ok(Map.of("message",
|
||||
messageSource.getMessage("presupuesto.exito.eliminado", null, locale)));
|
||||
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() : "")));
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping(path="/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());
|
||||
|
||||
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 {
|
||||
if (mode.equals("public")) {
|
||||
var resumen = presupuestoService.getTextosResumen(presupuesto, serviciosList, locale);
|
||||
presupuesto = presupuestoService.generateTotalizadores(presupuesto, serviciosList, resumen, locale);
|
||||
if (id != null) {
|
||||
presupuesto.setId(id); // para que actualice, no cree uno nuevo
|
||||
}
|
||||
}
|
||||
Map<String, Object> saveResult = presupuestoService.guardarPresupuesto(presupuesto);
|
||||
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() : "")));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user