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 collections import defaultdict
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
from itertools import groupby
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
|
|
||||||
import bleach
|
import bleach
|
||||||
@@ -554,31 +555,47 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
|
|||||||
pgettext('invoice', 'Amount'),
|
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')
|
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 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((
|
tdata.append((
|
||||||
Paragraph(
|
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']
|
self.stylesheet['Normal']
|
||||||
),
|
),
|
||||||
"1",
|
str(len(lines)),
|
||||||
localize(line.tax_rate) + " %",
|
localize(tax_rate) + " %",
|
||||||
money_filter(line.net_value, self.invoice.event.currency),
|
money_filter(net_value * len(lines), self.invoice.event.currency),
|
||||||
money_filter(line.gross_value, self.invoice.event.currency),
|
money_filter(gross_value * len(lines), self.invoice.event.currency),
|
||||||
))
|
))
|
||||||
else:
|
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((
|
tdata.append((
|
||||||
Paragraph(
|
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']
|
self.stylesheet['Normal']
|
||||||
),
|
),
|
||||||
"1",
|
str(len(lines)),
|
||||||
money_filter(line.gross_value, self.invoice.event.currency),
|
money_filter(gross_value * len(lines), self.invoice.event.currency),
|
||||||
))
|
))
|
||||||
taxvalue_map[line.tax_rate, line.tax_name] += line.tax_value
|
taxvalue_map[tax_rate, tax_name] += (gross_value - net_value) * len(lines)
|
||||||
grossvalue_map[line.tax_rate, line.tax_name] += line.gross_value
|
grossvalue_map[tax_rate, tax_name] += gross_value * len(lines)
|
||||||
total += line.gross_value
|
total += gross_value * len(lines)
|
||||||
|
|
||||||
if has_taxes:
|
if has_taxes:
|
||||||
tdata.append([
|
tdata.append([
|
||||||
|
|||||||
@@ -452,17 +452,19 @@ def build_preview_invoice_pdf(event):
|
|||||||
|
|
||||||
if event.tax_rules.exists():
|
if event.tax_rules.exists():
|
||||||
for i, tr in enumerate(event.tax_rules.all()):
|
for i, tr in enumerate(event.tax_rules.all()):
|
||||||
tax = tr.tax(Decimal('100.00'), base_price_is='gross')
|
for j in range(150):
|
||||||
InvoiceLine.objects.create(
|
tax = tr.tax(Decimal('100.00'), base_price_is='gross')
|
||||||
invoice=invoice, description=_("Sample product {}").format(i + 1),
|
InvoiceLine.objects.create(
|
||||||
gross_value=tax.gross, tax_value=tax.tax,
|
invoice=invoice, description=_("Sample product {}").format(i + 1),
|
||||||
tax_rate=tax.rate
|
gross_value=tax.gross, tax_value=tax.tax,
|
||||||
)
|
tax_rate=tax.rate
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
InvoiceLine.objects.create(
|
for i in range(150):
|
||||||
invoice=invoice, description=_("Sample product A"),
|
InvoiceLine.objects.create(
|
||||||
gross_value=100, tax_value=0, tax_rate=0
|
invoice=invoice, description=_("Sample product A"),
|
||||||
)
|
gross_value=100, tax_value=0, tax_rate=0
|
||||||
|
)
|
||||||
|
|
||||||
return event.invoice_renderer.generate(invoice)
|
return event.invoice_renderer.generate(invoice)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user