mirror of
https://git.imnavajas.es/jjimenez/erp-imprimelibros.git
synced 2026-01-24 09:40:21 +00:00
trabajando en el delete
This commit is contained in:
@ -46,6 +46,11 @@ public abstract class AbstractAuditedEntity {
|
|||||||
@Column(name = "deleted_at")
|
@Column(name = "deleted_at")
|
||||||
private Instant deletedAt;
|
private Instant deletedAt;
|
||||||
|
|
||||||
|
@LastModifiedBy
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "deleted_by")
|
||||||
|
private User deletedBy;
|
||||||
|
|
||||||
// Getters/Setters
|
// Getters/Setters
|
||||||
public Long getId() { return id; }
|
public Long getId() { return id; }
|
||||||
public void setId(Long id) { this.id = id; }
|
public void setId(Long id) { this.id = id; }
|
||||||
@ -67,4 +72,7 @@ public abstract class AbstractAuditedEntity {
|
|||||||
|
|
||||||
public Instant getDeletedAt() { return deletedAt; }
|
public Instant getDeletedAt() { return deletedAt; }
|
||||||
public void setDeletedAt(Instant deletedAt) { this.deletedAt = deletedAt; }
|
public void setDeletedAt(Instant deletedAt) { this.deletedAt = deletedAt; }
|
||||||
|
|
||||||
|
public User getDeletedBy() { return deletedBy; }
|
||||||
|
public void setDeletedBy(User deletedBy) { this.deletedBy = deletedBy; }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -320,8 +320,6 @@ public class MargenPresupuestoController {
|
|||||||
|
|
||||||
return repo.findById(id).map(u -> {
|
return repo.findById(id).map(u -> {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
|
||||||
u.setDeleted(true);
|
u.setDeleted(true);
|
||||||
u.setDeletedAt(LocalDateTime.now());
|
u.setDeletedAt(LocalDateTime.now());
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,11 @@
|
|||||||
package com.imprimelibros.erp.presupuesto;
|
package com.imprimelibros.erp.presupuesto;
|
||||||
|
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -21,12 +25,15 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
|||||||
import org.springframework.web.context.request.RequestContextHolder;
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
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.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.web.server.ResponseStatusException;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
@ -40,6 +47,9 @@ import com.imprimelibros.erp.presupuesto.classes.PresupuestoMarcapaginas;
|
|||||||
import com.imprimelibros.erp.presupuesto.dto.Presupuesto;
|
import com.imprimelibros.erp.presupuesto.dto.Presupuesto;
|
||||||
import com.imprimelibros.erp.presupuesto.service.PresupuestoService;
|
import com.imprimelibros.erp.presupuesto.service.PresupuestoService;
|
||||||
import com.imprimelibros.erp.presupuesto.validation.PresupuestoValidationGroups;
|
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;
|
||||||
import com.imprimelibros.erp.presupuesto.service.PresupuestoFormDataMapper.PresupuestoFormDataDto;
|
import com.imprimelibros.erp.presupuesto.service.PresupuestoFormDataMapper.PresupuestoFormDataDto;
|
||||||
|
|
||||||
@ -66,16 +76,18 @@ public class PresupuestoController {
|
|||||||
private final PresupuestoDatatableService dtService;
|
private final PresupuestoDatatableService dtService;
|
||||||
private final VariableService variableService;
|
private final VariableService variableService;
|
||||||
private final PresupuestoFormDataMapper formDataMapper;
|
private final PresupuestoFormDataMapper formDataMapper;
|
||||||
|
private final UserDao userRepo;
|
||||||
|
|
||||||
public PresupuestoController(ObjectMapper objectMapper, TranslationService translationService,
|
public PresupuestoController(ObjectMapper objectMapper, TranslationService translationService,
|
||||||
PresupuestoDatatableService dtService, PresupuestoRepository presupuestoRepository,
|
PresupuestoDatatableService dtService, PresupuestoRepository presupuestoRepository,
|
||||||
VariableService variableService, PresupuestoFormDataMapper formDataMapper) {
|
VariableService variableService, PresupuestoFormDataMapper formDataMapper, UserDao userRepo) {
|
||||||
this.objectMapper = objectMapper;
|
this.objectMapper = objectMapper;
|
||||||
this.translationService = translationService;
|
this.translationService = translationService;
|
||||||
this.dtService = dtService;
|
this.dtService = dtService;
|
||||||
this.presupuestoRepository = presupuestoRepository;
|
this.presupuestoRepository = presupuestoRepository;
|
||||||
this.variableService = variableService;
|
this.variableService = variableService;
|
||||||
this.formDataMapper = formDataMapper;
|
this.formDataMapper = formDataMapper;
|
||||||
|
this.userRepo = userRepo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/public/validar/datos-generales")
|
@PostMapping("/public/validar/datos-generales")
|
||||||
@ -122,7 +134,6 @@ public class PresupuestoController {
|
|||||||
errores.put(error.getField(), msg);
|
errores.put(error.getField(), msg);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// errores globales (@ConsistentTiradas...)
|
// errores globales (@ConsistentTiradas...)
|
||||||
result.getGlobalErrors().forEach(error -> errores.put("global", error.getDefaultMessage()));
|
result.getGlobalErrors().forEach(error -> errores.put("global", error.getDefaultMessage()));
|
||||||
|
|
||||||
@ -151,7 +162,6 @@ public class PresupuestoController {
|
|||||||
errores.put(error.getField(), msg);
|
errores.put(error.getField(), msg);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// errores globales (@ConsistentTiradas...)
|
// errores globales (@ConsistentTiradas...)
|
||||||
result.getGlobalErrors().forEach(error -> errores.put("global", error.getDefaultMessage()));
|
result.getGlobalErrors().forEach(error -> errores.put("global", error.getDefaultMessage()));
|
||||||
|
|
||||||
@ -187,7 +197,6 @@ public class PresupuestoController {
|
|||||||
errores.put(error.getField(), msg);
|
errores.put(error.getField(), msg);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// errores globales (@ConsistentTiradas...)
|
// errores globales (@ConsistentTiradas...)
|
||||||
result.getGlobalErrors().forEach(error -> errores.put("global", error.getDefaultMessage()));
|
result.getGlobalErrors().forEach(error -> errores.put("global", error.getDefaultMessage()));
|
||||||
|
|
||||||
@ -219,7 +228,6 @@ public class PresupuestoController {
|
|||||||
errores.put(error.getField(), msg);
|
errores.put(error.getField(), msg);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
if (!errores.isEmpty()) {
|
if (!errores.isEmpty()) {
|
||||||
return ResponseEntity.badRequest().body(errores);
|
return ResponseEntity.badRequest().body(errores);
|
||||||
}
|
}
|
||||||
@ -271,7 +279,6 @@ public class PresupuestoController {
|
|||||||
errores.put(error.getField(), msg);
|
errores.put(error.getField(), msg);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
if (!errores.isEmpty()) {
|
if (!errores.isEmpty()) {
|
||||||
return ResponseEntity.badRequest().body(errores);
|
return ResponseEntity.badRequest().body(errores);
|
||||||
}
|
}
|
||||||
@ -305,7 +312,6 @@ public class PresupuestoController {
|
|||||||
errores.put(error.getField(), msg);
|
errores.put(error.getField(), msg);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
if (!errores.isEmpty()) {
|
if (!errores.isEmpty()) {
|
||||||
return ResponseEntity.badRequest().body(errores);
|
return ResponseEntity.badRequest().body(errores);
|
||||||
}
|
}
|
||||||
@ -484,7 +490,15 @@ public class PresupuestoController {
|
|||||||
@GetMapping
|
@GetMapping
|
||||||
public String getPresupuestoList(Model model, Authentication authentication, Locale locale) {
|
public String getPresupuestoList(Model model, Authentication authentication, Locale locale) {
|
||||||
|
|
||||||
List<String> keys = List.of();
|
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");
|
||||||
|
|
||||||
Map<String, String> translations = translationService.getTranslations(locale, keys);
|
Map<String, String> translations = translationService.getTranslations(locale, keys);
|
||||||
model.addAttribute("languageBundle", translations);
|
model.addAttribute("languageBundle", translations);
|
||||||
@ -570,4 +584,55 @@ public class PresupuestoController {
|
|||||||
return dtService.datatableAnonimos(dt, locale);
|
return dtService.datatableAnonimos(dt, locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/{id}")
|
||||||
|
@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)));
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isOwner = ownerId != null && ownerId.equals(currentUserId);
|
||||||
|
|
||||||
|
if (isUser && !isOwner) {
|
||||||
|
throw new ResponseStatusException(
|
||||||
|
HttpStatus.FORBIDDEN,
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
// SOFT DELETE (no uses deleteById)
|
||||||
|
p.setDeleted(true);
|
||||||
|
p.setDeletedAt(Instant.now());
|
||||||
|
p.setDeletedBy(currentUser);
|
||||||
|
|
||||||
|
presupuestoRepository.save(p);
|
||||||
|
return ResponseEntity.ok(Map.of("message",
|
||||||
|
messageSource.getMessage("presupuesto.exito.eliminado", null, locale)));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -174,6 +174,7 @@ public class PresupuestoDatatableService {
|
|||||||
m.put("region", p.getRegion());
|
m.put("region", p.getRegion());
|
||||||
m.put("ciudad", p.getCiudad());
|
m.put("ciudad", p.getCiudad());
|
||||||
m.put("updatedAt", formatDate(p.getUpdatedAt(), locale));
|
m.put("updatedAt", formatDate(p.getUpdatedAt(), locale));
|
||||||
|
if(p.getEstado().equals(Presupuesto.Estado.borrador)){
|
||||||
m.put("actions",
|
m.put("actions",
|
||||||
"<div class=\"hstack gap-3 flex-wrap\">" +
|
"<div class=\"hstack gap-3 flex-wrap\">" +
|
||||||
"<a href=\"javascript:void(0);\" data-id=\"" + p.getId()
|
"<a href=\"javascript:void(0);\" data-id=\"" + p.getId()
|
||||||
@ -182,6 +183,14 @@ public class PresupuestoDatatableService {
|
|||||||
+ "\" class=\"link-danger btn-delete-anonimo fs-15\"><i class=\"ri-delete-bin-5-line\"></i></a>"
|
+ "\" class=\"link-danger btn-delete-anonimo fs-15\"><i class=\"ri-delete-bin-5-line\"></i></a>"
|
||||||
+
|
+
|
||||||
"</div>");
|
"</div>");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
m.put("actions",
|
||||||
|
"<div class=\"hstack gap-3 flex-wrap\">" +
|
||||||
|
"<a href=\"javascript:void(0);\" data-id=\"" + p.getId()
|
||||||
|
+ "\" class=\"link-success btn-edit-anonimo fs-15\"><i class=\"ri-eye-line\"></i></a>" +
|
||||||
|
"</div>");
|
||||||
|
}
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
presupuesto.title=Presupuestos
|
presupuesto.title=Presupuestos
|
||||||
presupuesto.editar.title=Editar presupuesto
|
presupuesto.editar.title=Editar presupuesto
|
||||||
|
presupuesto.eliminar=Eliminar presupuesto
|
||||||
presupuesto.datos-generales=Datos Generales
|
presupuesto.datos-generales=Datos Generales
|
||||||
presupuesto.interior=Interior
|
presupuesto.interior=Interior
|
||||||
presupuesto.cubierta=Cubierta
|
presupuesto.cubierta=Cubierta
|
||||||
@ -265,6 +266,18 @@ presupuesto.marcapaginas.acabado.plastificado-mate-2c=Plastificado mate 2/C
|
|||||||
presupuesto.marcapaginas.precio-unidad=Precio por unidad
|
presupuesto.marcapaginas.precio-unidad=Precio por unidad
|
||||||
presupuesto.marcapaginas.precio-total=Precio total
|
presupuesto.marcapaginas.precio-total=Precio total
|
||||||
|
|
||||||
|
# Mensajes de eliminación de presupuesto
|
||||||
|
presupuesto.delete.title=Eliminar presupuesto
|
||||||
|
presupuesto.delete.button=Si, ELIMINAR
|
||||||
|
presupuesto.delete.text=¿Está seguro de que desea eliminar este presupuesto?<br>Esta acción no se puede deshacer.
|
||||||
|
presupuesto.delete.ok.title=Presupuesto eliminado
|
||||||
|
presupuesto.delete.ok.text=El presupuesto ha sido eliminado con éxito.
|
||||||
|
presupuesto.exito.eliminado=Presupuesto eliminado con éxito.
|
||||||
|
presupuesto.error.delete-internal-error=No se puede eliminar: error interno.
|
||||||
|
presupuesto.error.delete-permission-denied=No se puede eliminar: permiso denegado.
|
||||||
|
presupuesto.error.delete-not-found=No se puede eliminar: presupuesto no encontrado.
|
||||||
|
presupuesto.error.delete-not-draft=Solo se pueden eliminar presupuestos en estado Borrador.
|
||||||
|
|
||||||
# Errores
|
# Errores
|
||||||
presupuesto.errores-title=Corrija los siguientes errores:
|
presupuesto.errores-title=Corrija los siguientes errores:
|
||||||
presupuesto.errores.titulo=El título es obligatorio
|
presupuesto.errores.titulo=El título es obligatorio
|
||||||
@ -292,3 +305,5 @@ presupuesto.errores.presupuesto-no-existe=El presupuesto con ID {0} no existe.
|
|||||||
|
|
||||||
presupuesto.errores.presupuesto-maquetacion=No se pudo calcular el presupuesto de maquetación.
|
presupuesto.errores.presupuesto-maquetacion=No se pudo calcular el presupuesto de maquetación.
|
||||||
presupuesto.errores.presupuesto-marcapaginas=No se pudo calcular el presupuesto de marcapáginas.
|
presupuesto.errores.presupuesto-marcapaginas=No se pudo calcular el presupuesto de marcapáginas.
|
||||||
|
|
||||||
|
presupuesto.info.presupuestos-anonimos-view=Estos presupuestos son anónimos y no están asociados a ningún cliente. No se guardarán los cambios (sólo consulta).
|
||||||
@ -1,20 +1,24 @@
|
|||||||
|
$('.imagen-container-group').on('click', '.image-container', function (e) {
|
||||||
|
e.preventDefault(); // <- evita que el label dispare el cambio nativo (2º change)
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
$('.imagen-container-group').on('click', '.image-container', function () {
|
|
||||||
const clicked = $(this);
|
const clicked = $(this);
|
||||||
const group = clicked.closest('.imagen-container-group');
|
const group = clicked.closest('.imagen-container-group');
|
||||||
|
|
||||||
// Limpiar selección anterior
|
// Si ya está seleccionado, no hagas nada
|
||||||
|
const $radio = clicked.find('input[type="radio"]');
|
||||||
|
if ($radio.prop('checked')) return;
|
||||||
|
|
||||||
|
// Limpiar selección anterior (solo clases/animación)
|
||||||
group.find('.image-container').removeClass('selected')
|
group.find('.image-container').removeClass('selected')
|
||||||
.find('.image-presupuesto').removeClass('zoom-anim');
|
.find('.image-presupuesto').removeClass('zoom-anim');
|
||||||
|
|
||||||
// Marcar nuevo seleccionado
|
// Marcar nuevo seleccionado (clases/animación)
|
||||||
clicked.addClass('selected');
|
clicked.addClass('selected');
|
||||||
|
|
||||||
// Aplicar animación de zoom
|
|
||||||
const img = clicked.find('.image-presupuesto');
|
const img = clicked.find('.image-presupuesto');
|
||||||
void img[0].offsetWidth; // Forzar reflow
|
void img[0].offsetWidth;
|
||||||
img.addClass('zoom-anim');
|
img.addClass('zoom-anim');
|
||||||
|
|
||||||
|
// Marca el radio y dispara UN único change
|
||||||
clicked.find('input[type="radio"]').prop('checked', true).trigger('change');
|
$radio.prop('checked', true).trigger('change');
|
||||||
});
|
});
|
||||||
|
|||||||
@ -173,6 +173,9 @@ export default class PresupuestoWizard {
|
|||||||
this.summaryTableSobrecubierta = $('#summary-sobrecubierta');
|
this.summaryTableSobrecubierta = $('#summary-sobrecubierta');
|
||||||
this.summaryTableFaja = $('#summary-faja');
|
this.summaryTableFaja = $('#summary-faja');
|
||||||
this.summaryTableExtras = $('#summary-servicios-extras');
|
this.summaryTableExtras = $('#summary-servicios-extras');
|
||||||
|
|
||||||
|
// variable para evitar disparar eventos al cargar datos
|
||||||
|
this._hydrating = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async init() {
|
async init() {
|
||||||
@ -181,9 +184,10 @@ export default class PresupuestoWizard {
|
|||||||
const mode = root?.dataset.mode || 'public';
|
const mode = root?.dataset.mode || 'public';
|
||||||
const presupuestoId = root?.dataset.id || null;
|
const presupuestoId = root?.dataset.id || null;
|
||||||
|
|
||||||
this.opts = { mode, presupuestoId };
|
let stored = null;
|
||||||
|
if(this.opts.useSessionCache) {
|
||||||
const stored = sessionStorage.getItem("formData");
|
stored = sessionStorage.getItem("formData");
|
||||||
|
}
|
||||||
|
|
||||||
this.#initDatosGenerales();
|
this.#initDatosGenerales();
|
||||||
|
|
||||||
@ -261,18 +265,11 @@ export default class PresupuestoWizard {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Limpiar el sessionStorage al salir de la página
|
|
||||||
window.addEventListener('beforeunload', () => {
|
|
||||||
sessionStorage.removeItem('formData');
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#cacheFormData() {
|
#cacheFormData() {
|
||||||
if (!this.opts.useSessionCache) return;
|
if (!this.opts.useSessionCache) return;
|
||||||
const key = this.opts.mode === 'edit' && this.opts.presupuestoId
|
sessionStorage.setItem('formData', JSON.stringify(this.formData));
|
||||||
? `formData:edit:${this.opts.presupuestoId}`
|
|
||||||
: `formData:${this.opts.mode}`;
|
|
||||||
sessionStorage.setItem(key, JSON.stringify(this.formData));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#changeTab(idContenidoTab) {
|
#changeTab(idContenidoTab) {
|
||||||
@ -382,8 +379,9 @@ export default class PresupuestoWizard {
|
|||||||
|
|
||||||
// Eventos para el resumen
|
// Eventos para el resumen
|
||||||
$(document).on('change', 'input[name="tipoEncuadernacion"]', (e) => {
|
$(document).on('change', 'input[name="tipoEncuadernacion"]', (e) => {
|
||||||
|
|
||||||
if ($(e.target).is(':checked')) {
|
if ($(e.target).is(':checked')) {
|
||||||
// Actualizar el resumen
|
|
||||||
Summary.updateEncuadernacion();
|
Summary.updateEncuadernacion();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -474,7 +472,7 @@ export default class PresupuestoWizard {
|
|||||||
paginasNegro: this.paginasNegro.val(),
|
paginasNegro: this.paginasNegro.val(),
|
||||||
paginasColor: this.paginasColor.val(),
|
paginasColor: this.paginasColor.val(),
|
||||||
posicionPaginasColor: this.posicionPaginasColor.val(),
|
posicionPaginasColor: this.posicionPaginasColor.val(),
|
||||||
tipoEncuadernacion: ($('.tipo-libro.selected').length > 0) ? $('.tipo-libro.selected').attr('id') : 'fresado',
|
tipoEncuadernacion: $('.tipo-libro input:checked').val() || 'fresado',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -519,7 +517,6 @@ export default class PresupuestoWizard {
|
|||||||
this.alto.val(this.formData.datosGenerales.alto);
|
this.alto.val(this.formData.datosGenerales.alto);
|
||||||
}
|
}
|
||||||
|
|
||||||
$('.tipo-libro').removeClass('selected');
|
|
||||||
$('input[name="tipoEncuadernacion"][value="' + this.formData.datosGenerales.tipoEncuadernacion + '"]')
|
$('input[name="tipoEncuadernacion"][value="' + this.formData.datosGenerales.tipoEncuadernacion + '"]')
|
||||||
.prop('checked', true);
|
.prop('checked', true);
|
||||||
this.#updateTipoEncuadernacion();
|
this.#updateTipoEncuadernacion();
|
||||||
@ -565,7 +562,7 @@ export default class PresupuestoWizard {
|
|||||||
#updateTipoEncuadernacion() {
|
#updateTipoEncuadernacion() {
|
||||||
|
|
||||||
const paginas = parseInt($('#paginas').val());
|
const paginas = parseInt($('#paginas').val());
|
||||||
const selectedTipo = $('.tipo-libro.selected').attr('id');
|
const selectedTipo = $('.tipo-libro input:checked').val();
|
||||||
$('.tipo-libro').removeClass('selected');
|
$('.tipo-libro').removeClass('selected');
|
||||||
|
|
||||||
if (paginas < 32) {
|
if (paginas < 32) {
|
||||||
@ -591,19 +588,17 @@ export default class PresupuestoWizard {
|
|||||||
$('.tipo-libro#grapado').removeClass('d-none');
|
$('.tipo-libro#grapado').removeClass('d-none');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectedTipo && $('.tipo-libro#' + selectedTipo).length > 0 && !$('.tipo-libro#' + selectedTipo).hasClass('d-none')) {
|
if (!(selectedTipo && $('.tipo-libro#' + selectedTipo).length > 0 && !$('.tipo-libro#' + selectedTipo).hasClass('d-none'))) {
|
||||||
$('.tipo-libro#' + selectedTipo).addClass('selected');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
let firstVisible = $('.tipo-libro').not('.d-none').first();
|
let firstVisible = $('.tipo-libro').not('.d-none').first();
|
||||||
|
|
||||||
if (firstVisible.length) {
|
if (firstVisible.length) {
|
||||||
firstVisible.addClass('selected');
|
firstVisible.trigger('click');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($('.tipo-libro.selected').length > 0) {
|
if ($('.tipo-libro input:checked').length > 0) {
|
||||||
this.formData.datosGenerales.tipoEncuadernacion = $('.tipo-libro.selected').attr('id');
|
this.formData.datosGenerales.tipoEncuadernacion = $('.tipo-libro input:checked').val();
|
||||||
Summary.updateEncuadernacion();
|
Summary.updateEncuadernacion();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -629,6 +624,8 @@ export default class PresupuestoWizard {
|
|||||||
|
|
||||||
|
|
||||||
$(document).on('change', 'input[name="tipoImpresion"]', (e) => {
|
$(document).on('change', 'input[name="tipoImpresion"]', (e) => {
|
||||||
|
if (!$(e.target).is(':checked'))
|
||||||
|
return;
|
||||||
|
|
||||||
const data = this.#getPresupuestoData();
|
const data = this.#getPresupuestoData();
|
||||||
Summary.updateTipoImpresion();
|
Summary.updateTipoImpresion();
|
||||||
@ -681,6 +678,10 @@ export default class PresupuestoWizard {
|
|||||||
|
|
||||||
|
|
||||||
$(document).on('change', 'input[name="papelInterior"]', (e) => {
|
$(document).on('change', 'input[name="papelInterior"]', (e) => {
|
||||||
|
|
||||||
|
if (!$(e.target).is(':checked'))
|
||||||
|
return;
|
||||||
|
|
||||||
const data = this.#getPresupuestoData();
|
const data = this.#getPresupuestoData();
|
||||||
|
|
||||||
Summary.updatePapelInterior();
|
Summary.updatePapelInterior();
|
||||||
@ -951,6 +952,12 @@ export default class PresupuestoWizard {
|
|||||||
|
|
||||||
$(document).on('change', 'input[name="tipoCubierta"]', (e) => {
|
$(document).on('change', 'input[name="tipoCubierta"]', (e) => {
|
||||||
|
|
||||||
|
if (!$(e.target).is(':checked'))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(this._hydrating)
|
||||||
|
return;
|
||||||
|
|
||||||
$('.tapa-dura-options').eq(0).removeClass('animate-fadeInUpBounce');
|
$('.tapa-dura-options').eq(0).removeClass('animate-fadeInUpBounce');
|
||||||
$('.tapa-blanda-options').eq(0).removeClass('animate-fadeInUpBounce');
|
$('.tapa-blanda-options').eq(0).removeClass('animate-fadeInUpBounce');
|
||||||
|
|
||||||
@ -971,6 +978,9 @@ export default class PresupuestoWizard {
|
|||||||
|
|
||||||
$(document).on('change', 'input[name="solapasCubierta"]', (e) => {
|
$(document).on('change', 'input[name="solapasCubierta"]', (e) => {
|
||||||
|
|
||||||
|
if (!$(e.target).is(':checked'))
|
||||||
|
return;
|
||||||
|
|
||||||
if (e.currentTarget.closest('.image-container').id === 'sin-solapas') {
|
if (e.currentTarget.closest('.image-container').id === 'sin-solapas') {
|
||||||
this.divSolapasCubierta.addClass('d-none');
|
this.divSolapasCubierta.addClass('d-none');
|
||||||
}
|
}
|
||||||
@ -986,7 +996,7 @@ export default class PresupuestoWizard {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
$(document).on('click', '.papel-cubierta', (e) => {
|
$(document).on('change', 'input[name="papel-cubierta"]', (e) => {
|
||||||
|
|
||||||
const data = this.#getPresupuestoData();
|
const data = this.#getPresupuestoData();
|
||||||
|
|
||||||
@ -1026,6 +1036,9 @@ export default class PresupuestoWizard {
|
|||||||
|
|
||||||
$(document).on('change', '.datos-cubierta', (e) => {
|
$(document).on('change', '.datos-cubierta', (e) => {
|
||||||
|
|
||||||
|
if(this._hydrating)
|
||||||
|
return;
|
||||||
|
|
||||||
const dataToStore = this.#getCubiertaData();
|
const dataToStore = this.#getCubiertaData();
|
||||||
this.#updateCubiertaData(dataToStore);
|
this.#updateCubiertaData(dataToStore);
|
||||||
this.#cacheFormData();
|
this.#cacheFormData();
|
||||||
@ -1165,13 +1178,13 @@ export default class PresupuestoWizard {
|
|||||||
if (item.extraData["sk-id"] == this.formData.cubierta.papelCubiertaId) {
|
if (item.extraData["sk-id"] == this.formData.cubierta.papelCubiertaId) {
|
||||||
item.setSelected(true);
|
item.setSelected(true);
|
||||||
}
|
}
|
||||||
|
item.group='papel-cubierta';
|
||||||
this.divPapelCubierta.append(item.render());
|
this.divPapelCubierta.append(item.render());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.divPapelCubierta.find('.image-container.selected').length === 0) {
|
if (this.divPapelCubierta.find('input[name="papel-cubierta"]:checked').length === 0) {
|
||||||
this.divPapelCubierta.find('.image-container').first().addClass('selected');
|
|
||||||
this.formData.cubierta.papelCubiertaId =
|
this.divPapelCubierta.find('input[name="papel-cubierta"]').first().prop('checked', true).trigger('change');
|
||||||
this.divPapelCubierta.find('.image-container').first().data('sk-id') || 3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#addGramajesCubierta(data.opciones_gramaje_cubierta);
|
this.#addGramajesCubierta(data.opciones_gramaje_cubierta);
|
||||||
@ -1192,13 +1205,13 @@ export default class PresupuestoWizard {
|
|||||||
|
|
||||||
#getCubiertaData() {
|
#getCubiertaData() {
|
||||||
|
|
||||||
const tipoCubierta = $('.tapa-cubierta.selected').attr('id') || 'tapaBlanda';
|
const tipoCubierta = $('.tapa-cubierta input:checked').val() || 'tapaBlanda';
|
||||||
const solapas = $('.solapas-cubierta.selected').id == 'sin-solapas' ? 0 : 1 || 0;
|
const solapas = $('.solapas-cubierta input:checked').val() == 'sin-solapas' ? 0 : 1 || 0;
|
||||||
const tamanioSolapasCubierta = $('#tamanio-solapas-cubierta').val() || '80';
|
const tamanioSolapasCubierta = $('#tamanio-solapas-cubierta').val() || '80';
|
||||||
const cubiertaCaras = parseInt(this.carasImpresionCubierta.val()) || 2;
|
const cubiertaCaras = parseInt(this.carasImpresionCubierta.val()) || 2;
|
||||||
const papelGuardasId = parseInt($('#papel-guardas option:selected').data('papel-id')) || 3;
|
const papelGuardasId = parseInt($('#papel-guardas option:selected').data('papel-id')) || 3;
|
||||||
const gramajeGuardas = parseInt($('#papel-guardas option:selected').data('gramaje')) || 170;
|
const gramajeGuardas = parseInt($('#papel-guardas option:selected').data('gramaje')) || 170;
|
||||||
const guardasImpresas = parseInt(this.guardasImpresas) || 0;
|
const guardasImpresas = parseInt(this.guardasImpresas.val()) || 0;
|
||||||
const cabezada = this.cabezada.val() || 'WHI';
|
const cabezada = this.cabezada.val() || 'WHI';
|
||||||
const papelCubiertaId = $('#div-papel-cubierta .image-container input:checked').parent().data('sk-id') || this.formData.cubierta.papelCubiertaId || 3;
|
const papelCubiertaId = $('#div-papel-cubierta .image-container input:checked').parent().data('sk-id') || this.formData.cubierta.papelCubiertaId || 3;
|
||||||
const gramajeCubierta = $('input[name="gramaje-cubierta"]:checked').data('gramaje') || this.formData.cubierta.gramajeCubierta || 170;
|
const gramajeCubierta = $('input[name="gramaje-cubierta"]:checked').data('gramaje') || this.formData.cubierta.gramajeCubierta || 170;
|
||||||
@ -1279,7 +1292,7 @@ export default class PresupuestoWizard {
|
|||||||
|
|
||||||
for (let i = 0; i < gramajes.length; i++) {
|
for (let i = 0; i < gramajes.length; i++) {
|
||||||
const gramaje = gramajes[i];
|
const gramaje = gramajes[i];
|
||||||
this.#addGramaje(this.divGramajeCubierta, 'gramaje-cubierta datos-cubierta', gramaje, 'gramaje-cubierta');
|
this.#addGramaje(this.divGramajeCubierta, 'gramaje-cubierta', gramaje, 'gramaje-cubierta');
|
||||||
|
|
||||||
// Seleccionar el gramaje por defecto
|
// Seleccionar el gramaje por defecto
|
||||||
if (this.formData.cubierta.gramajeCubierta === '' && i === 0) {
|
if (this.formData.cubierta.gramajeCubierta === '' && i === 0) {
|
||||||
@ -1298,6 +1311,8 @@ export default class PresupuestoWizard {
|
|||||||
|
|
||||||
#loadCubiertaData() {
|
#loadCubiertaData() {
|
||||||
|
|
||||||
|
this._hydrating = true;
|
||||||
|
|
||||||
$('input[name="tipoCubierta"][value="' + this.formData.cubierta.tipoCubierta + '"]')
|
$('input[name="tipoCubierta"][value="' + this.formData.cubierta.tipoCubierta + '"]')
|
||||||
.prop('checked', true);
|
.prop('checked', true);
|
||||||
|
|
||||||
@ -1315,15 +1330,16 @@ export default class PresupuestoWizard {
|
|||||||
this.cabezada.val(this.formData.cubierta.cabezada);
|
this.cabezada.val(this.formData.cubierta.cabezada);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._hydrating = false;
|
||||||
|
|
||||||
$('input[name="tipoCubierta"][value="' + this.formData.cubierta.tipoCubierta + '"]').trigger('change');
|
$('input[name="tipoCubierta"][value="' + this.formData.cubierta.tipoCubierta + '"]').trigger('change');
|
||||||
|
|
||||||
if (this.formData.cubierta.solapasCubierta === 0) {
|
if (this.formData.cubierta.solapasCubierta === 0) {
|
||||||
$('.solapas-cubierta#sin-solapas').addClass('selected');
|
$('.solapas-cubierta#sin-solapas input').prop('checked', true);
|
||||||
this.divSolapasCubierta.addClass('d-none');
|
this.divSolapasCubierta.addClass('d-none');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$('.solapas-cubierta').removeClass('selected');
|
$('.solapas-cubierta#con-solapas input').prop('checked', true);
|
||||||
$(`.solapas-cubierta#con-solapas`).addClass('selected');
|
|
||||||
this.divSolapasCubierta.removeClass('d-none');
|
this.divSolapasCubierta.removeClass('d-none');
|
||||||
this.carasImpresionCubierta.val(this.formData.cubierta.cubiertaCaras);
|
this.carasImpresionCubierta.val(this.formData.cubierta.cubiertaCaras);
|
||||||
this.tamanioSolapasCubierta.val(this.formData.cubierta.tamanioSolapasCubierta);
|
this.tamanioSolapasCubierta.val(this.formData.cubierta.tamanioSolapasCubierta);
|
||||||
|
|||||||
@ -67,6 +67,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
$('#presupuestos-anonimos-datatable').on('click', '.btn-edit-anonimo', function (e) {
|
$('#presupuestos-anonimos-datatable').on('click', '.btn-edit-anonimo', function (e) {
|
||||||
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const id = $(this).data('id');
|
const id = $(this).data('id');
|
||||||
if (id) {
|
if (id) {
|
||||||
@ -74,5 +75,48 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('#presupuestos-anonimos-datatable').on('click', '.btn-delete-anonimo', function (e) {
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
const id = $(this).data('id');
|
||||||
|
|
||||||
|
Swal.fire({
|
||||||
|
title: window.languageBundle.get(['presupuesto.delete.title']) || 'Eliminar presupuesto',
|
||||||
|
html: window.languageBundle.get(['presupuesto.delete.text']) || 'Esta acción no se puede deshacer.',
|
||||||
|
icon: 'warning',
|
||||||
|
showCancelButton: true,
|
||||||
|
buttonsStyling: false,
|
||||||
|
customClass: {
|
||||||
|
confirmButton: 'btn btn-danger w-xs mt-2',
|
||||||
|
cancelButton: 'btn btn-light w-xs mt-2'
|
||||||
|
},
|
||||||
|
confirmButtonText: window.languageBundle.get(['presupuesto.delete.button']) || 'Eliminar',
|
||||||
|
cancelButtonText: window.languageBundle.get(['app.cancelar']) || 'Cancelar',
|
||||||
|
}).then((result) => {
|
||||||
|
if (!result.isConfirmed) return;
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: '/presupuesto/' + id,
|
||||||
|
type: 'DELETE',
|
||||||
|
success: function () {
|
||||||
|
Swal.fire({
|
||||||
|
icon: 'success', title: window.languageBundle.get(['presupuesto.delete.ok.title']) || 'Eliminado',
|
||||||
|
text: window.languageBundle.get(['presupuesto.delete.ok.text']) || 'El presupuesto ha sido eliminado con éxito.',
|
||||||
|
showConfirmButton: true,
|
||||||
|
customClass: {
|
||||||
|
confirmButton: 'btn btn-secondary w-xs mt-2',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
$('#presupuestos-anonimos-datatable').DataTable().ajax.reload(null, false);
|
||||||
|
},
|
||||||
|
error: function (xhr) {
|
||||||
|
// usa el mensaje del backend; fallback genérico por si no llega JSON
|
||||||
|
const msg = (xhr.responseJSON && xhr.responseJSON.message)
|
||||||
|
|| 'Error al eliminar el presupuesto.';
|
||||||
|
Swal.fire({ icon: 'error', title: 'No se pudo eliminar', text: msg });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|||||||
@ -60,7 +60,7 @@
|
|||||||
<div th:if="${#authentication.principal.role == 'SUPERADMIN'}">
|
<div th:if="${#authentication.principal.role == 'SUPERADMIN'}">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a href="/configuracion/margenes-presupuesto" class="nav-link">
|
<a href="/configuracion/margenes-presupuesto" class="nav-link">
|
||||||
<i class="ri-discount-percent-line"></i>
|
<i class="ri-percent-line"></i>
|
||||||
<span th:text="#{margenes-presupuesto.titulo}">Márgenes de presupuesto</span>
|
<span th:text="#{margenes-presupuesto.titulo}">Márgenes de presupuesto</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@ -17,6 +17,7 @@
|
|||||||
<div class="card-body checkout-tab">
|
<div class="card-body checkout-tab">
|
||||||
|
|
||||||
<form action="#">
|
<form action="#">
|
||||||
|
<input type="hidden" id="cliente_id" th:value="${cliente_id} ?: null" />
|
||||||
<div class="step-arrow-nav mt-n3 mx-n3 mb-3">
|
<div class="step-arrow-nav mt-n3 mx-n3 mb-3">
|
||||||
|
|
||||||
<ul class="nav nav-pills nav-justified custom-nav" role="tablist">
|
<ul class="nav nav-pills nav-justified custom-nav" role="tablist">
|
||||||
|
|||||||
@ -37,6 +37,12 @@
|
|||||||
|
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
|
|
||||||
|
<!-- alert info -->
|
||||||
|
<div th:if="${appMode} == 'view'" class="alert alert-warning fade show" role="alert">
|
||||||
|
<i class="ri-information-fill me-1 align-middle"></i>
|
||||||
|
<span th:text="#{presupuesto.info.presupuestos-anonimos-view}"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div th:insert="~{imprimelibros/presupuestos/presupuestador :: presupuestador}"></div>
|
<div th:insert="~{imprimelibros/presupuestos/presupuestador :: presupuestador}"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user