diff --git a/src/pretix/base/services/tickets.py b/src/pretix/base/services/tickets.py index f3b4d0c48..a24119811 100644 --- a/src/pretix/base/services/tickets.py +++ b/src/pretix/base/services/tickets.py @@ -1,9 +1,14 @@ from datetime import timedelta from django.core.files.base import ContentFile +from django.db import transaction from django.utils.timezone import now +from django.utils.translation import ugettext as _ -from pretix.base.models import CachedFile, CachedTicket, Order, cachedfile_name +from pretix.base.i18n import language +from pretix.base.models import ( + CachedFile, CachedTicket, Event, Order, cachedfile_name, +) from pretix.base.signals import register_ticket_outputs from pretix.celery import app @@ -20,10 +25,40 @@ def generate(order: str, provider: str): ct.cachedfile = cf ct.save() - responses = register_ticket_outputs.send(order.event) - for receiver, response in responses: - prov = response(order.event) - if prov.identifier == provider: - ct.cachedfile.filename, ct.cachedfile.type, data = prov.generate(order) - ct.cachedfile.file.save(cachedfile_name(ct.cachedfile, ct.cachedfile.filename), ContentFile(data)) - ct.cachedfile.save() + with language(order.locale): + responses = register_ticket_outputs.send(order.event) + for receiver, response in responses: + prov = response(order.event) + if prov.identifier == provider: + ct.cachedfile.filename, ct.cachedfile.type, data = prov.generate(order) + ct.cachedfile.file.save(cachedfile_name(ct.cachedfile, ct.cachedfile.filename), ContentFile(data)) + ct.cachedfile.save() + + +class DummyRollbackException(Exception): + pass + + +def preview(event: int, provider: str): + event = Event.objects.get(id=event) + res = None + + try: + with transaction.atomic(), language(event.settings.locale): + item = event.items.create(name=_("Sample product"), default_price=42.23) + + order = event.orders.create(status=Order.STATUS_PENDING, datetime=now(), + expires=now(), code="PREVIEW1234", total=119) + + order.positions.create(item=item, attendee_name=_("John Doe"), price=item.default_price) + + responses = register_ticket_outputs.send(event) + for receiver, response in responses: + prov = response(event) + if prov.identifier == provider: + res = prov.generate(order) + raise DummyRollbackException() + except DummyRollbackException: + return res + else: + raise Exception('Invalid state, should have rolled back.') diff --git a/src/pretix/control/templates/pretixcontrol/event/tickets.html b/src/pretix/control/templates/pretixcontrol/event/tickets.html index cff15e567..6d4fbf011 100644 --- a/src/pretix/control/templates/pretixcontrol/event/tickets.html +++ b/src/pretix/control/templates/pretixcontrol/event/tickets.html @@ -10,13 +10,14 @@ {% bootstrap_field form.ticket_download layout="horizontal" %} {% bootstrap_field form.ticket_download_date layout="horizontal" %} {% for provider in providers %} -
+
-
-
-

{{ provider.verbose_name }}

-
-
+ + {% trans "Preview" %} + +

{{ provider.verbose_name }}

+
{% bootstrap_form provider.form layout='horizontal' %} diff --git a/src/pretix/control/urls.py b/src/pretix/control/urls.py index 0565341ca..1e857db87 100644 --- a/src/pretix/control/urls.py +++ b/src/pretix/control/urls.py @@ -42,6 +42,8 @@ urlpatterns = [ url(r'^settings/permissions$', event.EventPermissions.as_view(), name='event.settings.permissions'), url(r'^settings/payment$', event.PaymentSettings.as_view(), name='event.settings.payment'), url(r'^settings/tickets$', event.TicketSettings.as_view(), name='event.settings.tickets'), + url(r'^settings/tickets/preview/(?P[^/]+)$', event.TicketSettingsPreview.as_view(), + name='event.settings.tickets.preview'), url(r'^settings/email$', event.MailSettings.as_view(), name='event.settings.mail'), url(r'^settings/invoice$', event.InvoiceSettings.as_view(), name='event.settings.invoice'), url(r'^settings/invoice/preview$', event.InvoicePreview.as_view(), name='event.settings.invoice.preview'), diff --git a/src/pretix/control/views/event.py b/src/pretix/control/views/event.py index 1841313a5..5b51ce6b7 100644 --- a/src/pretix/control/views/event.py +++ b/src/pretix/control/views/event.py @@ -18,6 +18,7 @@ from pretix.base.forms import I18nModelForm from pretix.base.models import ( Event, EventPermission, Item, ItemVariation, User, ) +from pretix.base.services import tickets from pretix.base.services.invoices import build_preview_invoice_pdf from pretix.base.signals import ( register_payment_providers, register_ticket_outputs, @@ -378,6 +379,35 @@ class MailSettings(EventSettingsFormView): return self.get(request) +class TicketSettingsPreview(EventPermissionRequiredMixin, View): + permission = 'can_change_settings' + + @cached_property + def output(self): + responses = register_ticket_outputs.send(self.request.event) + for receiver, response in responses: + provider = response(self.request.event) + if provider.identifier == self.kwargs.get('output'): + return provider + + def get(self, request, *args, **kwargs): + if not self.output: + messages.error(request, _('You requested an invalid ticket output type.')) + return redirect(self.get_error_url()) + + fname, mimet, data = tickets.preview(self.request.event.pk, self.output.identifier) + resp = HttpResponse(data, content_type=mimet) + ftype = fname.split(".")[-1] + resp['Content-Disposition'] = 'attachment; filename="ticket-preview.{}"'.format(ftype) + return resp + + def get_error_url(self) -> str: + return reverse('control:event.settings.tickets', kwargs={ + 'organizer': self.request.event.organizer.slug, + 'event': self.request.event.slug + }) + + class TicketSettings(EventPermissionRequiredMixin, FormView): model = Event form_class = TicketSettingsForm diff --git a/src/static/pretixcontrol/scss/_forms.scss b/src/static/pretixcontrol/scss/_forms.scss index bed862ee5..a73667dd4 100644 --- a/src/static/pretixcontrol/scss/_forms.scss +++ b/src/static/pretixcontrol/scss/_forms.scss @@ -114,3 +114,6 @@ div[data-formset-body], div[data-formset-form], div[data-nested-formset-form], d } } } +.ticketoutput-panel .panel-title { + line-height: 30px; +}