mirror of
https://github.com/pretix/pretix.git
synced 2026-08-14 11:26:26 +00:00
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3840f4fad2 | ||
|
|
1f99890bc2 | ||
|
|
f050c2b45e |
@@ -354,38 +354,60 @@ class Order(LockModel, LoggedModel):
|
|||||||
def _transaction_key_reset(self):
|
def _transaction_key_reset(self):
|
||||||
self.__initial_status_paid_or_pending = self.status in (Order.STATUS_PENDING, Order.STATUS_PAID) and not self.require_approval
|
self.__initial_status_paid_or_pending = self.status in (Order.STATUS_PENDING, Order.STATUS_PAID) and not self.require_approval
|
||||||
|
|
||||||
def gracefully_delete(self, user=None, auth=None):
|
@classmethod
|
||||||
from . import GiftCard, GiftCardTransaction, Membership, Voucher
|
def gracefully_delete_bulk(cls, event, orders, user=None, auth=None):
|
||||||
|
# Expects to be called in a transaction
|
||||||
if not self.testmode:
|
from . import (
|
||||||
raise TypeError("Only test mode orders can be deleted.")
|
GiftCard, GiftCardTransaction, LogEntry, Membership, Voucher,
|
||||||
self.log_action(
|
|
||||||
'pretix.event.order.deleted', user=user, auth=auth,
|
|
||||||
data={
|
|
||||||
'code': self.code,
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
order_gracefully_delete.send(self.event, order=self)
|
if not transaction.get_connection().in_atomic_block:
|
||||||
|
raise Exception('gracefully_delete_bulk should only be called in atomic transaction!')
|
||||||
|
|
||||||
if self.status != Order.STATUS_CANCELED:
|
logs_create = []
|
||||||
for position in self.positions.all():
|
for o in orders:
|
||||||
if position.voucher:
|
if not o.testmode:
|
||||||
Voucher.objects.filter(pk=position.voucher.pk).update(redeemed=Greatest(0, F('redeemed') - 1))
|
raise TypeError("Only test mode orders can be deleted.")
|
||||||
|
order_gracefully_delete.send(event, order=o)
|
||||||
|
logs_create.append(o.log_action(
|
||||||
|
'pretix.event.order.deleted', user=user, auth=auth,
|
||||||
|
data={
|
||||||
|
'code': o.code,
|
||||||
|
},
|
||||||
|
save=False,
|
||||||
|
))
|
||||||
|
LogEntry.bulk_create_and_postprocess(logs_create)
|
||||||
|
|
||||||
GiftCardTransaction.objects.filter(payment__in=self.payments.all()).update(payment=None)
|
voucher_ids = OrderPosition.objects.filter(
|
||||||
GiftCardTransaction.objects.filter(refund__in=self.refunds.all()).update(refund=None)
|
order__in=orders,
|
||||||
GiftCardTransaction.objects.filter(order=self).update(order=None)
|
voucher__isnull=False
|
||||||
GiftCard.objects.filter(issued_in__in=self.positions.all()).update(issued_in=None)
|
).exclude(order__status=Order.STATUS_CANCELED).values_list("voucher_id", flat=True)
|
||||||
Membership.objects.filter(granted_in__order=self, testmode=True).update(granted_in=None)
|
voucher_usages = Counter(voucher_ids)
|
||||||
OrderPosition.all.filter(order=self, addon_to__isnull=False).delete()
|
for v_id, usage_count in voucher_usages.items():
|
||||||
OrderPosition.all.filter(order=self).delete()
|
Voucher.objects.filter(pk=v_id).update(redeemed=Greatest(0, F('redeemed') - usage_count))
|
||||||
OrderFee.all.filter(order=self).delete()
|
|
||||||
Transaction.objects.filter(order=self).delete()
|
GiftCardTransaction.objects.filter(payment__order__in=orders).update(payment=None)
|
||||||
self.refunds.all().delete()
|
GiftCardTransaction.objects.filter(refund__order__in=orders).update(refund=None)
|
||||||
self.payments.all().delete()
|
GiftCardTransaction.objects.filter(order__in=orders).update(order=None)
|
||||||
self.event.cache.delete('complain_testmode_orders')
|
GiftCard.objects.filter(issued_in__order__in=orders).update(issued_in=None)
|
||||||
self.delete()
|
Membership.objects.filter(granted_in__order__in=orders, testmode=True).update(granted_in=None)
|
||||||
|
OrderPosition.all.filter(order__in=orders, addon_to__isnull=False).delete()
|
||||||
|
OrderPosition.all.filter(order__in=orders).delete()
|
||||||
|
OrderFee.all.filter(order__in=orders).delete()
|
||||||
|
Transaction.objects.filter(order__in=orders).delete()
|
||||||
|
OrderRefund.objects.filter(order__in=orders).delete()
|
||||||
|
OrderPayment.objects.filter(order__in=orders).delete()
|
||||||
|
if isinstance(orders, models.QuerySet):
|
||||||
|
orders.delete()
|
||||||
|
else:
|
||||||
|
Order.objects.filter(pk__in=[o.pk for o in orders]).delete()
|
||||||
|
event.cache.delete('complain_testmode_orders')
|
||||||
|
|
||||||
|
def gracefully_delete(self, user=None, auth=None):
|
||||||
|
if not self.testmode:
|
||||||
|
raise TypeError("Only test mode orders can be deleted.")
|
||||||
|
|
||||||
|
Order.gracefully_delete_bulk(self.event, Order.objects.filter(pk=self.pk), user, auth)
|
||||||
|
|
||||||
def email_confirm_secret(self):
|
def email_confirm_secret(self):
|
||||||
return self.tagged_secret("email_confirm", 9)
|
return self.tagged_secret("email_confirm", 9)
|
||||||
|
|||||||
@@ -1148,8 +1148,11 @@ class EventLive(EventPermissionRequiredMixin, TemplateView):
|
|||||||
if request.POST.get("delete") == "yes":
|
if request.POST.get("delete") == "yes":
|
||||||
try:
|
try:
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
for order in request.event.orders.filter(testmode=True):
|
Order.gracefully_delete_bulk(
|
||||||
order.gracefully_delete(user=self.request.user)
|
request.event,
|
||||||
|
request.event.orders.filter(testmode=True),
|
||||||
|
user=self.request.user
|
||||||
|
)
|
||||||
except ProtectedError:
|
except ProtectedError:
|
||||||
messages.error(self.request, _('An order could not be deleted as some constraints (e.g. data '
|
messages.error(self.request, _('An order could not be deleted as some constraints (e.g. data '
|
||||||
'created by plug-ins) do not allow it.'))
|
'created by plug-ins) do not allow it.'))
|
||||||
|
|||||||
@@ -139,6 +139,7 @@ from pretix.helpers import OF_SELF
|
|||||||
from pretix.helpers.compat import CompatDeleteView
|
from pretix.helpers.compat import CompatDeleteView
|
||||||
from pretix.helpers.format import SafeFormatter, format_map
|
from pretix.helpers.format import SafeFormatter, format_map
|
||||||
from pretix.helpers.hierarkey import clean_filename
|
from pretix.helpers.hierarkey import clean_filename
|
||||||
|
from pretix.helpers.iter import chunked_iterable
|
||||||
from pretix.helpers.json import CustomJSONEncoder
|
from pretix.helpers.json import CustomJSONEncoder
|
||||||
from pretix.helpers.safedownload import check_token
|
from pretix.helpers.safedownload import check_token
|
||||||
from pretix.presale.signals import question_form_fields
|
from pretix.presale.signals import question_form_fields
|
||||||
@@ -240,7 +241,7 @@ class BaseOrderBulkActionView(OrderSearchMixin, EventPermissionRequiredMixin, As
|
|||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def execute_bulk(self, queryset: QuerySet, form: forms.Form):
|
def execute_bulk(self, queryset: QuerySet, form: forms.Form):
|
||||||
qs = self.allowed_for(self.allowed_for(self.get_queryset()))
|
qs = self.allowed_for(self.get_queryset())
|
||||||
total = qs.count()
|
total = qs.count()
|
||||||
orders_with_successful_action = 0
|
orders_with_successful_action = 0
|
||||||
for i, o in enumerate(qs):
|
for i, o in enumerate(qs):
|
||||||
@@ -394,9 +395,21 @@ class OrderDeleteBulkActionView(BaseOrderBulkActionView):
|
|||||||
testmode=True,
|
testmode=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
def execute_single(self, instance, form: forms.Form):
|
def execute_bulk(self, queryset: QuerySet, form: forms.Form):
|
||||||
instance.gracefully_delete(user=self.request.user)
|
qs = self.allowed_for(self.get_queryset())
|
||||||
return True
|
total = qs.count()
|
||||||
|
all_ids = list(qs.values_list("id", flat=True))
|
||||||
|
|
||||||
|
orders_with_successful_action = 0
|
||||||
|
for chunk in chunked_iterable(all_ids, 1000):
|
||||||
|
Order.gracefully_delete_bulk(
|
||||||
|
self.request.event,
|
||||||
|
qs.filter(id__in=chunk),
|
||||||
|
user=self.request.user,
|
||||||
|
)
|
||||||
|
orders_with_successful_action += len(chunk)
|
||||||
|
self.async_set_progress(orders_with_successful_action / total * 100)
|
||||||
|
return orders_with_successful_action, total
|
||||||
|
|
||||||
|
|
||||||
class OrderList(OrderSearchMixin, EventPermissionRequiredMixin, PaginationMixin, ListView):
|
class OrderList(OrderSearchMixin, EventPermissionRequiredMixin, PaginationMixin, ListView):
|
||||||
|
|||||||
Reference in New Issue
Block a user