Files
erp-imprimelibros/src/main/java/com/imprimelibros/erp/cart/CartController.java
2025-10-31 11:36:03 +01:00

203 lines
7.9 KiB
Java

package com.imprimelibros.erp.cart;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.context.MessageSource;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import com.imprimelibros.erp.common.Utils;
import com.imprimelibros.erp.direcciones.Direccion;
import com.imprimelibros.erp.direcciones.DireccionService;
import com.imprimelibros.erp.i18n.TranslationService;
import java.security.Principal;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import com.imprimelibros.erp.cart.dto.UpdateCartRequest;
@Controller
@RequestMapping("/cart")
public class CartController {
protected final CartService service;
protected DireccionService direccionService;
protected MessageSource messageSource;
protected TranslationService translationService;
public CartController(CartService service, DireccionService direccionService, MessageSource messageSource,
TranslationService translationService) {
this.service = service;
this.direccionService = direccionService;
this.messageSource = messageSource;
this.translationService = translationService;
}
/** Vista del carrito */
@GetMapping
public String viewCart(Model model, Principal principal, Locale locale) {
List<String> keys = List.of(
"app.cancelar",
"app.seleccionar",
"cart.shipping.add.title",
"cart.shipping.select-placeholder",
"cart.shipping.new-address",
"cart.shipping.errors.noAddressSelected",
"cart.shipping.enter-units",
"cart.shipping.units-label",
"cart.shipping.errors.units-error",
"cart.shipping.ud",
"cart.shipping.uds",
"cart.shipping.send-in-palets",
"cart.shipping.send-in-palets.info",
"cart.shipping.tipo-envio",
"cart.pass-to.customer.error",
"cart.pass-to.customer.error-move",
"app.yes",
"app.aceptar",
"app.cancelar");
Map<String, String> translations = translationService.getTranslations(locale, keys);
model.addAttribute("languageBundle", translations);
Long userId = Utils.currentUserId(principal);
Cart cart = service.getOrCreateActiveCart(userId);
var items = service.listItems(userId, locale);
model.addAttribute("items", items);
Map<String, Object> direcciones = service.getCartDirecciones(cart.getId(), locale);
if (direcciones != null && direcciones.containsKey("mainDir"))
model.addAttribute("mainDir", direcciones.get("mainDir"));
else if (direcciones != null && direcciones.containsKey("direcciones"))
model.addAttribute("direcciones", direcciones.get("direcciones"));
var summary = service.getCartSummary(cart, locale);
model.addAttribute("cartSummary", summary);
if (summary.get("errorShipmentCost") != null && (Boolean) summary.get("errorShipmentCost"))
model.addAttribute("errorEnvio", true);
else
model.addAttribute("errorEnvio", false);
model.addAttribute("cart", cart);
return "imprimelibros/cart/cart"; // crea esta vista si quieres (tabla simple)
}
/** Añadir presupuesto via POST form */
@PostMapping("/add")
public String add(@PathVariable(name = "presupuestoId", required = true) Long presupuestoId, Principal principal) {
service.addPresupuesto(Utils.currentUserId(principal), presupuestoId);
return "redirect:/cart";
}
/** Añadir presupuesto con ruta REST (opcional) */
@PostMapping("/add/{presupuestoId}")
public Object addPath(@PathVariable Long presupuestoId, Principal principal, HttpServletRequest request) {
service.addPresupuesto(Utils.currentUserId(principal), presupuestoId);
boolean isAjax = "XMLHttpRequest".equals(request.getHeader("X-Requested-With"));
if (isAjax) {
// Responder 200 con la URL a la que quieres ir
return ResponseEntity.ok(
Map.of("redirect", "/cart"));
}
// Navegación normal: redirección server-side
return "redirect:/cart";
}
@GetMapping("/count")
@ResponseBody
public long getCount(Principal principal) {
if (principal == null)
return 0;
return service.countItems(Utils.currentUserId(principal));
}
/** Eliminar línea por ID de item */
@DeleteMapping("/{itemId}/remove")
public String remove(@PathVariable Long itemId, Principal principal) {
service.removeItem(Utils.currentUserId(principal), itemId);
return "redirect:/cart";
}
/** Eliminar línea por presupuesto_id (opcional) */
@DeleteMapping("/delete/item/{presupuestoId}")
@ResponseBody
public String removeByPresupuesto(@PathVariable Long presupuestoId, Principal principal) {
service.removeByPresupuesto(Utils.currentUserId(principal), presupuestoId);
return "redirect:/cart";
}
/** Vaciar carrito completo */
@DeleteMapping("/clear")
public String clear(Principal principal) {
service.clear(Utils.currentUserId(principal));
return "redirect:/cart";
}
@GetMapping("/get-address/{id}")
public String getDireccionCard(@PathVariable Long id, @RequestParam(required = false) Long presupuestoId,
@RequestParam(required = false) Integer unidades,
@RequestParam(required = false) Integer isPalets,
Model model, Locale locale) {
Direccion dir = direccionService.findById(id)
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
model.addAttribute("pais", messageSource.getMessage("paises." + dir.getPais().getKeyword(), null,
dir.getPais().getKeyword(), locale));
model.addAttribute("presupuestoId", presupuestoId);
model.addAttribute("unidades", unidades);
model.addAttribute("isPalets", isPalets);
model.addAttribute("direccion", dir);
return "imprimelibros/direcciones/direccionCard :: direccionCard(direccion=${direccion})";
}
@PostMapping(value = "/update/{id}", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public String updateCart(@PathVariable Long id, UpdateCartRequest updateRequest, Model model, Locale locale,
Principal principal) {
try {
service.updateCart(id, updateRequest);
var cartSummary = service.getCartSummary(service.getCartById(id), locale);
model.addAttribute("cartSummary", cartSummary);
return "imprimelibros/cart/_cartSummary :: cartSummary(summary=${cartSummary})";
} catch (Exception e) {
// redirect to cart with error message
String errorMessage = messageSource.getMessage("cart.update.error", null, "Error updating cart", locale);
model.addAttribute("errorMessage", errorMessage);
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"));
}
}