Skip to content

Commit 67d2ac5

Browse files
Export orders with Wikimedia username (#1332)
* Export orders with Wikimedia username * Avoid logic of finding column index to insert --------- Co-authored-by: Mario Behling <[email protected]>
1 parent ab3731d commit 67d2ac5

File tree

5 files changed

+53
-11
lines changed

5 files changed

+53
-11
lines changed

app/eventyay/base/configurations/default_setting.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,15 @@ def primary_font_kwargs():
197197
help_text=_('Require attendees to enter their primary email address twice to help prevent errors.'),
198198
),
199199
},
200+
'include_wikimedia_username': {
201+
'default': 'False',
202+
'type': bool,
203+
'form_class': forms.BooleanField,
204+
'serializer_class': serializers.BooleanField,
205+
'form_kwargs': dict(
206+
label=_('Add the Wikimedia ID for users authenticated via Wikimedia'),
207+
),
208+
},
200209
'order_phone_asked': {
201210
'default': 'False',
202211
'type': bool,

app/eventyay/base/exporters/orderlist.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
Order,
3535
OrderPosition,
3636
Question,
37+
User,
3738
)
3839
from eventyay.base.models.orders import OrderFee, OrderPayment, OrderRefund
3940
from eventyay.base.services.quotas import QuotaAvailability
@@ -277,13 +278,20 @@ def iterate_orders(self, form_data: dict):
277278
.annotate(k=Count('id'))
278279
.values('k')
279280
)
281+
282+
# Always load wikimedia_username (lightweight data)
283+
wikimedia_query = User.objects.filter(
284+
email=OuterRef('email')
285+
).values('wikimedia_username')[:1]
286+
280287
qs = (
281288
Order.objects.filter(event__in=self.events)
282289
.annotate(
283290
payment_date=Subquery(p_date, output_field=DateTimeField()),
284291
payment_providers=Subquery(p_providers, output_field=CharField()),
285292
invoice_numbers=Subquery(i_numbers, output_field=CharField()),
286293
pcnt=Subquery(s, output_field=IntegerField()),
294+
wikimedia_username=Subquery(wikimedia_query, output_field=CharField()),
287295
)
288296
.select_related('invoice_address')
289297
)
@@ -294,18 +302,32 @@ def iterate_orders(self, form_data: dict):
294302
qs = qs.filter(status=Order.STATUS_PAID)
295303
tax_rates = self._get_all_tax_rates(qs)
296304

