forked from CGM_Public/pretix_original
Add modern invoice renderer
This commit is contained in:
@@ -9,14 +9,17 @@ import vat_moss.exchange_rates
|
|||||||
from django.contrib.staticfiles import finders
|
from django.contrib.staticfiles import finders
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from django.utils.formats import date_format, localize
|
from django.utils.formats import date_format, localize
|
||||||
from django.utils.translation import get_language, pgettext, ugettext
|
from django.utils.translation import (
|
||||||
|
get_language, pgettext, ugettext, ugettext_lazy,
|
||||||
|
)
|
||||||
from PIL.Image import BICUBIC
|
from PIL.Image import BICUBIC
|
||||||
from reportlab.lib import pagesizes
|
from reportlab.lib import pagesizes
|
||||||
from reportlab.lib.enums import TA_LEFT
|
from reportlab.lib.enums import TA_LEFT, TA_RIGHT
|
||||||
from reportlab.lib.styles import ParagraphStyle, StyleSheet1
|
from reportlab.lib.styles import ParagraphStyle, StyleSheet1
|
||||||
from reportlab.lib.units import mm
|
from reportlab.lib.units import mm
|
||||||
from reportlab.lib.utils import ImageReader
|
from reportlab.lib.utils import ImageReader
|
||||||
from reportlab.pdfbase import pdfmetrics
|
from reportlab.pdfbase import pdfmetrics
|
||||||
|
from reportlab.pdfbase.pdfmetrics import stringWidth
|
||||||
from reportlab.pdfbase.ttfonts import TTFont
|
from reportlab.pdfbase.ttfonts import TTFont
|
||||||
from reportlab.pdfgen.canvas import Canvas
|
from reportlab.pdfgen.canvas import Canvas
|
||||||
from reportlab.platypus import (
|
from reportlab.platypus import (
|
||||||
@@ -122,6 +125,7 @@ class BaseReportlabInvoiceRenderer(BaseInvoiceRenderer):
|
|||||||
"""
|
"""
|
||||||
stylesheet = StyleSheet1()
|
stylesheet = StyleSheet1()
|
||||||
stylesheet.add(ParagraphStyle(name='Normal', fontName=self.font_regular, fontSize=10, leading=12))
|
stylesheet.add(ParagraphStyle(name='Normal', fontName=self.font_regular, fontSize=10, leading=12))
|
||||||
|
stylesheet.add(ParagraphStyle(name='InvoiceFrom', parent=stylesheet['Normal']))
|
||||||
stylesheet.add(ParagraphStyle(name='Heading1', fontName=self.font_bold, fontSize=15, leading=15 * 1.2))
|
stylesheet.add(ParagraphStyle(name='Heading1', fontName=self.font_bold, fontSize=15, leading=15 * 1.2))
|
||||||
stylesheet.add(ParagraphStyle(name='FineprintHeading', fontName=self.font_bold, fontSize=8, leading=12))
|
stylesheet.add(ParagraphStyle(name='FineprintHeading', fontName=self.font_bold, fontSize=8, leading=12))
|
||||||
stylesheet.add(ParagraphStyle(name='Fineprint', fontName=self.font_regular, fontSize=8, leading=10))
|
stylesheet.add(ParagraphStyle(name='Fineprint', fontName=self.font_regular, fontSize=8, leading=10))
|
||||||
@@ -254,49 +258,64 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
|
|||||||
|
|
||||||
canvas.restoreState()
|
canvas.restoreState()
|
||||||
|
|
||||||
|
invoice_to_width = 85 * mm
|
||||||
|
invoice_to_height = 50 * mm
|
||||||
|
invoice_to_left = 25 * mm
|
||||||
|
invoice_to_top = 52 * mm
|
||||||
|
|
||||||
def _draw_invoice_to(self, canvas):
|
def _draw_invoice_to(self, canvas):
|
||||||
p = Paragraph(self.invoice.invoice_to.strip().replace('\n', '<br />\n'), style=self.stylesheet['Normal'])
|
p = Paragraph(self.invoice.address_invoice_to.strip().replace('\n', '<br />\n'), style=self.stylesheet['Normal'])
|
||||||
p.wrapOn(canvas, 85 * mm, 50 * mm)
|
p.wrapOn(canvas, self.invoice_to_width, self.invoice_to_height)
|
||||||
p_size = p.wrap(85 * mm, 50 * mm)
|
p_size = p.wrap(self.invoice_to_width, self.invoice_to_height)
|
||||||
p.drawOn(canvas, 25 * mm, (297 - 52) * mm - p_size[1])
|
p.drawOn(canvas, self.invoice_to_left, self.pagesize[1] - p_size[1] - self.invoice_to_top)
|
||||||
|
|
||||||
|
invoice_from_width = 70 * mm
|
||||||
|
invoice_from_height = 50 * mm
|
||||||
|
invoice_from_left = 25 * mm
|
||||||
|
invoice_from_top = 17 * mm
|
||||||
|
|
||||||
def _draw_invoice_from(self, canvas):
|
def _draw_invoice_from(self, canvas):
|
||||||
p = Paragraph(self.invoice.full_invoice_from.strip().replace('\n', '<br />\n'), style=self.stylesheet['Normal'])
|
p = Paragraph(self.invoice.full_invoice_from.strip().replace('\n', '<br />\n'), style=self.stylesheet[
|
||||||
p.wrapOn(canvas, 70 * mm, 50 * mm)
|
'InvoiceFrom'])
|
||||||
p_size = p.wrap(70 * mm, 50 * mm)
|
p.wrapOn(canvas, self.invoice_from_width, self.invoice_from_height)
|
||||||
p.drawOn(canvas, 25 * mm, (297 - 17) * mm - p_size[1])
|
p_size = p.wrap(self.invoice_from_width, self.invoice_from_height)
|
||||||
|
p.drawOn(canvas, self.invoice_from_left, self.pagesize[1] - p_size[1] - self.invoice_from_top)
|
||||||
def _on_first_page(self, canvas: Canvas, doc):
|
|
||||||
canvas.setCreator('pretix.eu')
|
|
||||||
canvas.setTitle(pgettext('invoice', 'Invoice {num}').format(num=self.invoice.number))
|
|
||||||
|
|
||||||
canvas.saveState()
|
|
||||||
canvas.setFont(self.font_regular, 8)
|
|
||||||
|
|
||||||
if self.invoice.order.testmode:
|
|
||||||
canvas.saveState()
|
|
||||||
canvas.setFont('OpenSansBd', 30)
|
|
||||||
canvas.setFillColorRGB(32, 0, 0)
|
|
||||||
canvas.drawRightString(self.pagesize[0] - 20 * mm, (297 - 100) * mm, ugettext('TEST MODE'))
|
|
||||||
canvas.restoreState()
|
|
||||||
|
|
||||||
for i, line in enumerate(self.invoice.footer_text.split('\n')[::-1]):
|
|
||||||
canvas.drawCentredString(self.pagesize[0] / 2, 25 + (3.5 * i) * mm, line.strip())
|
|
||||||
|
|
||||||
|
def _draw_invoice_from_label(self, canvas):
|
||||||
textobject = canvas.beginText(25 * mm, (297 - 15) * mm)
|
textobject = canvas.beginText(25 * mm, (297 - 15) * mm)
|
||||||
textobject.setFont(self.font_bold, 8)
|
textobject.setFont(self.font_bold, 8)
|
||||||
textobject.textLine(self._upper(pgettext('invoice', 'Invoice from')))
|
textobject.textLine(self._upper(pgettext('invoice', 'Invoice from')))
|
||||||
canvas.drawText(textobject)
|
canvas.drawText(textobject)
|
||||||
|
|
||||||
self._draw_invoice_from(canvas)
|
def _draw_invoice_to_label(self, canvas):
|
||||||
|
|
||||||
textobject = canvas.beginText(25 * mm, (297 - 50) * mm)
|
textobject = canvas.beginText(25 * mm, (297 - 50) * mm)
|
||||||
textobject.setFont(self.font_bold, 8)
|
textobject.setFont(self.font_bold, 8)
|
||||||
textobject.textLine(self._upper(pgettext('invoice', 'Invoice to')))
|
textobject.textLine(self._upper(pgettext('invoice', 'Invoice to')))
|
||||||
canvas.drawText(textobject)
|
canvas.drawText(textobject)
|
||||||
|
|
||||||
self._draw_invoice_to(canvas)
|
logo_width = 25 * mm
|
||||||
|
logo_height = 25 * mm
|
||||||
|
logo_left = 95 * mm
|
||||||
|
logo_top = 13 * mm
|
||||||
|
logo_anchor = 'n'
|
||||||
|
|
||||||
|
def _draw_logo(self, canvas):
|
||||||
|
if self.invoice.event.settings.invoice_logo_image:
|
||||||
|
logo_file = self.invoice.event.settings.get('invoice_logo_image', binary_file=True)
|
||||||
|
ir = ThumbnailingImageReader(logo_file)
|
||||||
|
try:
|
||||||
|
ir.resize(self.logo_width, self.logo_height, 300)
|
||||||
|
except:
|
||||||
|
logger.exception("Can not resize image")
|
||||||
|
pass
|
||||||
|
canvas.drawImage(ir,
|
||||||
|
self.logo_left,
|
||||||
|
self.pagesize[1] - self.logo_height - self.logo_top,
|
||||||
|
width=self.logo_width, height=self.logo_height,
|
||||||
|
preserveAspectRatio=True, anchor=self.logo_anchor,
|
||||||
|
mask='auto')
|
||||||
|
|
||||||
|
def _draw_metadata(self, canvas):
|
||||||
textobject = canvas.beginText(125 * mm, (297 - 38) * mm)
|
textobject = canvas.beginText(125 * mm, (297 - 38) * mm)
|
||||||
textobject.setFont(self.font_bold, 8)
|
textobject.setFont(self.font_bold, 8)
|
||||||
textobject.textLine(self._upper(pgettext('invoice', 'Order code')))
|
textobject.textLine(self._upper(pgettext('invoice', 'Order code')))
|
||||||
@@ -348,37 +367,37 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
|
|||||||
|
|
||||||
canvas.drawText(textobject)
|
canvas.drawText(textobject)
|
||||||
|
|
||||||
if self.invoice.event.settings.invoice_logo_image:
|
event_left = 125 * mm
|
||||||
logo_file = self.invoice.event.settings.get('invoice_logo_image', binary_file=True)
|
event_top = 17 * mm
|
||||||
ir = ThumbnailingImageReader(logo_file)
|
event_width = 65 * mm
|
||||||
try:
|
event_height = 50 * mm
|
||||||
ir.resize(25 * mm, 25 * mm, 300)
|
|
||||||
except:
|
|
||||||
logger.exception("Can not resize image")
|
|
||||||
pass
|
|
||||||
canvas.drawImage(ir,
|
|
||||||
95 * mm, (297 - 38) * mm,
|
|
||||||
width=25 * mm, height=25 * mm,
|
|
||||||
preserveAspectRatio=True, anchor='n',
|
|
||||||
mask='auto')
|
|
||||||
|
|
||||||
|
def _draw_event_label(self, canvas):
|
||||||
|
textobject = canvas.beginText(125 * mm, (297 - 15) * mm)
|
||||||
|
textobject.setFont(self.font_bold, 8)
|
||||||
|
textobject.textLine(self._upper(pgettext('invoice', 'Event')))
|
||||||
|
canvas.drawText(textobject)
|
||||||
|
|
||||||
|
def _draw_event(self, canvas):
|
||||||
def shorten(txt):
|
def shorten(txt):
|
||||||
txt = str(txt)
|
txt = str(txt)
|
||||||
p = Paragraph(txt.strip().replace('\n', '<br />\n'), style=self.stylesheet['Normal'])
|
p = Paragraph(txt.strip().replace('\n', '<br />\n'), style=self.stylesheet['Normal'])
|
||||||
p_size = p.wrap(65 * mm, 50 * mm)
|
p_size = p.wrap(self.event_width, self.event_height)
|
||||||
|
|
||||||
while p_size[1] > 2 * self.stylesheet['Normal'].leading:
|
while p_size[1] > 2 * self.stylesheet['Normal'].leading:
|
||||||
txt = ' '.join(txt.replace('…', '').split()[:-1]) + '…'
|
txt = ' '.join(txt.replace('…', '').split()[:-1]) + '…'
|
||||||
p = Paragraph(txt.strip().replace('\n', '<br />\n'), style=self.stylesheet['Normal'])
|
p = Paragraph(txt.strip().replace('\n', '<br />\n'), style=self.stylesheet['Normal'])
|
||||||
p_size = p.wrap(65 * mm, 50 * mm)
|
p_size = p.wrap(self.event_width, self.event_height)
|
||||||
return txt
|
return txt
|
||||||
|
|
||||||
if not self.invoice.event.has_subevents:
|
if not self.invoice.event.has_subevents:
|
||||||
if self.invoice.event.settings.show_date_to and self.invoice.event.date_to:
|
if self.invoice.event.settings.show_date_to and self.invoice.event.date_to:
|
||||||
p_str = (
|
p_str = (
|
||||||
shorten(self.invoice.event.name) + '\n' + pgettext('invoice', '{from_date}\nuntil {to_date}').format(
|
shorten(self.invoice.event.name) + '\n' +
|
||||||
|
pgettext('invoice', '{from_date}\nuntil {to_date}').format(
|
||||||
from_date=self.invoice.event.get_date_from_display(),
|
from_date=self.invoice.event.get_date_from_display(),
|
||||||
to_date=self.invoice.event.get_date_to_display())
|
to_date=self.invoice.event.get_date_to_display()
|
||||||
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
p_str = (
|
p_str = (
|
||||||
@@ -388,15 +407,38 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
|
|||||||
p_str = shorten(self.invoice.event.name)
|
p_str = shorten(self.invoice.event.name)
|
||||||
|
|
||||||
p = Paragraph(p_str.strip().replace('\n', '<br />\n'), style=self.stylesheet['Normal'])
|
p = Paragraph(p_str.strip().replace('\n', '<br />\n'), style=self.stylesheet['Normal'])
|
||||||
p.wrapOn(canvas, 65 * mm, 50 * mm)
|
p.wrapOn(canvas, self.event_width, self.event_height)
|
||||||
p_size = p.wrap(65 * mm, 50 * mm)
|
p_size = p.wrap(self.event_width, self.event_height)
|
||||||
p.drawOn(canvas, 125 * mm, (297 - 17) * mm - p_size[1])
|
p.drawOn(canvas, self.event_left, self.pagesize[1] - self.event_top - p_size[1])
|
||||||
|
self._draw_event_label(canvas)
|
||||||
|
|
||||||
textobject = canvas.beginText(125 * mm, (297 - 15) * mm)
|
def _draw_footer(self, canvas):
|
||||||
textobject.setFont(self.font_bold, 8)
|
canvas.setFont(self.font_regular, 8)
|
||||||
textobject.textLine(self._upper(pgettext('invoice', 'Event')))
|
for i, line in enumerate(self.invoice.footer_text.split('\n')[::-1]):
|
||||||
canvas.drawText(textobject)
|
canvas.drawCentredString(self.pagesize[0] / 2, 25 + (3.5 * i) * mm, line.strip())
|
||||||
|
|
||||||
|
def _draw_testmode(self, canvas):
|
||||||
|
if self.invoice.order.testmode:
|
||||||
|
canvas.saveState()
|
||||||
|
canvas.setFont('OpenSansBd', 30)
|
||||||
|
canvas.setFillColorRGB(32, 0, 0)
|
||||||
|
canvas.drawRightString(self.pagesize[0] - 20 * mm, (297 - 100) * mm, ugettext('TEST MODE'))
|
||||||
|
canvas.restoreState()
|
||||||
|
|
||||||
|
def _on_first_page(self, canvas: Canvas, doc):
|
||||||
|
canvas.setCreator('pretix.eu')
|
||||||
|
canvas.setTitle(pgettext('invoice', 'Invoice {num}').format(num=self.invoice.number))
|
||||||
|
|
||||||
|
canvas.saveState()
|
||||||
|
self._draw_footer(canvas)
|
||||||
|
self._draw_testmode(canvas)
|
||||||
|
self._draw_invoice_from_label(canvas)
|
||||||
|
self._draw_invoice_from(canvas)
|
||||||
|
self._draw_invoice_to_label(canvas)
|
||||||
|
self._draw_invoice_to(canvas)
|
||||||
|
self._draw_metadata(canvas)
|
||||||
|
self._draw_logo(canvas)
|
||||||
|
self._draw_event(canvas)
|
||||||
canvas.restoreState()
|
canvas.restoreState()
|
||||||
|
|
||||||
def _get_first_page_frames(self, doc):
|
def _get_first_page_frames(self, doc):
|
||||||
@@ -434,6 +476,13 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
|
|||||||
self.stylesheet['Normal']
|
self.stylesheet['Normal']
|
||||||
))
|
))
|
||||||
|
|
||||||
|
if self.invoice.invoice_to_vat_id:
|
||||||
|
story.append(Paragraph(
|
||||||
|
pgettext('invoice', 'Customer VAT ID') + ':<br />' +
|
||||||
|
bleach.clean(self.invoice.invoice_to_vat_id, tags=[]).replace("\n", "<br />\n"),
|
||||||
|
self.stylesheet['Normal']
|
||||||
|
))
|
||||||
|
|
||||||
if self.invoice.invoice_to_beneficiary:
|
if self.invoice.invoice_to_beneficiary:
|
||||||
story.append(Paragraph(
|
story.append(Paragraph(
|
||||||
pgettext('invoice', 'Beneficiary') + ':<br />' +
|
pgettext('invoice', 'Beneficiary') + ':<br />' +
|
||||||
@@ -554,6 +603,7 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
|
|||||||
colwidths = [a * doc.width for a in (.25, .15, .15, .15, .3)]
|
colwidths = [a * doc.width for a in (.25, .15, .15, .15, .3)]
|
||||||
table = Table(tdata, colWidths=colwidths, repeatRows=2, hAlign=TA_LEFT)
|
table = Table(tdata, colWidths=colwidths, repeatRows=2, hAlign=TA_LEFT)
|
||||||
table.setStyle(TableStyle(tstyledata))
|
table.setStyle(TableStyle(tstyledata))
|
||||||
|
story.append(Spacer(5 * mm, 5 * mm))
|
||||||
story.append(KeepTogether([
|
story.append(KeepTogether([
|
||||||
Paragraph(pgettext('invoice', 'Included taxes'), self.stylesheet['FineprintHeading']),
|
Paragraph(pgettext('invoice', 'Included taxes'), self.stylesheet['FineprintHeading']),
|
||||||
table
|
table
|
||||||
@@ -607,6 +657,114 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
|
|||||||
return story
|
return story
|
||||||
|
|
||||||
|
|
||||||
|
class Modern1Renderer(ClassicInvoiceRenderer):
|
||||||
|
identifier = 'modern1'
|
||||||
|
verbose_name = ugettext_lazy('Modern Invoice Renderer (pretix 2.7)')
|
||||||
|
bottom_margin = 16.9 * mm
|
||||||
|
top_margin = 16.9 * mm
|
||||||
|
right_margin = 20 * mm
|
||||||
|
invoice_to_height = 27.3 * mm
|
||||||
|
invoice_to_width = 80 * mm
|
||||||
|
invoice_to_left = 25 * mm
|
||||||
|
invoice_to_top = (40 + 17.7) * mm
|
||||||
|
invoice_from_left = 125 * mm
|
||||||
|
invoice_from_top = 50 * mm
|
||||||
|
invoice_from_width = pagesizes.A4[0] - invoice_from_left - right_margin
|
||||||
|
invoice_from_height = 50 * mm
|
||||||
|
|
||||||
|
logo_width = 75 * mm
|
||||||
|
logo_height = 25 * mm
|
||||||
|
logo_left = pagesizes.A4[0] - logo_width - right_margin
|
||||||
|
logo_top = top_margin
|
||||||
|
logo_anchor = 'e'
|
||||||
|
|
||||||
|
event_left = 25 * mm
|
||||||
|
event_top = top_margin
|
||||||
|
event_width = 80 * mm
|
||||||
|
event_height = 25 * mm
|
||||||
|
|
||||||
|
def _get_stylesheet(self):
|
||||||
|
stylesheet = super()._get_stylesheet()
|
||||||
|
stylesheet.add(ParagraphStyle(name='Sender', fontName=self.font_regular, fontSize=8, leading=10))
|
||||||
|
stylesheet['InvoiceFrom'].alignment = TA_RIGHT
|
||||||
|
return stylesheet
|
||||||
|
|
||||||
|
def _draw_invoice_from(self, canvas):
|
||||||
|
if not self.invoice.invoice_from:
|
||||||
|
return
|
||||||
|
c = self.invoice.address_invoice_from.strip().split('\n')
|
||||||
|
p = Paragraph(' · '.join(c), style=self.stylesheet['Sender'])
|
||||||
|
p.wrapOn(canvas, self.invoice_to_width, 15.7 * mm)
|
||||||
|
p.drawOn(canvas, self.invoice_to_left, self.pagesize[1] - self.invoice_to_top + 2 * mm)
|
||||||
|
super()._draw_invoice_from(canvas)
|
||||||
|
|
||||||
|
def _draw_invoice_to_label(self, canvas):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _draw_invoice_from_label(self, canvas):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _draw_event_label(self, canvas):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _get_first_page_frames(self, doc):
|
||||||
|
footer_length = 3.5 * len(self.invoice.footer_text.split('\n')) * mm
|
||||||
|
return [
|
||||||
|
Frame(doc.leftMargin, doc.bottomMargin, doc.width, doc.height - 95 * mm,
|
||||||
|
leftPadding=0, rightPadding=0, topPadding=0, bottomPadding=footer_length,
|
||||||
|
id='normal')
|
||||||
|
]
|
||||||
|
|
||||||
|
def _draw_metadata(self, canvas):
|
||||||
|
begin_top = 100 * mm
|
||||||
|
|
||||||
|
textobject = canvas.beginText(self.left_margin, self.pagesize[1] - begin_top)
|
||||||
|
textobject.setFont(self.font_regular, 8)
|
||||||
|
textobject.textLine(pgettext('invoice', 'Order code'))
|
||||||
|
textobject.moveCursor(0, 5)
|
||||||
|
textobject.setFont(self.font_regular, 10)
|
||||||
|
textobject.textLine(self.invoice.order.full_code)
|
||||||
|
canvas.drawText(textobject)
|
||||||
|
|
||||||
|
if self.invoice.is_cancellation:
|
||||||
|
textobject = canvas.beginText(self.left_margin + 50 * mm, self.pagesize[1] - begin_top)
|
||||||
|
textobject.setFont(self.font_regular, 8)
|
||||||
|
textobject.textLine(pgettext('invoice', 'Cancellation number'))
|
||||||
|
textobject.moveCursor(0, 5)
|
||||||
|
textobject.setFont(self.font_regular, 10)
|
||||||
|
textobject.textLine(self.invoice.number)
|
||||||
|
canvas.drawText(textobject)
|
||||||
|
|
||||||
|
textobject = canvas.beginText(self.left_margin + 100 * mm, self.pagesize[1] - begin_top)
|
||||||
|
textobject.setFont(self.font_regular, 8)
|
||||||
|
textobject.textLine(pgettext('invoice', 'Original invoice'))
|
||||||
|
textobject.moveCursor(0, 5)
|
||||||
|
textobject.setFont(self.font_regular, 10)
|
||||||
|
textobject.textLine(self.invoice.refers.number)
|
||||||
|
canvas.drawText(textobject)
|
||||||
|
else:
|
||||||
|
textobject = canvas.beginText(self.left_margin + 70 * mm, self.pagesize[1] - begin_top)
|
||||||
|
textobject.textLine(pgettext('invoice', 'Invoice number'))
|
||||||
|
textobject.moveCursor(0, 5)
|
||||||
|
textobject.setFont(self.font_regular, 10)
|
||||||
|
textobject.textLine(self.invoice.number)
|
||||||
|
canvas.drawText(textobject)
|
||||||
|
|
||||||
|
p = Paragraph(date_format(self.invoice.date, "DATE_FORMAT"), style=self.stylesheet['Normal'])
|
||||||
|
w = stringWidth(p.text, p.frags[0].fontName, p.frags[0].fontSize)
|
||||||
|
p.wrapOn(canvas, w, 15 * mm)
|
||||||
|
date_x = self.pagesize[0] - w - self.right_margin
|
||||||
|
p.drawOn(canvas, date_x, self.pagesize[1] - begin_top - 10 - 6)
|
||||||
|
|
||||||
|
textobject = canvas.beginText(date_x, self.pagesize[1] - begin_top)
|
||||||
|
textobject.setFont(self.font_regular, 8)
|
||||||
|
if self.invoice.is_cancellation:
|
||||||
|
textobject.textLine(pgettext('invoice', 'Cancellation date'))
|
||||||
|
else:
|
||||||
|
textobject.textLine(pgettext('invoice', 'Invoice date'))
|
||||||
|
canvas.drawText(textobject)
|
||||||
|
|
||||||
|
|
||||||
@receiver(register_invoice_renderers, dispatch_uid="invoice_renderer_classic")
|
@receiver(register_invoice_renderers, dispatch_uid="invoice_renderer_classic")
|
||||||
def recv_classic(sender, **kwargs):
|
def recv_classic(sender, **kwargs):
|
||||||
return ClassicInvoiceRenderer
|
return [ClassicInvoiceRenderer, Modern1Renderer]
|
||||||
|
|||||||
@@ -117,12 +117,35 @@ class Invoice(models.Model):
|
|||||||
self.invoice_from_name,
|
self.invoice_from_name,
|
||||||
self.invoice_from,
|
self.invoice_from,
|
||||||
(self.invoice_from_zipcode or "") + " " + (self.invoice_from_city or ""),
|
(self.invoice_from_zipcode or "") + " " + (self.invoice_from_city or ""),
|
||||||
str(self.invoice_from_country),
|
self.invoice_from_country.name if self.invoice_from_country else "",
|
||||||
pgettext("invoice", "VAT-ID: %s") % self.invoice_from_vat_id if self.invoice_from_vat_id else "",
|
pgettext("invoice", "VAT-ID: %s") % self.invoice_from_vat_id if self.invoice_from_vat_id else "",
|
||||||
pgettext("invoice", "Tax ID: %s") % self.invoice_from_tax_id if self.invoice_from_tax_id else "",
|
pgettext("invoice", "Tax ID: %s") % self.invoice_from_tax_id if self.invoice_from_tax_id else "",
|
||||||
]
|
]
|
||||||
return '\n'.join([p.strip() for p in parts if p and p.strip()])
|
return '\n'.join([p.strip() for p in parts if p and p.strip()])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def address_invoice_from(self):
|
||||||
|
parts = [
|
||||||
|
self.invoice_from_name,
|
||||||
|
self.invoice_from,
|
||||||
|
(self.invoice_from_zipcode or "") + " " + (self.invoice_from_city or ""),
|
||||||
|
self.invoice_from_country.name if self.invoice_from_country else "",
|
||||||
|
]
|
||||||
|
return '\n'.join([p.strip() for p in parts if p and p.strip()])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def address_invoice_to(self):
|
||||||
|
if self.invoice_to and not self.invoice_to_company and not self.invoice_to_name:
|
||||||
|
return self.invoice_to
|
||||||
|
parts = [
|
||||||
|
self.invoice_to_company,
|
||||||
|
self.invoice_to_name,
|
||||||
|
self.invoice_to_street,
|
||||||
|
(self.invoice_to_zipcode or "") + " " + (self.invoice_to_city or ""),
|
||||||
|
self.invoice_to_country.name if self.invoice_to_country else "",
|
||||||
|
]
|
||||||
|
return '\n'.join([p.strip() for p in parts if p and p.strip()])
|
||||||
|
|
||||||
def _get_numeric_invoice_number(self):
|
def _get_numeric_invoice_number(self):
|
||||||
numeric_invoices = Invoice.objects.filter(
|
numeric_invoices = Invoice.objects.filter(
|
||||||
event__organizer=self.event.organizer,
|
event__organizer=self.event.organizer,
|
||||||
|
|||||||
Reference in New Issue
Block a user