diff --git a/doc/development/api/payment.rst b/doc/development/api/payment.rst
index e9b95de938..870d58ebe2 100644
--- a/doc/development/api/payment.rst
+++ b/doc/development/api/payment.rst
@@ -62,6 +62,8 @@ The provider class
.. automethod:: settings_content_render
+ .. automethod:: render_invoice_text
+
.. automethod:: payment_form_render
.. automethod:: payment_form
diff --git a/doc/development/implementation/logging.rst b/doc/development/implementation/logging.rst
index f68efd9471..5c9c8a3bbd 100644
--- a/doc/development/implementation/logging.rst
+++ b/doc/development/implementation/logging.rst
@@ -29,7 +29,7 @@ Logging form actions
A very common use case is to log the changes to a model that have been done in a ``ModelForm``. In this case,
we generally use a custom ``form_valid`` method on our ``FormView`` that looks like this::
- @transaction.atomic()
+ @transaction.atomic
def form_valid(self, form):
if form.has_changed():
self.request.event.log_action('pretix.event.changed', user=self.request.user, data={
@@ -40,7 +40,7 @@ we generally use a custom ``form_valid`` method on our ``FormView`` that looks l
It gets a little bit more complicated if your form allows file uploads::
- @transaction.atomic()
+ @transaction.atomic
def form_valid(self, form):
if form.has_changed():
self.request.event.log_action(
diff --git a/src/pretix/base/migrations/0037_invoice_payment_provider_text.py b/src/pretix/base/migrations/0037_invoice_payment_provider_text.py
new file mode 100644
index 0000000000..9659a910ec
--- /dev/null
+++ b/src/pretix/base/migrations/0037_invoice_payment_provider_text.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.9 on 2016-09-06 21:31
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('pretixbase', '0036_auto_20160902_0755'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='invoice',
+ name='payment_provider_text',
+ field=models.TextField(blank=True),
+ ),
+ ]
diff --git a/src/pretix/base/models/invoices.py b/src/pretix/base/models/invoices.py
index ec73130b77..b65b688f22 100644
--- a/src/pretix/base/models/invoices.py
+++ b/src/pretix/base/models/invoices.py
@@ -43,6 +43,8 @@ class Invoice(models.Model):
:type introductory_text: str
:param additional_text: Additional text for the invoice
:type additional_text: str
+ :param payment_provider_text: A payment provider specific text
+ :type payment_provider_text: str
:param footer_text: A footer text, displayed smaller and centered on every page
:type footer_text: str
:param file: The filename of the rendered invoice
@@ -59,6 +61,7 @@ class Invoice(models.Model):
locale = models.CharField(max_length=50, default='en')
introductory_text = models.TextField(blank=True)
additional_text = models.TextField(blank=True)
+ payment_provider_text = models.TextField(blank=True)
footer_text = models.TextField(blank=True)
file = models.FileField(null=True, blank=True, upload_to=invoice_filename)
diff --git a/src/pretix/base/payment.py b/src/pretix/base/payment.py
index 3b8f636969..e0ded320e5 100644
--- a/src/pretix/base/payment.py
+++ b/src/pretix/base/payment.py
@@ -12,6 +12,7 @@ from django.template.loader import get_template
from django.utils.translation import ugettext_lazy as _
from pretix.base.decimal import round_decimal
+from pretix.base.i18n import I18nFormField, I18nTextarea, LazyI18nString
from pretix.base.models import CartPosition, Event, Order, Quota
from pretix.base.settings import SettingsSandbox
from pretix.base.signals import register_payment_providers
@@ -134,6 +135,13 @@ class BasePaymentProvider:
'above!'),
required=False
)),
+ ('_invoice_text',
+ I18nFormField(
+ label=_('Text on invoices'),
+ help_text=_('Will be printed just below the payment figures and above the closing text on invoices.'),
+ required=False,
+ widget=I18nTextarea,
+ )),
])
def settings_content_render(self, request: HttpRequest) -> str:
@@ -144,6 +152,14 @@ class BasePaymentProvider:
"""
pass
+ def render_invoice_text(self, order: Order) -> str:
+ """
+ This is called when an invoice for an order with this payment provider is generated.
+ The default implementation returns the content of the _invoice_text configuration
+ variable (an I18nString), or an empty string if unconfigured.
+ """
+ return self.settings.get('_invoice_text', as_type=LazyI18nString, default='')
+
@property
def payment_form_fields(self) -> dict:
"""
diff --git a/src/pretix/base/services/invoices.py b/src/pretix/base/services/invoices.py
index c9dde9c6c1..9099058f5b 100644
--- a/src/pretix/base/services/invoices.py
+++ b/src/pretix/base/services/invoices.py
@@ -26,37 +26,27 @@ from pretix.base.models import Invoice, InvoiceAddress, InvoiceLine, Order
from pretix.base.signals import register_payment_providers
-def generate_cancellation(invoice: Invoice):
- cancellation = copy.copy(invoice)
- cancellation.pk = None
- cancellation.is_cancellation = True
- cancellation.date = date.today()
- cancellation.refers = invoice
- cancellation.invoice_no = None
- cancellation.save()
- for line in invoice.lines.all():
- line.pk = None
- line.invoice = cancellation
- line.gross_value *= -1
- line.tax_value *= -1
- line.save()
-
- invoice_pdf(cancellation.pk)
- return cancellation
-
-
@transaction.atomic
-def regenerate_invoice(invoice: Invoice):
+def build_invoice(invoice: Invoice) -> Invoice:
with language(invoice.locale):
+ responses = register_payment_providers.send(invoice.event)
+ for receiver, response in responses:
+ provider = response(invoice.event)
+ if provider.identifier == invoice.order.payment_provider:
+ payment_provider = provider
+ break
+
invoice.invoice_from = invoice.event.settings.get('invoice_address_from')
introductory = invoice.event.settings.get('invoice_introductory_text', as_type=LazyI18nString)
additional = invoice.event.settings.get('invoice_additional_text', as_type=LazyI18nString)
footer = invoice.event.settings.get('invoice_footer_text', as_type=LazyI18nString)
+ payment = payment_provider.render_invoice_text(invoice.order)
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', '
')
try:
addr_template = pgettext("invoice", """{i.company}
@@ -72,15 +62,8 @@ def regenerate_invoice(invoice: Invoice):
invoice.file = None
invoice.save()
-
- responses = register_payment_providers.send(invoice.event)
- for receiver, response in responses:
- provider = response(invoice.event)
- if provider.identifier == invoice.order.payment_provider:
- payment_provider = provider
- break
-
invoice.lines.all().delete()
+
for p in invoice.order.positions.all():
desc = str(p.item.name)
if p.variation:
@@ -98,71 +81,60 @@ def regenerate_invoice(invoice: Invoice):
tax_rate=invoice.order.payment_fee_tax_rate
)
- invoice_pdf(invoice.pk)
+ return invoice
+
+
+def build_cancellation(invoice: Invoice):
+ invoice.lines.all().delete()
+
+ for line in invoice.refers.lines.all():
+ line.pk = None
+ line.invoice = invoice
+ line.gross_value *= -1
+ line.tax_value *= -1
+ line.save()
+ return invoice
+
+
+def generate_cancellation(invoice: Invoice):
+ cancellation = copy.copy(invoice)
+ cancellation.pk = None
+ cancellation.invoice_no = None
+ cancellation.refers = invoice
+ cancellation.is_cancellation = True
+ cancellation.date = date.today()
+ cancellation.payment_provider_text = ''
+ cancellation.save()
+
+ cancellation = build_cancellation(cancellation)
+ invoice_pdf(cancellation.pk)
+ return cancellation
+
+
+def regenerate_invoice(invoice: Invoice):
+ if invoice.is_cancellation:
+ invoice = build_cancellation(invoice)
+ else:
+ invoice = build_invoice(invoice)
+ invoice_pdf(invoice.pk)
return invoice
-@transaction.atomic
def generate_invoice(order: Order):
locale = order.event.settings.get('invoice_language')
if locale:
if locale == '__user__':
locale = order.locale
- with language(locale):
- i = Invoice(order=order, event=order.event)
- i.invoice_from = order.event.settings.get('invoice_address_from')
-
- introductory = i.event.settings.get('invoice_introductory_text', as_type=LazyI18nString)
- additional = i.event.settings.get('invoice_additional_text', as_type=LazyI18nString)
- footer = i.event.settings.get('invoice_footer_text', as_type=LazyI18nString)
-
- i.introductory_text = str(introductory).replace('\n', '
')
- i.additional_text = str(additional).replace('\n', '