falta actualizar bien el resumen

This commit is contained in:
2025-10-30 19:48:26 +01:00
parent feff9ee94a
commit 167c136dca
28 changed files with 518 additions and 342 deletions

View File

@ -28,8 +28,8 @@ spring.jpa.show-sql=false
#
# Safekat API Configuration
#
#safekat.api.url=http://localhost:8000/
safekat.api.url=https://erp-dev.safekat.es/
safekat.api.url=http://localhost:8000/
#safekat.api.url=https://erp-dev.safekat.es/
safekat.api.email=imnavajas@coit.es
safekat.api.password=Safekat2024
@ -114,7 +114,13 @@ redsys.terminal=1
redsys.currency=978
redsys.transaction-type=0
redsys.secret-key=sq7HjrUOBfKmC576ILgskD5srU870gJ7
redsys.urls.ok=https://localhost:8080/pagos/redsys/ok
redsys.urls.ko=https://localhost:8080/pagos/redsys/ko
redsys.urls.notify=https://localhost:8080/pagos/redsys/notify
redsys.urls.ok=http://localhost:8080/pagos/redsys/ok
redsys.urls.ko=http://localhost:8080/pagos/redsys/ko
redsys.urls.notify=http://localhost:8080/pagos/redsys/notify
# Mensajes de error mas cortos
# Oculta el stack trace en los errores del servidor
server.error.include-stacktrace=never
# No mostrar el mensaje completo de excepción en la respuesta
server.error.include-message=always

View File

@ -22,6 +22,15 @@ databaseChangeLog:
constraints:
nullable: false
- column:
name: total
type: DECIMAL(19,6)
defaultValueNumeric: 0
remarks: "Total del carrito"
afterColumn: only_one_shipment
constraints:
nullable: false
rollback:
- dropColumn:
tableName: carts

View File

@ -50,12 +50,7 @@ databaseChangeLog:
constraints:
nullable: false
defaultValue: false
- column:
name: base
type: DECIMAL(12, 2)
- createIndex:
indexName: idx_cart_dir_direccion_id
tableName: cart_direcciones

View File

@ -31,6 +31,7 @@ cart.shipping.errors.fillAddressesItems=Debe seleccionar una dirección de enví
cart.resumen.title=Resumen de la cesta
cart.resumen.base=Base imponible:
cart.resumen.envio=Coste de envío:
cart.resumen.iva-4=IVA 4%:
cart.resumen.iva-21=IVA 21%:
cart.resumen.total=Total cesta:
@ -38,4 +39,5 @@ cart.resumen.tramitar=Tramitar pedido
cart.resumen.fidelizacion=Si tiene descuento por fidelización, se aplicará al tramitar el pedido.
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.

View File

@ -11,4 +11,7 @@ checkout.shipping.onlyOneShipment=Todo el pedido se envía a una única direcci
checkout.summary.presupuesto=#Presupuesto
checkout.summary.titulo=Título
checkout.summary.base=Base
checkout.summary.base=Base
checkout.summary.iva-4=IVA 4%
checkout.summary.iva-21=IVA 21%
checkout.summary.envio=Envío

Binary file not shown.

View File

@ -24,7 +24,10 @@ $(() => {
$(this).find('.item-tirada').attr('name', 'direcciones[' + i + '].unidades');
});
$.post(form.attr('action'), form.serialize(), (response) => {
// handle response
// if success and received html, replace container summary
if (response) {
$('.cart-summary-container').replaceWith(response);
}
}).always(() => {
hideLoader();
});

View File

