mirror of
https://github.com/pretix/pretix.git
synced 2026-05-03 14:54:04 +00:00
Refs #118 -- Asynchronous cart position removal
This commit is contained in:
@@ -167,6 +167,18 @@ def add_items_to_cart(event: int, items: List[Tuple[int, Optional[int], int]], c
|
||||
raise CartError(error_messages['busy'])
|
||||
|
||||
|
||||
def _remove_items_from_cart(event: int, items: List[Tuple[int, Optional[int], int]], cart_id: int) -> None:
|
||||
with event.lock():
|
||||
for item, variation, cnt in items:
|
||||
cw = Q(cart_id=cart_id) & Q(item_id=item) & Q(event=event)
|
||||
if variation:
|
||||
cw &= Q(variation_id=variation)
|
||||
else:
|
||||
cw &= Q(variation__isnull=True)
|
||||
for cp in CartPosition.objects.filter(cw).order_by("-price")[:cnt]:
|
||||
cp.delete()
|
||||
|
||||
|
||||
def remove_items_from_cart(event: int, items: List[Tuple[int, Optional[int], int]], cart_id: int=None) -> None:
|
||||
"""
|
||||
Removes a list of items from a user's cart.
|
||||
@@ -175,15 +187,10 @@ def remove_items_from_cart(event: int, items: List[Tuple[int, Optional[int], int
|
||||
:param session: Session ID of a guest
|
||||
"""
|
||||
event = Event.objects.get(id=event)
|
||||
|
||||
for item, variation, cnt in items:
|
||||
cw = Q(cart_id=cart_id) & Q(item_id=item) & Q(event=event)
|
||||
if variation:
|
||||
cw &= Q(variation_id=variation)
|
||||
else:
|
||||
cw &= Q(variation__isnull=True)
|
||||
for cp in CartPosition.objects.filter(cw).order_by("-price")[:cnt]:
|
||||
cp.delete()
|
||||
try:
|
||||
_remove_items_from_cart(event, items, cart_id)
|
||||
except EventLock.LockTimeoutException:
|
||||
raise CartError(error_messages['busy'])
|
||||
|
||||
|
||||
if settings.HAS_CELERY:
|
||||
@@ -197,4 +204,13 @@ if settings.HAS_CELERY:
|
||||
except EventLock.LockTimeoutException:
|
||||
self.retry(exc=CartError(error_messages['busy']))
|
||||
|
||||
@app.task(bind=True, max_retries=5, default_retry_delay=2)
|
||||
def remove_items_from_cart_task(self, event: int, items: List[Tuple[int, Optional[int], int]], cart_id: str):
|
||||
event = Event.objects.get(id=event)
|
||||
try:
|
||||
_remove_items_from_cart(event, items, cart_id)
|
||||
except EventLock.LockTimeoutException:
|
||||
self.retry(exc=CartError(error_messages['busy']))
|
||||
|
||||
add_items_to_cart.task = add_items_to_cart_task
|
||||
remove_items_from_cart.task = remove_items_from_cart_task
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<div class="col-md-2 col-xs-6 count">
|
||||
{% if editable %}
|
||||
<form action="{% eventurl event "presale:event.cart.remove" %}"
|
||||
method="post">
|
||||
method="post" data-asynctask>
|
||||
{% csrf_token %}
|
||||
{% if line.variation %}
|
||||
<input type="hidden" name="variation_{{ line.item.id }}_{{ line.variation.id }}"
|
||||
|
||||
@@ -53,16 +53,30 @@ class CartActionMixin:
|
||||
return items
|
||||
|
||||
|
||||
class CartRemove(EventViewMixin, CartActionMixin, View):
|
||||
class CartRemove(EventViewMixin, CartActionMixin, AsyncAction, View):
|
||||
task = remove_items_from_cart
|
||||
|
||||
def post(self, *args, **kwargs):
|
||||
def get_success_message(self, value):
|
||||
return _('Your cart has been updated.')
|
||||
|
||||
def get_error_message(self, exception):
|
||||
if isinstance(exception, dict) and exception['exc_type'] == 'CartError':
|
||||
return exception['exc_message']
|
||||
elif isinstance(exception, CartError):
|
||||
return str(exception)
|
||||
return super().get_error_message(exception)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
items = self._items_from_post_data()
|
||||
if not items:
|
||||
return redirect(self.get_error_url())
|
||||
|
||||
remove_items_from_cart(self.request.event.id, items, self.request.session.session_key)
|
||||
messages.success(self.request, _('Your cart has been updated.'))
|
||||
return redirect(self.get_success_url())
|
||||
if items:
|
||||
return self.do(self.request.event.id, items, self.request.session.session_key)
|
||||
else:
|
||||
if 'ajax' in self.request.GET or 'ajax' in self.request.POST:
|
||||
return JsonResponse({
|
||||
'redirect': self.get_error_url()
|
||||
})
|
||||
else:
|
||||
return redirect(self.get_error_url())
|
||||
|
||||
|
||||
class CartAdd(EventViewMixin, CartActionMixin, AsyncAction, View):
|
||||
|
||||
Reference in New Issue
Block a user