mirror of
https://github.com/Crocmagnon/checkout.git
synced 2024-11-22 08:08:04 +01:00
Display total amount preview. Close #2
This commit is contained in:
parent
3de1c13995
commit
9b381a0e18
5 changed files with 67 additions and 12 deletions
|
@ -2,6 +2,7 @@ from crispy_forms.bootstrap import InlineRadios
|
||||||
from crispy_forms.helper import FormHelper
|
from crispy_forms.helper import FormHelper
|
||||||
from crispy_forms.layout import Div, Layout, Submit
|
from crispy_forms.layout import Div, Layout, Submit
|
||||||
from django import forms
|
from django import forms
|
||||||
|
from django.urls import reverse
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
from purchase.layout import BasketItemField
|
from purchase.layout import BasketItemField
|
||||||
|
@ -25,6 +26,12 @@ class BasketForm(forms.ModelForm):
|
||||||
self.helper = FormHelper()
|
self.helper = FormHelper()
|
||||||
self.helper.form_class = "form-horizontal"
|
self.helper.form_class = "form-horizontal"
|
||||||
self.helper.add_input(Submit("submit", _("Save")))
|
self.helper.add_input(Submit("submit", _("Save")))
|
||||||
|
self.helper.attrs = {
|
||||||
|
"hx_post": reverse("purchase:price_preview"),
|
||||||
|
"hx_trigger": "change",
|
||||||
|
"hx_target": "#price_preview",
|
||||||
|
"hx_swap": "innerHTML",
|
||||||
|
}
|
||||||
self.helper.layout = Layout()
|
self.helper.layout = Layout()
|
||||||
products = {}
|
products = {}
|
||||||
basket = kwargs.get("instance")
|
basket = kwargs.get("instance")
|
||||||
|
@ -51,6 +58,7 @@ class BasketForm(forms.ModelForm):
|
||||||
css_id="products",
|
css_id="products",
|
||||||
),
|
),
|
||||||
InlineRadios("payment_method"),
|
InlineRadios("payment_method"),
|
||||||
|
Div(css_id="price_preview", css_class="mb-2"),
|
||||||
)
|
)
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
|
|
|
@ -1,14 +1,25 @@
|
||||||
window.incrementValue = function (id) {
|
window.incrementValue = function (id) {
|
||||||
let value = parseInt(document.getElementById(id).value);
|
const element = document.getElementById(id);
|
||||||
|
let value = parseInt(element.value);
|
||||||
value = isNaN(value) ? 0 : value;
|
value = isNaN(value) ? 0 : value;
|
||||||
value++;
|
value++;
|
||||||
document.getElementById(id).value = value;
|
element.value = value;
|
||||||
|
|
||||||
|
window.dispatchChanged(element);
|
||||||
};
|
};
|
||||||
|
|
||||||
window.decrementValue = function (id) {
|
window.decrementValue = function (id) {
|
||||||
let value = parseInt(document.getElementById(id).value);
|
const element = document.getElementById(id);
|
||||||
|
let value = parseInt(element.value);
|
||||||
value = isNaN(value) ? 0 : value;
|
value = isNaN(value) ? 0 : value;
|
||||||
value--;
|
value--;
|
||||||
value = value < 0 ? 0 : value;
|
value = value < 0 ? 0 : value;
|
||||||
document.getElementById(id).value = value;
|
element.value = value;
|
||||||
|
|
||||||
|
window.dispatchChanged(element);
|
||||||
|
};
|
||||||
|
|
||||||
|
window.dispatchChanged = function (element) {
|
||||||
|
const event = new Event("change", { bubbles: true });
|
||||||
|
element.dispatchEvent(event);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,12 +1,19 @@
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
|
|
||||||
from purchase.views import delete_basket, list_baskets, new_basket, update_basket
|
from purchase.views import (
|
||||||
from purchase.views.basket import additional_unpriced_product
|
additional_unpriced_product,
|
||||||
|
delete_basket,
|
||||||
|
list_baskets,
|
||||||
|
new_basket,
|
||||||
|
price_preview,
|
||||||
|
update_basket,
|
||||||
|
)
|
||||||
from purchase.views.reports import by_hour_plot_view, products_plots_view, reports
|
from purchase.views.reports import by_hour_plot_view, products_plots_view, reports
|
||||||
|
|
||||||
app_name = "purchase"
|
app_name = "purchase"
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("", list_baskets, name="list"),
|
path("", list_baskets, name="list"),
|
||||||
|
path("price_preview/", price_preview, name="price_preview"),
|
||||||
path("new/", new_basket, name="new"),
|
path("new/", new_basket, name="new"),
|
||||||
path("<int:pk>/update/", update_basket, name="update"),
|
path("<int:pk>/update/", update_basket, name="update"),
|
||||||
path("<int:pk>/delete/", delete_basket, name="delete"),
|
path("<int:pk>/delete/", delete_basket, name="delete"),
|
||||||
|
|
|
@ -1,3 +1,17 @@
|
||||||
from .basket import delete_basket, list_baskets, new_basket, update_basket
|
from .basket import (
|
||||||
|
additional_unpriced_product,
|
||||||
|
delete_basket,
|
||||||
|
list_baskets,
|
||||||
|
new_basket,
|
||||||
|
price_preview,
|
||||||
|
update_basket,
|
||||||
|
)
|
||||||
|
|
||||||
__all__ = ["new_basket", "update_basket", "delete_basket", "list_baskets"]
|
__all__ = [
|
||||||
|
"new_basket",
|
||||||
|
"update_basket",
|
||||||
|
"delete_basket",
|
||||||
|
"list_baskets",
|
||||||
|
"additional_unpriced_product",
|
||||||
|
"price_preview",
|
||||||
|
]
|
||||||
|
|
|
@ -3,7 +3,7 @@ import logging
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth.decorators import permission_required
|
from django.contrib.auth.decorators import permission_required
|
||||||
from django.core.handlers.wsgi import WSGIRequest
|
from django.core.handlers.wsgi import WSGIRequest
|
||||||
from django.http import HttpRequest, HttpResponse
|
from django.http import HttpResponse
|
||||||
from django.shortcuts import get_object_or_404, redirect, render
|
from django.shortcuts import get_object_or_404, redirect, render
|
||||||
from django.template.response import TemplateResponse
|
from django.template.response import TemplateResponse
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
@ -12,7 +12,7 @@ from django.utils.translation import gettext_lazy as _
|
||||||
from django.views.decorators.http import condition, require_http_methods
|
from django.views.decorators.http import condition, require_http_methods
|
||||||
from django_htmx.http import trigger_client_event
|
from django_htmx.http import trigger_client_event
|
||||||
|
|
||||||
from purchase.forms import UNPRICED_PREFIX, BasketForm
|
from purchase.forms import PRICED_PREFIX, UNPRICED_PREFIX, BasketForm
|
||||||
from purchase.models import Basket, Product, reports_etag, reports_last_modified
|
from purchase.models import Basket, Product, reports_etag, reports_last_modified
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -100,14 +100,14 @@ def additional_unpriced_product(request: WSGIRequest) -> HttpResponse:
|
||||||
|
|
||||||
@permission_required("purchase.view_basket")
|
@permission_required("purchase.view_basket")
|
||||||
@condition(etag_func=reports_etag, last_modified_func=reports_last_modified)
|
@condition(etag_func=reports_etag, last_modified_func=reports_last_modified)
|
||||||
def list_baskets(request: HttpRequest) -> HttpResponse:
|
def list_baskets(request: WSGIRequest) -> HttpResponse:
|
||||||
context = {"baskets": Basket.objects.priced().order_by("-id")}
|
context = {"baskets": Basket.objects.priced().order_by("-id")}
|
||||||
return TemplateResponse(request, "purchase/basket_list.html", context)
|
return TemplateResponse(request, "purchase/basket_list.html", context)
|
||||||
|
|
||||||
|
|
||||||
@require_http_methods(["GET", "POST"])
|
@require_http_methods(["GET", "POST"])
|
||||||
@permission_required("purchase.delete_basket")
|
@permission_required("purchase.delete_basket")
|
||||||
def delete_basket(request: HttpRequest, pk: int) -> HttpResponse:
|
def delete_basket(request: WSGIRequest, pk: int) -> HttpResponse:
|
||||||
basket = get_object_or_404(Basket, pk=pk)
|
basket = get_object_or_404(Basket, pk=pk)
|
||||||
if request.method == "GET":
|
if request.method == "GET":
|
||||||
context = {"basket": basket}
|
context = {"basket": basket}
|
||||||
|
@ -115,3 +115,18 @@ def delete_basket(request: HttpRequest, pk: int) -> HttpResponse:
|
||||||
basket.delete()
|
basket.delete()
|
||||||
messages.success(request, _("Basket successfully deleted."))
|
messages.success(request, _("Basket successfully deleted."))
|
||||||
return redirect("purchase:list")
|
return redirect("purchase:list")
|
||||||
|
|
||||||
|
|
||||||
|
@require_http_methods(["POST"])
|
||||||
|
@permission_required("purchase.add_basket")
|
||||||
|
def price_preview(request: WSGIRequest) -> HttpResponse:
|
||||||
|
total = 0
|
||||||
|
for name in request.POST:
|
||||||
|
if name.startswith(PRICED_PREFIX):
|
||||||
|
product_id = name[len(PRICED_PREFIX) :]
|
||||||
|
product = get_object_or_404(Product, pk=product_id)
|
||||||
|
total += product.unit_price_cents * int(request.POST.get(name, 0))
|
||||||
|
elif name.startswith(UNPRICED_PREFIX):
|
||||||
|
total += sum(map(int, request.POST.getlist(name)))
|
||||||
|
|
||||||
|
return HttpResponse(f"Montant total : {total/100:.2f}€")
|
||||||
|
|
Loading…
Reference in a new issue