mirror of
https://github.com/pretix/pretix.git
synced 2026-05-08 15:44:02 +00:00
Tax list report
This commit is contained in:
@@ -578,7 +578,8 @@ class ExportView(EventPermissionRequiredMixin, TemplateView):
|
|||||||
for receiver, response in responses:
|
for receiver, response in responses:
|
||||||
ex = response(self.request.event)
|
ex = response(self.request.event)
|
||||||
ex.form = ExporterForm(
|
ex.form = ExporterForm(
|
||||||
data=(self.request.POST if self.request.method == 'POST' else None)
|
data=(self.request.POST if self.request.method == 'POST' else None),
|
||||||
|
prefix=ex.identifier
|
||||||
)
|
)
|
||||||
ex.form.fields = ex.export_form_fields
|
ex.form.fields = ex.export_form_fields
|
||||||
exporters.append(ex)
|
exporters.append(ex)
|
||||||
|
|||||||
@@ -1,11 +1,17 @@
|
|||||||
import tempfile
|
import tempfile
|
||||||
|
from collections import OrderedDict, defaultdict
|
||||||
|
from decimal import Decimal
|
||||||
|
|
||||||
|
from django import forms
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.staticfiles import finders
|
from django.contrib.staticfiles import finders
|
||||||
|
from django.db.models import Sum
|
||||||
|
from django.utils.formats import date_format
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
from pretix.base.exporter import BaseExporter
|
from pretix.base.exporter import BaseExporter
|
||||||
|
from pretix.base.models import Order, OrderPosition
|
||||||
from pretix.base.services.stats import order_overview
|
from pretix.base.services.stats import order_overview
|
||||||
|
|
||||||
|
|
||||||
@@ -28,6 +34,7 @@ class Report(BaseExporter):
|
|||||||
return pagesizes.portrait(pagesizes.A4)
|
return pagesizes.portrait(pagesizes.A4)
|
||||||
|
|
||||||
def render(self, form_data):
|
def render(self, form_data):
|
||||||
|
self.form_data = form_data
|
||||||
return 'report-%s.pdf' % self.event.slug, 'application/pdf', self.create()
|
return 'report-%s.pdf' % self.event.slug, 'application/pdf', self.create()
|
||||||
|
|
||||||
def get_filename(self):
|
def get_filename(self):
|
||||||
@@ -208,3 +215,144 @@ class OverviewReport(Report):
|
|||||||
table.setStyle(TableStyle(tstyledata))
|
table.setStyle(TableStyle(tstyledata))
|
||||||
story.append(table)
|
story.append(table)
|
||||||
return story
|
return story
|
||||||
|
|
||||||
|
|
||||||
|
class OrderTaxListReport(Report):
|
||||||
|
name = "ordertaxlist"
|
||||||
|
identifier = 'ordertaxes'
|
||||||
|
verbose_name = _('List of orders with taxes (PDF)')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def export_form_fields(self):
|
||||||
|
return OrderedDict(
|
||||||
|
[
|
||||||
|
('status',
|
||||||
|
forms.MultipleChoiceField(
|
||||||
|
label=_('Filter by status'),
|
||||||
|
initial=[Order.STATUS_PAID],
|
||||||
|
choices=Order.STATUS_CHOICE,
|
||||||
|
widget=forms.CheckboxSelectMultiple,
|
||||||
|
required=False
|
||||||
|
)),
|
||||||
|
('sort',
|
||||||
|
forms.ChoiceField(
|
||||||
|
label=_('Sort by'),
|
||||||
|
initial='datetime',
|
||||||
|
choices=(
|
||||||
|
('datetime', _('Order date')),
|
||||||
|
('payment_date', _('Payment date')),
|
||||||
|
),
|
||||||
|
widget=forms.RadioSelect,
|
||||||
|
required=False
|
||||||
|
)),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def pagesize(self):
|
||||||
|
from reportlab.lib import pagesizes
|
||||||
|
|
||||||
|
return pagesizes.landscape(pagesizes.A4)
|
||||||
|
|
||||||
|
def get_story(self, doc):
|
||||||
|
from reportlab.platypus import Paragraph, Spacer, TableStyle, Table
|
||||||
|
from reportlab.lib.units import mm
|
||||||
|
|
||||||
|
headlinestyle = self.get_style()
|
||||||
|
headlinestyle.fontSize = 15
|
||||||
|
headlinestyle.fontName = 'OpenSansBd'
|
||||||
|
|
||||||
|
tax_rates = set(
|
||||||
|
self.event.orders.exclude(payment_fee=0).values_list('payment_fee_tax_rate', flat=True)
|
||||||
|
.filter(status__in=self.form_data['status'])
|
||||||
|
.distinct().order_by()
|
||||||
|
)
|
||||||
|
tax_rates |= set(
|
||||||
|
a for a
|
||||||
|
in OrderPosition.objects.filter(order__event=self.event)
|
||||||
|
.filter(order__status__in=self.form_data['status'])
|
||||||
|
.values_list('tax_rate', flat=True).distinct().order_by()
|
||||||
|
)
|
||||||
|
tax_rates = sorted(tax_rates)
|
||||||
|
|
||||||
|
# Cols: Order ID | Order date | Status | Payment Date | Total | {gross tax} for t in taxes
|
||||||
|
colwidths = [a * doc.width for a in [0.12, 0.1, 0.10, 0.12, 0.08]]
|
||||||
|
if tax_rates:
|
||||||
|
colwidths += [0.48 / (len(tax_rates) * 2) * doc.width] * (len(tax_rates) * 2)
|
||||||
|
|
||||||
|
tstyledata = [
|
||||||
|
# Alignment
|
||||||
|
('ALIGN', (0, 0), (3, 0), 'LEFT'), # Headlines
|
||||||
|
('ALIGN', (4, 0), (-1, 0), 'CENTER'), # Headlines
|
||||||
|
('ALIGN', (4, 1), (-1, -1), 'RIGHT'), # Money
|
||||||
|
('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
|
||||||
|
|
||||||
|
# Fonts
|
||||||
|
('FONTNAME', (0, 0), (-1, 0), 'OpenSansBd'), # Headlines
|
||||||
|
('FONTNAME', (0, -1), (-1, -1), 'OpenSansBd'), # Sums
|
||||||
|
]
|
||||||
|
for i, rate in enumerate(tax_rates):
|
||||||
|
tstyledata.append(('SPAN', (5 + 2 * i, 0), (6 + 2 * i, 0)))
|
||||||
|
|
||||||
|
story = [
|
||||||
|
Paragraph(_('Orders by tax rate ({currency})').format(currency=self.event.currency), headlinestyle),
|
||||||
|
Spacer(1, 5 * mm)
|
||||||
|
]
|
||||||
|
tdata = [
|
||||||
|
[
|
||||||
|
_('Order code'), _('Order date'), _('Status'), _('Payment date'), _('Order total'),
|
||||||
|
] + sum(([str(t) + ' %', ''] for t in tax_rates), []),
|
||||||
|
[
|
||||||
|
'', '', '', '', ''
|
||||||
|
] + sum(([_('Gross'), 'Tax'] for t in tax_rates), []),
|
||||||
|
]
|
||||||
|
|
||||||
|
qs = OrderPosition.objects.filter(
|
||||||
|
order__status__in=self.form_data['status'],
|
||||||
|
order__event=self.event,
|
||||||
|
).values(
|
||||||
|
'order__code', 'order__datetime', 'order__payment_date', 'order__total', 'order__payment_fee',
|
||||||
|
'order__payment_fee_tax_rate', 'order__payment_fee_tax_value', 'tax_rate', 'order__status'
|
||||||
|
).annotate(prices=Sum('price'), tax_values=Sum('tax_value')).order_by(
|
||||||
|
'order__datetime' if self.form_data['sort'] == 'datetime' else 'order__payment_date',
|
||||||
|
'order__datetime',
|
||||||
|
'order__code'
|
||||||
|
)
|
||||||
|
last_order_code = None
|
||||||
|
tax_sums = defaultdict(Decimal)
|
||||||
|
price_sums = defaultdict(Decimal)
|
||||||
|
status_labels = dict(Order.STATUS_CHOICE)
|
||||||
|
for op in qs:
|
||||||
|
if op['order__code'] != last_order_code:
|
||||||
|
tdata.append(
|
||||||
|
[
|
||||||
|
op['order__code'],
|
||||||
|
date_format(op['order__datetime'], "SHORT_DATE_FORMAT"),
|
||||||
|
status_labels[op['order__status']],
|
||||||
|
date_format(op['order__payment_date'], "SHORT_DATE_FORMAT") if op['order__payment_date'] else '',
|
||||||
|
str(op['order__total'])
|
||||||
|
] + sum((['', ''] for t in tax_rates), []),
|
||||||
|
)
|
||||||
|
last_order_code = op['order__code']
|
||||||
|
if op['order__payment_fee_tax_value']:
|
||||||
|
tdata[-1][5 + 2 * tax_rates.index(op['order__payment_fee_tax_rate'])] = str(op['order__payment_fee'])
|
||||||
|
tdata[-1][6 + 2 * tax_rates.index(op['order__payment_fee_tax_rate'])] = str(op['order__payment_fee_tax_value'])
|
||||||
|
tax_sums[op['order__payment_fee_tax_rate']] += op['order__payment_fee_tax_value']
|
||||||
|
price_sums[op['order__payment_fee_tax_rate']] += op['order__payment_fee']
|
||||||
|
|
||||||
|
i = tax_rates.index(op['tax_rate'])
|
||||||
|
tdata[-1][5 + 2 * i] = str(Decimal(tdata[-1][5 + 2 * i] or '0') + op['prices'])
|
||||||
|
tdata[-1][6 + 2 * i] = str(Decimal(tdata[-1][6 + 2 * i] or '0') + op['tax_values'])
|
||||||
|
tax_sums[op['tax_rate']] += op['tax_values']
|
||||||
|
price_sums[op['tax_rate']] += op['prices']
|
||||||
|
|
||||||
|
tdata.append(
|
||||||
|
[
|
||||||
|
_('Total'), '', '', '', ''
|
||||||
|
] + sum(([str(price_sums.get(t)), str(tax_sums.get(t))] for t in tax_rates), []),
|
||||||
|
)
|
||||||
|
|
||||||
|
table = Table(tdata, colWidths=colwidths, repeatRows=2)
|
||||||
|
table.setStyle(TableStyle(tstyledata))
|
||||||
|
story.append(table)
|
||||||
|
return story
|
||||||
|
|||||||
@@ -7,3 +7,9 @@ from pretix.base.signals import register_data_exporters
|
|||||||
def register_report_pdf(sender, **kwargs):
|
def register_report_pdf(sender, **kwargs):
|
||||||
from .exporters import OverviewReport
|
from .exporters import OverviewReport
|
||||||
return OverviewReport
|
return OverviewReport
|
||||||
|
|
||||||
|
|
||||||
|
@receiver(register_data_exporters, dispatch_uid="export_overview_report_ordertaxlist")
|
||||||
|
def register_report_ordertaxlist(sender, **kwargs):
|
||||||
|
from .exporters import OrderTaxListReport
|
||||||
|
return OrderTaxListReport
|
||||||
|
|||||||
Reference in New Issue
Block a user