Writing an invoice renderer plugin

An invoice renderer controls how invoice files are built. The creation of such a plugin is very similar to creating an export output.

Please read Creating a plugin first, if you haven’t already.

Output registration

The invoice renderer API does not make a lot of usage from signals, however, it does use a signal to get a list of all available invoice renderers. Your plugin should listen for this signal and return the subclass of pretix.base.invoice.BaseInvoiceRenderer that we’ll provide in this plugin:

1
2
3
4
5
6
7
8
9
from django.dispatch import receiver

from pretix.base.signals import register_invoice_renderers


@receiver(register_invoice_renderers, dispatch_uid="output_custom")
def register_infoice_renderers(sender, **kwargs):
    from .invoice import MyInvoiceRenderer
    return MyInvoiceRenderer

The renderer class

class pretix.base.invoice.BaseInvoiceRenderer

The central object of each invoice renderer is the subclass of BaseInvoiceRenderer.

BaseInvoiceRenderer.event

The default constructor sets this property to the event we are currently working for.

BaseInvoiceRenderer.identifier

A short and unique identifier for this renderer. This should only contain lowercase letters and in most cases will be the same as your package name.

This is an abstract attribute, you must override this!

BaseInvoiceRenderer.verbose_name

A human-readable name for this renderer. This should be short but self-explanatory. Good examples include ‘German DIN 5008’ or ‘Italian invoice’.

This is an abstract attribute, you must override this!

BaseInvoiceRenderer.generate(invoice: pretix.base.models.invoices.Invoice) → typing.Tuple[[str, str], str]

This method should generate the invoice file and return a tuple consisting of a filename, a file type and file content. The extension will be taken from the filename which is otherwise ignored.

Helper class for reportlab-base renderers

All PDF rendering that ships with pretix is based on reportlab. We recommend to read the reportlab User Guide to understand all the concepts used here.

If you want to implement a renderer that also uses report lab, this helper class might be convenient to you:

class pretix.base.invoice.BaseReportlabInvoiceRenderer
BaseReportlabInvoiceRenderer.pagesize
BaseReportlabInvoiceRenderer.left_margin
BaseReportlabInvoiceRenderer.right_margin
BaseReportlabInvoiceRenderer.top_margin
BaseReportlabInvoiceRenderer.bottom_margin
BaseReportlabInvoiceRenderer.doc_template_class
BaseReportlabInvoiceRenderer.invoice
BaseReportlabInvoiceRenderer._init()

Initialize the renderer. By default, this registers fonts and sets self.stylesheet.

BaseReportlabInvoiceRenderer._get_stylesheet()

Get a stylesheet. By default, this contains the “Normal” and “Heading1” styles.

BaseReportlabInvoiceRenderer._register_fonts()

Register fonts with reportlab. By default, this registers the OpenSans font family

BaseReportlabInvoiceRenderer._on_first_page(canvas: reportlab.pdfgen.canvas.Canvas, doc)

Called when a new page is rendered that is the first page.

BaseReportlabInvoiceRenderer._on_other_page(canvas: reportlab.pdfgen.canvas.Canvas, doc)

Called when a new page is rendered that is not the first page.

BaseReportlabInvoiceRenderer._get_first_page_frames(doc)

Called to create a list of frames for the first page.

BaseReportlabInvoiceRenderer._get_other_page_frames(doc)

Called to create a list of frames for the other pages.

BaseReportlabInvoiceRenderer._build_doc(fhandle)

Build a PDF document in a given file handle