diff --git a/src/pretix/base/services/invoices.py b/src/pretix/base/services/invoices.py index c6c138efd..919c5bdce 100644 --- a/src/pretix/base/services/invoices.py +++ b/src/pretix/base/services/invoices.py @@ -9,6 +9,7 @@ from django.contrib.staticfiles import finders from django.core.files.base import ContentFile from django.db import transaction from django.utils.formats import date_format +from django.utils.timezone import now from django.utils.translation import pgettext, ugettext as _ from reportlab.lib import pagesizes from reportlab.lib.styles import ParagraphStyle, StyleSheet1 @@ -399,3 +400,53 @@ def invoice_pdf(*args, **kwargs): # was committed and therefore fails to find the invoice object. The invoice_pdf_task # will prevent this kind of race condition. invoice_pdf_task.apply_async(args=args, kwargs=kwargs) + + +class DummyRollbackException(Exception): + pass + + +def build_preview_invoice_pdf(event): + locale = event.settings.invoice_language + pdf = None + if not locale or locale == '__user__': + locale = event.settings.locale + + try: + with transaction.atomic(), language(locale): + order = event.orders.create(status=Order.STATUS_PENDING, datetime=now(), + expires=now(), code="PREVIEW", total=119) + invoice = Invoice( + order=order, event=event, invoice_no="PREVIEW", + date=date.today(), locale=locale + ) + invoice.invoice_from = event.settings.get('invoice_address_from') + + introductory = event.settings.get('invoice_introductory_text', as_type=LazyI18nString) + additional = event.settings.get('invoice_additional_text', as_type=LazyI18nString) + footer = event.settings.get('invoice_footer_text', as_type=LazyI18nString) + payment = _("A payment provider specific text might appear here.") + + invoice.introductory_text = str(introductory).replace('\n', '
') + invoice.additional_text = str(additional).replace('\n', '
') + invoice.footer_text = str(footer) + invoice.payment_provider_text = str(payment).replace('\n', '
') + invoice.invoice_to = _("John Doe\n214th Example Street\n012345 Somecity") + invoice.file = None + invoice.save() + invoice.lines.all().delete() + + InvoiceLine.objects.create( + invoice=invoice, description=_("Sample product A"), + gross_value=119, tax_value=19, + tax_rate=19 + ) + with tempfile.NamedTemporaryFile(suffix=".pdf") as f: + _invoice_generate_german(invoice, f) + f.seek(0) + pdf = f.read() + raise DummyRollbackException() + except DummyRollbackException: + return pdf + else: + raise Exception('Invalid state, should have rolled back.') diff --git a/src/pretix/control/templates/pretixcontrol/event/invoicing.html b/src/pretix/control/templates/pretixcontrol/event/invoicing.html index 1aa3b9942..044b64011 100644 --- a/src/pretix/control/templates/pretixcontrol/event/invoicing.html +++ b/src/pretix/control/templates/pretixcontrol/event/invoicing.html @@ -19,6 +19,9 @@ {% bootstrap_field form.invoice_footer_text layout="horizontal" %}
+ diff --git a/src/pretix/control/urls.py b/src/pretix/control/urls.py index 8232a8160..0565341ca 100644 --- a/src/pretix/control/urls.py +++ b/src/pretix/control/urls.py @@ -44,6 +44,7 @@ urlpatterns = [ url(r'^settings/tickets$', event.TicketSettings.as_view(), name='event.settings.tickets'), 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'), url(r'^settings/display', event.DisplaySettings.as_view(), name='event.settings.display'), url(r'^items/$', item.ItemList.as_view(), name='event.items'), url(r'^items/add$', item.ItemCreate.as_view(), name='event.items.add'), diff --git a/src/pretix/control/views/event.py b/src/pretix/control/views/event.py index 5c70ff63d..1841313a5 100644 --- a/src/pretix/control/views/event.py +++ b/src/pretix/control/views/event.py @@ -6,17 +6,19 @@ from django.core.files import File from django.core.urlresolvers import reverse from django.db import transaction from django.forms import modelformset_factory +from django.http import HttpResponse from django.shortcuts import redirect from django.utils.functional import cached_property from django.utils.translation import ugettext_lazy as _ from django.views.generic import FormView -from django.views.generic.base import TemplateView +from django.views.generic.base import TemplateView, View from django.views.generic.detail import SingleObjectMixin from pretix.base.forms import I18nModelForm from pretix.base.models import ( Event, EventPermission, Item, ItemVariation, User, ) +from pretix.base.services.invoices import build_preview_invoice_pdf from pretix.base.signals import ( register_payment_providers, register_ticket_outputs, ) @@ -273,12 +275,27 @@ class InvoiceSettings(EventSettingsFormView): permission = 'can_change_settings' def get_success_url(self) -> str: + if 'preview' in self.request.POST: + return reverse('control:event.settings.invoice.preview', kwargs={ + 'organizer': self.request.event.organizer.slug, + 'event': self.request.event.slug + }) return reverse('control:event.settings.invoice', kwargs={ 'organizer': self.request.event.organizer.slug, 'event': self.request.event.slug }) +class InvoicePreview(EventPermissionRequiredMixin, View): + permission = 'can_change_settings' + + def get(self, request, *args, **kwargs): + pdf = build_preview_invoice_pdf(request.event) + resp = HttpResponse(pdf, content_type='application/pdf') + resp['Content-Disposition'] = 'attachment; filename="invoice-preview.pdf"' + return resp + + class DisplaySettings(EventSettingsFormView): model = Event form_class = DisplaySettingsForm