mirror of
https://git.imnavajas.es/jjimenez/erp-imprimelibros.git
synced 2026-01-12 16:38:48 +00:00
falta la vista de los presupuestos aceptados
This commit is contained in:
@ -11,6 +11,8 @@ 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;
|
||||
@ -20,10 +22,10 @@ import com.imprimelibros.erp.cart.dto.DireccionCardDTO;
|
||||
import com.imprimelibros.erp.cart.dto.DireccionShipment;
|
||||
import com.imprimelibros.erp.cart.dto.UpdateCartRequest;
|
||||
import com.imprimelibros.erp.common.Utils;
|
||||
import com.imprimelibros.erp.direcciones.Direccion;
|
||||
import com.imprimelibros.erp.direcciones.DireccionService;
|
||||
import com.imprimelibros.erp.externalApi.skApiClient;
|
||||
import com.imprimelibros.erp.pedido.PedidoService;
|
||||
import com.imprimelibros.erp.pedidos.Pedido;
|
||||
import com.imprimelibros.erp.pedidos.PedidoService;
|
||||
import com.imprimelibros.erp.presupuesto.PresupuestoRepository;
|
||||
|
||||
@Service
|
||||
@ -191,14 +193,13 @@ public class CartService {
|
||||
return resumen;
|
||||
}
|
||||
|
||||
public Map<String, Object> getCartSummary(Cart cart, Locale locale) {
|
||||
public Map<String, Object> getCartSummaryRaw(Cart cart, Locale locale) {
|
||||
|
||||
double base = 0.0;
|
||||
double iva4 = 0.0;
|
||||
double iva21 = 0.0;
|
||||
double shipment = 0.0;
|
||||
|
||||
Boolean errorShipementCost = false;
|
||||
boolean errorShipementCost = false;
|
||||
|
||||
List<CartItem> items = cart.getItems();
|
||||
List<CartDireccion> direcciones = cart.getDirecciones();
|
||||
@ -209,28 +210,29 @@ public class CartService {
|
||||
base += p.getBaseImponible().doubleValue();
|
||||
iva4 += p.getIvaImporte4().doubleValue();
|
||||
iva21 += p.getIvaImporte21().doubleValue();
|
||||
|
||||
if (cart.getOnlyOneShipment() != null && cart.getOnlyOneShipment()) {
|
||||
// Si es envío único, que es a españa y no ha canarias
|
||||
if (direcciones != null && direcciones.size() > 0) {
|
||||
if (direcciones != null && !direcciones.isEmpty()) {
|
||||
CartDireccion cd = direcciones.get(0);
|
||||
Boolean freeShipment = direccionService.checkFreeShipment(cd.getDireccion().getCp(),
|
||||
boolean freeShipment = direccionService.checkFreeShipment(
|
||||
cd.getDireccion().getCp(),
|
||||
cd.getDireccion().getPaisCode3()) && !cd.getIsPalets();
|
||||
|
||||
if (!freeShipment) {
|
||||
Integer unidades = p.getSelectedTirada();
|
||||
Map<String, Object> res = getShippingCost(cd, peso, unidades, locale);
|
||||
if (res.get("success").equals(Boolean.FALSE)) {
|
||||
if (Boolean.FALSE.equals(res.get("success"))) {
|
||||
errorShipementCost = true;
|
||||
} else {
|
||||
shipment += (Double) res.get("shipment");
|
||||
iva21 += (Double) res.get("iva21");
|
||||
}
|
||||
|
||||
}
|
||||
// si tiene prueba de envio, hay que añadir el coste
|
||||
if (p.getServiciosJson() != null && p.getServiciosJson().contains("ejemplar-prueba")) {
|
||||
|
||||
// ejemplar de prueba
|
||||
if (p.getServiciosJson() != null && p.getServiciosJson().contains("ejemplar-prueba")) {
|
||||
Map<String, Object> res = getShippingCost(cd, peso, 1, locale);
|
||||
if (res.get("success").equals(Boolean.FALSE)) {
|
||||
if (Boolean.FALSE.equals(res.get("success"))) {
|
||||
errorShipementCost = true;
|
||||
} else {
|
||||
shipment += (Double) res.get("shipment");
|
||||
@ -239,23 +241,27 @@ public class CartService {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// envio por cada presupuesto
|
||||
// buscar la direccion asignada a este presupuesto
|
||||
if (direcciones == null)
|
||||
continue;
|
||||
|
||||
List<CartDireccion> cd_presupuesto = direcciones.stream()
|
||||
.filter(d -> d.getPresupuesto() != null && d.getPresupuesto().getId().equals(p.getId())
|
||||
&& d.getUnidades() != null && d.getUnidades() != null && d.getUnidades() > 0)
|
||||
.filter(d -> d.getPresupuesto() != null
|
||||
&& d.getPresupuesto().getId().equals(p.getId())
|
||||
&& d.getUnidades() != null
|
||||
&& d.getUnidades() > 0)
|
||||
.toList();
|
||||
Boolean firstDirection = true;
|
||||
|
||||
boolean firstDirection = true;
|
||||
for (CartDireccion cd : cd_presupuesto) {
|
||||
Integer unidades = cd.getUnidades();
|
||||
if (firstDirection) {
|
||||
Boolean freeShipment = direccionService.checkFreeShipment(cd.getDireccion().getCp(),
|
||||
boolean freeShipment = direccionService.checkFreeShipment(
|
||||
cd.getDireccion().getCp(),
|
||||
cd.getDireccion().getPaisCode3()) && !cd.getIsPalets();
|
||||
|
||||
if (!freeShipment && unidades != null && unidades > 0) {
|
||||
Map<String, Object> res = getShippingCost(cd, peso, unidades, locale);
|
||||
if (res.get("success").equals(Boolean.FALSE)) {
|
||||
if (Boolean.FALSE.equals(res.get("success"))) {
|
||||
errorShipementCost = true;
|
||||
} else {
|
||||
shipment += (Double) res.get("shipment");
|
||||
@ -265,7 +271,7 @@ public class CartService {
|
||||
firstDirection = false;
|
||||
} else {
|
||||
Map<String, Object> res = getShippingCost(cd, peso, unidades, locale);
|
||||
if (res.get("success").equals(Boolean.FALSE)) {
|
||||
if (Boolean.FALSE.equals(res.get("success"))) {
|
||||
errorShipementCost = true;
|
||||
} else {
|
||||
shipment += (Double) res.get("shipment");
|
||||
@ -273,15 +279,17 @@ public class CartService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ejemplar de prueba
|
||||
CartDireccion cd_prueba = direcciones.stream()
|
||||
.filter(d -> d.getPresupuesto() != null && d.getPresupuesto().getId().equals(p.getId())
|
||||
.filter(d -> d.getPresupuesto() != null
|
||||
&& d.getPresupuesto().getId().equals(p.getId())
|
||||
&& d.getUnidades() == null)
|
||||
.findFirst().orElse(null);
|
||||
if (cd_prueba != null) {
|
||||
|
||||
if (cd_prueba != null) {
|
||||
Map<String, Object> res = getShippingCost(cd_prueba, peso, 1, locale);
|
||||
if (res.get("success").equals(Boolean.FALSE)) {
|
||||
if (Boolean.FALSE.equals(res.get("success"))) {
|
||||
errorShipementCost = true;
|
||||
} else {
|
||||
shipment += (Double) res.get("shipment");
|
||||
@ -291,11 +299,45 @@ public class CartService {
|
||||
}
|
||||
}
|
||||
|
||||
double total = base + iva4 + iva21 + shipment;
|
||||
|
||||
double totalBeforeDiscount = base + iva4 + iva21 + shipment;
|
||||
int fidelizacion = pedidoService.getDescuentoFidelizacion();
|
||||
double descuento = (total) * fidelizacion / 100.0;
|
||||
total -= descuento;
|
||||
double descuento = totalBeforeDiscount * fidelizacion / 100.0;
|
||||
double total = totalBeforeDiscount - descuento;
|
||||
|
||||
// Redondeo a 2 decimales
|
||||
base = Utils.round2(base);
|
||||
iva4 = Utils.round2(iva4);
|
||||
iva21 = Utils.round2(iva21);
|
||||
shipment = Utils.round2(shipment);
|
||||
descuento = Utils.round2(descuento);
|
||||
total = Utils.round2(total);
|
||||
|
||||
Map<String, Object> summary = new HashMap<>();
|
||||
summary.put("base", base);
|
||||
summary.put("iva4", iva4);
|
||||
summary.put("iva21", iva21);
|
||||
summary.put("shipment", shipment);
|
||||
summary.put("fidelizacion", fidelizacion);
|
||||
summary.put("descuento", descuento);
|
||||
summary.put("total", total);
|
||||
summary.put("amountCents", Math.round(total * 100));
|
||||
summary.put("errorShipmentCost", errorShipementCost);
|
||||
summary.put("cartId", cart.getId());
|
||||
|
||||
return summary;
|
||||
}
|
||||
|
||||
|
||||
public Map<String, Object> getCartSummary(Cart cart, Locale locale) {
|
||||
Map<String, Object> raw = getCartSummaryRaw(cart, locale);
|
||||
|
||||
double base = (Double) raw.get("base");
|
||||
double iva4 = (Double) raw.get("iva4");
|
||||
double iva21 = (Double) raw.get("iva21");
|
||||
double shipment = (Double) raw.get("shipment");
|
||||
int fidelizacion = (Integer) raw.get("fidelizacion");
|
||||
double descuento = (Double) raw.get("descuento");
|
||||
double total = (Double) raw.get("total");
|
||||
|
||||
Map<String, Object> summary = new HashMap<>();
|
||||
summary.put("base", Utils.formatCurrency(base, locale));
|
||||
@ -303,11 +345,11 @@ public class CartService {
|
||||
summary.put("iva21", Utils.formatCurrency(iva21, locale));
|
||||
summary.put("shipment", Utils.formatCurrency(shipment, locale));
|
||||
summary.put("fidelizacion", fidelizacion + "%");
|
||||
summary.put("descuento", Utils.formatCurrency(-descuento, locale));
|
||||
summary.put("descuento", Utils.formatCurrency(-descuento, locale)); // negativo para mostrar
|
||||
summary.put("total", Utils.formatCurrency(total, locale));
|
||||
summary.put("amountCents", Math.round(total * 100));
|
||||
summary.put("errorShipmentCost", errorShipementCost);
|
||||
summary.put("cartId", cart.getId());
|
||||
summary.put("amountCents", raw.get("amountCents"));
|
||||
summary.put("errorShipmentCost", raw.get("errorShipmentCost"));
|
||||
summary.put("cartId", raw.get("cartId"));
|
||||
|
||||
return summary;
|
||||
}
|
||||
@ -402,17 +444,18 @@ public class CartService {
|
||||
// delete cart directions by direccion id in ACTIVE carts
|
||||
@Transactional
|
||||
public void deleteCartDireccionesByDireccionId(Long direccionId) {
|
||||
|
||||
|
||||
cartDireccionRepo.deleteByDireccionIdAndCartStatus(direccionId, Cart.Status.ACTIVE);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Long crearPedido(Long cartId) {
|
||||
public Long crearPedido(Long cartId, Locale locale) {
|
||||
|
||||
Cart cart = this.getCartById(cartId);
|
||||
List<CartItem> items = cart.getItems();
|
||||
|
||||
List<Map<String, Object>> presupuestoRequests = new ArrayList<>();
|
||||
List<Long> presupuestoIds = new ArrayList<>();
|
||||
|
||||
for (Integer i = 0; i < items.size(); i++) {
|
||||
CartItem item = items.get(i);
|
||||
@ -427,9 +470,8 @@ public class CartService {
|
||||
if (datosCabecera != null) {
|
||||
Object tituloOriginal = datosCabecera.get("titulo");
|
||||
datosCabecera.put(
|
||||
"titulo",
|
||||
"[" + (i + 1) + "/" + items.size() + "] " + (tituloOriginal != null ? tituloOriginal : "")
|
||||
);
|
||||
"titulo",
|
||||
"[" + (i + 1) + "/" + items.size() + "] " + (tituloOriginal != null ? tituloOriginal : ""));
|
||||
}
|
||||
}
|
||||
Map<String, Object> direcciones_presupuesto = this.getDireccionesPresupuesto(cart, p);
|
||||
@ -453,24 +495,36 @@ public class CartService {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> dataMap = (Map<String, Object>) dataRaw;
|
||||
Long presId = ((Number) dataMap.get("id")).longValue();
|
||||
String skin = ((String) dataMap.get("iskn")).toString();
|
||||
p.setProveedor("Safekat");
|
||||
p.setProveedorRef1(skin);
|
||||
p.setProveedorRef2(presId);
|
||||
p.setEstado(Presupuesto.Estado.aceptado);
|
||||
presupuestoRepo.save(p);
|
||||
presupuestoIds.add(p.getId());
|
||||
|
||||
presupuestoRequests.add(dataMap);
|
||||
}
|
||||
|
||||
// Crear el pedido en base a los presupuestos guardados
|
||||
if(presupuestoRequests.isEmpty()) {
|
||||
if (presupuestoRequests.isEmpty()) {
|
||||
throw new IllegalStateException("No se pudieron guardar los presupuestos en SK.");
|
||||
}
|
||||
else{
|
||||
List<Long> presupuestoIds = new ArrayList<>();
|
||||
} else {
|
||||
ArrayList<Long> presupuestoSkIds = new ArrayList<>();
|
||||
for (Map<String, Object> presData : presupuestoRequests) {
|
||||
Long presId = ((Number) presData.get("id")).longValue();
|
||||
presupuestoIds.add(presId);
|
||||
presupuestoSkIds.add(presId);
|
||||
}
|
||||
Map<String, Object> ids = new HashMap<>();
|
||||
ids.put("presupuesto_ids", presupuestoIds);
|
||||
ids.put("presupuesto_ids", presupuestoSkIds);
|
||||
Long pedidoId = skApiClient.crearPedido(ids);
|
||||
return pedidoId;
|
||||
if (pedidoId == null) {
|
||||
throw new IllegalStateException("No se pudo crear el pedido en SK.");
|
||||
}
|
||||
Pedido pedidoInterno = pedidoService.crearPedido(presupuestoIds, this.getCartSummaryRaw(cart, locale),
|
||||
"Safekat", String.valueOf(pedidoId), cart.getUserId());
|
||||
return pedidoInterno.getId();
|
||||
}
|
||||
}
|
||||
|
||||
@ -510,7 +564,7 @@ public class CartService {
|
||||
for (CartDireccion cd : cart.getDirecciones()) {
|
||||
|
||||
// direccion de ejemplar de prueba
|
||||
if(cd.getPresupuesto() == null || !cd.getPresupuesto().getId().equals(presupuesto.getId())) {
|
||||
if (cd.getPresupuesto() == null || !cd.getPresupuesto().getId().equals(presupuesto.getId())) {
|
||||
continue;
|
||||
}
|
||||
if (cd.getUnidades() == null || cd.getUnidades() <= 0) {
|
||||
@ -535,9 +589,9 @@ public class CartService {
|
||||
}
|
||||
Map<String, Object> direccionesRet = new HashMap<>();
|
||||
direccionesRet.put("direcciones", direccionesPresupuesto);
|
||||
if(!direccionesPrueba.isEmpty())
|
||||
if (!direccionesPrueba.isEmpty())
|
||||
direccionesRet.put("direccionesFP1", direccionesPrueba.get(0));
|
||||
else{
|
||||
else {
|
||||
direccionesRet.put("direccionesFP1", new ArrayList<>());
|
||||
}
|
||||
return direccionesRet;
|
||||
|
||||
@ -47,10 +47,17 @@ public class Utils {
|
||||
this.messageSource = messageSource;
|
||||
}
|
||||
|
||||
public static double round2(double value) {
|
||||
return BigDecimal.valueOf(value)
|
||||
.setScale(2, RoundingMode.HALF_UP)
|
||||
.doubleValue();
|
||||
}
|
||||
|
||||
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"));
|
||||
.anyMatch(a -> a.getAuthority().equals("ROLE_ADMIN")
|
||||
|| a.getAuthority().equals("ROLE_SUPERADMIN"));
|
||||
}
|
||||
|
||||
public static Long currentUserId(Principal principal) {
|
||||
|
||||
@ -295,11 +295,11 @@ public class PaymentController {
|
||||
}
|
||||
|
||||
@PostMapping(value = "/transfer/completed/{id}", produces = "application/json")
|
||||
public ResponseEntity<Map<String, Object>> markTransferAsCaptured(@PathVariable Long id) {
|
||||
public ResponseEntity<Map<String, Object>> markTransferAsCaptured(@PathVariable Long id, Locale locale) {
|
||||
|
||||
Map<String, Object> response;
|
||||
try {
|
||||
paymentService.markBankTransferAsCaptured(id);
|
||||
paymentService.markBankTransferAsCaptured(id, locale);
|
||||
response = Map.of("success", true);
|
||||
return ResponseEntity.ok(response);
|
||||
|
||||
|
||||
@ -15,6 +15,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import com.imprimelibros.erp.payments.repo.WebhookEventRepository;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
@Service
|
||||
@ -82,7 +83,7 @@ public class PaymentService {
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void handleRedsysNotification(String dsSignature, String dsMerchantParameters) throws Exception {
|
||||
public void handleRedsysNotification(String dsSignature, String dsMerchantParameters, Locale locale) throws Exception {
|
||||
|
||||
// 0) Intentamos parsear la notificación. Si falla, registramos el webhook crudo
|
||||
// y salimos.
|
||||
@ -197,7 +198,7 @@ public class PaymentService {
|
||||
}
|
||||
|
||||
if (authorized) {
|
||||
processOrder(notif.cartId);
|
||||
processOrder(notif.cartId, locale);
|
||||
}
|
||||
|
||||
payRepo.save(p);
|
||||
@ -317,7 +318,7 @@ public class PaymentService {
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void markBankTransferAsCaptured(Long paymentId) {
|
||||
public void markBankTransferAsCaptured(Long paymentId, Locale locale) {
|
||||
Payment p = payRepo.findById(paymentId)
|
||||
.orElseThrow(() -> new IllegalArgumentException("Payment no encontrado: " + paymentId));
|
||||
|
||||
@ -354,7 +355,7 @@ public class PaymentService {
|
||||
|
||||
// 4) Procesar el pedido asociado al carrito (si existe)
|
||||
if (p.getOrderId() != null) {
|
||||
processOrder(p.getOrderId());
|
||||
processOrder(p.getOrderId(), locale);
|
||||
}
|
||||
}
|
||||
|
||||
@ -450,19 +451,26 @@ public class PaymentService {
|
||||
return code >= 0 && code <= 99;
|
||||
}
|
||||
|
||||
private Boolean processOrder(Long cartId) {
|
||||
// GENERAR PEDIDO A PARTIR DEL CARRITO
|
||||
/**
|
||||
* Procesa el pedido asociado al carrito:
|
||||
* - bloquea el carrito
|
||||
* - crea el pedido a partir del carrito
|
||||
*
|
||||
*/
|
||||
private Boolean processOrder(Long cartId, Locale locale) {
|
||||
|
||||
Cart cart = this.cartService.findById(cartId);
|
||||
if (cart != null) {
|
||||
// Bloqueamos el carrito
|
||||
this.cartService.lockCartById(cart.getId());
|
||||
// Creamos el pedido
|
||||
this.cartService.crearPedido(cart.getId());
|
||||
// order ID es generado dentro de createOrderFromCart donde se marcan los
|
||||
// presupuestos como no editables
|
||||
// Long orderId =
|
||||
// this.cartService.pedidoService.createOrderFromCart(cart.getId(), p.getId());
|
||||
// p.setOrderId(orderId);
|
||||
Long orderId = this.cartService.crearPedido(cart.getId(), locale);
|
||||
if(orderId == null){
|
||||
return false;
|
||||
}
|
||||
else{
|
||||
// envio de correo de confirmacion de pedido podria ir aqui
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
|
||||
@ -1,42 +0,0 @@
|
||||
package com.imprimelibros.erp.pedido;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.imprimelibros.erp.externalApi.skApiClient;
|
||||
import com.imprimelibros.erp.presupuesto.service.PresupuestoService;
|
||||
|
||||
|
||||
@Service
|
||||
public class PedidoService {
|
||||
|
||||
protected final skApiClient skApiClient;
|
||||
protected final PresupuestoService presupuestoService;
|
||||
|
||||
public PedidoService(skApiClient skApiClient, PresupuestoService presupuestoService) {
|
||||
this.skApiClient = skApiClient;
|
||||
this.presupuestoService = presupuestoService;
|
||||
}
|
||||
|
||||
public int getDescuentoFidelizacion() {
|
||||
// descuento entre el 1% y el 6% para clientes fidelidad (mas de 1500€ en el
|
||||
// ultimo año)
|
||||
double totalGastado = 1600.0; // Ejemplo, deberías obtenerlo del historial del cliente
|
||||
if (totalGastado < 1200) {
|
||||
return 0;
|
||||
} else if (totalGastado >= 1200 && totalGastado < 1999) {
|
||||
return 1;
|
||||
} else if (totalGastado >= 2000 && totalGastado < 2999) {
|
||||
return 2;
|
||||
} else if (totalGastado >= 3000 && totalGastado < 3999) {
|
||||
return 3;
|
||||
} else if (totalGastado >= 4000 && totalGastado < 4999) {
|
||||
return 4;
|
||||
} else if (totalGastado >= 5000) {
|
||||
return 5;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
191
src/main/java/com/imprimelibros/erp/pedidos/Pedido.java
Normal file
191
src/main/java/com/imprimelibros/erp/pedidos/Pedido.java
Normal file
@ -0,0 +1,191 @@
|
||||
package com.imprimelibros.erp.pedidos;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Entity
|
||||
@Table(name = "pedidos")
|
||||
public class Pedido {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
// Campos económicos
|
||||
@Column(name = "base", nullable = false)
|
||||
private Double base;
|
||||
|
||||
@Column(name = "envio", nullable = false)
|
||||
private Double envio = 0.0;
|
||||
|
||||
@Column(name = "iva4", nullable = false)
|
||||
private Double iva4 = 0.0;
|
||||
|
||||
@Column(name = "iva21", nullable = false)
|
||||
private Double iva21 = 0.0;
|
||||
|
||||
@Column(name = "descuento", nullable = false)
|
||||
private Double descuento = 0.0;
|
||||
|
||||
@Column(name = "total", nullable = false)
|
||||
private Double total = 0.0;
|
||||
|
||||
// Datos de proveedor
|
||||
@Column(name = "proveedor", length = 100)
|
||||
private String proveedor;
|
||||
|
||||
@Column(name = "proveedor_ref", length = 100)
|
||||
private String proveedorRef;
|
||||
|
||||
// Auditoría básica (coincidiendo con las columnas que se ven en la captura)
|
||||
@Column(name = "created_by")
|
||||
private Long createdBy;
|
||||
|
||||
@Column(name = "updated_by")
|
||||
private Long updatedBy;
|
||||
|
||||
@Column(name = "deleted_by")
|
||||
private Long deletedBy;
|
||||
|
||||
@Column(name = "deleted", nullable = false)
|
||||
private boolean deleted = false;
|
||||
|
||||
@Column(name = "created_at", updatable = false)
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@Column(name = "updated_at")
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
@Column(name = "deleted_at")
|
||||
private LocalDateTime deletedAt;
|
||||
|
||||
// --- Getters y setters ---
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Double getBase() {
|
||||
return base;
|
||||
}
|
||||
|
||||
public void setBase(Double base) {
|
||||
this.base = base;
|
||||
}
|
||||
|
||||
public Double getEnvio() {
|
||||
return envio;
|
||||
}
|
||||
|
||||
public void setEnvio(Double envio) {
|
||||
this.envio = envio;
|
||||
}
|
||||
|
||||
public Double getIva4() {
|
||||
return iva4;
|
||||
}
|
||||
|
||||
public void setIva4(Double iva4) {
|
||||
this.iva4 = iva4;
|
||||
}
|
||||
|
||||
public Double getIva21() {
|
||||
return iva21;
|
||||
}
|
||||
|
||||
public void setIva21(Double iva21) {
|
||||
this.iva21 = iva21;
|
||||
}
|
||||
|
||||
public Double getDescuento() {
|
||||
return descuento;
|
||||
}
|
||||
|
||||
public void setDescuento(Double descuento) {
|
||||
this.descuento = descuento;
|
||||
}
|
||||
|
||||
public Double getTotal() {
|
||||
return total;
|
||||
}
|
||||
|
||||
public void setTotal(Double total) {
|
||||
this.total = total;
|
||||
}
|
||||
|
||||
public String getProveedor() {
|
||||
return proveedor;
|
||||
}
|
||||
|
||||
public void setProveedor(String proveedor) {
|
||||
this.proveedor = proveedor;
|
||||
}
|
||||
|
||||
public String getProveedorRef() {
|
||||
return proveedorRef;
|
||||
}
|
||||
|
||||
public void setProveedorRef(String proveedorRef) {
|
||||
this.proveedorRef = proveedorRef;
|
||||
}
|
||||
|
||||
public Long getCreatedBy() {
|
||||
return createdBy;
|
||||
}
|
||||
|
||||
public void setCreatedBy(Long createdBy) {
|
||||
this.createdBy = createdBy;
|
||||
}
|
||||
|
||||
public Long getUpdatedBy() {
|
||||
return updatedBy;
|
||||
}
|
||||
|
||||
public void setUpdatedBy(Long updatedBy) {
|
||||
this.updatedBy = updatedBy;
|
||||
}
|
||||
|
||||
public Long getDeletedBy() {
|
||||
return deletedBy;
|
||||
}
|
||||
|
||||
public void setDeletedBy(Long deletedBy) {
|
||||
this.deletedBy = deletedBy;
|
||||
}
|
||||
|
||||
public boolean isDeleted() {
|
||||
return deleted;
|
||||
}
|
||||
|
||||
public void setDeleted(boolean deleted) {
|
||||
this.deleted = deleted;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public void setCreatedAt(LocalDateTime createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
public LocalDateTime getUpdatedAt() {
|
||||
return updatedAt;
|
||||
}
|
||||
|
||||
public void setUpdatedAt(LocalDateTime updatedAt) {
|
||||
this.updatedAt = updatedAt;
|
||||
}
|
||||
|
||||
public LocalDateTime getDeletedAt() {
|
||||
return deletedAt;
|
||||
}
|
||||
|
||||
public void setDeletedAt(LocalDateTime deletedAt) {
|
||||
this.deletedAt = deletedAt;
|
||||
}
|
||||
}
|
||||
71
src/main/java/com/imprimelibros/erp/pedidos/PedidoLinea.java
Normal file
71
src/main/java/com/imprimelibros/erp/pedidos/PedidoLinea.java
Normal file
@ -0,0 +1,71 @@
|
||||
package com.imprimelibros.erp.pedidos;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import com.imprimelibros.erp.presupuesto.dto.Presupuesto;
|
||||
|
||||
@Entity
|
||||
@Table(name = "pedidos_lineas")
|
||||
public class PedidoLinea {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY, optional = false)
|
||||
@JoinColumn(name = "pedido_id", nullable = false)
|
||||
private Pedido pedido;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY, optional = false)
|
||||
@JoinColumn(name = "presupuesto_id", nullable = false)
|
||||
private Presupuesto presupuesto;
|
||||
|
||||
@Column(name = "created_at")
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@Column(name = "created_by", nullable = false)
|
||||
private Long createdBy;
|
||||
|
||||
// --- Getters y setters ---
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Pedido getPedido() {
|
||||
return pedido;
|
||||
}
|
||||
|
||||
public void setPedido(Pedido pedido) {
|
||||
this.pedido = pedido;
|
||||
}
|
||||
|
||||
public Presupuesto getPresupuesto() {
|
||||
return presupuesto;
|
||||
}
|
||||
|
||||
public void setPresupuesto(Presupuesto presupuesto) {
|
||||
this.presupuesto = presupuesto;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public void setCreatedAt(LocalDateTime createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
public Long getCreatedBy() {
|
||||
return createdBy;
|
||||
}
|
||||
|
||||
public void setCreatedBy(Long createdBy) {
|
||||
this.createdBy = createdBy;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
package com.imprimelibros.erp.pedidos;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface PedidoLineaRepository extends JpaRepository<PedidoLinea, Long> {
|
||||
|
||||
List<PedidoLinea> findByPedidoId(Long pedidoId);
|
||||
|
||||
List<PedidoLinea> findByPresupuestoId(Long presupuestoId);
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
package com.imprimelibros.erp.pedidos;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface PedidoRepository extends JpaRepository<Pedido, Long> {
|
||||
// aquí podrás añadir métodos tipo:
|
||||
// List<Pedido> findByDeletedFalse();
|
||||
}
|
||||
102
src/main/java/com/imprimelibros/erp/pedidos/PedidoService.java
Normal file
102
src/main/java/com/imprimelibros/erp/pedidos/PedidoService.java
Normal file
@ -0,0 +1,102 @@
|
||||
package com.imprimelibros.erp.pedidos;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import com.imprimelibros.erp.presupuesto.PresupuestoRepository;
|
||||
import com.imprimelibros.erp.presupuesto.dto.Presupuesto;
|
||||
import com.imprimelibros.erp.presupuesto.service.PresupuestoService;
|
||||
|
||||
@Service
|
||||
public class PedidoService {
|
||||
|
||||
private final PedidoRepository pedidoRepository;
|
||||
private final PedidoLineaRepository pedidoLineaRepository;
|
||||
private final PresupuestoRepository presupuestoRepository;
|
||||
|
||||
public PedidoService(PedidoRepository pedidoRepository, PedidoLineaRepository pedidoLineaRepository,
|
||||
PresupuestoRepository presupuestoRepository) {
|
||||
this.pedidoRepository = pedidoRepository;
|
||||
this.pedidoLineaRepository = pedidoLineaRepository;
|
||||
this.presupuestoRepository = presupuestoRepository;
|
||||
}
|
||||
|
||||
public int getDescuentoFidelizacion() {
|
||||
// descuento entre el 1% y el 6% para clientes fidelidad (mas de 1500€ en el
|
||||
// ultimo año)
|
||||
double totalGastado = 1600.0; // Ejemplo, deberías obtenerlo del historial del cliente
|
||||
if (totalGastado < 1200) {
|
||||
return 0;
|
||||
} else if (totalGastado >= 1200 && totalGastado < 1999) {
|
||||
return 1;
|
||||
} else if (totalGastado >= 2000 && totalGastado < 2999) {
|
||||
return 2;
|
||||
} else if (totalGastado >= 3000 && totalGastado < 3999) {
|
||||
return 3;
|
||||
} else if (totalGastado >= 4000 && totalGastado < 4999) {
|
||||
return 4;
|
||||
} else if (totalGastado >= 5000) {
|
||||
return 5;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crea un pedido a partir de:
|
||||
* - lista de IDs de presupuesto
|
||||
* - resumen numérico del carrito (getCartSummaryRaw)
|
||||
* - datos de proveedor
|
||||
* - usuario que crea el pedido
|
||||
*/
|
||||
@Transactional
|
||||
public Pedido crearPedido(List<Long> presupuestoIds,
|
||||
Map<String, Object> cartSummaryRaw,
|
||||
String proveedor,
|
||||
String proveedorRef,
|
||||
Long userId) {
|
||||
|
||||
Pedido pedido = new Pedido();
|
||||
|
||||
// Datos económicos (ojo con las claves, son las del summaryRaw)
|
||||
pedido.setBase((Double) cartSummaryRaw.getOrDefault("base", 0.0d));
|
||||
pedido.setEnvio((Double) cartSummaryRaw.getOrDefault("shipment", 0.0d));
|
||||
pedido.setIva4((Double) cartSummaryRaw.getOrDefault("iva4", 0.0d));
|
||||
pedido.setIva21((Double) cartSummaryRaw.getOrDefault("iva21", 0.0d));
|
||||
pedido.setDescuento((Double) cartSummaryRaw.getOrDefault("descuento", 0.0d));
|
||||
pedido.setTotal((Double) cartSummaryRaw.getOrDefault("total", 0.0d));
|
||||
|
||||
// Proveedor
|
||||
pedido.setProveedor(proveedor);
|
||||
pedido.setProveedorRef(proveedorRef);
|
||||
|
||||
// Auditoría mínima
|
||||
pedido.setCreatedBy(userId);
|
||||
pedido.setCreatedAt(LocalDateTime.now());
|
||||
pedido.setDeleted(false);
|
||||
pedido.setUpdatedAt(LocalDateTime.now());
|
||||
pedido.setUpdatedBy(userId);
|
||||
|
||||
// Guardamos el pedido
|
||||
Pedido saved = pedidoRepository.save(pedido);
|
||||
|
||||
// Crear líneas del pedido
|
||||
for (Long presupuestoId : presupuestoIds) {
|
||||
Presupuesto presupuesto = presupuestoRepository.getReferenceById(presupuestoId);
|
||||
|
||||
PedidoLinea linea = new PedidoLinea();
|
||||
linea.setPedido(saved);
|
||||
linea.setPresupuesto(presupuesto);
|
||||
linea.setCreatedBy(userId);
|
||||
linea.setCreatedAt(LocalDateTime.now());
|
||||
|
||||
pedidoLineaRepository.save(linea);
|
||||
}
|
||||
|
||||
return saved;
|
||||
}
|
||||
|
||||
}
|
||||
@ -573,7 +573,7 @@ public class PresupuestoController {
|
||||
String path = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
|
||||
.getRequest().getRequestURI();
|
||||
String mode = path.contains("/view/") ? "view" : "edit";
|
||||
if (mode.equals("view")) {
|
||||
if (mode.equals("view") || presupuestoOpt.get().getEstado() != Presupuesto.Estado.borrador) {
|
||||
model.addAttribute("appMode", "view");
|
||||
} else {
|
||||
model.addAttribute("cliente_id", presupuestoOpt.get().getUser().getId());
|
||||
|
||||
@ -120,7 +120,7 @@ public class PresupuestoDatatableService {
|
||||
String id = String.valueOf(p.getId());
|
||||
String editBtn = "<a href=\"javascript:void(0);\" data-id=\"" + id + "\" class=\"link-success btn-edit-" +
|
||||
(p.getOrigen().equals(Presupuesto.Origen.publico) ? "anonimo" : "privado") + " fs-15\"><i class=\"ri-" +
|
||||
(p.getOrigen().equals(Presupuesto.Origen.publico) ? "eye" : "pencil") + "-line\"></i></a>";
|
||||
(p.getOrigen().equals(Presupuesto.Origen.publico) || p.getEstado() == Presupuesto.Estado.aceptado ? "eye" : "pencil") + "-line\"></i></a>";
|
||||
|
||||
String deleteBtn = borrador ? "<a href=\"javascript:void(0);\" data-id=\"" + id
|
||||
+ "\" class=\"link-danger btn-delete-"
|
||||
|
||||
@ -99,23 +99,27 @@ public class Presupuesto extends AbstractAuditedEntity implements Cloneable {
|
||||
modificado("presupuesto.estado.modificado");
|
||||
|
||||
private final String messageKey;
|
||||
|
||||
Estado(String messageKey) {
|
||||
this.messageKey = messageKey;
|
||||
}
|
||||
|
||||
public String getMessageKey() {
|
||||
return messageKey;
|
||||
}
|
||||
}
|
||||
|
||||
public enum Entrega{
|
||||
public enum Entrega {
|
||||
peninsula("presupuesto.entrega.peninsula"),
|
||||
canarias("presupuesto.entrega.canarias"),
|
||||
paises_ue("presupuesto.entrega.paises-ue");
|
||||
|
||||
private final String messageKey;
|
||||
|
||||
Entrega(String messageKey) {
|
||||
this.messageKey = messageKey;
|
||||
}
|
||||
|
||||
public String getMessageKey() {
|
||||
return messageKey;
|
||||
}
|
||||
@ -371,6 +375,18 @@ public class Presupuesto extends AbstractAuditedEntity implements Cloneable {
|
||||
@Column(name = "alto_faja")
|
||||
private Integer altoFaja = 0;
|
||||
|
||||
@Column(name = "comentario", columnDefinition = "TEXT")
|
||||
private String comentario;
|
||||
|
||||
@Column(name = "proveedor", length = 100)
|
||||
private String proveedor;
|
||||
|
||||
@Column(name = "proveedor_ref1", length = 100)
|
||||
private String proveedorRef1;
|
||||
|
||||
@Column(name = "proveedor_ref2")
|
||||
private Long proveedorRef2;
|
||||
|
||||
// ====== MÉTODOS AUX ======
|
||||
|
||||
public String resumenPresupuesto() {
|
||||
@ -912,16 +928,48 @@ public class Presupuesto extends AbstractAuditedEntity implements Cloneable {
|
||||
this.altoFaja = altoFaja;
|
||||
}
|
||||
|
||||
public Long getId(){
|
||||
public Long getId() {
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id){
|
||||
public String getComentario() {
|
||||
return comentario;
|
||||
}
|
||||
|
||||
public void setComentario(String comentario) {
|
||||
this.comentario = comentario;
|
||||
}
|
||||
|
||||
public String getProveedor() {
|
||||
return proveedor;
|
||||
}
|
||||
|
||||
public void setProveedor(String proveedor) {
|
||||
this.proveedor = proveedor;
|
||||
}
|
||||
|
||||
public String getProveedorRef1() {
|
||||
return proveedorRef1;
|
||||
}
|
||||
|
||||
public void setProveedorRef1(String proveedorRef1) {
|
||||
this.proveedorRef1 = proveedorRef1;
|
||||
}
|
||||
|
||||
public Long getProveedorRef2() {
|
||||
return proveedorRef2;
|
||||
}
|
||||
|
||||
public void setProveedorRef2(Long proveedorRef2) {
|
||||
this.proveedorRef2 = proveedorRef2;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Double getPeso(){
|
||||
public Double getPeso() {
|
||||
// get peso from first element of pricingSnapshotJson (need to parse JSON)
|
||||
// pricingSnapshotJson = {"xxx":{"peso":0.5,...}} is a String
|
||||
if (this.pricingSnapshotJson != null && !this.pricingSnapshotJson.isEmpty()) {
|
||||
|
||||
@ -103,10 +103,10 @@ public class RedsysController {
|
||||
@PostMapping(value = "/ok", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||
@ResponseBody
|
||||
public ResponseEntity<String> okPost(@RequestParam("Ds_Signature") String signature,
|
||||
@RequestParam("Ds_MerchantParameters") String merchantParameters) {
|
||||
@RequestParam("Ds_MerchantParameters") String merchantParameters, Locale locale) {
|
||||
try {
|
||||
// opcional: idempotente, si /notify ya ha hecho el trabajo no pasa nada
|
||||
paymentService.handleRedsysNotification(signature, merchantParameters);
|
||||
paymentService.handleRedsysNotification(signature, merchantParameters, locale);
|
||||
return ResponseEntity.ok("<h2>Pago realizado correctamente</h2><a href=\"/cart\">Volver</a>");
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity.badRequest()
|
||||
@ -127,11 +127,11 @@ public class RedsysController {
|
||||
@ResponseBody
|
||||
public ResponseEntity<String> koPost(
|
||||
@RequestParam("Ds_Signature") String signature,
|
||||
@RequestParam("Ds_MerchantParameters") String merchantParameters) {
|
||||
@RequestParam("Ds_MerchantParameters") String merchantParameters, Locale locale) {
|
||||
|
||||
try {
|
||||
// Procesamos la notificación IGUAL que en /ok y /notify
|
||||
paymentService.handleRedsysNotification(signature, merchantParameters);
|
||||
paymentService.handleRedsysNotification(signature, merchantParameters, locale);
|
||||
|
||||
// Mensaje para el usuario (pago cancelado/rechazado)
|
||||
String html = "<h2>Pago cancelado o rechazado</h2><a href=\"/checkout\">Volver</a>";
|
||||
@ -146,9 +146,9 @@ public class RedsysController {
|
||||
@PostMapping(value = "/notify", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||
@ResponseBody
|
||||
public String notifyRedsys(@RequestParam("Ds_Signature") String signature,
|
||||
@RequestParam("Ds_MerchantParameters") String merchantParameters) {
|
||||
@RequestParam("Ds_MerchantParameters") String merchantParameters, Locale locale) {
|
||||
try {
|
||||
paymentService.handleRedsysNotification(signature, merchantParameters);
|
||||
paymentService.handleRedsysNotification(signature, merchantParameters, locale);
|
||||
return "OK";
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace(); // 👈 para ver el motivo del 500 en logs
|
||||
|
||||
@ -0,0 +1,210 @@
|
||||
databaseChangeLog:
|
||||
- changeSet:
|
||||
id: 0011-update-pedidos-presupuesto
|
||||
author: jjo
|
||||
|
||||
changes:
|
||||
# 1) Nuevas columnas en PRESUPUESTO
|
||||
- addColumn:
|
||||
tableName: presupuesto
|
||||
columns:
|
||||
- column:
|
||||
name: comentario
|
||||
type: TEXT
|
||||
afterColumn: pricing_snapshot
|
||||
constraints:
|
||||
nullable: true
|
||||
- column:
|
||||
name: proveedor
|
||||
type: VARCHAR(100)
|
||||
constraints:
|
||||
nullable: true
|
||||
- column:
|
||||
name: proveedor_ref1
|
||||
type: VARCHAR(100)
|
||||
constraints:
|
||||
nullable: true
|
||||
- column:
|
||||
name: proveedor_ref2
|
||||
type: BIGINT
|
||||
constraints:
|
||||
nullable: true
|
||||
|
||||
# 2) Cambios en PEDIDOS
|
||||
# 2.1 Eliminar FK fk_pedidos_presupuesto
|
||||
- dropForeignKeyConstraint:
|
||||
baseTableName: pedidos
|
||||
constraintName: fk_pedidos_presupuesto
|
||||
|
||||
# 2.2 Eliminar columna presupuesto_id
|
||||
- dropColumn:
|
||||
tableName: pedidos
|
||||
columnName: presupuesto_id
|
||||
|
||||
# 2.3 Añadir nuevas columnas después de id
|
||||
- addColumn:
|
||||
tableName: pedidos
|
||||
columns:
|
||||
- column:
|
||||
name: base
|
||||
type: DOUBLE
|
||||
afterColumn: id
|
||||
constraints:
|
||||
nullable: false
|
||||
- column:
|
||||
name: envio
|
||||
type: DOUBLE
|
||||
defaultValueNumeric: 0
|
||||
constraints:
|
||||
nullable: false
|
||||
- column:
|
||||
name: iva4
|
||||
type: DOUBLE
|
||||
defaultValueNumeric: 0
|
||||
constraints:
|
||||
nullable: false
|
||||
- column:
|
||||
name: iva21
|
||||
type: DOUBLE
|
||||
defaultValueNumeric: 0
|
||||
constraints:
|
||||
nullable: false
|
||||
- column:
|
||||
name: descuento
|
||||
type: DOUBLE
|
||||
defaultValueNumeric: 0
|
||||
constraints:
|
||||
nullable: false
|
||||
- column:
|
||||
name: total
|
||||
type: DOUBLE
|
||||
defaultValueNumeric: 0
|
||||
constraints:
|
||||
nullable: false
|
||||
- column:
|
||||
name: proveedor
|
||||
type: VARCHAR(100)
|
||||
afterColumn: total
|
||||
constraints:
|
||||
nullable: true
|
||||
- column:
|
||||
name: proveedor_ref
|
||||
type: VARCHAR(100)
|
||||
afterColumn: proveedor
|
||||
constraints:
|
||||
nullable: true
|
||||
|
||||
# 3) Crear tabla PEDIDOS_LINEAS
|
||||
- createTable:
|
||||
tableName: pedidos_lineas
|
||||
columns:
|
||||
- column:
|
||||
name: id
|
||||
type: BIGINT
|
||||
autoIncrement: true
|
||||
constraints:
|
||||
primaryKey: true
|
||||
nullable: false
|
||||
- column:
|
||||
name: pedido_id
|
||||
type: BIGINT
|
||||
constraints:
|
||||
nullable: false
|
||||
- column:
|
||||
name: presupuesto_id
|
||||
type: BIGINT
|
||||
constraints:
|
||||
nullable: false
|
||||
- column:
|
||||
name: created_at
|
||||
type: DATETIME(3)
|
||||
constraints:
|
||||
nullable: true
|
||||
- column:
|
||||
name: created_by
|
||||
type: BIGINT
|
||||
constraints:
|
||||
nullable: false
|
||||
|
||||
# FKs de pedidos_lineas
|
||||
- addForeignKeyConstraint:
|
||||
baseTableName: pedidos_lineas
|
||||
baseColumnNames: pedido_id
|
||||
constraintName: fk_pedidos_lineas_pedido
|
||||
referencedTableName: pedidos
|
||||
referencedColumnNames: id
|
||||
onDelete: RESTRICT
|
||||
|
||||
- addForeignKeyConstraint:
|
||||
baseTableName: pedidos_lineas
|
||||
baseColumnNames: presupuesto_id
|
||||
constraintName: fk_pedidos_lineas_presupuesto
|
||||
referencedTableName: presupuesto
|
||||
referencedColumnNames: id
|
||||
onDelete: RESTRICT
|
||||
|
||||
- addForeignKeyConstraint:
|
||||
baseTableName: pedidos_lineas
|
||||
baseColumnNames: created_by
|
||||
constraintName: fk_pedidos_lineas_created_by_user
|
||||
referencedTableName: users
|
||||
referencedColumnNames: id
|
||||
onDelete: RESTRICT
|
||||
|
||||
rollback:
|
||||
# 3) Eliminar tabla pedidos_lineas y sus FKs
|
||||
- dropTable:
|
||||
tableName: pedidos_lineas
|
||||
|
||||
# 2) Revertir cambios en PEDIDOS
|
||||
- dropColumn:
|
||||
tableName: pedidos
|
||||
columns:
|
||||
- column:
|
||||
name: base
|
||||
- column:
|
||||
name: envio
|
||||
- column:
|
||||
name: iva4
|
||||
- column:
|
||||
name: iva21
|
||||
- column:
|
||||
name: descuento
|
||||
- column:
|
||||
name: total
|
||||
- column:
|
||||
name: proveedor
|
||||
- column:
|
||||
name: proveedor_ref
|
||||
|
||||
# 2.2 Volver a crear presupuesto_id
|
||||
- addColumn:
|
||||
tableName: pedidos
|
||||
columns:
|
||||
- column:
|
||||
name: presupuesto_id
|
||||
type: BIGINT
|
||||
constraints:
|
||||
nullable: true
|
||||
|
||||
# 2.1 Volver a crear la FK fk_pedidos_presupuesto
|
||||
- addForeignKeyConstraint:
|
||||
baseTableName: pedidos
|
||||
baseColumnNames: presupuesto_id
|
||||
constraintName: fk_pedidos_presupuesto
|
||||
referencedTableName: presupuesto
|
||||
referencedColumnNames: id
|
||||
onDelete: RESTRICT
|
||||
|
||||
# 1) Eliminar columnas añadidas en PRESUPUESTO
|
||||
- dropColumn:
|
||||
tableName: presupuesto
|
||||
columns:
|
||||
- column:
|
||||
name: comentario
|
||||
- column:
|
||||
name: proveedor
|
||||
- column:
|
||||
name: proveedor_ref1
|
||||
- column:
|
||||
name: proveedor_ref2
|
||||
@ -18,4 +18,6 @@ databaseChangeLog:
|
||||
- include:
|
||||
file: db/changelog/changesets/0009-add-composite-unique-txid-type.yml
|
||||
- include:
|
||||
file: db/changelog/changesets/0010-drop-unique-tx-gateway.yml
|
||||
file: db/changelog/changesets/0010-drop-unique-tx-gateway.yml
|
||||
- include:
|
||||
file: db/changelog/changesets/0011-update-pedidos-presupuesto.yml
|
||||
@ -0,0 +1,72 @@
|
||||
<div id="presupuesto-app" th:data-mode="${appMode} ?: 'public'" th:data-id="${id} ?: ''" th:fragment="presupuestador">
|
||||
|
||||
<div class="row" id="presupuesto-row">
|
||||
<div class="animate-fadeInUpBounce">
|
||||
|
||||
<!-- Ribbon Shape -->
|
||||
<div class="card ribbon-box border shadow-none mb-lg-0 material-shadow">
|
||||
<div class="card-body">
|
||||
<div class="ribbon ribbon-primary ribbon-shape" th:text="#{presupuesto.resumen}">Resumen
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ribbon-content mt-4">
|
||||
<div id="div-extras" class="hstack gap-2 justify-content-center flex-wrap">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- End Ribbon Shape -->
|
||||
|
||||
<div class="col-9 mx-auto mt-4">
|
||||
<h5 id="resumen-titulo" class="text-center"></h5>
|
||||
<table id="resumen-tabla-final" class="table table-borderless table-striped mt-3"
|
||||
th:data-currency="#{app.currency}">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th th:text="#{presupuesto.resumen.tabla.descripcion}">Descripción</th>
|
||||
<th th:text="#{presupuesto.resumen.tabla.cantidad}">Cantidad</th>
|
||||
<th th:text="#{presupuesto.resumen.tabla.precio-unidad}">Precio unitario</th>
|
||||
<th th:text="#{presupuesto.resumen.tabla.precio-total}">Precio total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr class="table-active">
|
||||
<th colspan="4" class="text-end" th:text="#{presupuesto.resumen.tabla.base}">Total</th>
|
||||
<th class="text-end" id="resumen-base">0,00 €</th>
|
||||
</tr>
|
||||
<tr id="tr-resumen-iva4" class="table-active">
|
||||
<th colspan="4" class="text-end" th:text="#{presupuesto.resumen.tabla.iva4}">IVA (4%)</th>
|
||||
<th class="text-end" id="resumen-iva4">0,00 €</th>
|
||||
</tr>
|
||||
<tr id="tr-resumen-iva21" class="table-active">
|
||||
<th colspan="4" class="text-end" th:text="#{presupuesto.resumen.tabla.iva21}">IVA (21%)</th>
|
||||
<th class="text-end" id="resumen-iva21">0,00 €</th>
|
||||
</tr>
|
||||
<tr class="table-active">
|
||||
<th colspan="4" class="text-end" th:text="#{presupuesto.resumen.tabla.total}">Total con IVA
|
||||
</th>
|
||||
<th class="text-end" id="resumen-total">0,00 €</th>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mt-4 w-100">
|
||||
<button type="button"
|
||||
class="btn btn-secondary d-flex align-items-center mx-2 btn-imprimir">
|
||||
<i class="ri-printer-line me-2"></i>
|
||||
<span th:text="#{app.imprimir}">Imprimir</span>
|
||||
</button>
|
||||
|
||||
<button type="button"
|
||||
class="btn btn-secondary d-flex align-items-center mx-2 add-cart-btn">
|
||||
<i class="ri-shopping-cart-line me-2"></i>
|
||||
<span th:text="#{presupuesto.add-to-cart}">Añadir a la cesta</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--end row-->
|
||||
</div>
|
||||
@ -1,5 +1,7 @@
|
||||
package com.imprimelibros.erp.presupuesto;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
@ -14,7 +16,8 @@ public class savePresupuestosTest {
|
||||
|
||||
@Test
|
||||
void testGuardarPresupuesto() {
|
||||
Long resultado = cartService.crearPedido(9L);
|
||||
Locale locale = new Locale("es", "ES");
|
||||
Long resultado = cartService.crearPedido(9L, locale);
|
||||
|
||||
System.out.println("📦 Presupuesto guardado:");
|
||||
System.out.println(resultado);
|
||||
|
||||
Reference in New Issue
Block a user