305+
# Check if we need to include wikimedia_username in the export
306+
should_include_wikimedia = any(
307+
self.event_object_cache[event_id].settings.get('include_wikimedia_username', False)
308+
for event_id in self.event_object_cache.keys()
309+
)
310+
297311
headers = [
298312
_('Event slug'),
299313
_('Order code'),
300314
_('Order total'),
301315
_('Status'),
302316
_('Email'),
317+
]
318+
319+
# Add wikimedia_username header if setting is enabled
320+
if should_include_wikimedia:
321+
headers.append(_('Wikimedia username'))
322+
323+
headers += [
303324
_('Phone number'),
304325
_('Order date'),
305326
_('Order time'),
306327
_('Company'),
307328
_('Name'),
308329
]
330+
309331
name_scheme = PERSON_NAME_SCHEMES[self.event.settings.name_scheme] if not self.is_multievent else None
310332
if name_scheme and len(name_scheme['fields']) > 1:
311333
for k, label, w in name_scheme['fields']:
@@ -394,10 +416,19 @@ def iterate_orders(self, form_data: dict):
394416
order.total,
395417
order.get_status_display(),
396418
order.email,
419+
]
420+
421+
# Add wikimedia_username if setting is enabled (insert before phone number)
422+
if should_include_wikimedia:
423+
wikimedia_username = getattr(order, 'wikimedia_username', '') or ''
424+
row.append(wikimedia_username)
425+
426+
row += [
397427
str(order.phone) if order.phone else '',
398428
order.datetime.astimezone(tz).strftime('%Y-%m-%d'),
399429
order.datetime.astimezone(tz).strftime('%H:%M:%S %Z'),
400430
]
431+
401432
try:
402433
row += [
403434
order.invoice_address.company,

app/eventyay/control/forms/event.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from urllib.parse import urlencode, urlparse
1+
from urllib.parse import urlencode
22

33
from django import forms
44
from django.conf import settings
@@ -7,9 +7,9 @@
77
from django.db.models import Q
88
from django.forms import CheckboxSelectMultiple, formset_factory
99
from django.urls import reverse
10+
from django.utils.crypto import get_random_string
1011
from django.utils.html import escape
1112
from django.utils.safestring import mark_safe
12-
from django.utils.crypto import get_random_string
1313
from django.utils.timezone import get_current_timezone_name
1414
from django.utils.translation import gettext, pgettext_lazy
1515
from django.utils.translation import gettext_lazy as _
@@ -78,7 +78,7 @@ def __init__(self, *args, **kwargs):
7878
# Make organizer required only if more than one exists
7979
organizer_count = qs.count()
8080
is_required = organizer_count > 1
81-
81+
8282
self.fields['organizer'] = forms.ModelChoiceField(
8383
label=_('Organizer'),
8484
queryset=qs,
@@ -176,11 +176,11 @@ def __init__(self, *args, **kwargs):
176176
self.fields['location'].widget.attrs['rows'] = '3'
177177
self.fields['location'].widget.attrs['placeholder'] = _('Sample Conference Center\nHeidelberg, Germany')
178178
self.fields['slug'].widget.prefix = build_absolute_uri(self.organizer, 'presale:organizer.index')
179-
179+
180180
# Generate a unique slug if none provided
181181
if not self.initial.get('slug'):
182182
charset = list('abcdefghjklmnpqrstuvwxyz3789')
183-
183+
184184
# Try different lengths until we find a unique slug
185185
length = 6
186186
counter = 0
@@ -192,11 +192,11 @@ def __init__(self, *args, **kwargs):
192192
# Fallback: add counter to ensure uniqueness
193193
candidate = f'{get_random_string(length=4, allowed_chars=charset)}{counter}'
194194
counter += 1
195-
195+
196196
if not self.organizer.events.filter(slug__iexact=candidate).exists():
197197
self.initial['slug'] = candidate
198198
break
199-
199+
200200
if self.has_subevents:
201201
del self.fields['presale_start']
202202
del self.fields['presale_end']
@@ -549,6 +549,7 @@ class EventSettingsForm(SettingsForm):
549549
'banner_text',
550550
'banner_text_bottom',
551551
'order_email_asked_twice',
552+
'include_wikimedia_username',
552553
'allow_modifications',
553554
'last_order_modification_date',
554555
'allow_modifications_after_checkin',

app/eventyay/control/templates/pretixcontrol/event/settings.html

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ <h4>{% trans "Customer data (once per order)" %}</h4>
6262
</div>
6363
</div>
6464
{% bootstrap_field sform.order_email_asked_twice layout="control" %}
65+
{% bootstrap_field sform.include_wikimedia_username layout="control" %}
6566
{% bootstrap_field sform.order_phone_asked_required layout="control" %}
6667
<div class="form-group">
6768
<label class="control-label col-md-3">
@@ -101,7 +102,7 @@ <h4>{% trans "Other settings" %}</h4>
101102
{% bootstrap_field sform.name_scheme layout="control" %}
102103
{% bootstrap_field sform.name_scheme_titles layout="control" %}
103104
{% bootstrap_field sform.checkout_show_copy_answers_button layout="control" %}
104-
105+
105106
<h4>{% translate "Changes to existing orders" %}</h4>
106107
{% bootstrap_field sform.allow_modifications layout="control" %}
107108
<div data-display-dependency='#id_settings-allow_modifications_0' data-inverse>
@@ -190,7 +191,7 @@ <h4>{% translate "Changes to existing orders" %}</h4>
190191
{% bootstrap_field sform.banner_text_bottom layout="control" %}
191192
{% bootstrap_field sform.event_info_text layout="control" %}
192193
</fieldset>
193-
194+
194195

195196
<fieldset>
196197
<legend>{% trans "Timeline" %}</legend>

app/eventyay/control/views/orders.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,10 @@
6161
Checkin,
6262
Invoice,
6363
InvoiceAddress,
64-
Product,
65-
ProductVariation,
6664
LogEntry,
6765
Order,
66+
Product,
67+
ProductVariation,
6868
QuestionAnswer,
6969
Quota,
7070
generate_secret,

0 commit comments

Comments
 (0)