Show minimal check-in status in order export (Z#23154920) (#4223)

* Show minimal check-in status in order export (Z#23154920)

* Update src/pretix/helpers/database.py

Co-authored-by: Mira <weller@rami.io>

* Review note

---------

Co-authored-by: Mira <weller@rami.io>
This commit is contained in:
Raphael Michel
2024-06-24 17:34:10 +02:00
committed by GitHub
parent 70b48fdd4b
commit 4f9297e7d8
2 changed files with 31 additions and 13 deletions

View File

@@ -37,6 +37,7 @@ from decimal import Decimal
from zoneinfo import ZoneInfo from zoneinfo import ZoneInfo
from django import forms from django import forms
from django.conf import settings
from django.db.models import ( from django.db.models import (
Case, CharField, Count, DateTimeField, F, IntegerField, Max, Min, OuterRef, Case, CharField, Count, DateTimeField, F, IntegerField, Max, Min, OuterRef,
Q, Subquery, Sum, When, Q, Subquery, Sum, When,
@@ -54,7 +55,7 @@ from openpyxl.comments import Comment
from openpyxl.styles import Font, PatternFill from openpyxl.styles import Font, PatternFill
from pretix.base.models import ( from pretix.base.models import (
GiftCard, GiftCardTransaction, Invoice, InvoiceAddress, Order, Checkin, GiftCard, GiftCardTransaction, Invoice, InvoiceAddress, Order,
OrderPosition, Question, OrderPosition, Question,
) )
from pretix.base.models.orders import ( from pretix.base.models.orders import (
@@ -541,6 +542,22 @@ class OrderListExporter(MultiSheetListExporter):
).order_by() ).order_by()
qs = base_qs.annotate( qs = base_qs.annotate(
payment_providers=Subquery(p_providers, output_field=CharField()), payment_providers=Subquery(p_providers, output_field=CharField()),
checked_in_lists=Subquery(
Checkin.objects.filter(
successful=True,
type=Checkin.TYPE_ENTRY,
position=OuterRef("pk"),
).order_by().values("position").annotate(
c=GroupConcat(
"list__name",
# These appear not to work properly on SQLite. Well, we don't support SQLite outside testing
# anyways.
ordered='sqlite' not in settings.DATABASES['default']['ENGINE'],
distinct='sqlite' not in settings.DATABASES['default']['ENGINE'],
delimiter=", "
)
).values("c")
),
).select_related( ).select_related(
'order', 'order__invoice_address', 'order__customer', 'item', 'variation', 'order', 'order__invoice_address', 'order__customer', 'item', 'variation',
'voucher', 'tax_rule' 'voucher', 'tax_rule'
@@ -638,6 +655,7 @@ class OrderListExporter(MultiSheetListExporter):
_('Sales channel'), _('Order locale'), _('Sales channel'), _('Order locale'),
_('E-mail address verified'), _('E-mail address verified'),
_('External customer ID'), _('External customer ID'),
_('Check-in lists'),
_('Payment providers'), _('Payment providers'),
] ]
@@ -776,6 +794,7 @@ class OrderListExporter(MultiSheetListExporter):
_('Yes') if order.email_known_to_work else _('No'), _('Yes') if order.email_known_to_work else _('No'),
str(order.customer.external_identifier) if order.customer and order.customer.external_identifier else '', str(order.customer.external_identifier) if order.customer and order.customer.external_identifier else '',
] ]
row.append(op.checked_in_lists or "")
row.append(', '.join([ row.append(', '.join([
str(self.providers.get(p, p)) for p in sorted(set((op.payment_providers or '').split(','))) str(self.providers.get(p, p)) for p in sorted(set((op.payment_providers or '').split(',')))
if p and p != 'free' if p and p != 'free'

View File

@@ -64,7 +64,8 @@ def casual_reads():
class GroupConcat(Aggregate): class GroupConcat(Aggregate):
function = 'group_concat' function = 'group_concat'
template = '%(function)s(%(field)s, "%(separator)s")' template = '%(function)s(%(distinct)s%(field)s, "%(separator)s")'
allow_distinct = True
def __init__(self, *expressions, ordered=False, **extra): def __init__(self, *expressions, ordered=False, **extra):
self.ordered = ordered self.ordered = ordered
@@ -73,19 +74,17 @@ class GroupConcat(Aggregate):
extra.update({'separator': ','}) extra.update({'separator': ','})
super().__init__(*expressions, **extra) super().__init__(*expressions, **extra)
def as_postgresql(self, compiler, connection): def as_postgresql(self, compiler, connection, **extra_context):
if self.ordered: if self.ordered:
return super().as_sql( template = "%(function)s(%(distinct)s%(field)s::text, '%(separator)s' ORDER BY %(field)s::text ASC)"
compiler, connection,
function='string_agg',
template="%(function)s(%(field)s::text, '%(separator)s' ORDER BY %(field)s ASC)",
)
else: else:
return super().as_sql( template = "%(function)s(%(distinct)s%(field)s::text, '%(separator)s')"
compiler, connection, return super().as_sql(
function='string_agg', compiler, connection,
template="%(function)s(%(field)s::text, '%(separator)s')", function='string_agg',
) template=template,
**extra_context,
)
class ReplicaRouter: class ReplicaRouter: