shop
Raz 8 months ago
parent 039a3448f6
commit 9177b59198
  1. 181
      shop/static/shop/css/shop.css
  2. 192
      shop/templates/shop/cart.html
  3. 51
      shop/templates/shop/partials/order_items_display.html
  4. 30
      shop/templates/shop/payment_success.html
  5. 49
      shop/templates/shop/product_item.html
  6. 6
      shop/templates/shop/product_list.html
  7. 2
      shop/urls.py
  8. 96
      shop/views.py

@ -1,8 +1,7 @@
/* Product Display */ /* Product Display */
.options-container { .options-container {
display: grid; display: grid;
grid-template-columns: 1fr 0.35fr 0.35fr; grid-template-columns: 1fr 30%;
column-gap: 8px;
align-content: center; align-content: center;
} }
@ -12,6 +11,7 @@
width: 100%; width: 100%;
object-fit: contain; /* This will maintain the aspect ratio of the image */ object-fit: contain; /* This will maintain the aspect ratio of the image */
background-color: black; background-color: black;
border-radius: 12px;
} }
.no-image { .no-image {
@ -31,44 +31,52 @@
/* Grid Layout */ /* Grid Layout */
.option-element { .option-element {
align-content: center; align-content: center;
height: 39px;
background-color: white !important;
} }
.option-element.product-title {
.option-element:nth-child(1) { grid-column: 1 / span 2;
grid-column: 1;
grid-row: 1; grid-row: 1;
height: 64px; background-color: blue;
} }
.option-element:nth-child(2) { .option-element.product-price {
grid-column: 2 / span 3; grid-column: 2;
grid-row: 1; grid-row: 2;
text-align: right; text-align: center;
background-color: green;
} }
.option-element:nth-child(3) { .option-element.color-label {
grid-column: 1; grid-column: 1;
grid-row: 2; grid-row: 2;
font-size: 12px;
background-color: yellow;
} }
.option-element:nth-child(4) { .option-element.color-selector {
grid-column: 2; grid-column: 1;
grid-row: 2; grid-row: 3;
background-color: red;
} }
.option-element:nth-child(5) { .option-element.size-selector {
grid-column: 3; grid-column: 2;
grid-row: 2; grid-row: 3;
font-size: 12px;
text-align: center;
background-color: purple;
} }
.option-element:nth-child(6) { .option-element.quantity-selector {
grid-column: 1; grid-column: 1;
grid-row: 3; grid-row: 4;
} }
.option-element:nth-child(7) { .option-element.total-price {
grid-column: 2 / span 3; grid-column: 2;
grid-row: 3; grid-row: 4;
text-align: right; text-align: center;
} }
/* Buttons */ /* Buttons */
@ -173,7 +181,7 @@
.quantity-controls { .quantity-controls {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: left;
} }
.quantity-form { .quantity-form {
@ -193,7 +201,6 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
padding: 0; padding: 0;
margin: 0 3px;
font-size: 16px; font-size: 16px;
transition: background-color 0.3s ease; transition: background-color 0.3s ease;
} }
@ -210,8 +217,7 @@
} }
.quantity-value { .quantity-value {
margin: 0 5px; width: 44px;
min-width: 20px;
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
font-size: 14px; font-size: 14px;
@ -311,14 +317,13 @@
.color-samples { .color-samples {
display: flex; display: flex;
margin-bottom: 12px;
gap: 0px 8px; gap: 0px 8px;
vertical-align: middle; vertical-align: middle;
align-items: center; align-items: center;
} }
.color-sample { .color-sample {
width: 32px; width: 28px;
aspect-ratio: 1; aspect-ratio: 1;
border-radius: 50%; border-radius: 50%;
cursor: pointer; cursor: pointer;
@ -353,3 +358,121 @@
color: white; color: white;
border-color: #f39200; border-color: #f39200;
} }
v .cart-table {
display: block;
width: 100%;
}
.cart-table thead {
display: none; /* Hide header on small screens */
}
.cart-table tbody,
.cart-table tr,
.cart-table tfoot {
display: block;
width: 100%;
}
.cart-table tbody tr {
/* margin-bottom: 15px;
padding: 10px;
border-radius: 8px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1); */
}
.cart-table td {
display: flex;
/* padding: 8px 5px;
text-align: right;
justify-content: space-between;
align-items: center; */
}
.cart-table .price-column,
.cart-table .text-left {
/* text-align: right !important; */
}
.cart-table td.product-name {
grid-column: 1 / span 2;
grid-row: 1;
font-weight: bold;
font-size: 1.1em;
}
.cart-table td.product-color {
grid-column: 1 / span 2;
grid-row: 2;
}
/* .cart-table td.product-size {
grid-column: 2;
grid-row: 2;
} */
.cart-table td.product-quantity {
grid-column: 1;
grid-row: 3;
}
.cart-table td.product-price {
grid-column: 3;
grid-row: 3;
justify-content: right;
}
.cart-table td.product-actions {
grid-column: 3;
grid-row: 1;
justify-content: right;
}
/* Make each product a grid container */
.cart-table tbody tr {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
/* Cart summary buttons */
.cart-summary {
flex-direction: column;
gap: 10px;
}
.checkout-button {
width: 100%;
text-align: center;
height: 44px; /* Fixed height */
line-height: 24px; /* Vertically center text */
display: flex;
align-items: center;
justify-content: center;
}
.cart-table tfoot tr {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
.cart-table tfoot td {
display: block;
width: 100%;
}
.cart-table tfoot td.total-quantity {
grid-column: 1;
grid-row: 1;
text-align: left;
}
.cart-table tfoot td.total-price {
grid-column: 3;
grid-row: 1;
text-align: right;
}
.cart-table tfoot td:empty {
display: none;
}

@ -5,124 +5,6 @@
{% block second_title %}Plein de goodies !{% endblock %} {% block second_title %}Plein de goodies !{% endblock %}
{% block content %} {% block content %}
<style>
.cart-table {
display: block;
width: 100%;
}
.cart-table thead {
display: none; /* Hide header on small screens */
}
.cart-table tbody, .cart-table tr, .cart-table tfoot {
display: block;
width: 100%;
}
.cart-table tbody tr {
/* margin-bottom: 15px;
padding: 10px;
border-radius: 8px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1); */
}
.cart-table td {
display: flex;
/* padding: 8px 5px;
text-align: right;
justify-content: space-between;
align-items: center; */
}
.cart-table .price-column,
.cart-table .text-left {
/* text-align: right !important; */
}
.cart-table td.product-name {
grid-column: 1 / span 2;
grid-row: 1;
font-weight: bold;
font-size: 1.1em;
}
.cart-table td.product-color {
grid-column: 1 / span 2;
grid-row: 2;
}
/* .cart-table td.product-size {
grid-column: 2;
grid-row: 2;
} */
.cart-table td.product-quantity {
grid-column: 1;
grid-row: 3;
}
.cart-table td.product-price {
grid-column: 3;
grid-row: 3;
justify-content: right;
}
.cart-table td.product-actions {
grid-column: 3;
grid-row: 1;
justify-content: right;
}
/* Make each product a grid container */
.cart-table tbody tr {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
/* Cart summary buttons */
.cart-summary {
flex-direction: column;
gap: 10px;
}
.checkout-button {
width: 100%;
text-align: center;
height: 44px; /* Fixed height */
line-height: 24px; /* Vertically center text */
display: flex;
align-items: center;
justify-content: center;
}
.cart-table tfoot tr {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
.cart-table tfoot td {
display: block;
width: 100%;
}
.cart-table tfoot td.total-quantity {
grid-column: 1;
grid-row: 1;
text-align: left;
}
.cart-table tfoot td.total-price {
grid-column: 3;
grid-row: 1;
text-align: right;
}
.cart-table tfoot td:empty {
display: none;
}
</style>
<nav class="margin10"> <nav class="margin10">
<a href="{% url 'shop:product_list' %}">La Boutique</a> <a href="{% url 'shop:product_list' %}">La Boutique</a>
<a href="{% url 'index' %}" class="orange">Accueil</a> <a href="{% url 'index' %}" class="orange">Accueil</a>
@ -138,60 +20,8 @@
<div class="small-12 medium-9 large-6 my-block"> <div class="small-12 medium-9 large-6 my-block">
<h1 class="club my-block topmargin20">Votre panier</h1> <h1 class="club my-block topmargin20">Votre panier</h1>
<div class="bubble"> <div class="bubble">
{% if cart_items %} {% if display_data.items %}
<table class="cart-table"> {% include 'shop/partials/order_items_display.html' with items=display_data.items total_quantity=display_data.total_quantity total_price=display_data.total_price edit_mode=True %}
<!-- <thead>
<tr>
<th class="text-left">Produit</th>
<th>Couleur</th>
<th>Taille</th>
<th>Quantité</th>
<th class="price-column">Prix</th>
<th></th>
</tr>
</thead> -->
<tbody>
{% for item in cart_items %}
<tr class="{% cycle 'odd' 'even' %}">
<td class="text-left product-name" data-label="Produit">{{ item.product.title }}</td>
<td class="product-color" data-label="Couleur">
<div class="color-display">
<div class="color-sample-cart" style="background-color: {{ item.color.colorHex }}"></div>
{{ item.color.name }} | {{ item.size.name }}
</div>
</td>
<td class="product-quantity" data-label="Quantité">
<div class="quantity-controls">
<form method="post" action="{% url 'shop:update_cart_item' %}" class="quantity-form">
{% csrf_token %}
<input type="hidden" name="item_id" value="{{ item.id }}">
<button type="submit" name="action" value="decrease" class="quantity-btn" {% if item.quantity <= 1 %}disabled{% endif %}>-</button>
<span class="quantity-value">{{ item.quantity }}</span>
<button type="submit" name="action" value="increase" class="quantity-btn">+</button>
</form>
</div>
</td>
<td class="price-column product-price" data-label="Prix">{{ item.get_total_price }} €</td>
<td class="product-actions">
<form method="post" action="{% url 'shop:remove_from_cart' %}" class="remove-form">
{% csrf_token %}
<input type="hidden" name="item_id" value="{{ item.id }}">
<button type="submit" class="remove-btn">retirer</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
<td class="total-quantity" data-label="total-quantity">{{ total_quantity }} produit(s)</td>
<td class="total-label text-left"></td>
<td class="total-label text-left"></td>
<td class="price-column total-price" data-label="total-price">{{ total }} €</td>
<td class="total-label text-left"></td>
</tr>
</tfoot>
</table>
<div class="cart-summary"> <div class="cart-summary">
@ -207,13 +37,29 @@
</div> </div>
{% endif %} {% endif %}
<hr> <hr>
{% if cart_items %} {% if display_data.items %}
<a class="cancel-nav-button checkout-button" href="{% url 'shop:clear_cart' %}" onclick="return confirm('Êtes-vous sûr de vouloir supprimer votre panier ?');">Vider le panier</a> <a class="cancel-nav-button checkout-button" href="{% url 'shop:clear_cart' %}" onclick="return confirm('Êtes-vous sûr de vouloir supprimer votre panier ?');">Vider le panier</a>
{% endif %} {% endif %}
<!-- Debug buttons -->
{% if settings.DEBUG %}
<div style="margin-top: 20px; padding-top: 20px; border-top: 1px dashed #ccc;">
<h3>Debug Payment Simulation</h3>
<div style="display: flex; gap: 10px;">
<a class="confirm-nav-button checkout-button" href="{% url 'shop:simulate_payment_success' %}" style="background-color: #28a745;">
Simuler Paiement Réussi
</a>
<a class="cancel-nav-button checkout-button" href="{% url 'shop:simulate_payment_failure' %}" style="background-color: #dc3545;">
Simuler Paiement Échoué
</a>
</div>
</div>
{% endif %}
</div> </div>
{% else %} {% else %}
<p>Votre panier est vide.</p> <p>Votre panier est vide.</p>
<a class="confirm-nav-button checkout-button" href="{% url 'shop:product_list' %}">Retourner à la boutique</a>
{% endif %} {% endif %}
</div> </div>
</div> </div>

@ -0,0 +1,51 @@
<table class="cart-table">
<tbody>
{% for item in items %}
<tr class="{% cycle 'odd' 'even' %}">
<td class="text-left product-name" data-label="Produit">{{ item.product_title }}</td>
<td class="product-color" data-label="Couleur">
<div class="color-display">
<div class="color-sample-cart" style="background-color: {{ item.color_hex }}"></div>
{{ item.color_name }} | {{ item.size_name }}
</div>
</td>
<td class="product-quantity" data-label="Quantité">
{% if edit_mode %}
<div class="quantity-controls">
<form method="post" action="{% url 'shop:update_cart_item' %}" class="quantity-form">
{% csrf_token %}
<input type="hidden" name="item_id" value="{{ item.id }}">
<button type="submit" name="action" value="decrease" class="quantity-btn" {% if item.quantity <= 1 %}disabled{% endif %}>-</button>
<span class="quantity-value">{{ item.quantity }}</span>
<button type="submit" name="action" value="increase" class="quantity-btn">+</button>
</form>
</div>
{% else %}
<span>x {{ item.quantity }}</span>
{% endif %}
</td>
<td class="price-column product-price" data-label="Prix">{{ item.total_price }} €</td>
{% if edit_mode %}
<td class="product-actions">
<form method="post" action="{% url 'shop:remove_from_cart' %}" class="remove-form">
{% csrf_token %}
<input type="hidden" name="item_id" value="{{ item.id }}">
<button type="submit" class="remove-btn">retirer</button>
</form>
</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
<td class="total-quantity" data-label="total-quantity">{{ total_quantity }} produit(s)</td>
<td class="total-label text-left"></td>
<td class="total-label text-left"></td>
<td class="price-column total-price" data-label="total-price">{{ total_price }} €</td>
{% if edit_mode %}
<td class="total-label text-left"></td>
{% endif %}
</tr>
</tfoot>
</table>

@ -27,35 +27,7 @@
<!-- Order details --> <!-- Order details -->
<h3>Détails de la commande</h3> <h3>Détails de la commande</h3>
<table class="cart-table"> {% include 'shop/partials/order_items_display.html' with items=display_data.items total_quantity=display_data.total_quantity total_price=display_data.total_price edit_mode=False %}
<thead>
<tr>
<th class="text-left">Produit</th>
<th>Couleur</th>
<th>Taille</th>
<th>Quantité</th>
<th class="price-column">Prix</th>
</tr>
</thead>
<tbody>
{% for item in order_items %}
<tr class="{% cycle 'odd' 'even' %}">
<td class="text-left">{{ item.product.title }}</td>
<td>{{ item.color.name|default:"N/A" }}</td>
<td>{{ item.size.name|default:"N/A" }}</td>
<td>{{ item.quantity }}</td>
<td class="price-column">{{ item.get_total_price }} €</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
<td colspan="3" class="total-label text-left">Total:</td>
<td class="total-quantity">{{ order_items.count }}</td>
<td class="price-column total-price">{{ total }} €</td>
</tr>
</tfoot>
</table>
<div class="cart-summary"> <div class="cart-summary">
<a class="confirm-nav-button checkout-button" href="{% url 'shop:product_list' %}">Retour à la boutique</a> <a class="confirm-nav-button checkout-button" href="{% url 'shop:product_list' %}">Retour à la boutique</a>

@ -10,10 +10,10 @@
<div class="options-container"> <div class="options-container">
<div class="option-element product-title"> <div class="option-element product-title">
{{ product.title }} {{ product.title }}
<div class="color-label"><span id="selected-color-name-{{ product.id }}">{{ product.colors.all.0.name }}</span></div>
</div> </div>
<div class="option-element product-price">{{ product.price }} €</div> <div class="option-element product-price">{{ product.price }} €</div>
<div class="option-element form-group"> <div class="option-element color-label"><span id="selected-color-name-{{ product.id }}">{{ product.colors.all.0.name }}</span></div>
<div class="option-element color-selector form-group">
{% if product.colors.exists %} {% if product.colors.exists %}
<input type="hidden" name="color" id="color-{{ product.id }}" value="{{ product.colors.all.0.id }}" required> <input type="hidden" name="color" id="color-{{ product.id }}" value="{{ product.colors.all.0.id }}" required>
<div class="color-samples"> <div class="color-samples">
@ -30,10 +30,12 @@
</div> </div>
<div class="option-element form-group"> <div class="option-element size-selector form-group">
{% if product.sizes.exists %} {% if product.sizes.exists %}
{% if product.sizes.all|length == 1 %} {% if product.sizes.all|length == 1 %}
<input type="hidden" name="size" value="{{ product.sizes.all.0.id }}"> <input type="hidden" name="size" value="{{ product.sizes.all.0.id }}">
<div>Taille Unique</div>
{% else %} {% else %}
<select name="size" id="size-{{ product.id }}" class="form-control" required> <select name="size" id="size-{{ product.id }}" class="form-control" required>
<option value="" disabled selected>Taille</option> <option value="" disabled selected>Taille</option>
@ -44,12 +46,15 @@
{% endif %} {% endif %}
{% endif %} {% endif %}
</div> </div>
<div class="option-element form-group quantity-group"> <div class="option-element quantity-selector form-group">
<input type="number" id="quantity-{{ product.id }}" name="quantity" value="1" min="1" max="10" class="quantity-input" oninput="updateTotal({{ product.id }}, {{ product.price }})"> <div class="quantity-controls">
<input type="hidden" name="quantity" id="quantity-{{ product.id }}" value="1">
<button type="button" class="quantity-btn decrease-btn" onclick="adjustQuantity('{{ product.id }}', -1, {{ product.price }})" disabled>-</button>
<span class="quantity-value" id="quantity-display-{{ product.id }}">1</span>
<button type="button" class="quantity-btn increase-btn" onclick="adjustQuantity('{{ product.id }}', 1, {{ product.price }})">+</button>
</div>
</div> </div>
<div class="option-element total-price form-group"><span id="total-price-{{ product.id }}">{{ product.price }}</span></div>
<div class="option-element form-group">Total</div>
<div class="option-element form-group"><span id="total-price-{{ product.id }}">{{ product.price }}</span></div>
</div> </div>
<button type="submit" class="add-to-cart-button">Ajouter au panier</button> <button type="submit" class="add-to-cart-button">Ajouter au panier</button>
</form> </form>
@ -57,6 +62,34 @@
</div> </div>
<script> <script>
function adjustQuantity(productId, change, price) {
let quantityInput = document.getElementById(`quantity-${productId}`);
let quantityDisplay = document.getElementById(`quantity-display-${productId}`);
// Get the decrease button that's within the same form as the quantity input
let decreaseBtn = quantityInput.closest('.quantity-controls').querySelector('.decrease-btn');
let currentQuantity = parseInt(quantityInput.value) || 1;
// Calculate new quantity
let newQuantity = currentQuantity + change;
// Enforce min/max limits
if (newQuantity < 1) newQuantity = 1;
if (newQuantity > 10) newQuantity = 10;
// Update quantity in hidden input and display
quantityInput.value = newQuantity;
quantityDisplay.textContent = newQuantity;
// Enable/disable decrease button based on quantity
decreaseBtn.disabled = (newQuantity <= 1);
// Update total price
updateTotal(productId, price);
}
function updateTotal(productId, price) { function updateTotal(productId, price) {
let quantityInput = document.getElementById(`quantity-${productId}`); let quantityInput = document.getElementById(`quantity-${productId}`);
let totalPriceElement = document.getElementById(`total-price-${productId}`); let totalPriceElement = document.getElementById(`total-price-${productId}`);

@ -1,8 +1,8 @@
{% extends 'tournaments/base.html' %} {% extends 'tournaments/base.html' %}
{% block head_title %}La boutique{% endblock %} {% block head_title %}La Boutique{% endblock %}
{% block first_title %}La boutique Padel Club{% endblock %} {% block first_title %}Padel Club{% endblock %}
{% block second_title %}Plein de goodies !{% endblock %} {% block second_title %}La Boutique{% endblock %}
{% block content %} {% block content %}

@ -20,5 +20,7 @@ urlpatterns = [
path('create-checkout-session/', views.create_checkout_session, name='create_checkout_session'), path('create-checkout-session/', views.create_checkout_session, name='create_checkout_session'),
path('cart/update-item/', views.update_cart_item, name='update_cart_item'), path('cart/update-item/', views.update_cart_item, name='update_cart_item'),
path('cart/remove-item/', views.remove_from_cart, name='remove_from_cart'), path('cart/remove-item/', views.remove_from_cart, name='remove_from_cart'),
path('debug/simulate-payment-success/', views.simulate_payment_success, name='simulate_payment_success'),
path('debug/simulate-payment-failure/', views.simulate_payment_failure, name='simulate_payment_failure'),
] ]

@ -97,11 +97,12 @@ def view_cart(request):
cart_items = cart.get_cart_items(request) cart_items = cart.get_cart_items(request)
total = cart.get_cart_total(request) total = cart.get_cart_total(request)
total_quantity = cart_items.aggregate(total_quantity=Sum('quantity'))['total_quantity'] total_quantity = cart_items.aggregate(total_quantity=Sum('quantity'))['total_quantity']
display_data = prepare_item_display_data(cart_items, is_cart=True)
context = { context = {
'cart_items': cart_items, 'display_data': display_data,
'total': total, 'total': total,
'total_quantity': total_quantity, 'total_quantity': total_quantity,
'settings': settings, # Add this line to pass settings to template
} }
# Add Stripe publishable key for authenticated users # Add Stripe publishable key for authenticated users
@ -303,11 +304,12 @@ def payment_success(request, order_id):
# Get order items for template # Get order items for template
order_items = order.items.all() order_items = order.items.all()
total = sum(item.get_total_price() for item in order_items) total = sum(item.get_total_price() for item in order_items)
display_data = prepare_item_display_data(order_items, is_cart=False)
print(display_data)
return render(request, 'shop/payment_success.html', { return render(request, 'shop/payment_success.html', {
'order': order, 'order': order,
'order_items': order_items, 'display_data' : display_data,
'total': total
}) })
def payment_cancel(request, order_id): def payment_cancel(request, order_id):
@ -386,3 +388,89 @@ def remove_from_cart(request):
messages.error(request, f"Error removing item: {str(e)}") messages.error(request, f"Error removing item: {str(e)}")
return redirect('shop:view_cart') return redirect('shop:view_cart')
def prepare_item_display_data(items, is_cart=True):
"""
Transform cart items or order items into a standardized format for display
Args:
items: QuerySet of CartItem or OrderItem
is_cart: True if items are CartItems, False if OrderItems
Returns:
Dictionary with standardized item data
"""
prepared_items = []
total_quantity = 0
total_price = 0
for item in items:
if is_cart:
# For CartItem
item_data = {
'id': item.id,
'product_title': item.product.title,
'color_name': item.color.name if item.color else 'N/A',
'color_hex': item.color.colorHex if item.color else '#FFFFFF',
'size_name': item.size.name if item.size else 'N/A',
'quantity': item.quantity,
'total_price': item.get_total_price()
}
total_price += item.get_total_price()
else:
# For OrderItem
item_data = {
'id': item.id,
'product_title': item.product.title,
'color_name': item.color.name if item.color else 'N/A',
'color_hex': item.color.colorHex if item.color else '#FFFFFF',
'size_name': item.size.name if item.size else 'N/A',
'quantity': item.quantity,
'total_price': item.get_total_price()
}
total_price += item.get_total_price()
total_quantity += item.quantity
prepared_items.append(item_data)
return {
'items': prepared_items,
'total_quantity': total_quantity,
'total_price': total_price
}
def simulate_payment_success(request):
"""Debug function to simulate successful payment without Stripe"""
# Create an order from the cart
order = create_order(request)
if not order:
messages.error(request, "Could not create order from cart")
return redirect('shop:view_cart')
# Set order as paid
order.status = OrderStatus.PAID
order.payment_status = 'PAID'
order.save()
# Clear the cart
cart.clear_cart(request)
return redirect('shop:payment_success', order_id=order.id)
def simulate_payment_failure(request):
"""Debug function to simulate failed payment without Stripe"""
# Create an order from the cart
order = create_order(request)
if not order:
messages.error(request, "Could not create order from cart")
return redirect('shop:view_cart')
# Set order as canceled
order.status = OrderStatus.CANCELED
order.payment_status = 'FAILED'
order.save()
return redirect('shop:payment_cancel', order_id=order.id)

Loading…
Cancel
Save