@ -10,7 +10,7 @@ $(() => {
$('.nav-product').addClass('d-none');
document.querySelectorAll('.card.product').forEach(card => {
const detailsBtn = card.querySelector('.nav-link[id^="pills-details-"][id$="-tab"]');
if (detailsBtn) $(new bootstrap.Tab(detailsBtn)).removeClass('d-none');
if (detailsBtn) new bootstrap.Tab(detailsBtn).show();
});
$('#shippingAddressesContainer').empty().removeClass('d-none');
$('.shipping-addresses-item').toArray().forEach(element => {
@ -235,7 +235,7 @@ $(() => {
return false;
}
}
else if(presupuestoId == null){ // caso para todas los envios a la misma direccion
else if (presupuestoId == null && direccionId) { // caso para todas los envios a la misma direccion
const isPaletsValue = await getTipoEnvio();
if (isPaletsValue !== null) {
isPalets = isPaletsValue ? 1 : 0;
@ -285,13 +285,13 @@ $(() => {
value="${tirada}" class="form-control text-center">
</div>
<div class="form-check form-switch form-switch-custom mb-3 d-flex align-items-center justify-content-center ps-0">
<input type="checkbox"
id="swal-input-palets"
class="form-check-input ms-0 me-2 float-none">
<label for="swal-input-palets" class="form-check-label mb-0">
${window.languageBundle['cart.shipping.send-in-palets'] || 'Enviar en palets'}
</label>
</div>
<input type="checkbox"
id="swal-input-palets"
class="form-check-input ms-0 me-2 float-none">
<label for="swal-input-palets" class="form-check-label mb-0">
${window.languageBundle['cart.shipping.send-in-palets'] || 'Enviar en palets'}
</label>
</div>
<span class="form-text text-muted">
${window.languageBundle['cart.shipping.send-in-palets.info'] || 'En palets la entrega se realizará a pie de calle.'}
</span>
@ -327,19 +327,19 @@ $(() => {
}
async function getTipoEnvio() {
const { value: checkValue } = await Swal.fire({
const { isConfirmed, value } = await Swal.fire({
title: window.languageBundle['cart.shipping.tipo-envio'] || 'Tipo de envío',
html: `
<div class="form-check form-switch form-switch-custom my-3 d-flex align-items-center justify-content-center gap-2">
<input type="checkbox" class="form-check-input" id="swal-input-palets">
<label for="swal-input-palets" class="form-label mb-0">
<div class="form-check form-switch form-switch-custom my-3 d-flex align-items-center justify-content-center gap-2">
<input type="checkbox" class="form-check-input" id="swal-input-palets">
<label for="swal-input-palets" class="form-label mb-0">
${window.languageBundle['cart.shipping.send-in-palets'] || 'Enviar en palets'}
</label>
</div>
<span class="form-text text-muted">
${window.languageBundle['cart.shipping.send-in-palets.info'] || 'En palets la entrega se realizará a pie de calle.'}
</span>
`,
</label>
</div>
<span class="form-text text-muted">
${window.languageBundle['cart.shipping.send-in-palets.info'] || 'En palets la entrega se realizará a pie de calle.'}
</span>
`,
focusConfirm: false,
showCancelButton: true,
buttonsStyling: false,
@ -350,17 +350,18 @@ $(() => {
confirmButtonText: window.languageBundle['app.aceptar'] || 'Aceptar',
cancelButtonText: window.languageBundle['app.cancelar'] || 'Cancelar',
preConfirm: () => {
const isPalets = document.getElementById('swal-input-palets').checked;
return isPalets;
const popup = Swal.getPopup();
const chk = popup.querySelector('#swal-input-palets');
// Devuelve un OBJETO (siempre truthy) con el booleano dentro
return { isPalets: !!chk?.checked };
}
});
if (checkValue !== undefined) {
return checkValue; // boolean
}
return null; // Si se cancela el Swal
if (!isConfirmed) return null; // cancelado
return value.isPalets; // true / false
}
function checkTotalUnits(container, tirada) {
const totalUnits = container.find('.direccion-card').toArray().reduce((acc, el) => {

View File

@ -10,6 +10,7 @@
<div th:if="${items.isEmpty()}">
<div class="alert alert-info" role="alert" th:text="#{cart.empty}"></div>
</div>
<div id="errorEnvio" th:class="${'alert alert-danger' + (errorEnvio ? '' : ' d-none')}" role="alert" th:text="#{cart.errors.shipping}"></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"
@ -24,17 +25,30 @@
<p th:text="#{cart.shipping.info}"></p>
<div
class="form-check form-switch form-switch-custom form-switch-presupuesto mb-3 d-flex align-items-center">
<input type="checkbox" class="form-check-input datos-generales-data me-2" id="onlyOneShipment"
th:field="${cart.onlyOneShipment}"/>
th:field="${cart.onlyOneShipment}" />
<label for="onlyOneShipment" class="form-label d-flex align-items-center mb-0">
<span th:text="#{cart.shipping.onlyOneShipment}" class="me-2"></span>
</label>
</div>
<button type="button" th:class="${'btn btn-secondary' + (!cart.onlyOneShipment or mainDir?.size > 0 ? ' d-none' : '')}" id="addOrderAddress"
th:text="#{cart.shipping.add}">Añadir dirección</button>
<button type="button"
th:class="${'btn btn-secondary' + (!cart.onlyOneShipment or #lists.size(mainDir ?: {}) > 0 ? ' d-none' : '')}"
id="addOrderAddress" th:text="#{cart.shipping.add}">Añadir dirección</button>
<div id="shippingAddressesContainer" class="shipping-order-address d-flex flex-wrap gap-3 mt-4"></div>
<div id="shippingAddressesContainer" class="shipping-order-address d-flex flex-wrap gap-3 mt-4">
<div th:replace="${cart.onlyOneShipment and mainDir != null}
? ~{imprimelibros/direcciones/direccionCard :: direccionCard(
${mainDir.direccion},
${mainDir.pais},
${mainDir.presupuestoId},
${mainDir.unidades},
${mainDir.isPalets}
)}
: ~{}">
</div>
</div>
</div>
</div>

View File

@ -4,11 +4,12 @@
data-base=${item.base}">
<div class="card-body">
<input type="hidden" class="item-presupuesto-id" th:value="${item.cartItemId}" />
<input type="hidden" class="item-presupuesto-id" th:value="${item.presupuestoId}" />
<input type="hidden" class="item-tirada" th:value="${item.tirada}" />
<div class="step-arrow-nav mt-n3 mx-n3 mb-3">
<ul th:class="${'nav nav-pills nav-justified custom-nav nav-product' + (cart.onlyOneShipment ? ' d-none' : '')}" role="tablist">
<ul th:class="${'nav nav-pills nav-justified custom-nav nav-product' + (cart.onlyOneShipment ? ' d-none' : '')}"
role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link fs-15 active" th:id="${'pills-details-' + item.cartItemId + '-tab'}"
th:data-bs-target="${'#pills-details-' + item.cartItemId}" type="button" role="tab"
@ -131,7 +132,22 @@
<button type="button" class="btn btn-secondary btn-add-shipping"
th:text="#{cart.shipping.add}">Añadir dirección</button>
<div class="shipping-addresses-item d-flex flex-wrap gap-3 mt-4"></div>
<div class="shipping-addresses-item d-flex flex-wrap gap-3 mt-4">
<th:block th:each="dir : ${direcciones}">
<th:block
th:if="${dir != null and dir.unidades != null and dir.unidades > 0 and dir.presupuestoId == item.presupuestoId}">
<div th:replace="~{imprimelibros/direcciones/direccionCard ::
direccionCard(
direccion=${dir.direccion},
pais=${dir.pais},
presupuestoId=${dir.presupuestoId},
unidades=${dir.unidades},
isPalets=${dir.isPalets} )}">
</div>
</th:block>
</th:block>
</div>
</div>
</div>
</div>
@ -149,7 +165,22 @@
<button type="button" class="btn btn-secondary btn-add-shipping-sample"
th:text="#{cart.shipping.add}">Añadir dirección</button>
<div class="shipping-addresses-sample d-flex flex-wrap gap-3 mt-4"></div>
<div class="shipping-addresses-sample d-flex flex-wrap gap-3 mt-4">
<th:block th:each="dir : ${direcciones}">
<th:block
th:if="${dir != null and dir.unidades == null and dir.presupuestoId == item.presupuestoId}">
<div th:replace="~{imprimelibros/direcciones/direccionCard ::
direccionCard(
direccion=${dir.direccion},
pais=${dir.pais},
presupuestoId=${dir.presupuestoId},
unidades=${dir.unidades},
isPalets=${dir.isPalets} )}">
</div>
</th:block>
</th:block>
</div>
</div>
</div>
</div>

View File

@ -1,4 +1,4 @@
<div th:fragment="cartSummary(summary)" class="col-xl-4">
<div th:fragment="cartSummary(summary)" class="col-xl-4 cart-summary-container">
<div class="sticky-side-div">
<div class="card">
<div class="card-header border-bottom-dashed">
@ -12,6 +12,10 @@
<td><span th:text="#{cart.resumen.base}"></span></td>
<td class="text-end" id="base-cesta" th:text="${summary.base}"></td>
</tr>
<tr>
<td><span th:text="#{cart.resumen.envio}"></span></td>
<td class="text-end" id="envio-cesta" th:text="${summary.shipment}"></td>
</tr>
<tr id="tr-iva-4">
<td><span th:text="#{cart.resumen.iva-4}"></span> : </td>
<td class="text-end" id="iva-4-cesta" th:text="${summary.iva4}"></td>
@ -28,8 +32,12 @@
</tr>
</tbody>
</table>
<button type="button" class="btn btn-secondary w-100 mt-2" id="btn-checkout"
th:onclick="location.href='/checkout'" th:text="#{cart.resumen.tramitar}">Checkout</button>
<form th:action="@{/pagos/redsys/crear}" method="post">
<input type="hidden" name="order" value="123456789012"/>
<input type="hidden" name="amountCents" value="12525"/>
<button type="submit" class="btn btn-secondary w-100 mt-2"
th:text="#{cart.resumen.tramitar}">Checkout</button>
</form>
</div>
<!-- end table-responsive -->
</div>

View File

@ -1,4 +1,4 @@
<div th:fragment="direccionCard(direccion)" name="direccion"
<div th:fragment="direccionCard(direccion, pais, presupuestoId, unidades, isPalets)" name="direccion"
class="card card border mb-3 direccion-card bg-light w-100 mx-2">
<div class="card-body">