mirror of
https://git.imnavajas.es/jjimenez/erp-imprimelibros.git
synced 2026-01-13 00:48:49 +00:00
terminado carrito
This commit is contained in:
@ -59,6 +59,8 @@ public class CartController {
|
|||||||
"cart.shipping.send-in-palets",
|
"cart.shipping.send-in-palets",
|
||||||
"cart.shipping.send-in-palets.info",
|
"cart.shipping.send-in-palets.info",
|
||||||
"cart.shipping.tipo-envio",
|
"cart.shipping.tipo-envio",
|
||||||
|
"cart.pass-to.customer.error",
|
||||||
|
"cart.pass-to.customer.error-move",
|
||||||
"app.yes",
|
"app.yes",
|
||||||
"app.aceptar",
|
"app.aceptar",
|
||||||
"app.cancelar");
|
"app.cancelar");
|
||||||
@ -73,14 +75,14 @@ public class CartController {
|
|||||||
model.addAttribute("items", items);
|
model.addAttribute("items", items);
|
||||||
|
|
||||||
Map<String, Object> direcciones = service.getCartDirecciones(cart.getId(), locale);
|
Map<String, Object> direcciones = service.getCartDirecciones(cart.getId(), locale);
|
||||||
if(direcciones != null && direcciones.containsKey("mainDir"))
|
if (direcciones != null && direcciones.containsKey("mainDir"))
|
||||||
model.addAttribute("mainDir", direcciones.get("mainDir"));
|
model.addAttribute("mainDir", direcciones.get("mainDir"));
|
||||||
else if(direcciones != null && direcciones.containsKey("direcciones"))
|
else if (direcciones != null && direcciones.containsKey("direcciones"))
|
||||||
model.addAttribute("direcciones", direcciones.get("direcciones"));
|
model.addAttribute("direcciones", direcciones.get("direcciones"));
|
||||||
|
|
||||||
var summary = service.getCartSummary(cart, locale);
|
var summary = service.getCartSummary(cart, locale);
|
||||||
model.addAttribute("cartSummary", summary);
|
model.addAttribute("cartSummary", summary);
|
||||||
if(summary.get("errorShipmentCost") != null && (Boolean)summary.get("errorShipmentCost"))
|
if (summary.get("errorShipmentCost") != null && (Boolean) summary.get("errorShipmentCost"))
|
||||||
model.addAttribute("errorEnvio", true);
|
model.addAttribute("errorEnvio", true);
|
||||||
else
|
else
|
||||||
model.addAttribute("errorEnvio", false);
|
model.addAttribute("errorEnvio", false);
|
||||||
@ -158,7 +160,8 @@ public class CartController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(value = "/update/{id}", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
@PostMapping(value = "/update/{id}", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||||
public String updateCart(@PathVariable Long id, UpdateCartRequest updateRequest, Model model, Locale locale, Principal principal) {
|
public String updateCart(@PathVariable Long id, UpdateCartRequest updateRequest, Model model, Locale locale,
|
||||||
|
Principal principal) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
service.updateCart(id, updateRequest);
|
service.updateCart(id, updateRequest);
|
||||||
@ -174,7 +177,26 @@ public class CartController {
|
|||||||
model.addAttribute("errorMessage", errorMessage);
|
model.addAttribute("errorMessage", errorMessage);
|
||||||
return "redirect:/cart";
|
return "redirect:/cart";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping(value = "/pass-to-customer/{customerId}")
|
||||||
|
public ResponseEntity<?> moveToCustomer(
|
||||||
|
@PathVariable Long customerId,
|
||||||
|
Principal principal) {
|
||||||
|
|
||||||
|
if(!Utils.isCurrentUserAdmin()) {
|
||||||
|
return ResponseEntity.status(403).body(Map.of("error", "Forbidden"));
|
||||||
|
}
|
||||||
|
|
||||||
|
Long userId = Utils.currentUserId(principal);
|
||||||
|
Cart cart = service.getOrCreateActiveCart(userId);
|
||||||
|
|
||||||
|
boolean ok = service.moveCartToCustomer(cart.getId(), customerId);
|
||||||
|
|
||||||
|
if (ok)
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
return ResponseEntity.status(400).body(Map.of("error", "cart.errors.move-cart"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -112,8 +112,9 @@ public class CartService {
|
|||||||
@Transactional
|
@Transactional
|
||||||
public void removeByPresupuesto(Long userId, Long presupuestoId) {
|
public void removeByPresupuesto(Long userId, Long presupuestoId) {
|
||||||
Cart cart = getOrCreateActiveCart(userId);
|
Cart cart = getOrCreateActiveCart(userId);
|
||||||
itemRepo.findByCartIdAndPresupuestoId(cart.getId(), presupuestoId)
|
CartItem item = itemRepo.findByCartIdAndPresupuestoId(cart.getId(), presupuestoId)
|
||||||
.ifPresent(itemRepo::delete);
|
.orElseThrow(() -> new IllegalArgumentException("Item no encontrado"));
|
||||||
|
itemRepo.deleteById(item.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Vacía todo el carrito activo. */
|
/** Vacía todo el carrito activo. */
|
||||||
@ -355,6 +356,33 @@ public class CartService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean moveCartToCustomer(Long cartId, Long customerId) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
// Remove the cart from the customer if they have one
|
||||||
|
Cart existingCart = cartRepo.findByUserIdAndStatus(customerId, Cart.Status.ACTIVE)
|
||||||
|
.orElse(null);
|
||||||
|
if (existingCart != null) {
|
||||||
|
cartRepo.delete(existingCart);
|
||||||
|
}
|
||||||
|
|
||||||
|
Cart cart = cartRepo.findById(cartId)
|
||||||
|
.orElseThrow(() -> new IllegalArgumentException("Carrito no encontrado"));
|
||||||
|
|
||||||
|
cart.setUserId(customerId);
|
||||||
|
cartRepo.save(cart);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
// Manejo de excepciones
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************
|
||||||
|
* MÉTODOS PRIVADOS
|
||||||
|
***************************************/
|
||||||
|
|
||||||
private Map<String, Object> getShippingCost(
|
private Map<String, Object> getShippingCost(
|
||||||
CartDireccion cd,
|
CartDireccion cd,
|
||||||
Double peso,
|
Double peso,
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import java.util.function.BiFunction;
|
|||||||
|
|
||||||
import org.springframework.context.MessageSource;
|
import org.springframework.context.MessageSource;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
@ -44,6 +45,12 @@ public class Utils {
|
|||||||
this.messageSource = messageSource;
|
this.messageSource = messageSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isCurrentUserAdmin() {
|
||||||
|
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
return auth.getAuthorities().stream()
|
||||||
|
.anyMatch(a -> a.getAuthority().equals("ROLE_ADMIN") || a.getAuthority().equals("ROLE_SUPERADMIN"));
|
||||||
|
}
|
||||||
|
|
||||||
public static Long currentUserId(Principal principal) {
|
public static Long currentUserId(Principal principal) {
|
||||||
|
|
||||||
if (principal == null) {
|
if (principal == null) {
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import org.springframework.stereotype.Controller;
|
|||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
|
|
||||||
|
import java.security.Principal;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@ -621,14 +622,14 @@ public class PresupuestoController {
|
|||||||
@ResponseBody
|
@ResponseBody
|
||||||
public DataTablesResponse<Map<String, Object>> datatable(
|
public DataTablesResponse<Map<String, Object>> datatable(
|
||||||
HttpServletRequest request, Authentication auth, Locale locale,
|
HttpServletRequest request, Authentication auth, Locale locale,
|
||||||
@PathVariable("tipo") String tipo) {
|
@PathVariable("tipo") String tipo, Principal principal) {
|
||||||
|
|
||||||
DataTablesRequest dt = DataTablesParser.from(request);
|
DataTablesRequest dt = DataTablesParser.from(request);
|
||||||
|
|
||||||
if ("anonimos".equals(tipo)) {
|
if ("anonimos".equals(tipo)) {
|
||||||
return dtService.datatablePublicos(dt, locale);
|
return dtService.datatablePublicos(dt, locale, principal);
|
||||||
} else if ("clientes".equals(tipo)) {
|
} else if ("clientes".equals(tipo)) {
|
||||||
return dtService.datatablePrivados(dt, locale);
|
return dtService.datatablePrivados(dt, locale, principal);
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("Tipo de datatable no válido");
|
throw new IllegalArgumentException("Tipo de datatable no válido");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,15 +1,18 @@
|
|||||||
package com.imprimelibros.erp.presupuesto;
|
package com.imprimelibros.erp.presupuesto;
|
||||||
|
|
||||||
import com.imprimelibros.erp.common.Utils;
|
import com.imprimelibros.erp.common.Utils;
|
||||||
|
import com.imprimelibros.erp.configuracion.margenes_presupuestos.MargenPresupuesto;
|
||||||
import com.imprimelibros.erp.datatables.*;
|
import com.imprimelibros.erp.datatables.*;
|
||||||
import com.imprimelibros.erp.presupuesto.dto.Presupuesto;
|
import com.imprimelibros.erp.presupuesto.dto.Presupuesto;
|
||||||
|
|
||||||
import jakarta.persistence.criteria.Expression;
|
import jakarta.persistence.criteria.Expression;
|
||||||
|
|
||||||
import org.springframework.context.MessageSource;
|
import org.springframework.context.MessageSource;
|
||||||
|
import org.springframework.data.jpa.domain.Specification;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.security.Principal;
|
||||||
import java.time.*;
|
import java.time.*;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@ -26,18 +29,29 @@ public class PresupuestoDatatableService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
public DataTablesResponse<Map<String, Object>> datatablePublicos(DataTablesRequest dt, Locale locale) {
|
public DataTablesResponse<Map<String, Object>> datatablePublicos(DataTablesRequest dt, Locale locale,
|
||||||
return commonDataTable(dt, locale, "publico", true);
|
Principal principal) {
|
||||||
|
return commonDataTable(dt, locale, "publico", true, principal);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
public DataTablesResponse<Map<String, Object>> datatablePrivados(DataTablesRequest dt, Locale locale) {
|
public DataTablesResponse<Map<String, Object>> datatablePrivados(DataTablesRequest dt, Locale locale,
|
||||||
return commonDataTable(dt, locale, "privado", false);
|
Principal principal) {
|
||||||
|
return commonDataTable(dt, locale, "privado", false, principal);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataTablesResponse<Map<String, Object>> commonDataTable(DataTablesRequest dt, Locale locale, String origen,
|
private DataTablesResponse<Map<String, Object>> commonDataTable(DataTablesRequest dt, Locale locale, String origen,
|
||||||
boolean publico) {
|
boolean publico, Principal principal) {
|
||||||
Long count = repo.findAllByOrigen(Presupuesto.Origen.valueOf(origen)).stream().count();
|
|
||||||
|
Specification<Presupuesto> base = Specification.allOf(
|
||||||
|
(root, query, cb) -> cb.equal(root.get("origen"), Presupuesto.Origen.valueOf(origen)));
|
||||||
|
|
||||||
|
Boolean isAdmin = Utils.isCurrentUserAdmin();
|
||||||
|
if (!isAdmin) {
|
||||||
|
base = base.and((root, query, cb) -> cb.equal(root.get("user").get("id"), Utils.currentUserId(principal)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Long count = repo.count(base);
|
||||||
|
|
||||||
List<String> orderable = List.of(
|
List<String> orderable = List.of(
|
||||||
"id", "titulo", "user.fullName", "tipoEncuadernacion", "tipoCubierta", "tipoImpresion",
|
"id", "titulo", "user.fullName", "tipoEncuadernacion", "tipoCubierta", "tipoImpresion",
|
||||||
@ -74,6 +88,7 @@ public class PresupuestoDatatableService {
|
|||||||
.add("updatedAt", p -> formatDate(p.getUpdatedAt(), locale))
|
.add("updatedAt", p -> formatDate(p.getUpdatedAt(), locale))
|
||||||
.addIf(!publico, "user", p -> p.getUser() != null ? p.getUser().getFullName() : "")
|
.addIf(!publico, "user", p -> p.getUser() != null ? p.getUser().getFullName() : "")
|
||||||
.add("actions", this::generarBotones)
|
.add("actions", this::generarBotones)
|
||||||
|
.where(base)
|
||||||
.toJson(count);
|
.toJson(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
package com.imprimelibros.erp.users;
|
package com.imprimelibros.erp.users;
|
||||||
|
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
|
|
||||||
|
|||||||
@ -2,10 +2,21 @@ package com.imprimelibros.erp.users;
|
|||||||
|
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
|
|
||||||
|
import java.text.Collator;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import com.imprimelibros.erp.direcciones.Direccion;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class UserServiceImpl implements UserService {
|
public class UserServiceImpl implements UserService {
|
||||||
|
|
||||||
@ -29,5 +40,4 @@ public class UserServiceImpl implements UserService {
|
|||||||
if (query == null || query.isBlank()) query = null;
|
if (query == null || query.isBlank()) query = null;
|
||||||
return userDao.searchUsers(role, query, pageable);
|
return userDao.searchUsers(role, query, pageable);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -44,6 +44,7 @@ cart.pass-to.customer.warning=Advertencia: Esta acción no se puede deshacer y s
|
|||||||
cart.pass-to.select-customer=Seleccione un cliente
|
cart.pass-to.select-customer=Seleccione un cliente
|
||||||
cart.pass-to.button=Mover cesta
|
cart.pass-to.button=Mover cesta
|
||||||
cart.pass-to.success=Cesta movida correctamente al cliente {0}.
|
cart.pass-to.success=Cesta movida correctamente al cliente {0}.
|
||||||
|
cart.pass-to.customer.error=Debe seleccionar un cliente para mover la cesta.
|
||||||
|
cart.pass-to.customer.error-move=Error al mover la cesta de la compra
|
||||||
cart.errors.update-cart=Error al actualizar la cesta de la compra: {0}
|
cart.errors.update-cart=Error al actualizar la cesta de la compra: {0}
|
||||||
cart.errors.shipping=No se puede calcular el coste del envío para alguna de las direcciones seleccionadas. Por favor, póngase en contacto con el servicio de atención al cliente.
|
cart.errors.shipping=No se puede calcular el coste del envío para alguna de las direcciones seleccionadas. Por favor, póngase en contacto con el servicio de atención al cliente.
|
||||||
@ -16,10 +16,10 @@ $(() => {
|
|||||||
$(this).find('.direccion-id').attr('name', 'direcciones[' + i + '].id');
|
$(this).find('.direccion-id').attr('name', 'direcciones[' + i + '].id');
|
||||||
$(this).find('.direccion-cp').attr('name', 'direcciones[' + i + '].cp');
|
$(this).find('.direccion-cp').attr('name', 'direcciones[' + i + '].cp');
|
||||||
$(this).find('.direccion-pais-code3').attr('name', 'direcciones[' + i + '].paisCode3');
|
$(this).find('.direccion-pais-code3').attr('name', 'direcciones[' + i + '].paisCode3');
|
||||||
if($(this).find('.presupuesto-id').length > 0 && $(this).find('.presupuesto-id').val() !== null
|
if ($(this).find('.presupuesto-id').length > 0 && $(this).find('.presupuesto-id').val() !== null
|
||||||
&& $(this).find('.presupuesto-id').val() !== "")
|
&& $(this).find('.presupuesto-id').val() !== "")
|
||||||
$(this).find('.presupuesto-id').attr('name', 'direcciones[' + i + '].presupuestoId');
|
$(this).find('.presupuesto-id').attr('name', 'direcciones[' + i + '].presupuestoId');
|
||||||
if($(this).find('.item-tirada').length > 0 && $(this).find('.item-tirada').val() !== null
|
if ($(this).find('.item-tirada').length > 0 && $(this).find('.item-tirada').val() !== null
|
||||||
&& $(this).find('.item-tirada').val() !== "")
|
&& $(this).find('.item-tirada').val() !== "")
|
||||||
$(this).find('.item-tirada').attr('name', 'direcciones[' + i + '].unidades');
|
$(this).find('.item-tirada').attr('name', 'direcciones[' + i + '].unidades');
|
||||||
});
|
});
|
||||||
@ -31,15 +31,28 @@ $(() => {
|
|||||||
}).always(() => {
|
}).always(() => {
|
||||||
hideLoader();
|
hideLoader();
|
||||||
});
|
});
|
||||||
|
|
||||||
checkAddressesForItems();
|
checkAddressesForItems();
|
||||||
});
|
});
|
||||||
|
|
||||||
checkAddressesForItems();
|
checkAddressesForItems();
|
||||||
|
|
||||||
function checkAddressesForItems(){
|
function checkAddressesForItems() {
|
||||||
if($('#onlyOneShipment').is(':checked')){
|
if ($('.product').length === 0) {
|
||||||
if($("#shippingAddressesContainer .direccion-card").length === 0){
|
$("#alert-empty").removeClass("d-none");
|
||||||
|
$('.cart-content').addClass('d-none');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$('.cart-content').removeClass('d-none');
|
||||||
|
$("#alert-empty").addClass("d-none");
|
||||||
|
// check if select2 is initialized
|
||||||
|
if ($('#select-customer').length && !$('#select-customer').hasClass('select2-hidden-accessible')) {
|
||||||
|
initMoveCartToCustomer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($('#onlyOneShipment').is(':checked')) {
|
||||||
|
if ($("#shippingAddressesContainer .direccion-card").length === 0) {
|
||||||
$(".alert-shipment").removeClass("d-none");
|
$(".alert-shipment").removeClass("d-none");
|
||||||
$('#btn-checkout').prop('disabled', true);
|
$('#btn-checkout').prop('disabled', true);
|
||||||
return;
|
return;
|
||||||
@ -47,42 +60,42 @@ $(() => {
|
|||||||
$(".alert-shipment").addClass("d-none");
|
$(".alert-shipment").addClass("d-none");
|
||||||
$('#btn-checkout').prop('disabled', false);
|
$('#btn-checkout').prop('disabled', false);
|
||||||
}
|
}
|
||||||
else{
|
else {
|
||||||
const items = $(".product");
|
const items = $(".product");
|
||||||
let errorFound = false;
|
let errorFound = false;
|
||||||
for(let i=0; i<items.length; i++){
|
for (let i = 0; i < items.length; i++) {
|
||||||
let errorFoundItem = false;
|
let errorFoundItem = false;
|
||||||
const item = $(items[i]);
|
const item = $(items[i]);
|
||||||
const tirada = parseInt(item.find(".item-tirada").val()) || 0;
|
const tirada = parseInt(item.find(".item-tirada").val()) || 0;
|
||||||
const direcciones = item.find(".direccion-card");
|
const direcciones = item.find(".direccion-card");
|
||||||
let totalUnidades = 0;
|
let totalUnidades = 0;
|
||||||
direcciones.each(function(){
|
direcciones.each(function () {
|
||||||
const unidades = parseInt($(this).find(".item-tirada").val()) || 0;
|
const unidades = parseInt($(this).find(".item-tirada").val()) || 0;
|
||||||
totalUnidades += unidades;
|
totalUnidades += unidades;
|
||||||
});
|
});
|
||||||
if(totalUnidades < tirada){
|
if (totalUnidades < tirada) {
|
||||||
errorFoundItem = true;
|
errorFoundItem = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(item.find(".shipping-addresses-sample")){
|
if (item.find(".shipping-addresses-sample")) {
|
||||||
const container = item.find(".shipping-addresses-sample");
|
const container = item.find(".shipping-addresses-sample");
|
||||||
if(container.find('.direccion-card').toArray().length === 0){
|
if (container.find('.direccion-card').toArray().length === 0) {
|
||||||
errorFoundItem = true;
|
errorFoundItem = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(errorFoundItem){
|
if (errorFoundItem) {
|
||||||
errorFound = true;
|
errorFound = true;
|
||||||
item.find(".alert-icon-shipment").removeClass("d-none");
|
item.find(".alert-icon-shipment").removeClass("d-none");
|
||||||
}
|
}
|
||||||
else{
|
else {
|
||||||
item.find(".alert-icon-shipment").addClass("d-none");
|
item.find(".alert-icon-shipment").addClass("d-none");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(errorFound){
|
if (errorFound) {
|
||||||
$(".alert-shipment").removeClass("d-none");
|
$(".alert-shipment").removeClass("d-none");
|
||||||
$('#btn-checkout').prop('disabled', true);
|
$('#btn-checkout').prop('disabled', true);
|
||||||
}
|
}
|
||||||
else{
|
else {
|
||||||
$(".alert-shipment").addClass("d-none");
|
$(".alert-shipment").addClass("d-none");
|
||||||
$('#btn-checkout').prop('disabled', false);
|
$('#btn-checkout').prop('disabled', false);
|
||||||
}
|
}
|
||||||
@ -92,7 +105,7 @@ $(() => {
|
|||||||
$(document).on("click", ".delete-item", async function (event) {
|
$(document).on("click", ".delete-item", async function (event) {
|
||||||
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const cartItemId = $(this).data("cart-item-id");
|
const presupuestoId = $(this).data("cart-item-id");
|
||||||
const card = $(this).closest('.card.product');
|
const card = $(this).closest('.card.product');
|
||||||
|
|
||||||
// CSRF (Spring Security)
|
// CSRF (Spring Security)
|
||||||
@ -100,7 +113,7 @@ $(() => {
|
|||||||
const csrfHeader = document.querySelector('meta[name="_csrf_header"]')?.content || 'X-CSRF-TOKEN';
|
const csrfHeader = document.querySelector('meta[name="_csrf_header"]')?.content || 'X-CSRF-TOKEN';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await fetch(`/cart/delete/item/${cartItemId}`, {
|
const res = await fetch(`/cart/delete/item/${presupuestoId}`, {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
headers: { [csrfHeader]: csrfToken }
|
headers: { [csrfHeader]: csrfToken }
|
||||||
});
|
});
|
||||||
@ -111,11 +124,79 @@ $(() => {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
card?.remove();
|
card?.remove();
|
||||||
updateTotal();
|
$(document).trigger('updateCart');
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Error en la solicitud:', err);
|
console.error('Error en la solicitud:', err);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function initMoveCartToCustomer() {
|
||||||
|
if ($('#select-customer').length) {
|
||||||
|
|
||||||
|
$('#moveCart').on('click', async function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const customerId = $('#select-customer').val();
|
||||||
|
if (!customerId) {
|
||||||
|
// set text and show alert
|
||||||
|
$('#alert-select-customer').text(window.languageBundle['cart.pass-to.customer.error'] || 'Debe seleccionar un cliente para mover la cesta.');
|
||||||
|
$('#alert-select-customer').removeClass('d-none').hide().fadeIn();
|
||||||
|
setTimeout(() => {
|
||||||
|
$('#alert-select-customer').fadeOut(function () {
|
||||||
|
$(this).addClass('d-none');
|
||||||
|
});
|
||||||
|
}, 5000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CSRF (Spring Security)
|
||||||
|
const csrfToken = document.querySelector('meta[name="_csrf"]')?.content || '';
|
||||||
|
const csrfHeader = document.querySelector('meta[name="_csrf_header"]')?.content || 'X-CSRF-TOKEN';
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await fetch(`/cart/pass-to-customer/${customerId}`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { [csrfHeader]: csrfToken }
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
$('#alert-select-customer').text(window.languageBundle['cart.pass-to.customer.move.error'] || 'Error al mover la cesta de la compra');
|
||||||
|
$('#alert-select-customer').removeClass('d-none').hide().fadeIn();
|
||||||
|
setTimeout(() => {
|
||||||
|
$('#alert-select-customer').fadeOut(function () {
|
||||||
|
$(this).addClass('d-none');
|
||||||
|
});
|
||||||
|
}, 5000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
window.location.href = '/cart';
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error en la solicitud:', err);
|
||||||
|
$('#alert-select-customer').text(window.languageBundle['cart.errors.move-cart'] || 'Error al mover la cesta de la compra');
|
||||||
|
$('#alert-select-customer').removeClass('d-none').hide().fadeIn();
|
||||||
|
setTimeout(() => {
|
||||||
|
$('#alert-select-customer').fadeOut(function () {
|
||||||
|
$(this).addClass('d-none');
|
||||||
|
});
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#select-customer').select2({
|
||||||
|
width: '100%',
|
||||||
|
ajax: {
|
||||||
|
url: 'users/api/get-users',
|
||||||
|
dataType: 'json',
|
||||||
|
delay: 250,
|
||||||
|
},
|
||||||
|
allowClear: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
initMoveCartToCustomer();
|
||||||
|
|
||||||
});
|
});
|
||||||
@ -1,4 +1,4 @@
|
|||||||
<div th:fragment="cartContent(items, cartId)" class="cart-content container-fluid row gy-4">
|
<div th:fragment="cartContent(items, cartId)" th:class="${'cart-content container-fluid row gy-4' + (items.isEmpty() ? ' d-none' : '')}">
|
||||||
|
|
||||||
<div id="sectionLoader" class="position-absolute top-0 start-0 w-100 h-100 d-none justify-content-center align-items-center
|
<div id="sectionLoader" class="position-absolute top-0 start-0 w-100 h-100 d-none justify-content-center align-items-center
|
||||||
bg-body bg-opacity-75" style="z-index:10;">
|
bg-body bg-opacity-75" style="z-index:10;">
|
||||||
@ -7,11 +7,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div th:if="${items.isEmpty()}">
|
<div id="errorEnvio" th:class="${'alert alert-danger' + (errorEnvio ? '' : ' d-none')}" role="alert"
|
||||||
<div class="alert alert-info" role="alert" th:text="#{cart.empty}"></div>
|
th:text="#{cart.errors.shipping}"></div>
|
||||||
</div>
|
<div th:if="${!#strings.isEmpty(errorMessage) and items != null and !items.isEmpty()}" class="alert alert-danger "
|
||||||
<div id="errorEnvio" th:class="${'alert alert-danger' + (errorEnvio ? '' : ' d-none')}" role="alert" th:text="#{cart.errors.shipping}"></div>
|
role="alert" th:text="${errorMessage}"></div>
|
||||||
<div th:if="${errorMessage}" class="alert alert-danger " role="alert" th:text="${errorMessage}"></div>
|
|
||||||
|
|
||||||
<div class="alert alert-danger alert-shipment d-none" role="alert"
|
<div class="alert alert-danger alert-shipment d-none" role="alert"
|
||||||
th:text="#{cart.shipping.errors.fillAddressesItems}"></div>
|
th:text="#{cart.shipping.errors.fillAddressesItems}"></div>
|
||||||
|
|||||||
@ -198,7 +198,7 @@
|
|||||||
<!-- Botón eliminar -->
|
<!-- Botón eliminar -->
|
||||||
<div>
|
<div>
|
||||||
<a href="javascript:void(0);" class="d-block text-body p-1 px-2 delete-item"
|
<a href="javascript:void(0);" class="d-block text-body p-1 px-2 delete-item"
|
||||||
th:attr="data-cart-item-id=${item.cartItemId}">
|
th:attr="data-cart-item-id=${item.presupuestoId}">
|
||||||
<i class="ri-delete-bin-fill text-muted align-bottom me-1"></i> Eliminar
|
<i class="ri-delete-bin-fill text-muted align-bottom me-1"></i> Eliminar
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -25,7 +25,9 @@
|
|||||||
<td class="text-end" id="iva-21-cesta" th:text="${summary.iva21}"></td>
|
<td class="text-end" id="iva-21-cesta" th:text="${summary.iva21}"></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr id="tr-iva-21">
|
<tr id="tr-iva-21">
|
||||||
<td><span th:text="#{cart.resumen.descuento} + ' (' + ${summary.fidelizacion} + ')'"></span> : </td>
|
<td><span
|
||||||
|
th:text="#{cart.resumen.descuento} + ' (' + ${summary.fidelizacion} + ')'"></span>
|
||||||
|
: </td>
|
||||||
<td class="text-end" id="descuento-cesta" th:text="${summary.descuento}"></td>
|
<td class="text-end" id="descuento-cesta" th:text="${summary.descuento}"></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="table-active">
|
<tr class="table-active">
|
||||||
@ -37,8 +39,8 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<form th:action="@{/pagos/redsys/crear}" method="post">
|
<form th:action="@{/pagos/redsys/crear}" method="post">
|
||||||
<input type="hidden" name="order" value="123456789012"/>
|
<input type="hidden" name="order" value="123456789012" />
|
||||||
<input type="hidden" name="amountCents" value="12525"/>
|
<input type="hidden" name="amountCents" value="12525" />
|
||||||
<button id="btn-checkout" type="submit" class="btn btn-secondary w-100 mt-2"
|
<button id="btn-checkout" type="submit" class="btn btn-secondary w-100 mt-2"
|
||||||
th:text="#{cart.resumen.tramitar}">Checkout</button>
|
th:text="#{cart.resumen.tramitar}">Checkout</button>
|
||||||
</form>
|
</form>
|
||||||
@ -47,25 +49,27 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div sec:authorize="isAuthenticated() and hasAnyRole('SUPERADMIN','ADMIN')" class="card">
|
||||||
<div class="card">
|
|
||||||
<div class="card-header border-bottom-dashed">
|
<div class="card-header border-bottom-dashed">
|
||||||
<h5 th:text="#{cart.pass-to.customer}" class="card-title mb-0"></h5>
|
<h5 th:text="#{cart.pass-to.customer}" class="card-title mb-0"></h5>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body pt-2">
|
<div class="card-body pt-2">
|
||||||
<div class="alert alert-info" role="alert" th:text="#{cart.pass-to.customer.info}"></div>
|
<div class="alert alert-info" role="alert" th:text="#{cart.pass-to.customer.info}"></div>
|
||||||
<div class="alert alert-warning" role="alert" th:text="#{cart.pass-to.customer.warning}"></div>
|
<div class="alert alert-warning" role="alert" th:text="#{cart.pass-to.customer.warning}"></div>
|
||||||
<form th:action="@{/cart/pass-to-customer}" method="post">
|
<div id="alert-select-customer" class="alert alert-danger d-none" role="alert"
|
||||||
<div class="mb-3">
|
th:text="#{cart.pass-to.customer.error}"></div>
|
||||||
<label for="select-customer" class="form-label" th:text="#{cart.pass-to.select-customer}"></label>
|
<div class="mb-3">
|
||||||
<select id="select-customer" name="customerId" class="form-select" required>
|
<label for="select-customer" class="form-label" th:text="#{cart.pass-to.select-customer}"></label>
|
||||||
</select>
|
<select id="select-customer" name="customerId" class="form-select" required>
|
||||||
</div>
|
</select>
|
||||||
<button type="submit" class="btn btn-secondary w-100"
|
</div>
|
||||||
th:text="#{cart.pass-to.button}">Mover cesta</button>
|
<div class="mb-3">
|
||||||
|
<button id="moveCart" class="btn btn-secondary w-100" th:text="#{cart.pass-to.button}">Mover
|
||||||
|
cesta</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<!-- end stickey -->
|
<!-- end stickey -->
|
||||||
|
|
||||||
|
|||||||
@ -36,6 +36,10 @@
|
|||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div th:if="${items.isEmpty()}">
|
||||||
|
<div id="alert-empty"class="alert alert-info" role="alert" th:text="#{cart.empty}"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div th:insert="~{imprimelibros/cart/_cartContent :: cartContent(${items}, ${cartId})}"></div>
|
<div th:insert="~{imprimelibros/cart/_cartContent :: cartContent(${items}, ${cartId})}"></div>
|
||||||
|
|
||||||
</th:block>
|
</th:block>
|
||||||
|
|||||||
Reference in New Issue
Block a user