mirror of
https://github.com/Crocmagnon/checkout.git
synced 2024-11-22 16:18:03 +01:00
Display articles count
This commit is contained in:
parent
724e18fd76
commit
0fd0a8ac5d
4 changed files with 54 additions and 5 deletions
|
@ -53,8 +53,10 @@ class BasketForm(forms.ModelForm):
|
||||||
)
|
)
|
||||||
fields.append(BasketItemField(field_name, product=product))
|
fields.append(BasketItemField(field_name, product=product))
|
||||||
total = 0
|
total = 0
|
||||||
|
count = 0
|
||||||
if basket:
|
if basket:
|
||||||
total = basket.price / 100
|
total = basket.price / 100
|
||||||
|
count = basket.articles_count
|
||||||
self.helper.layout = Layout(
|
self.helper.layout = Layout(
|
||||||
Div(
|
Div(
|
||||||
*fields,
|
*fields,
|
||||||
|
@ -63,7 +65,9 @@ class BasketForm(forms.ModelForm):
|
||||||
),
|
),
|
||||||
InlineRadios("payment_method"),
|
InlineRadios("payment_method"),
|
||||||
Div(
|
Div(
|
||||||
layout.HTML(f"Montant total : {total:.2f}€"),
|
layout.HTML(
|
||||||
|
f"Montant total : {total:.2f}€<br>Nombre d'articles: {count}",
|
||||||
|
),
|
||||||
css_id="price_preview",
|
css_id="price_preview",
|
||||||
css_class="mb-2",
|
css_class="mb-2",
|
||||||
),
|
),
|
||||||
|
|
|
@ -157,6 +157,9 @@ class Product(Model):
|
||||||
|
|
||||||
|
|
||||||
class BasketQuerySet(models.QuerySet):
|
class BasketQuerySet(models.QuerySet):
|
||||||
|
def with_articles_count(self) -> BasketQuerySet:
|
||||||
|
return self.annotate(articles_count=Sum(F("items__quantity")))
|
||||||
|
|
||||||
def priced(self) -> BasketQuerySet:
|
def priced(self) -> BasketQuerySet:
|
||||||
return self.annotate(
|
return self.annotate(
|
||||||
price=Coalesce(Sum(F("items__quantity") * F("items__unit_price_cents")), 0),
|
price=Coalesce(Sum(F("items__quantity") * F("items__unit_price_cents")), 0),
|
||||||
|
|
37
src/purchase/tests/test_models.py
Normal file
37
src/purchase/tests/test_models.py
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
from purchase.models import Basket, BasketItem
|
||||||
|
from purchase.tests.factories import (
|
||||||
|
PaymentMethodFactory,
|
||||||
|
ProductFactory,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_with_articles_count(db):
|
||||||
|
products = [
|
||||||
|
ProductFactory(),
|
||||||
|
ProductFactory(),
|
||||||
|
ProductFactory(),
|
||||||
|
]
|
||||||
|
payment_method = PaymentMethodFactory()
|
||||||
|
|
||||||
|
basket = Basket.objects.create(payment_method=payment_method)
|
||||||
|
BasketItem.objects.create(
|
||||||
|
basket=basket,
|
||||||
|
product=products[0],
|
||||||
|
quantity=1,
|
||||||
|
unit_price_cents=1,
|
||||||
|
)
|
||||||
|
BasketItem.objects.create(
|
||||||
|
basket=basket,
|
||||||
|
product=products[1],
|
||||||
|
quantity=2,
|
||||||
|
unit_price_cents=2,
|
||||||
|
)
|
||||||
|
BasketItem.objects.create(
|
||||||
|
basket=basket,
|
||||||
|
product=products[2],
|
||||||
|
quantity=3,
|
||||||
|
unit_price_cents=3,
|
||||||
|
)
|
||||||
|
basket = Basket.objects.priced().with_articles_count().first()
|
||||||
|
assert basket.articles_count == 6
|
||||||
|
assert basket.price == 14
|
|
@ -60,7 +60,7 @@ def update_with_unpriced_products(basket: Basket, post_data: MultiValueDict):
|
||||||
@require_http_methods(["GET", "POST"])
|
@require_http_methods(["GET", "POST"])
|
||||||
@permission_required("purchase.change_basket")
|
@permission_required("purchase.change_basket")
|
||||||
def update_basket(request: WSGIRequest, pk: int) -> HttpResponse:
|
def update_basket(request: WSGIRequest, pk: int) -> HttpResponse:
|
||||||
basket = get_object_or_404(Basket.objects.priced(), pk=pk)
|
basket = get_object_or_404(Basket.objects.priced().with_articles_count(), pk=pk)
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
form = BasketForm(request.POST, instance=basket)
|
form = BasketForm(request.POST, instance=basket)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
|
@ -120,15 +120,20 @@ def delete_basket(request: WSGIRequest, pk: int) -> HttpResponse:
|
||||||
@permission_required("purchase.add_basket")
|
@permission_required("purchase.add_basket")
|
||||||
def price_preview(request: WSGIRequest) -> HttpResponse:
|
def price_preview(request: WSGIRequest) -> HttpResponse:
|
||||||
total = 0
|
total = 0
|
||||||
|
count = 0
|
||||||
for name in request.POST:
|
for name in request.POST:
|
||||||
if name.startswith(PRICED_PREFIX):
|
if name.startswith(PRICED_PREFIX):
|
||||||
product_id = name[len(PRICED_PREFIX) :]
|
product_id = name[len(PRICED_PREFIX) :]
|
||||||
product = get_object_or_404(Product, pk=product_id)
|
product = get_object_or_404(Product, pk=product_id)
|
||||||
total += product.unit_price_cents * int(request.POST.get(name, 0))
|
number = int(request.POST.get(name, 0))
|
||||||
|
total += product.unit_price_cents * number
|
||||||
|
count += number
|
||||||
elif name.startswith(UNPRICED_PREFIX):
|
elif name.startswith(UNPRICED_PREFIX):
|
||||||
total += sum(map(int, request.POST.getlist(name)))
|
prices = list(filter(lambda x: x > 0, map(int, request.POST.getlist(name))))
|
||||||
|
total += sum(prices)
|
||||||
|
count += len(prices)
|
||||||
|
|
||||||
total = f"{total/100:.2f}€"
|
total = f"{total/100:.2f}€"
|
||||||
return HttpResponse(
|
return HttpResponse(
|
||||||
f'<span hx-swap-oob="true" id="basket-price" class="badge bg-secondary">{total}</span>Montant total : {total}',
|
f'<span hx-swap-oob="true" id="basket-price" class="badge bg-secondary">{total}</span>Montant total : {total}<br>Nombre d\'articles: {count}',
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue