mirror of
https://github.com/pretix/pretix.git
synced 2026-05-06 15:24:02 +00:00
Add a footer and a second text field to invoices
Also, move to using localized strings for Invoice.additional_text settings for consistency.
This commit is contained in:
@@ -39,8 +39,12 @@ class Invoice(models.Model):
|
||||
:type date: date
|
||||
:param locale: The locale in which the invoice should be printed
|
||||
:type locale: str
|
||||
:param introductory_text: Introductory text for the invoice, e.g. for a greeting
|
||||
:type introductory_text: str
|
||||
:param additional_text: Additional text for the invoice
|
||||
:type additional_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
|
||||
:type file: File
|
||||
"""
|
||||
@@ -53,7 +57,9 @@ class Invoice(models.Model):
|
||||
invoice_to = models.TextField()
|
||||
date = models.DateField(default=date.today)
|
||||
locale = models.CharField(max_length=50, default='en')
|
||||
introductory_text = models.TextField(blank=True)
|
||||
additional_text = models.TextField(blank=True)
|
||||
footer_text = models.TextField(blank=True)
|
||||
file = models.FileField(null=True, blank=True, upload_to=invoice_filename)
|
||||
|
||||
@staticmethod
|
||||
|
||||
@@ -21,7 +21,7 @@ from reportlab.platypus import (
|
||||
Table, TableStyle,
|
||||
)
|
||||
|
||||
from pretix.base.i18n import language
|
||||
from pretix.base.i18n import LazyI18nString, language
|
||||
from pretix.base.models import Invoice, InvoiceAddress, InvoiceLine, Order
|
||||
from pretix.base.signals import register_payment_providers
|
||||
|
||||
@@ -49,7 +49,14 @@ def generate_cancellation(invoice: Invoice):
|
||||
def regenerate_invoice(invoice: Invoice):
|
||||
with language(invoice.locale):
|
||||
invoice.invoice_from = invoice.event.settings.get('invoice_address_from')
|
||||
invoice.additional_text = invoice.event.settings.get('invoice_additional_text').replace('\n','<br />')
|
||||
|
||||
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)
|
||||
|
||||
invoice.introductory_text = str(introductory).replace('\n', '<br />')
|
||||
invoice.additional_text = str(additional).replace('\n', '<br /')
|
||||
invoice.footer_text = str(footer)
|
||||
|
||||
try:
|
||||
addr_template = pgettext("invoice", """{i.company}
|
||||
@@ -105,7 +112,14 @@ def generate_invoice(order: Order):
|
||||
with language(locale):
|
||||
i = Invoice(order=order, event=order.event)
|
||||
i.invoice_from = order.event.settings.get('invoice_address_from')
|
||||
i.additional_text = order.event.settings.get('invoice_additional_text').replace('\n','<br />')
|
||||
|
||||
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', '<br />')
|
||||
i.additional_text = str(additional).replace('\n', '<br /')
|
||||
i.footer_text = str(footer)
|
||||
|
||||
try:
|
||||
addr_template = pgettext("invoice", """{i.company}
|
||||
@@ -173,6 +187,10 @@ def _invoice_generate_german(invoice, f):
|
||||
canvas.saveState()
|
||||
canvas.setFont('OpenSans', 8)
|
||||
canvas.drawRightString(pagesize[0] - 20 * mm, 10 * mm, _("Page %d") % (doc.page,))
|
||||
|
||||
for i, line in enumerate(invoice.footer_text.split('\n')[::-1]):
|
||||
canvas.drawCentredString(pagesize[0] / 2, 25 + (3.5 * i) * mm, line.strip())
|
||||
|
||||
canvas.restoreState()
|
||||
|
||||
def on_first_page(canvas, doc):
|
||||
@@ -183,6 +201,9 @@ def _invoice_generate_german(invoice, f):
|
||||
canvas.setFont('OpenSans', 8)
|
||||
canvas.drawRightString(pagesize[0] - 20 * mm, 10 * mm, _("Page %d") % (doc.page,))
|
||||
|
||||
for i, line in enumerate(invoice.footer_text.split('\n')[::-1]):
|
||||
canvas.drawCentredString(pagesize[0] / 2, 25 + (3.5 * i) * mm, line.strip())
|
||||
|
||||
textobject = canvas.beginText(25 * mm, (297 - 15) * mm)
|
||||
textobject.setFont('OpenSansBd', 8)
|
||||
textobject.textLine(pgettext('invoice', 'Invoice from').upper())
|
||||
@@ -275,14 +296,16 @@ def _invoice_generate_german(invoice, f):
|
||||
doc = BaseDocTemplate(f.name, pagesize=pagesizes.A4,
|
||||
leftMargin=25 * mm, rightMargin=20 * mm,
|
||||
topMargin=20 * mm, bottomMargin=15 * mm)
|
||||
|
||||
footer_length = 3.5 * len(invoice.footer_text.split('\n')) * mm
|
||||
frames_p1 = [
|
||||
Frame(doc.leftMargin, doc.bottomMargin, doc.width, doc.height - 75 * mm,
|
||||
leftPadding=0, rightPadding=0, topPadding=0, bottomPadding=0,
|
||||
leftPadding=0, rightPadding=0, topPadding=0, bottomPadding=footer_length,
|
||||
id='normal')
|
||||
]
|
||||
frames = [
|
||||
Frame(doc.leftMargin, doc.bottomMargin, doc.width, doc.height,
|
||||
leftPadding=0, rightPadding=0, topPadding=0, bottomPadding=0,
|
||||
leftPadding=0, rightPadding=0, topPadding=0, bottomPadding=footer_length,
|
||||
id='normal')
|
||||
]
|
||||
doc.addPageTemplates([
|
||||
@@ -299,6 +322,10 @@ def _invoice_generate_german(invoice, f):
|
||||
NextPageTemplate('OtherPages'),
|
||||
]
|
||||
|
||||
if invoice.introductory_text:
|
||||
story.append(Paragraph(invoice.introductory_text, styles['Normal']))
|
||||
story.append(Spacer(1, 10 * mm))
|
||||
|
||||
taxvalue_map = defaultdict(Decimal)
|
||||
grossvalue_map = defaultdict(Decimal)
|
||||
|
||||
@@ -334,8 +361,10 @@ def _invoice_generate_german(invoice, f):
|
||||
story.append(table)
|
||||
|
||||
story.append(Spacer(1, 15 * mm))
|
||||
story.append(Paragraph(invoice.additional_text, styles['Normal']))
|
||||
story.append(Spacer(1, 15 * mm))
|
||||
|
||||
if invoice.additional_text:
|
||||
story.append(Paragraph(invoice.additional_text, styles['Normal']))
|
||||
story.append(Spacer(1, 15 * mm))
|
||||
|
||||
tstyledata = [
|
||||
('SPAN', (1, 0), (-1, 0)),
|
||||
|
||||
@@ -77,9 +77,17 @@ DEFAULTS = {
|
||||
'default': '',
|
||||
'type': str
|
||||
},
|
||||
'invoice_introductory_text': {
|
||||
'default': '',
|
||||
'type': LazyI18nString
|
||||
},
|
||||
'invoice_additional_text': {
|
||||
'default': '',
|
||||
'type': str
|
||||
'type': LazyI18nString
|
||||
},
|
||||
'invoice_footer_text': {
|
||||
'default': '',
|
||||
'type': LazyI18nString
|
||||
},
|
||||
'invoice_language': {
|
||||
'default': '__user__',
|
||||
|
||||
@@ -275,11 +275,24 @@ class InvoiceSettingsForm(SettingsForm):
|
||||
help_text=_("Will be printed as the sender on invoices. Be sure to include relevant details required in "
|
||||
"your jurisdiction (e.g. your VAT ID).")
|
||||
)
|
||||
invoice_additional_text = forms.CharField(
|
||||
widget=forms.Textarea(attrs={'rows': 5}), required=False,
|
||||
invoice_introductory_text = I18nFormField(
|
||||
widget=I18nTextarea,
|
||||
required=False,
|
||||
label=_("Introductory text"),
|
||||
help_text=_("Will be printed on every invoice above the invoice rows.")
|
||||
)
|
||||
invoice_additional_text = I18nFormField(
|
||||
widget=I18nTextarea,
|
||||
required=False,
|
||||
label=_("Additional text"),
|
||||
help_text=_("Will be printed on every invoice below the invoice total.")
|
||||
)
|
||||
invoice_footer_text = I18nFormField(
|
||||
widget=I18nTextarea,
|
||||
required=False,
|
||||
label=_("Footer"),
|
||||
help_text=_("Will be printed centered and in a smaller font at the end of every invoice page.")
|
||||
)
|
||||
invoice_language = forms.ChoiceField(
|
||||
widget=forms.Select, required=True,
|
||||
label=_("Invoice language"),
|
||||
|
||||
@@ -14,7 +14,9 @@
|
||||
{% bootstrap_field form.invoice_generate layout="horizontal" %}
|
||||
{% bootstrap_field form.invoice_language layout="horizontal" %}
|
||||
{% bootstrap_field form.invoice_address_from layout="horizontal" %}
|
||||
{% bootstrap_field form.invoice_introductory_text layout="horizontal" %}
|
||||
{% bootstrap_field form.invoice_additional_text layout="horizontal" %}
|
||||
{% bootstrap_field form.invoice_footer_text layout="horizontal" %}
|
||||
</fieldset>
|
||||
<div class="form-group submit-group">
|
||||
<button type="submit" class="btn btn-primary btn-save">
|
||||
|
||||
Reference in New Issue
Block a user