primera versión de pedido realizada

This commit is contained in:
2025-11-10 21:06:53 +01:00
parent cc696d7a99
commit 4ceb4fb8e4
14 changed files with 436 additions and 101 deletions

View File

@ -11,8 +11,6 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.math.BigDecimal;
import java.math.RoundingMode;
import com.imprimelibros.erp.presupuesto.classes.PresupuestoFormatter;
import com.imprimelibros.erp.presupuesto.dto.Presupuesto;
@ -327,7 +325,6 @@ public class CartService {
return summary;
}
public Map<String, Object> getCartSummary(Cart cart, Locale locale) {
Map<String, Object> raw = getCartSummaryRaw(cart, locale);
@ -502,6 +499,7 @@ public class CartService {
p.setProveedorRef2(presId);
p.setEstado(Presupuesto.Estado.aceptado);
presupuestoRepo.save(p);
presupuestoIds.add(p.getId());
presupuestoRequests.add(dataMap);

View File

@ -47,6 +47,26 @@ public class Utils {
this.messageSource = messageSource;
}
public static List<Map<String, Object>> decodeJsonList(String json) {
ObjectMapper mapper = new ObjectMapper();
try {
return mapper.readValue(json, new TypeReference<List<Map<String, Object>>>() {
});
} catch (JsonProcessingException e) {
return new ArrayList<>();
}
}
public static Map<String, Object> decodeJsonMap(String json) {
ObjectMapper mapper = new ObjectMapper();
try {
return mapper.readValue(json, new TypeReference<Map<String, Object>>() {
});
} catch (JsonProcessingException e) {
return new HashMap<>();
}
}
public static double round2(double value) {
return BigDecimal.valueOf(value)
.setScale(2, RoundingMode.HALF_UP)

View File

@ -52,6 +52,7 @@ import com.imprimelibros.erp.users.UserDao;
import com.imprimelibros.erp.users.UserDetailsImpl;
import com.imprimelibros.erp.presupuesto.service.PresupuestoFormDataMapper;
import com.imprimelibros.erp.presupuesto.service.PresupuestoFormDataMapper.PresupuestoFormDataDto;
import com.imprimelibros.erp.common.Utils;
import com.imprimelibros.erp.common.web.IpUtils;
import jakarta.servlet.http.HttpServletRequest;
@ -561,6 +562,20 @@ public class PresupuestoController {
return "redirect:/presupuesto";
}
if(presupuestoOpt.get().getEstado() == Presupuesto.Estado.aceptado){
Map<String, Object> resumen = presupuestoService.getTextosResumen(
presupuestoOpt.get(),
Utils.decodeJsonList(presupuestoOpt.get().getServiciosJson()),
Utils.decodeJsonMap(presupuestoOpt.get().getDatosMaquetacionJson()),
Utils.decodeJsonMap(presupuestoOpt.get().getDatosMarcapaginasJson()),
locale);
model.addAttribute("resumen", resumen);
model.addAttribute("presupuesto", presupuestoOpt.get());
return "imprimelibros/presupuestos/presupuestador-view";
}
if (!presupuestoService.canAccessPresupuesto(presupuestoOpt.get(), authentication)) {
// Añadir mensaje flash para mostrar alerta
redirectAttributes.addFlashAttribute("errorMessage",

View File

@ -918,6 +918,7 @@ public class PresupuestoService {
/ Double.parseDouble(servicio.get("units").toString())
: servicio.get("price"));
servicioData.put("unidades", servicio.get("units"));
servicioData.put("id", servicio.get("id"));
serviciosExtras.add(servicioData);
}
}

View File

@ -1,9 +1,22 @@
package com.imprimelibros.erp.redsys;
import com.imprimelibros.erp.common.Utils;
import com.imprimelibros.erp.payments.PaymentService;
import com.imprimelibros.erp.payments.model.Payment;
import com.imprimelibros.erp.redsys.RedsysService.FormPayload;
import jakarta.servlet.ServletContext;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.thymeleaf.context.WebContext;
import org.thymeleaf.web.IWebExchange;
import org.thymeleaf.web.servlet.JakartaServletWebApplication;
import org.thymeleaf.spring6.SpringTemplateEngine;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.context.MessageSource;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
@ -22,37 +35,51 @@ public class RedsysController {
private final PaymentService paymentService;
private final MessageSource messageSource;
private final SpringTemplateEngine templateEngine;
private final ServletContext servletContext;
public RedsysController(PaymentService paymentService, MessageSource messageSource) {
public RedsysController(PaymentService paymentService, MessageSource messageSource,
SpringTemplateEngine templateEngine, ServletContext servletContext) {
this.paymentService = paymentService;
this.messageSource = messageSource;
this.templateEngine = templateEngine;
this.servletContext = servletContext;
}
@PostMapping(value = "/crear", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
@ResponseBody
public ResponseEntity<byte[]> crearPago(@RequestParam("amountCents") Long amountCents,
@RequestParam("method") String method, @RequestParam("cartId") Long cartId) throws Exception {
@RequestParam("method") String method, @RequestParam("cartId") Long cartId,
HttpServletRequest request,
HttpServletResponse response, Locale locale)
throws Exception {
if ("bank-transfer".equalsIgnoreCase(method)) {
// 1) Creamos el Payment interno SIN orderId (null)
Payment p = paymentService.createBankTransferPayment(cartId, amountCents, "EUR");
// 2) Mostramos instrucciones de transferencia
String html = """
<html><head><meta charset="utf-8"><title>Pago por transferencia</title></head>
<body>
<h2>Pago por transferencia bancaria</h2>
<p>Hemos registrado tu intención de pedido.</p>
<p><strong>Importe:</strong> %s €</p>
<p><strong>IBAN:</strong> ES00 1234 5678 9012 3456 7890</p>
<p><strong>Concepto:</strong> TRANSF-%d</p>
<p>En cuanto recibamos la transferencia, procesaremos tu pedido.</p>
<p><a href="/checkout/resumen">Volver al resumen</a></p>
</body></html>
""".formatted(
String.format("%.2f", amountCents / 100.0),
p.getId() // usamos el ID del Payment como referencia
);
// 1⃣ Crear la "aplicación" web de Thymeleaf (Jakarta)
JakartaServletWebApplication app = JakartaServletWebApplication.buildApplication(servletContext);
// 2⃣ Construir el intercambio web desde request/response
response.setContentType("text/html;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
IWebExchange exchange = app.buildExchange(request, response);
// 3⃣ Crear el contexto WebContext con Locale
WebContext ctx = new WebContext(exchange, locale);
String importeFormateado = Utils.formatCurrency(amountCents / 100.0, locale);
ctx.setVariable("importe", importeFormateado);
ctx.setVariable("concepto", "TRANSF-" + p.getId());
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
boolean isAuth = auth != null
&& auth.isAuthenticated()
&& !(auth instanceof AnonymousAuthenticationToken);
ctx.setVariable("isAuth", isAuth);
// 3) Renderizamos la plantilla a HTML
String html = templateEngine.process("imprimelibros/pagos/transfer", ctx);
byte[] body = html.getBytes(StandardCharsets.UTF_8);
return ResponseEntity.ok()
@ -92,7 +119,8 @@ public class RedsysController {
// GET: cuando el usuario cae aquí sin parámetros, o Redsys redirige por GET
@GetMapping("/ok")
public String okGet(RedirectAttributes redirectAttrs, Model model, Locale locale) {
String msg = messageSource.getMessage("checkout.success.payment", null, "Pago realizado con éxito. Gracias por su compra.", locale);
String msg = messageSource.getMessage("checkout.success.payment", null,
"Pago realizado con éxito. Gracias por su compra.", locale);
model.addAttribute("successPago", msg);
redirectAttrs.addFlashAttribute("successPago", msg);
return "redirect:/cart";
@ -117,7 +145,9 @@ public class RedsysController {
@GetMapping("/ko")
public String koGet(RedirectAttributes redirectAttrs, Model model, Locale locale) {
String msg = messageSource.getMessage("checkout.error.payment", null, "Error al procesar el pago: el pago ha sido cancelado o rechazado Por favor, inténtelo de nuevo.", locale);
String msg = messageSource.getMessage("checkout.error.payment", null,
"Error al procesar el pago: el pago ha sido cancelado o rechazado Por favor, inténtelo de nuevo.",
locale);
model.addAttribute("errorPago", msg);
redirectAttrs.addFlashAttribute("errorPago", msg);
return "redirect:/cart";