forked from CGM_Public/pretix_original
Group identical lines on invoice PDF (#2918)
This commit is contained in:
@@ -23,6 +23,7 @@ import logging
|
||||
from collections import defaultdict
|
||||
from decimal import Decimal
|
||||
from io import BytesIO
|
||||
from itertools import groupby
|
||||
from typing import Tuple
|
||||
|
||||
import bleach
|
||||
@@ -554,31 +555,47 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
|
||||
pgettext('invoice', 'Amount'),
|
||||
)]
|
||||
|
||||
def _group_key(line):
|
||||
return (line.description, line.tax_rate, line.tax_name, line.net_value, line.gross_value, line.subevent_id,
|
||||
line.event_date_from, line.event_date_to)
|
||||
|
||||
total = Decimal('0.00')
|
||||
for line in self.invoice.lines.all():
|
||||
for (description, tax_rate, tax_name, net_value, gross_value, *ignored), lines in groupby(self.invoice.lines.all(), key=_group_key):
|
||||
lines = list(lines)
|
||||
if has_taxes:
|
||||
if len(lines) > 1:
|
||||
single_price_line = pgettext('invoice', 'Single price: {net_price} net / {gross_price} gross').format(
|
||||
net_price=money_filter(net_value, self.invoice.event.currency),
|
||||
gross_price=money_filter(gross_value, self.invoice.event.currency),
|
||||
)
|
||||
description = description + "\n" + single_price_line
|
||||
tdata.append((
|
||||
Paragraph(
|
||||
bleach.clean(line.description, tags=['br']).strip().replace('<br>', '<br/>').replace('\n', '<br />\n'),
|
||||
bleach.clean(description, tags=['br']).strip().replace('<br>', '<br/>').replace('\n', '<br />\n'),
|
||||
self.stylesheet['Normal']
|
||||
),
|
||||
"1",
|
||||
localize(line.tax_rate) + " %",
|
||||
money_filter(line.net_value, self.invoice.event.currency),
|
||||
money_filter(line.gross_value, self.invoice.event.currency),
|
||||
str(len(lines)),
|
||||
localize(tax_rate) + " %",
|
||||
money_filter(net_value * len(lines), self.invoice.event.currency),
|
||||
money_filter(gross_value * len(lines), self.invoice.event.currency),
|
||||
))
|
||||
else:
|
||||
if len(lines) > 1:
|
||||
single_price_line = pgettext('invoice', 'Single price: {price}').format(
|
||||
price=money_filter(gross_value, self.invoice.event.currency),
|
||||
)
|
||||
description = description + "\n" + single_price_line
|
||||
tdata.append((
|
||||
Paragraph(
|
||||
bleach.clean(line.description, tags=['br']).strip().replace('<br>', '<br/>').replace('\n', '<br />\n'),
|
||||
bleach.clean(description, tags=['br']).strip().replace('<br>', '<br/>').replace('\n', '<br />\n'),
|
||||
self.stylesheet['Normal']
|
||||
),
|
||||
"1",
|
||||
money_filter(line.gross_value, self.invoice.event.currency),
|
||||
str(len(lines)),
|
||||
money_filter(gross_value * len(lines), self.invoice.event.currency),
|
||||
))
|
||||
taxvalue_map[line.tax_rate, line.tax_name] += line.tax_value
|
||||
grossvalue_map[line.tax_rate, line.tax_name] += line.gross_value
|
||||
total += line.gross_value
|
||||
taxvalue_map[tax_rate, tax_name] += (gross_value - net_value) * len(lines)
|
||||
grossvalue_map[tax_rate, tax_name] += gross_value * len(lines)
|
||||
total += gross_value * len(lines)
|
||||
|
||||
if has_taxes:
|
||||
tdata.append([
|
||||
|
||||
@@ -452,17 +452,19 @@ def build_preview_invoice_pdf(event):
|
||||
|
||||
if event.tax_rules.exists():
|
||||
for i, tr in enumerate(event.tax_rules.all()):
|
||||
tax = tr.tax(Decimal('100.00'), base_price_is='gross')
|
||||
InvoiceLine.objects.create(
|
||||
invoice=invoice, description=_("Sample product {}").format(i + 1),
|
||||
gross_value=tax.gross, tax_value=tax.tax,
|
||||
tax_rate=tax.rate
|
||||
)
|
||||
for j in range(150):
|
||||
tax = tr.tax(Decimal('100.00'), base_price_is='gross')
|
||||
InvoiceLine.objects.create(
|
||||
invoice=invoice, description=_("Sample product {}").format(i + 1),
|
||||
gross_value=tax.gross, tax_value=tax.tax,
|
||||
tax_rate=tax.rate
|
||||
)
|
||||
else:
|
||||
InvoiceLine.objects.create(
|
||||
invoice=invoice, description=_("Sample product A"),
|
||||
gross_value=100, tax_value=0, tax_rate=0
|
||||
)
|
||||
for i in range(150):
|
||||
InvoiceLine.objects.create(
|
||||
invoice=invoice, description=_("Sample product A"),
|
||||
gross_value=100, tax_value=0, tax_rate=0
|
||||
)
|
||||
|
||||
return event.invoice_renderer.generate(invoice)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user