clean invalid items from eboutic baskets

This commit is contained in:
imperosol
2026-05-22 14:46:40 +02:00
parent 839e1883f9
commit 140d1ec81f
3 changed files with 34 additions and 23 deletions
+17 -11
View File
@@ -11,7 +11,7 @@ const BASKET_CACHE_KEY = "basket";
const BASKET_CACHE_VERSION = 1; const BASKET_CACHE_VERSION = 1;
document.addEventListener("alpine:init", () => { document.addEventListener("alpine:init", () => {
Alpine.data("basket", (lastPurchaseTime?: number) => ({ Alpine.data("basket", (validPrices: number[], lastPurchaseTime?: number) => ({
basket: [] as BasketItem[], basket: [] as BasketItem[],
init() { init() {
@@ -19,15 +19,6 @@ document.addEventListener("alpine:init", () => {
this.$watch("basket", () => { this.$watch("basket", () => {
this.saveBasket(); this.saveBasket();
}); });
// Invalidate basket if a purchase was made
if (lastPurchaseTime !== null && localStorage.basketTimestamp !== undefined) {
if (
new Date(lastPurchaseTime) >=
new Date(Number.parseInt(localStorage.basketTimestamp, 10))
) {
this.basket = [];
}
}
document document
.getElementById("id_form-TOTAL_FORMS") .getElementById("id_form-TOTAL_FORMS")
.setAttribute(":value", "basket.length"); .setAttribute(":value", "basket.length");
@@ -37,7 +28,22 @@ document.addEventListener("alpine:init", () => {
const cached = versionedLocalStorage.getItem<BasketItem[]>(BASKET_CACHE_KEY, { const cached = versionedLocalStorage.getItem<BasketItem[]>(BASKET_CACHE_KEY, {
version: BASKET_CACHE_VERSION, version: BASKET_CACHE_VERSION,
}); });
return cached ?? []; if (!cached) {
return [];
}
if (
lastPurchaseTime !== null &&
localStorage.basketTimestamp !== undefined &&
new Date(lastPurchaseTime) >=
new Date(Number.parseInt(localStorage.basketTimestamp, 10))
) {
// Invalidate basket if a purchase was made
return [];
}
// The basket is cached and not expired, so return it,
// but without items that are invalid
// (e.g. because the product is archived, or sold out)
return cached.filter((item) => validPrices.includes(item.priceId));
}, },
saveBasket() { saveBasket() {
+11 -1
View File
@@ -30,7 +30,17 @@
{% block content %} {% block content %}
<h1 id="eboutic-title">{% trans %}Eboutic{% endtrans %}</h1> <h1 id="eboutic-title">{% trans %}Eboutic{% endtrans %}</h1>
<div id="eboutic" x-data="basket({{ last_purchase_time }})"> <div
id="eboutic"
x-data="basket(
[{%- for prices in categories -%}
{%- for p in prices -%}
{% if not p.sold_out %}{{ p.id }},{% endif %}
{%- endfor -%}
{%- endfor -%}],
{{ last_purchase_time }},
)"
>
<div id="basket"> <div id="basket">
<h3>Panier</h3> <h3>Panier</h3>
<form method="post" action=""> <form method="post" action="">
+6 -11
View File
@@ -1,6 +1,8 @@
import re
from datetime import datetime, timezone from datetime import datetime, timezone
import pytest import pytest
from bs4 import BeautifulSoup
from django.http import HttpResponse from django.http import HttpResponse
from django.test import TestCase from django.test import TestCase
from django.test.client import Client from django.test.client import Client
@@ -130,9 +132,11 @@ def test_eboutic_basket_expiry(
_bulk_create=True, _bulk_create=True,
) )
soup = BeautifulSoup(client.get(reverse("eboutic:main")).text, "lxml")
assert ( assert (
f'x-data="basket({int(expected.timestamp() * 1000) if expected else "null"})"' # remove any space from the value before asserting
in client.get(reverse("eboutic:main")).text re.sub(r"\s+", "", soup.find(id="eboutic").attrs["x-data"])
== f"basket([],{int(expected.timestamp() * 1000) if expected else 'null'},)"
) )
@@ -243,15 +247,6 @@ class TestEboutic(TestCase):
assert response.status_code == 200 assert response.status_code == 200
assert Basket.objects.first() is None assert Basket.objects.first() is None
self.client.force_login(self.new_customer)
response = self.submit_basket([BasketItem(self.cotiz.id, 1)])
assert response.status_code == 200
assert Basket.objects.first() is None
response = self.submit_basket([BasketItem(self.not_in_counter.id, 1)])
assert response.status_code == 200
assert Basket.objects.first() is None
def test_create_basket(self): def test_create_basket(self):
self.client.force_login(self.new_customer) self.client.force_login(self.new_customer)
assertRedirects( assertRedirects(