first commit

This commit is contained in:
2026-02-15 09:23:44 +01:00
commit 5a22d3abae
276 changed files with 231906 additions and 0 deletions
+172
View File
@@ -0,0 +1,172 @@
{% extends "tienda/base.html" %}
{% load static %}
{% load vat_filters %}
{% block head %}
<script src="https://js.stripe.com/v3/"></script>
<script src="{% static 'js/checkout.js' %}"></script>
<script defer src="https://use.fontawesome.com/releases/v6.4.0/js/all.js"></script>
<style>
.payment-methods {
display: flex;
gap: 15px;
flex-wrap: wrap;
margin-top: 20px;
}
.payment-btn {
flex: 1;
min-width: 200px;
padding: 12px 20px;
font-size: 16px;
font-weight: 500;
}
.payment-section {
background-color: #f8f9fa;
padding: 30px;
border-radius: 8px;
margin-top: 20px;
}
.payment-section h3 {
margin-bottom: 20px;
color: #212529;
}
</style>
{% endblock %}
{% block content %}
<div class="row mt-2">
<div class="col-md-12">
<!-- Token CSRF para requests AJAX -->
{% csrf_token %}
<div class="d-flex justify-content-between align-items-center mb-3">
<h1>Checkout</h1>
<a href="{% url 'view_cart' %}" class="btn btn-outline-secondary">← Volver al carrito</a>
</div>
{% if cart_items %}
<div class="table-responsive mb-4">
<table class="table table-striped align-middle">
<thead>
<tr>
<th>Producto</th>
<th class="text-end">Precio (sin IVA)</th>
<th class="text-end">Cantidad</th>
<th class="text-end">Subtotal (con IVA)</th>
</tr>
</thead>
<tbody>
{% for item in cart_items %}
<tr>
<td>{{ item.product.name }}</td>
<td class="text-end">{{ item.product.price|format_price }}€</td>
<td class="text-end">{{ item.quantity }}</td>
<td class="text-end">{{ item.get_subtotal_with_vat|format_price }}€</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
<th colspan="2" class="text-end">Subtotal:</th>
<th colspan="2" class="text-end">{{ cart.get_total|format_price }}€</th>
</tr>
<tr>
<th colspan="2" class="text-end">IVA (21%):</th>
<th colspan="2" class="text-end text-success">+{{ cart.get_vat_amount|format_price }}€</th>
</tr>
<tr style="background-color: #f8f9fa;">
<th colspan="2" class="text-end" style="font-size: 1.1rem;">Total:</th>
<th colspan="2" class="text-end" style="font-size: 1.1rem;">{{ cart.get_total_with_vat|format_price }}€</th>
</tr>
</tfoot>
</table>
</div>
<div class="payment-section">
<h3>Selecciona tu método de pago</h3>
<div class="payment-methods">
<button
id="checkout-button"
class="btn btn-primary payment-btn"
data-config-url="/tienda/config/"
data-session-url="/tienda/create-checkout-session/">
💳 Pagar con Stripe
</button>
<button
id="paypal-button"
class="btn btn-warning payment-btn"
data-payment-url="{% url 'create_paypal_payment' %}">
🅿️ Pagar con PayPal
</button>
</div>
</div>
{% else %}
<div class="alert alert-info">Tu carrito está vacío.</div>
{% endif %}
</div>
</div>
<script>
// Manejo del botón de PayPal
document.getElementById('paypal-button').addEventListener('click', async function(e) {
e.preventDefault();
const button = this;
const originalText = button.innerHTML;
button.disabled = true;
button.innerHTML = '<span class="spinner-border spinner-border-sm me-2"></span>Procesando...';
try {
// Obtener CSRF token de múltiples formas
let csrfToken = document.querySelector('[name=csrfmiddlewaretoken]')?.value;
if (!csrfToken) {
csrfToken = document.querySelector('input[name="csrfmiddlewaretoken"]')?.value;
}
if (!csrfToken) {
csrfToken = document.cookie.split('; ').find(row => row.startsWith('csrftoken='))?.split('=')[1];
}
console.log('CSRF Token encontrado:', csrfToken ? 'Sí' : 'No');
const response = await fetch(button.dataset.paymentUrl, {
method: 'POST',
headers: {
'X-CSRFToken': csrfToken || '',
'Content-Type': 'application/json',
}
});
console.log('Response status:', response.status);
const data = await response.json();
console.log('Response data:', data);
if (response.ok && data.redirect) {
// Redirigir a PayPal
console.log('Redirigiendo a:', data.redirect);
window.location.href = data.redirect;
} else if (data.error) {
console.error('Error en respuesta:', data.error);
alert('Error: ' + data.error);
button.disabled = false;
button.innerHTML = originalText;
} else {
console.error('Respuesta inesperada:', data);
alert('Error inesperado al procesar el pago');
button.disabled = false;
button.innerHTML = originalText;
}
} catch (error) {
console.error('Error en fetch:', error);
alert('Error al procesar el pago con PayPal: ' + error.message);
button.disabled = false;
button.innerHTML = originalText;
}
});
</script>
{% endblock %}