From 434b6e4729b151c636358a24145ac83507964d3d Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Fri, 1 Feb 2019 17:20:00 +0100 Subject: [PATCH] Offer multi-sheet order report --- src/pretix/base/exporters/orderlist.py | 195 ++++++++++++++++++++++++- 1 file changed, 193 insertions(+), 2 deletions(-) diff --git a/src/pretix/base/exporters/orderlist.py b/src/pretix/base/exporters/orderlist.py index 6b0354a9b..22d8bf5b3 100644 --- a/src/pretix/base/exporters/orderlist.py +++ b/src/pretix/base/exporters/orderlist.py @@ -18,10 +18,18 @@ from ..exporter import ListExporter, MultiSheetListExporter from ..signals import register_data_exporters -class OrderListExporter(ListExporter): +class OrderListExporter(MultiSheetListExporter): identifier = 'orderlist' verbose_name = ugettext_lazy('Order data') + @property + def sheets(self): + return ( + ('orders', _('Orders')), + ('positions', _('Order positions')), + ('fees', _('Order fees')), + ) + @property def additional_form_fields(self): return OrderedDict( @@ -51,7 +59,15 @@ class OrderListExporter(ListExporter): tax_rates = sorted(tax_rates) return tax_rates - def iterate_list(self, form_data: dict): + def iterate_sheet(self, form_data, sheet): + if sheet == 'orders': + return self.iterate_orders(form_data) + elif sheet == 'positions': + return self.iterate_positions(form_data) + elif sheet == 'fees': + return self.iterate_fees(form_data) + + def iterate_orders(self, form_data: dict): tz = pytz.timezone(self.event.settings.timezone) p_date = OrderPayment.objects.filter( @@ -162,6 +178,181 @@ class OrderListExporter(ListExporter): row.append(', '.join([i.number for i in order.invoices.all()])) yield row + def iterate_fees(self, form_data: dict): + tz = pytz.timezone(self.event.settings.timezone) + + qs = OrderFee.objects.filter( + order__event=self.event, + ).select_related('order', 'order__invoice_address', 'tax_rule') + if form_data['paid_only']: + qs = qs.filter(order__status=Order.STATUS_PAID) + + headers = [ + _('Order code'), + _('Status'), + _('Email'), + _('Order date'), + _('Fee type'), + _('Description'), + _('Price'), + _('Tax rate'), + _('Tax rule'), + _('Tax value'), + _('Company'), + _('Invoice address name'), + ] + name_scheme = PERSON_NAME_SCHEMES[self.event.settings.name_scheme] + if len(name_scheme['fields']) > 1: + for k, label, w in name_scheme['fields']: + headers.append(_('Invoice address name') + ': ' + str(label)) + headers += [ + _('Address'), _('ZIP code'), _('City'), _('Country'), _('VAT ID'), + ] + + yield headers + + for op in qs.order_by('order__datetime'): + order = op.order + row = [ + order.code, + order.get_status_display(), + order.email, + order.datetime.astimezone(tz).strftime('%Y-%m-%d'), + op.get_fee_type_display(), + op.description, + op.value, + op.tax_rate, + str(op.tax_rule) if op.tax_rule else '', + op.tax_value, + ] + try: + row += [ + order.invoice_address.company, + order.invoice_address.name, + ] + if len(name_scheme['fields']) > 1: + for k, label, w in name_scheme['fields']: + row.append( + order.invoice_address.name_parts.get(k, '') + ) + row += [ + order.invoice_address.street, + order.invoice_address.zipcode, + order.invoice_address.city, + order.invoice_address.country if order.invoice_address.country else + order.invoice_address.country_old, + order.invoice_address.vat_id, + ] + except InvoiceAddress.DoesNotExist: + row += [''] * (7 + (len(name_scheme['fields']) if len(name_scheme['fields']) > 1 else 0)) + yield row + + def iterate_positions(self, form_data: dict): + tz = pytz.timezone(self.event.settings.timezone) + + qs = OrderPosition.objects.filter( + order__event=self.event, + ).select_related( + 'order', 'order__invoice_address', 'item', 'variation', + 'voucher', 'tax_rule' + ).prefetch_related( + 'answers', 'answers__question' + ) + if form_data['paid_only']: + qs = qs.filter(order__status=Order.STATUS_PAID) + + headers = [ + _('Order code'), + _('Position ID'), + _('Status'), + _('Email'), + _('Order date'), + _('Product'), + _('Variation'), + _('Price'), + _('Tax rate'), + _('Tax rule'), + _('Tax value'), + _('Attendee name'), + ] + name_scheme = PERSON_NAME_SCHEMES[self.event.settings.name_scheme] + if len(name_scheme['fields']) > 1: + for k, label, w in name_scheme['fields']: + headers.append(_('Attendee name') + ': ' + str(label)) + headers += [ + _('Attendee email'), + _('Voucher'), + _('Pseudonymization ID'), + ] + questions = list(self.event.questions.all()) + for q in questions: + headers.append(str(q.question)) + headers += [ + _('Company'), + _('Invoice address name'), + ] + if len(name_scheme['fields']) > 1: + for k, label, w in name_scheme['fields']: + headers.append(_('Invoice address name') + ': ' + str(label)) + headers += [ + _('Address'), _('ZIP code'), _('City'), _('Country'), _('VAT ID'), + ] + + yield headers + + for op in qs.order_by('order__datetime', 'positionid'): + order = op.order + row = [ + order.code, + op.positionid, + order.get_status_display(), + order.email, + order.datetime.astimezone(tz).strftime('%Y-%m-%d'), + str(op.item), + str(op.variation) if op.variation else '', + op.price, + op.tax_rate, + str(op.tax_rule) if op.tax_rule else '', + op.tax_value, + op.attendee_name, + ] + if len(name_scheme['fields']) > 1: + for k, label, w in name_scheme['fields']: + row.append( + op.attendee_name_parts.get(k, '') + ) + row += [ + op.attendee_email, + op.voucher.code if op.voucher else '', + op.pseudonymization_id, + ] + acache = {} + for a in op.answers.all(): + acache[a.question_id] = str(a) + for q in questions: + row.append(acache.get(q.pk, '')) + try: + row += [ + order.invoice_address.company, + order.invoice_address.name, + ] + if len(name_scheme['fields']) > 1: + for k, label, w in name_scheme['fields']: + row.append( + order.invoice_address.name_parts.get(k, '') + ) + row += [ + order.invoice_address.street, + order.invoice_address.zipcode, + order.invoice_address.city, + order.invoice_address.country if order.invoice_address.country else + order.invoice_address.country_old, + order.invoice_address.vat_id, + ] + except InvoiceAddress.DoesNotExist: + row += [''] * (7 + (len(name_scheme['fields']) if len(name_scheme['fields']) > 1 else 0)) + yield row + def get_filename(self): return '{}_orders'.format(self.event.slug)