import copy import tempfile from collections import defaultdict from datetime import date from decimal import Decimal from locale import format as lformat from django.conf import settings 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.translation import pgettext, ugettext as _ from reportlab.lib import pagesizes from reportlab.lib.styles import ParagraphStyle, StyleSheet1 from reportlab.lib.units import mm from reportlab.pdfbase import pdfmetrics from reportlab.pdfbase.ttfonts import TTFont from reportlab.platypus import ( BaseDocTemplate, Frame, NextPageTemplate, PageTemplate, Paragraph, Spacer, Table, TableStyle, ) from pretix.base.i18n import LazyI18nString, language 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): with language(invoice.locale): 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) invoice.introductory_text = str(introductory).replace('\n', '
') invoice.additional_text = str(additional).replace('\n', '
') i.additional_text = str(additional).replace('\n', '
2: colwidths = [a * doc.width for a in (.45, .10, .15, .15, .15)] table = Table(tdata, colWidths=colwidths, repeatRows=2) table.setStyle(TableStyle(tstyledata)) story.append(table) doc.build(story) return doc def invoice_pdf(invoice: int): i = Invoice.objects.get(pk=invoice) with language(i.locale): with tempfile.NamedTemporaryFile(suffix=".pdf") as f: _invoice_generate_german(i, f) f.seek(0) i.file.save('invoice.pdf', ContentFile(f.read())) i.save() return i.file.name def invoice_qualified(order: Order): if order.total == Decimal('0.00'): return False return True if settings.HAS_CELERY: from pretix.celery import app invoice_pdf_task = app.task(invoice_pdf) def invoice_pdf(*args, **kwargs): # We introduce a 2 second delay, because otherwise we run into conditions where # the task worker tries to generate the PDF even before our database transaction # was committed and therefore fails to find the invoice object. invoice_pdf_task.apply_async(args=args, kwargs=kwargs, countdown=2)