diff --git a/src/pretix/api/views/order.py b/src/pretix/api/views/order.py index 75d664c48..aa2bd9425 100644 --- a/src/pretix/api/views/order.py +++ b/src/pretix/api/views/order.py @@ -32,6 +32,7 @@ from pretix.base.models import ( generate_position_secret, generate_secret, ) from pretix.base.payment import PaymentException +from pretix.base.services import tickets from pretix.base.services.invoices import ( generate_cancellation, generate_invoice, invoice_pdf, invoice_qualified, regenerate_invoice, @@ -370,6 +371,8 @@ class OrderViewSet(viewsets.ModelViewSet): order.save(update_fields=['secret']) CachedTicket.objects.filter(order_position__order=order).delete() CachedCombinedTicket.objects.filter(order=order).delete() + tickets.invalidate_cache.apply_async(kwargs={'event': self.request.event.pk, + 'order': order.pk}) order.log_action( 'pretix.event.order.secret.changed', user=self.request.user, diff --git a/src/pretix/base/services/orders.py b/src/pretix/base/services/orders.py index 7e12505c6..5258120dd 100644 --- a/src/pretix/base/services/orders.py +++ b/src/pretix/base/services/orders.py @@ -28,12 +28,13 @@ from pretix.base.models import ( from pretix.base.models.event import SubEvent from pretix.base.models.items import ItemBundle from pretix.base.models.orders import ( - CachedCombinedTicket, CachedTicket, InvoiceAddress, OrderFee, OrderRefund, - generate_position_secret, generate_secret, + InvoiceAddress, OrderFee, OrderRefund, generate_position_secret, + generate_secret, ) from pretix.base.models.organizer import TeamAPIToken from pretix.base.models.tax import TaxedPrice from pretix.base.payment import BasePaymentProvider, PaymentException +from pretix.base.services import tickets from pretix.base.services.invoices import ( generate_cancellation, generate_invoice, invoice_qualified, ) @@ -857,6 +858,7 @@ class OrderChangeManager: self.order = order self.user = user self.auth = auth + self.event = order.event self.split_order = None self._committed = False self._totaldiff = 0 @@ -1159,8 +1161,8 @@ class OrderChangeManager: elif isinstance(op, self.RegenerateSecretOperation): op.position.secret = generate_position_secret() op.position.save() - CachedTicket.objects.filter(order_position__order=self.order).delete() - CachedCombinedTicket.objects.filter(order=self.order).delete() + tickets.invalidate_cache.apply_async(kwargs={'event': self.event.pk, + 'order': self.order.pk}) self.order.log_action('pretix.event.order.changed.secret', user=self.user, auth=self.auth, data={ 'position': op.position.pk, 'positionid': op.position.positionid, @@ -1393,11 +1395,11 @@ class OrderChangeManager: order_changed.send(self.order.event, order=self.order) def _clear_tickets_cache(self): - CachedTicket.objects.filter(order_position__order=self.order).delete() - CachedCombinedTicket.objects.filter(order=self.order).delete() + tickets.invalidate_cache.apply_async(kwargs={'event': self.event.pk, + 'order': self.order.pk}) if self.split_order: - CachedTicket.objects.filter(order_position__order=self.split_order).delete() - CachedCombinedTicket.objects.filter(order=self.split_order).delete() + tickets.invalidate_cache.apply_async(kwargs={'event': self.event.pk, + 'order': self.split_order.pk}) def _get_payment_provider(self): lp = self.order.payments.last() diff --git a/src/pretix/base/services/tickets.py b/src/pretix/base/services/tickets.py index 158ef9ff0..6028eedd7 100644 --- a/src/pretix/base/services/tickets.py +++ b/src/pretix/base/services/tickets.py @@ -156,3 +156,26 @@ def get_tickets_for_order(order): logger.exception('Failed to generate ticket.') return tickets + + +@app.task(base=ProfiledTask) +def invalidate_cache(event: int, item: int=None, provider: str=None, order: int=None, **kwargs): + event = Event.objects.get(id=event) + qs = CachedTicket.objects.filter(order_position__order__event=event) + qsc = CachedCombinedTicket.objects.filter(order__event=event) + + if item: + qs = qs.filter(order_position__item_id=item) + + if provider: + qs = qs.filter(provider=provider) + qsc = qsc.filter(provider=provider) + + if order: + qs = qs.filter(order_position__order_id=order) + qsc = qsc.filter(order_id=Order) + + for ct in qs: + ct.delete() + for ct in qsc: + ct.delete() diff --git a/src/pretix/control/views/event.py b/src/pretix/control/views/event.py index 5326cb3e1..2275362c4 100644 --- a/src/pretix/control/views/event.py +++ b/src/pretix/control/views/event.py @@ -31,8 +31,7 @@ from pytz import timezone from pretix.base.channels import get_all_sales_channels from pretix.base.i18n import LazyCurrencyNumber from pretix.base.models import ( - CachedCombinedTicket, CachedTicket, Event, LogEntry, Order, RequiredAction, - TaxRule, Voucher, + Event, LogEntry, Order, RequiredAction, TaxRule, Voucher, ) from pretix.base.models.event import EventMetaValue from pretix.base.services import tickets @@ -789,12 +788,7 @@ class TicketSettings(EventSettingsViewMixin, EventPermissionRequiredMixin, FormV for k in provider.form.changed_data } ) - CachedTicket.objects.filter( - order_position__order__event=self.request.event, provider=provider.identifier - ).delete() - CachedCombinedTicket.objects.filter( - order__event=self.request.event, provider=provider.identifier - ).delete() + tickets.invalidate_cache.apply_async(kwargs={'event': self.request.event.pk, 'provider': provider.identifier}) else: success = False form = self.get_form(self.get_form_class()) diff --git a/src/pretix/control/views/item.py b/src/pretix/control/views/item.py index baddaa4e6..d814e63b5 100644 --- a/src/pretix/control/views/item.py +++ b/src/pretix/control/views/item.py @@ -18,11 +18,12 @@ from django.views.generic.edit import DeleteView from pretix.base.forms import I18nFormSet from pretix.base.models import ( - CachedTicket, CartPosition, Item, ItemCategory, ItemVariation, Order, - Question, QuestionAnswer, QuestionOption, Quota, Voucher, + CartPosition, Item, ItemCategory, ItemVariation, Order, Question, + QuestionAnswer, QuestionOption, Quota, Voucher, ) from pretix.base.models.event import SubEvent from pretix.base.models.items import ItemAddOn, ItemBundle +from pretix.base.services.tickets import invalidate_cache from pretix.control.forms.item import ( CategoryForm, ItemAddOnForm, ItemAddOnsFormSet, ItemBundleForm, ItemBundleFormSet, ItemCreateForm, ItemUpdateForm, ItemVariationForm, @@ -875,7 +876,7 @@ class ItemUpdateGeneral(ItemDetailMixin, EventPermissionRequiredMixin, UpdateVie self.object.log_action( 'pretix.event.item.changed', user=self.request.user, data=data ) - CachedTicket.objects.filter(order_position__item=self.item).delete() + invalidate_cache.apply_async(kwargs={'event': self.request.event.pk, 'item': self.object.pk}) for f in self.plugin_forms: f.save() return super().form_valid(form) diff --git a/src/pretix/control/views/orders.py b/src/pretix/control/views/orders.py index f5d781203..d1d46c052 100644 --- a/src/pretix/control/views/orders.py +++ b/src/pretix/control/views/orders.py @@ -43,6 +43,7 @@ from pretix.base.models.orders import ( ) from pretix.base.models.tax import EU_COUNTRIES from pretix.base.payment import PaymentException +from pretix.base.services import tickets from pretix.base.services.export import export from pretix.base.services.invoices import ( generate_cancellation, generate_invoice, invoice_pdf, invoice_pdf_task, @@ -1319,8 +1320,7 @@ class OrderModifyInformation(OrderQuestionsViewMixin, OrderView): 'you need to do this manually.') messages.success(self.request, _(success_message)) - CachedTicket.objects.filter(order_position__order=self.order).delete() - CachedCombinedTicket.objects.filter(order=self.order).delete() + tickets.invalidate_cache.apply_async(kwargs={'event': self.request.event.pk, 'order': self.order.pk}) order_modified.send(sender=self.request.event, order=self.order) return redirect(self.get_order_url()) @@ -1363,8 +1363,7 @@ class OrderContactChange(OrderView): for op in self.order.all_positions.all(): op.secret = generate_position_secret() op.save() - CachedTicket.objects.filter(order_position__order=self.order).delete() - CachedCombinedTicket.objects.filter(order=self.order).delete() + tickets.invalidate_cache.apply_async(kwargs={'event': self.request.event.pk, 'order': self.order.pk}) self.order.log_action('pretix.event.order.secret.changed', user=self.request.user) self.form.save() diff --git a/src/pretix/plugins/ticketoutputpdf/forms.py b/src/pretix/plugins/ticketoutputpdf/forms.py index ec65fc58d..a17afb9e1 100644 --- a/src/pretix/plugins/ticketoutputpdf/forms.py +++ b/src/pretix/plugins/ticketoutputpdf/forms.py @@ -1,7 +1,7 @@ from django import forms from django.utils.translation import ugettext_lazy as _ -from pretix.base.models import CachedCombinedTicket, CachedTicket +from pretix.base.services import tickets from .models import TicketLayout, TicketLayoutItem @@ -18,7 +18,7 @@ class TicketLayoutItemForm(forms.ModelForm): fields = ('layout',) def __init__(self, *args, **kwargs): - event = kwargs.pop('event') + self.event = kwargs.pop('event') self.sales_channel = kwargs.pop('sales_channel') super().__init__(*args, **kwargs) if self.sales_channel.identifier != 'web': @@ -29,7 +29,7 @@ class TicketLayoutItemForm(forms.ModelForm): else: self.fields['layout'].label = _('PDF ticket layout') self.fields['layout'].empty_label = _('(Event default)') - self.fields['layout'].queryset = event.ticket_layouts.all() + self.fields['layout'].queryset = self.event.ticket_layouts.all() self.fields['layout'].required = False def save(self, commit=True): @@ -41,9 +41,5 @@ class TicketLayoutItemForm(forms.ModelForm): return else: return super().save(commit=commit) - CachedTicket.objects.filter( - order_position__item_id=self.instance.item, provider='pdf' - ).delete() - CachedCombinedTicket.objects.filter( - order__all_positions__item=self.instance.item - ).delete() + tickets.invalidate_cache.apply_async(kwargs={'event': self.event.pk, 'provider': 'pdf', + 'item': self.instance.item_id}) diff --git a/src/pretix/plugins/ticketoutputpdf/views.py b/src/pretix/plugins/ticketoutputpdf/views.py index 996b5239c..2f0e1520a 100644 --- a/src/pretix/plugins/ticketoutputpdf/views.py +++ b/src/pretix/plugins/ticketoutputpdf/views.py @@ -18,10 +18,9 @@ from django.views.generic import CreateView, DeleteView, DetailView, ListView from reportlab.lib import pagesizes from reportlab.pdfgen import canvas -from pretix.base.models import ( - CachedCombinedTicket, CachedFile, CachedTicket, OrderPosition, -) +from pretix.base.models import CachedFile, OrderPosition from pretix.base.pdf import Renderer +from pretix.base.services.tickets import invalidate_cache from pretix.control.permissions import EventPermissionRequiredMixin from pretix.control.views.pdf import BaseEditorView from pretix.plugins.ticketoutputpdf.forms import TicketLayoutForm @@ -40,12 +39,7 @@ class EditorView(BaseEditorView): def save_layout(self): super().save_layout() - CachedTicket.objects.filter( - order_position__order__event=self.request.event, provider='pdf' - ).delete() - CachedCombinedTicket.objects.filter( - order__event=self.request.event, provider='pdf' - ).delete() + invalidate_cache.apply_async(kwargs={'event': self.request.event.pk, 'provider': 'pdf'}) def get_layout_settings_key(self): return 'ticketoutput_pdf_layout' @@ -212,10 +206,7 @@ class LayoutEditorView(BaseEditorView): self.layout.save(update_fields=['layout']) self.layout.log_action(action='pretix.plugins.ticketoutputpdf.layout.changed', user=self.request.user, data={'layout': self.request.POST.get("data")}) - for ct in CachedTicket.objects.filter(order_position__order__event=self.request.event, provider='pdf'): - ct.delete() - for ct in CachedCombinedTicket.objects.filter(order__event=self.request.event, provider='pdf'): - ct.delete() + invalidate_cache.apply_async(kwargs={'event': self.request.event.pk, 'provider': 'pdf'}) def get_default_background(self): return static('pretixpresale/pdf/ticket_default_a4.pdf') @@ -251,9 +242,4 @@ class LayoutEditorView(BaseEditorView): if self.layout.background: self.layout.background.delete() self.layout.background.save('background.pdf', f.file) - CachedTicket.objects.filter( - order_position__order__event=self.request.event, provider='pdf' - ).delete() - CachedCombinedTicket.objects.filter( - order__event=self.request.event, provider='pdf' - ).delete() + invalidate_cache.apply_async(kwargs={'event': self.request.event.pk, 'provider': 'pdf'}) diff --git a/src/pretix/presale/views/order.py b/src/pretix/presale/views/order.py index 71278e1f3..70ce304d2 100644 --- a/src/pretix/presale/views/order.py +++ b/src/pretix/presale/views/order.py @@ -29,7 +29,7 @@ from pretix.base.services.invoices import ( ) from pretix.base.services.mail import SendMailException from pretix.base.services.orders import cancel_order, change_payment_provider -from pretix.base.services.tickets import generate +from pretix.base.services.tickets import generate, invalidate_cache from pretix.base.signals import ( allow_ticket_download, order_modified, register_ticket_outputs, ) @@ -548,6 +548,7 @@ class OrderModify(EventViewMixin, OrderDetailMixin, OrderQuestionsViewMixin, Tem 'to regenerate your invoice.') messages.success(self.request, _(success_message)) + invalidate_cache.apply_async(kwargs={'event': self.request.event.pk, 'order': self.order.pk}) CachedTicket.objects.filter(order_position__order=self.order).delete() CachedCombinedTicket.objects.filter(order=self.order).delete() return redirect(self.get_order_url())