forked from CGM_Public/pretix_original
Compare commits
4 Commits
waitlist_s
...
django31
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bc64109e11 | ||
|
|
40018b0937 | ||
|
|
cffcddaf26 | ||
|
|
bd70a2e7bf |
@@ -60,10 +60,7 @@ Here is the currently recommended set of commands::
|
||||
CREATE INDEX CONCURRENTLY pretix_addidx_ia_company
|
||||
ON pretixbase_invoiceaddress
|
||||
USING gin (upper("company") gin_trgm_ops);
|
||||
CREATE INDEX CONCURRENTLY pretix_addidx_orderpos_email_upper
|
||||
ON public.pretixbase_orderposition (upper((attendee_email)::text));
|
||||
CREATE INDEX CONCURRENTLY pretix_addidx_voucher_code_upper
|
||||
ON public.pretixbase_voucher (upper((code)::text));
|
||||
CREATE INDEX CONCURRENTLY pretix_addidx_orderpos_email_upper ON public.pretixbase_orderposition (upper((attendee_email)::text));
|
||||
|
||||
|
||||
Also, if you use our ``pretix-shipping`` plugin::
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class FullAccessSecurityProfile:
|
||||
@@ -10,7 +10,7 @@ class FullAccessSecurityProfile:
|
||||
|
||||
|
||||
class AllowListSecurityProfile:
|
||||
allowlist = ()
|
||||
allowlist = tuple()
|
||||
|
||||
def is_allowed(self, request):
|
||||
key = (request.method, f"{request.resolver_match.namespace}:{request.resolver_match.url_name}")
|
||||
@@ -95,8 +95,6 @@ class PretixPosSecurityProfile(AllowListSecurityProfile):
|
||||
('GET', 'api-v1:taxrule-list'),
|
||||
('GET', 'api-v1:ticketlayout-list'),
|
||||
('GET', 'api-v1:ticketlayoutitem-list'),
|
||||
('GET', 'api-v1:badgelayout-list'),
|
||||
('GET', 'api-v1:badgeitem-list'),
|
||||
('GET', 'api-v1:order-list'),
|
||||
('POST', 'api-v1:order-list'),
|
||||
('GET', 'api-v1:order-detail'),
|
||||
|
||||
@@ -309,7 +309,7 @@ class EventSerializer(I18nAwareModelSerializer):
|
||||
|
||||
# Item Meta properties
|
||||
if item_meta_properties is not None:
|
||||
current = list(event.item_meta_properties.all())
|
||||
current = [imp for imp in event.item_meta_properties.all()]
|
||||
for key, value in item_meta_properties.items():
|
||||
prop = self.item_meta_props.get(key)
|
||||
if prop in current:
|
||||
|
||||
@@ -18,18 +18,18 @@ class FormFieldWrapperField(serializers.Field):
|
||||
|
||||
|
||||
simple_mappings = (
|
||||
(forms.DateField, serializers.DateField, ()),
|
||||
(forms.TimeField, serializers.TimeField, ()),
|
||||
(forms.SplitDateTimeField, serializers.DateTimeField, ()),
|
||||
(forms.DateTimeField, serializers.DateTimeField, ()),
|
||||
(forms.DateField, serializers.DateField, tuple()),
|
||||
(forms.TimeField, serializers.TimeField, tuple()),
|
||||
(forms.SplitDateTimeField, serializers.DateTimeField, tuple()),
|
||||
(forms.DateTimeField, serializers.DateTimeField, tuple()),
|
||||
(forms.DecimalField, serializers.DecimalField, ('max_digits', 'decimal_places', 'min_value', 'max_value')),
|
||||
(forms.FloatField, serializers.FloatField, ()),
|
||||
(forms.IntegerField, serializers.IntegerField, ()),
|
||||
(forms.EmailField, serializers.EmailField, ()),
|
||||
(forms.UUIDField, serializers.UUIDField, ()),
|
||||
(forms.URLField, serializers.URLField, ()),
|
||||
(forms.NullBooleanField, serializers.NullBooleanField, ()),
|
||||
(forms.BooleanField, serializers.BooleanField, ()),
|
||||
(forms.FloatField, serializers.FloatField, tuple()),
|
||||
(forms.IntegerField, serializers.IntegerField, tuple()),
|
||||
(forms.EmailField, serializers.EmailField, tuple()),
|
||||
(forms.UUIDField, serializers.UUIDField, tuple()),
|
||||
(forms.URLField, serializers.URLField, tuple()),
|
||||
(forms.NullBooleanField, serializers.NullBooleanField, tuple()),
|
||||
(forms.BooleanField, serializers.BooleanField, tuple()),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -8,9 +8,7 @@ from pretix.api.models import ApiCall, WebHookCall
|
||||
from pretix.base.signals import periodic_task
|
||||
from pretix.helpers.periodic import minimum_interval
|
||||
|
||||
register_webhook_events = Signal(
|
||||
providing_args=[]
|
||||
)
|
||||
register_webhook_events = Signal()
|
||||
"""
|
||||
This signal is sent out to get all known webhook events. Receivers should return an
|
||||
instance of a subclass of pretix.api.webhooks.WebhookEvent or a list of such
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import importlib
|
||||
|
||||
from django.apps import apps
|
||||
from django.conf.urls import include, url
|
||||
from django.conf.urls import include, re_path
|
||||
from rest_framework import routers
|
||||
|
||||
from pretix.api.views import cart
|
||||
@@ -72,30 +72,32 @@ for app in apps.get_app_configs():
|
||||
importlib.import_module(app.name + '.urls')
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^', include(router.urls)),
|
||||
url(r'^organizers/(?P<organizer>[^/]+)/', include(orga_router.urls)),
|
||||
url(r'^organizers/(?P<organizer>[^/]+)/settings/$', organizer.OrganizerSettingsView.as_view(),
|
||||
name="organizer.settings"),
|
||||
url(r'^organizers/(?P<organizer>[^/]+)/giftcards/(?P<giftcard>[^/]+)/', include(giftcard_router.urls)),
|
||||
url(r'^organizers/(?P<organizer>[^/]+)/events/(?P<event>[^/]+)/settings/$', event.EventSettingsView.as_view(),
|
||||
name="event.settings"),
|
||||
url(r'^organizers/(?P<organizer>[^/]+)/events/(?P<event>[^/]+)/', include(event_router.urls)),
|
||||
url(r'^organizers/(?P<organizer>[^/]+)/teams/(?P<team>[^/]+)/', include(team_router.urls)),
|
||||
url(r'^organizers/(?P<organizer>[^/]+)/events/(?P<event>[^/]+)/items/(?P<item>[^/]+)/', include(item_router.urls)),
|
||||
url(r'^organizers/(?P<organizer>[^/]+)/events/(?P<event>[^/]+)/questions/(?P<question>[^/]+)/',
|
||||
include(question_router.urls)),
|
||||
url(r'^organizers/(?P<organizer>[^/]+)/events/(?P<event>[^/]+)/checkinlists/(?P<list>[^/]+)/',
|
||||
include(checkinlist_router.urls)),
|
||||
url(r'^organizers/(?P<organizer>[^/]+)/events/(?P<event>[^/]+)/orders/(?P<order>[^/]+)/', include(order_router.urls)),
|
||||
url(r"^oauth/authorize$", oauth.AuthorizationView.as_view(), name="authorize"),
|
||||
url(r"^oauth/token$", oauth.TokenView.as_view(), name="token"),
|
||||
url(r"^oauth/revoke_token$", oauth.RevokeTokenView.as_view(), name="revoke-token"),
|
||||
url(r"^device/initialize$", device.InitializeView.as_view(), name="device.initialize"),
|
||||
url(r"^device/update$", device.UpdateView.as_view(), name="device.update"),
|
||||
url(r"^device/roll$", device.RollKeyView.as_view(), name="device.roll"),
|
||||
url(r"^device/revoke$", device.RevokeKeyView.as_view(), name="device.revoke"),
|
||||
url(r"^device/eventselection$", device.EventSelectionView.as_view(), name="device.eventselection"),
|
||||
url(r"^upload$", upload.UploadView.as_view(), name="upload"),
|
||||
url(r"^me$", user.MeView.as_view(), name="user.me"),
|
||||
url(r"^version$", version.VersionView.as_view(), name="version"),
|
||||
re_path(r'^', include(router.urls)),
|
||||
re_path(r'^organizers/(?P<organizer>[^/]+)/', include(orga_router.urls)),
|
||||
re_path(r'^organizers/(?P<organizer>[^/]+)/settings/$', organizer.OrganizerSettingsView.as_view(),
|
||||
name="organizer.settings"),
|
||||
re_path(r'^organizers/(?P<organizer>[^/]+)/giftcards/(?P<giftcard>[^/]+)/', include(giftcard_router.urls)),
|
||||
re_path(r'^organizers/(?P<organizer>[^/]+)/events/(?P<event>[^/]+)/settings/$', event.EventSettingsView.as_view(),
|
||||
name="event.settings"),
|
||||
re_path(r'^organizers/(?P<organizer>[^/]+)/events/(?P<event>[^/]+)/', include(event_router.urls)),
|
||||
re_path(r'^organizers/(?P<organizer>[^/]+)/teams/(?P<team>[^/]+)/', include(team_router.urls)),
|
||||
re_path(r'^organizers/(?P<organizer>[^/]+)/events/(?P<event>[^/]+)/items/(?P<item>[^/]+)/',
|
||||
include(item_router.urls)),
|
||||
re_path(r'^organizers/(?P<organizer>[^/]+)/events/(?P<event>[^/]+)/questions/(?P<question>[^/]+)/',
|
||||
include(question_router.urls)),
|
||||
re_path(r'^organizers/(?P<organizer>[^/]+)/events/(?P<event>[^/]+)/checkinlists/(?P<list>[^/]+)/',
|
||||
include(checkinlist_router.urls)),
|
||||
re_path(r'^organizers/(?P<organizer>[^/]+)/events/(?P<event>[^/]+)/orders/(?P<order>[^/]+)/',
|
||||
include(order_router.urls)),
|
||||
re_path(r"^oauth/authorize$", oauth.AuthorizationView.as_view(), name="authorize"),
|
||||
re_path(r"^oauth/token$", oauth.TokenView.as_view(), name="token"),
|
||||
re_path(r"^oauth/revoke_token$", oauth.RevokeTokenView.as_view(), name="revoke-token"),
|
||||
re_path(r"^device/initialize$", device.InitializeView.as_view(), name="device.initialize"),
|
||||
re_path(r"^device/update$", device.UpdateView.as_view(), name="device.update"),
|
||||
re_path(r"^device/roll$", device.RollKeyView.as_view(), name="device.roll"),
|
||||
re_path(r"^device/revoke$", device.RevokeKeyView.as_view(), name="device.revoke"),
|
||||
re_path(r"^device/eventselection$", device.EventSelectionView.as_view(), name="device.eventselection"),
|
||||
re_path(r"^upload$", upload.UploadView.as_view(), name="upload"),
|
||||
re_path(r"^me$", user.MeView.as_view(), name="user.me"),
|
||||
re_path(r"^version$", version.VersionView.as_view(), name="version"),
|
||||
]
|
||||
|
||||
@@ -53,8 +53,8 @@ class DeviceSerializer(serializers.ModelSerializer):
|
||||
|
||||
|
||||
class InitializeView(APIView):
|
||||
authentication_classes = ()
|
||||
permission_classes = ()
|
||||
authentication_classes = tuple()
|
||||
permission_classes = tuple()
|
||||
|
||||
def post(self, request, format=None):
|
||||
serializer = InitializationRequestSerializer(data=request.data)
|
||||
|
||||
@@ -100,7 +100,7 @@ class NamePartsWidget(forms.MultiWidget):
|
||||
if not isinstance(value, list):
|
||||
value = self.decompress(value)
|
||||
output = []
|
||||
final_attrs = self.build_attrs(attrs or {})
|
||||
final_attrs = self.build_attrs(attrs or dict())
|
||||
if 'required' in final_attrs:
|
||||
del final_attrs['required']
|
||||
id_ = final_attrs.get('id', None)
|
||||
@@ -122,8 +122,6 @@ class NamePartsWidget(forms.MultiWidget):
|
||||
these_attrs.pop('data-no-required-attr', None)
|
||||
these_attrs['autocomplete'] = (self.attrs.get('autocomplete', '') + ' ' + self.autofill_map.get(self.scheme['fields'][i][0], 'off')).strip()
|
||||
these_attrs['data-size'] = self.scheme['fields'][i][2]
|
||||
if len(self.widgets) > 1:
|
||||
these_attrs['aria-label'] = self.scheme['fields'][i][1]
|
||||
else:
|
||||
these_attrs = final_attrs
|
||||
output.append(widget.render(name + '_%s' % i, widget_value, these_attrs, renderer=renderer))
|
||||
@@ -222,7 +220,7 @@ class WrappedPhonePrefixSelect(Select):
|
||||
country_name = locale.territories.get(country_code)
|
||||
if country_name:
|
||||
choices.append((prefix, "{} {}".format(country_name, prefix)))
|
||||
super().__init__(choices=sorted(choices, key=lambda item: item[1]), attrs={'aria-label': pgettext_lazy('phonenumber', 'International area code')})
|
||||
super().__init__(choices=sorted(choices, key=lambda item: item[1]))
|
||||
|
||||
def render(self, name, value, *args, **kwargs):
|
||||
return super().render(name, value or self.initial, *args, **kwargs)
|
||||
@@ -245,10 +243,7 @@ class WrappedPhonePrefixSelect(Select):
|
||||
class WrappedPhoneNumberPrefixWidget(PhoneNumberPrefixWidget):
|
||||
|
||||
def __init__(self, attrs=None, initial=None):
|
||||
attrs = {
|
||||
'aria-label': pgettext_lazy('phonenumber', 'Phone number (without international area code)')
|
||||
}
|
||||
widgets = (WrappedPhonePrefixSelect(initial), forms.TextInput(attrs=attrs))
|
||||
widgets = (WrappedPhonePrefixSelect(initial), forms.TextInput())
|
||||
super(PhoneNumberPrefixWidget, self).__init__(widgets, attrs)
|
||||
|
||||
def render(self, name, value, attrs=None, renderer=None):
|
||||
|
||||
@@ -445,7 +445,7 @@ class ClassicInvoiceRenderer(BaseReportlabInvoiceRenderer):
|
||||
if self.invoice.custom_field:
|
||||
story.append(Paragraph(
|
||||
'{}: {}'.format(
|
||||
bleach.clean(str(self.invoice.event.settings.invoice_address_custom_field), tags=[]).strip().replace('\n', '<br />\n'),
|
||||
bleach.clean(self.invoice.event.settings.invoice_address_custom_field, tags=[]).strip().replace('\n', '<br />\n'),
|
||||
bleach.clean(self.invoice.custom_field, tags=[]).strip().replace('\n', '<br />\n'),
|
||||
),
|
||||
self.stylesheet['Normal']
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Generated by Django 2.1 on 2018-10-17 00:24
|
||||
|
||||
import jsonfallback.fields
|
||||
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.db import migrations
|
||||
from django_mysql.checks import mysql_connections
|
||||
@@ -77,19 +77,19 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='cartposition',
|
||||
name='attendee_name_parts',
|
||||
field=jsonfallback.fields.FallbackJSONField(null=False, default=dict),
|
||||
field=models.JSONField(null=False, default=dict),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='orderposition',
|
||||
name='attendee_name_parts',
|
||||
field=jsonfallback.fields.FallbackJSONField(null=False, default=dict),
|
||||
field=models.JSONField(null=False, default=dict),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='invoiceaddress',
|
||||
name='name_parts',
|
||||
field=jsonfallback.fields.FallbackJSONField(default=dict),
|
||||
field=models.JSONField(default=dict),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.RunPython(set_attendee_name_parts, migrations.RunPython.noop)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# Generated by Django 2.1.1 on 2018-11-21 12:24
|
||||
|
||||
import django.db.models.deletion
|
||||
import jsonfallback.fields
|
||||
from django.db import migrations, models
|
||||
|
||||
import pretix.base.models.fields
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import django.db.models.deletion
|
||||
import django.db.models.manager
|
||||
import jsonfallback.fields
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# Generated by Django 2.1 on 2019-01-12 15:12
|
||||
|
||||
import django.db.models.deletion
|
||||
import jsonfallback.fields
|
||||
from django.db import migrations, models
|
||||
|
||||
import pretix.base.models.fields
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# Generated by Django 2.1.5 on 2019-01-29 13:37
|
||||
|
||||
import django.db.models.deletion
|
||||
import jsonfallback.fields
|
||||
from django.db import migrations, models
|
||||
|
||||
import pretix.base.models.fields
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# Generated by Django 2.1.5 on 2019-02-01 15:27
|
||||
|
||||
import django.db.models.deletion
|
||||
import jsonfallback.fields
|
||||
from django.db import migrations, models
|
||||
|
||||
import pretix.base.models.fields
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
from decimal import Decimal
|
||||
|
||||
import django.db.models.deletion
|
||||
import jsonfallback.fields
|
||||
from django.conf import settings
|
||||
from django.core.cache import cache
|
||||
from django.db import migrations, models
|
||||
@@ -190,7 +189,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='cartposition',
|
||||
name='attendee_name_parts',
|
||||
field=jsonfallback.fields.FallbackJSONField(default=dict),
|
||||
field=models.JSONField(default=dict),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cartposition',
|
||||
@@ -210,7 +209,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='invoiceaddress',
|
||||
name='name_parts',
|
||||
field=jsonfallback.fields.FallbackJSONField(default=dict),
|
||||
field=models.JSONField(default=dict),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='item',
|
||||
@@ -225,7 +224,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='orderposition',
|
||||
name='attendee_name_parts',
|
||||
field=jsonfallback.fields.FallbackJSONField(default=dict),
|
||||
field=models.JSONField(default=dict),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='orderposition',
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# Generated by Django 2.1 on 2019-02-08 14:32
|
||||
|
||||
import django.db.models.deletion
|
||||
import jsonfallback.fields
|
||||
from django.db import migrations, models
|
||||
|
||||
import pretix.base.models.fields
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# Generated by Django 2.1.5 on 2019-02-19 12:45
|
||||
|
||||
import django.db.models.deletion
|
||||
import jsonfallback.fields
|
||||
from django.db import migrations, models
|
||||
|
||||
import pretix.base.models.fields
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# Generated by Django 2.1.5 on 2019-02-19 09:49
|
||||
|
||||
import django.db.models.deletion
|
||||
import jsonfallback.fields
|
||||
from django.db import migrations, models
|
||||
|
||||
import pretix.base.models.fields
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# Generated by Django 2.1.5 on 2019-03-12 09:42
|
||||
|
||||
import django.db.models.deletion
|
||||
import jsonfallback.fields
|
||||
from django.db import migrations, models
|
||||
|
||||
import pretix.base.models.fields
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# Generated by Django 2.1.7 on 2019-03-16 10:14
|
||||
|
||||
import django.db.models.deletion
|
||||
import jsonfallback.fields
|
||||
from django.db import migrations, models
|
||||
|
||||
import pretix.base.models.fields
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
from decimal import Decimal
|
||||
|
||||
import django.db.models.deletion
|
||||
import jsonfallback.fields
|
||||
from django.db import migrations, models
|
||||
|
||||
import pretix.base.models.fields
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# Generated by Django 2.1.5 on 2019-04-02 07:22
|
||||
|
||||
import django.db.models.deletion
|
||||
import jsonfallback.fields
|
||||
from django.db import migrations, models
|
||||
|
||||
import pretix.base.models.fields
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# Generated by Django 2.2 on 2019-04-23 08:39
|
||||
|
||||
import django.db.models.deletion
|
||||
import jsonfallback.fields
|
||||
from django.db import migrations, models
|
||||
|
||||
import pretix.base.models.fields
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# Generated by Django 2.2 on 2019-05-09 06:54
|
||||
|
||||
import django.db.models.deletion
|
||||
import jsonfallback.fields
|
||||
from django.db import migrations, models
|
||||
|
||||
import pretix.base.models.fields
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# Generated by Django 2.2 on 2019-05-09 07:36
|
||||
|
||||
import django.db.models.deletion
|
||||
import jsonfallback.fields
|
||||
from django.db import migrations, models
|
||||
|
||||
import pretix.base.models.fields
|
||||
@@ -17,7 +16,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='cartposition',
|
||||
name='attendee_name_parts',
|
||||
field=jsonfallback.fields.FallbackJSONField(default=dict),
|
||||
field=models.JSONField(default=dict),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cartposition',
|
||||
@@ -37,7 +36,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='invoiceaddress',
|
||||
name='name_parts',
|
||||
field=jsonfallback.fields.FallbackJSONField(default=dict),
|
||||
field=models.JSONField(default=dict),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='item',
|
||||
@@ -52,7 +51,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='orderposition',
|
||||
name='attendee_name_parts',
|
||||
field=jsonfallback.fields.FallbackJSONField(default=dict),
|
||||
field=models.JSONField(default=dict),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='orderposition',
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import django.db.models.deletion
|
||||
import django_countries.fields
|
||||
import jsonfallback.fields
|
||||
from django.db import migrations, models
|
||||
|
||||
import pretix.helpers.countries
|
||||
@@ -43,7 +42,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='checkinlist',
|
||||
name='rules',
|
||||
field=jsonfallback.fields.FallbackJSONField(default=dict),
|
||||
field=models.JSONField(default=dict),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='checkin',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Generated by Django 3.0.10 on 2021-03-01 15:10
|
||||
|
||||
import jsonfallback.fields
|
||||
|
||||
import phonenumber_field.modelfields
|
||||
from django.db import migrations, models
|
||||
|
||||
@@ -20,7 +20,7 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='waitinglistentry',
|
||||
name='name_parts',
|
||||
field=jsonfallback.fields.FallbackJSONField(default=dict),
|
||||
field=models.JSONField(default=dict),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='waitinglistentry',
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
# Generated by Django 3.0.10 on 2021-03-11 16:53
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def clean_duplicates(apps, schema_editor):
|
||||
while True:
|
||||
delete_options = """
|
||||
DELETE
|
||||
FROM pretixbase_questionanswer_options
|
||||
WHERE questionanswer_id IN (
|
||||
SELECT MIN(qa.id)
|
||||
FROM pretixbase_questionanswer qa
|
||||
GROUP BY qa.cartposition_id, qa.orderposition_id, qa.question_id
|
||||
HAVING COUNT(*) > 1
|
||||
);
|
||||
"""
|
||||
delete_answers = """
|
||||
DELETE
|
||||
FROM pretixbase_questionanswer
|
||||
WHERE pretixbase_questionanswer.id IN (
|
||||
SELECT MIN(qa.id)
|
||||
FROM pretixbase_questionanswer qa
|
||||
GROUP BY qa.cartposition_id, qa.orderposition_id, qa.question_id
|
||||
HAVING COUNT(*) > 1
|
||||
);
|
||||
"""
|
||||
with schema_editor.connection.cursor() as cursor:
|
||||
cursor.execute(delete_options)
|
||||
cursor.execute(delete_answers)
|
||||
if cursor.rowcount == 0:
|
||||
return
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pretixbase', '0178_auto_20210308_1326'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
clean_duplicates,
|
||||
migrations.RunPython.noop,
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='questionanswer',
|
||||
unique_together={('orderposition', 'question'), ('cartposition', 'question')},
|
||||
),
|
||||
]
|
||||
@@ -4,7 +4,6 @@ from django.db.models import Exists, F, Max, OuterRef, Q, Subquery
|
||||
from django.utils.timezone import now
|
||||
from django.utils.translation import gettext_lazy as _, pgettext_lazy
|
||||
from django_scopes import ScopedManager, scopes_disabled
|
||||
from jsonfallback.fields import FallbackJSONField
|
||||
|
||||
from pretix.base.models import LoggedModel
|
||||
from pretix.base.models.fields import MultiStringField
|
||||
@@ -47,7 +46,7 @@ class CheckinList(LoggedModel):
|
||||
'any of the selected sales channels. This option can be useful when tickets sold at the box office '
|
||||
'are not checked again before entry and should be considered validated directly upon purchase.')
|
||||
)
|
||||
rules = FallbackJSONField(default=dict, blank=True)
|
||||
rules = models.JSONField(default=dict, blank=True)
|
||||
|
||||
objects = ScopedManager(organizer='event__organizer')
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@ from django.utils.translation import gettext_lazy as _, pgettext_lazy
|
||||
from django_countries.fields import Country
|
||||
from django_scopes import ScopedManager, scopes_disabled
|
||||
from i18nfield.strings import LazyI18nString
|
||||
from jsonfallback.fields import FallbackJSONField
|
||||
from phonenumber_field.modelfields import PhoneNumberField
|
||||
from phonenumber_field.phonenumber import PhoneNumber
|
||||
from phonenumbers import NumberParseException
|
||||
@@ -983,9 +982,6 @@ class QuestionAnswer(models.Model):
|
||||
|
||||
objects = ScopedManager(organizer='question__event__organizer')
|
||||
|
||||
class Meta:
|
||||
unique_together = [['orderposition', 'question'], ['cartposition', 'question']]
|
||||
|
||||
@property
|
||||
def backend_file_url(self):
|
||||
if self.file:
|
||||
@@ -1135,7 +1131,7 @@ class AbstractPosition(models.Model):
|
||||
blank=True, null=True,
|
||||
help_text=_("Empty, if this product is not an admission ticket")
|
||||
)
|
||||
attendee_name_parts = FallbackJSONField(
|
||||
attendee_name_parts = models.JSONField(
|
||||
blank=True, default=dict
|
||||
)
|
||||
attendee_email = models.EmailField(
|
||||
@@ -2255,7 +2251,7 @@ class InvoiceAddress(models.Model):
|
||||
is_business = models.BooleanField(default=False, verbose_name=_('Business customer'))
|
||||
company = models.CharField(max_length=255, blank=True, verbose_name=_('Company name'))
|
||||
name_cached = models.CharField(max_length=255, verbose_name=_('Full name'), blank=True)
|
||||
name_parts = FallbackJSONField(default=dict)
|
||||
name_parts = models.JSONField(default=dict)
|
||||
street = models.TextField(verbose_name=_('Address'), blank=False)
|
||||
zipcode = models.CharField(max_length=30, verbose_name=_('ZIP code'), blank=False)
|
||||
city = models.CharField(max_length=255, verbose_name=_('City'), blank=False)
|
||||
|
||||
@@ -5,7 +5,6 @@ from django.db import models, transaction
|
||||
from django.utils.timezone import now
|
||||
from django.utils.translation import gettext_lazy as _, pgettext_lazy
|
||||
from django_scopes import ScopedManager
|
||||
from jsonfallback.fields import FallbackJSONField
|
||||
from phonenumber_field.modelfields import PhoneNumberField
|
||||
|
||||
from pretix.base.email import get_email_context
|
||||
@@ -45,7 +44,7 @@ class WaitingListEntry(LoggedModel):
|
||||
verbose_name=_("Name"),
|
||||
blank=True, null=True,
|
||||
)
|
||||
name_parts = FallbackJSONField(
|
||||
name_parts = models.JSONField(
|
||||
blank=True, default=dict
|
||||
)
|
||||
email = models.EmailField(
|
||||
|
||||
@@ -241,7 +241,7 @@ class CartManager:
|
||||
raise CartError(_(error_messages['max_items']) % (self.event.settings.max_items_per_order,))
|
||||
|
||||
def _check_item_constraints(self, op, current_ops=[]):
|
||||
if isinstance(op, (self.AddOperation, self.ExtendOperation)):
|
||||
if isinstance(op, self.AddOperation) or isinstance(op, self.ExtendOperation):
|
||||
if not (
|
||||
(isinstance(op, self.AddOperation) and op.addon_to == 'FAKE') or
|
||||
(isinstance(op, self.ExtendOperation) and op.position.is_bundled)
|
||||
@@ -863,7 +863,7 @@ class CartManager:
|
||||
op.position.addons.all().delete()
|
||||
op.position.delete()
|
||||
|
||||
elif isinstance(op, (self.AddOperation, self.ExtendOperation)):
|
||||
elif isinstance(op, self.AddOperation) or isinstance(op, self.ExtendOperation):
|
||||
# Create a CartPosition for as much items as we can
|
||||
requested_count = quota_available_count = voucher_available_count = op.count
|
||||
|
||||
|
||||
@@ -3,21 +3,22 @@ from i18nfield.strings import LazyI18nString
|
||||
|
||||
from pretix.base.email import get_email_context
|
||||
from pretix.base.i18n import language
|
||||
from pretix.base.models import Event, LogEntry, User, Voucher
|
||||
from pretix.base.models import Event, User, Voucher
|
||||
from pretix.base.services.mail import mail
|
||||
from pretix.base.services.tasks import TransactionAwareProfiledEventTask
|
||||
from pretix.celery_app import app
|
||||
|
||||
|
||||
def vouchers_send(event: Event, vouchers: list, subject: str, message: str, recipients: list, user: int,
|
||||
progress=None) -> None:
|
||||
@app.task(base=TransactionAwareProfiledEventTask, acks_late=True)
|
||||
def vouchers_send(event: Event, vouchers: list, subject: str, message: str, recipients: list, user: int) -> None:
|
||||
vouchers = list(Voucher.objects.filter(id__in=vouchers).order_by('id'))
|
||||
user = User.objects.get(pk=user)
|
||||
for ir, r in enumerate(recipients):
|
||||
for r in recipients:
|
||||
voucher_list = []
|
||||
for i in range(r['number']):
|
||||
voucher_list.append(vouchers.pop())
|
||||
with language(event.settings.locale):
|
||||
email_context = get_email_context(event=event, name=r.get('name') or '',
|
||||
voucher_list=[v.code for v in voucher_list])
|
||||
email_context = get_email_context(event=event, name=r.get('name') or '', voucher_list=[v.code for v in voucher_list])
|
||||
mail(
|
||||
r['email'],
|
||||
subject,
|
||||
@@ -26,14 +27,14 @@ def vouchers_send(event: Event, vouchers: list, subject: str, message: str, reci
|
||||
event,
|
||||
locale=event.settings.locale,
|
||||
)
|
||||
logs = []
|
||||
for v in voucher_list:
|
||||
if r.get('tag') and r.get('tag') != v.tag:
|
||||
v.tag = r.get('tag')
|
||||
if v.comment:
|
||||
v.comment += '\n\n'
|
||||
v.comment = gettext('The voucher has been sent to {recipient}.').format(recipient=r['email'])
|
||||
logs.append(v.log_action(
|
||||
v.save(update_fields=['tag', 'comment'])
|
||||
v.log_action(
|
||||
'pretix.voucher.sent',
|
||||
user=user,
|
||||
data={
|
||||
@@ -41,11 +42,5 @@ def vouchers_send(event: Event, vouchers: list, subject: str, message: str, reci
|
||||
'name': r.get('name'),
|
||||
'subject': subject,
|
||||
'message': message,
|
||||
},
|
||||
save=False
|
||||
))
|
||||
Voucher.objects.bulk_update(voucher_list, fields=['comment', 'tag'], batch_size=500)
|
||||
LogEntry.objects.bulk_create(logs, batch_size=500)
|
||||
|
||||
if progress and ir % 50 == 0:
|
||||
progress(ir / len(recipients))
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1799,7 +1799,7 @@ Your {event} team"""))
|
||||
),
|
||||
},
|
||||
'theme_color_danger': {
|
||||
'default': '#C44F4F',
|
||||
'default': '#D36060',
|
||||
'type': str,
|
||||
'form_class': forms.CharField,
|
||||
'serializer_class': serializers.CharField,
|
||||
|
||||
@@ -164,9 +164,7 @@ class DeprecatedSignal(django.dispatch.Signal):
|
||||
super().connect(receiver, sender=None, weak=True, dispatch_uid=None)
|
||||
|
||||
|
||||
event_live_issues = EventPluginSignal(
|
||||
providing_args=[]
|
||||
)
|
||||
event_live_issues = EventPluginSignal()
|
||||
"""
|
||||
This signal is sent out to determine whether an event can be taken live. If you want to
|
||||
prevent the event from going live, return a string that will be displayed to the user
|
||||
@@ -176,9 +174,7 @@ As with all event-plugin signals, the ``sender`` keyword argument will contain t
|
||||
"""
|
||||
|
||||
|
||||
register_payment_providers = EventPluginSignal(
|
||||
providing_args=[]
|
||||
)
|
||||
register_payment_providers = EventPluginSignal()
|
||||
"""
|
||||
This signal is sent out to get all known payment providers. Receivers should return a
|
||||
subclass of pretix.base.payment.BasePaymentProvider or a list of these
|
||||
@@ -186,9 +182,7 @@ subclass of pretix.base.payment.BasePaymentProvider or a list of these
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
register_mail_placeholders = EventPluginSignal(
|
||||
providing_args=[]
|
||||
)
|
||||
register_mail_placeholders = EventPluginSignal()
|
||||
"""
|
||||
This signal is sent out to get all known email text placeholders. Receivers should return
|
||||
an instance of a subclass of pretix.base.email.BaseMailTextPlaceholder or a list of these.
|
||||
@@ -196,9 +190,7 @@ an instance of a subclass of pretix.base.email.BaseMailTextPlaceholder or a list
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
register_html_mail_renderers = EventPluginSignal(
|
||||
providing_args=[]
|
||||
)
|
||||
register_html_mail_renderers = EventPluginSignal()
|
||||
"""
|
||||
This signal is sent out to get all known HTML email renderers. Receivers should return a
|
||||
subclass of pretix.base.email.BaseHTMLMailRenderer or a list of these
|
||||
@@ -206,9 +198,7 @@ subclass of pretix.base.email.BaseHTMLMailRenderer or a list of these
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
register_invoice_renderers = EventPluginSignal(
|
||||
providing_args=[]
|
||||
)
|
||||
register_invoice_renderers = EventPluginSignal()
|
||||
"""
|
||||
This signal is sent out to get all known invoice renderers. Receivers should return a
|
||||
subclass of pretix.base.invoice.BaseInvoiceRenderer or a list of these
|
||||
@@ -216,9 +206,7 @@ subclass of pretix.base.invoice.BaseInvoiceRenderer or a list of these
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
register_ticket_secret_generators = EventPluginSignal(
|
||||
providing_args=[]
|
||||
)
|
||||
register_ticket_secret_generators = EventPluginSignal()
|
||||
"""
|
||||
This signal is sent out to get all known ticket secret generators. Receivers should return a
|
||||
subclass of ``pretix.base.secrets.BaseTicketSecretGenerator`` or a list of these
|
||||
@@ -226,9 +214,7 @@ subclass of ``pretix.base.secrets.BaseTicketSecretGenerator`` or a list of these
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
register_data_shredders = EventPluginSignal(
|
||||
providing_args=[]
|
||||
)
|
||||
register_data_shredders = EventPluginSignal()
|
||||
"""
|
||||
This signal is sent out to get all known data shredders. Receivers should return a
|
||||
subclass of pretix.base.shredder.BaseDataShredder or a list of these
|
||||
@@ -236,9 +222,7 @@ subclass of pretix.base.shredder.BaseDataShredder or a list of these
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
register_ticket_outputs = EventPluginSignal(
|
||||
providing_args=[]
|
||||
)
|
||||
register_ticket_outputs = EventPluginSignal()
|
||||
"""
|
||||
This signal is sent out to get all known ticket outputs. Receivers should return a
|
||||
subclass of pretix.base.ticketoutput.BaseTicketOutput
|
||||
@@ -246,9 +230,7 @@ subclass of pretix.base.ticketoutput.BaseTicketOutput
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
register_notification_types = EventPluginSignal(
|
||||
providing_args=[]
|
||||
)
|
||||
register_notification_types = EventPluginSignal()
|
||||
"""
|
||||
This signal is sent out to get all known notification types. Receivers should return an
|
||||
instance of a subclass of pretix.base.notifications.NotificationType or a list of such
|
||||
@@ -259,18 +241,14 @@ however for this signal, the ``sender`` **may also be None** to allow creating t
|
||||
notification settings!
|
||||
"""
|
||||
|
||||
register_sales_channels = django.dispatch.Signal(
|
||||
providing_args=[]
|
||||
)
|
||||
register_sales_channels = django.dispatch.Signal()
|
||||
"""
|
||||
This signal is sent out to get all known sales channels types. Receivers should return an
|
||||
instance of a subclass of ``pretix.base.channels.SalesChannel`` or a list of such
|
||||
instances.
|
||||
"""
|
||||
|
||||
register_data_exporters = EventPluginSignal(
|
||||
providing_args=[]
|
||||
)
|
||||
register_data_exporters = EventPluginSignal()
|
||||
"""
|
||||
This signal is sent out to get all known data exporters. Receivers should return a
|
||||
subclass of pretix.base.exporter.BaseExporter
|
||||
@@ -278,21 +256,20 @@ subclass of pretix.base.exporter.BaseExporter
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
register_multievent_data_exporters = django.dispatch.Signal(
|
||||
providing_args=["event"]
|
||||
)
|
||||
register_multievent_data_exporters = django.dispatch.Signal()
|
||||
"""
|
||||
Arguments: ``event``
|
||||
|
||||
This signal is sent out to get all known data exporters, which support exporting data for
|
||||
multiple events. Receivers should return a subclass of pretix.base.exporter.BaseExporter
|
||||
|
||||
The ``sender`` keyword argument will contain an organizer.
|
||||
"""
|
||||
|
||||
validate_order = EventPluginSignal(
|
||||
providing_args=["payment_provider", "positions", "email", "locale", "invoice_address",
|
||||
"meta_info"]
|
||||
)
|
||||
validate_order = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``payment_provider``, ``positions``, ``email``, ``locale``, ``invoice_address``, ``meta_info``
|
||||
|
||||
This signal is sent out when the user tries to confirm the order, before we actually create
|
||||
the order. It allows you to inspect the cart positions. Your return value will be ignored,
|
||||
but you can raise an OrderError with an appropriate exception message if you like to block
|
||||
@@ -301,10 +278,10 @@ the order. We strongly discourage making changes to the order here.
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
validate_cart = EventPluginSignal(
|
||||
providing_args=["positions"]
|
||||
)
|
||||
validate_cart = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``positions``
|
||||
|
||||
This signal is sent out before the user starts checkout. It includes an iterable
|
||||
with the current CartPosition objects.
|
||||
The response of receivers will be ignored, but you can raise a CartError with an
|
||||
@@ -313,10 +290,10 @@ appropriate exception message.
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
validate_cart_addons = EventPluginSignal(
|
||||
providing_args=["addons", "base_position", "iao"]
|
||||
)
|
||||
validate_cart_addons = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``addons``, ``base_position``, ``iao``
|
||||
|
||||
This signal is sent when a user tries to select a combination of addons. In contrast to
|
||||
``validate_cart``, this is executed before the cart is actually modified. You are passed
|
||||
an argument ``addons`` containing a dict of ``(item, variation or None) → count`` tuples as well
|
||||
@@ -328,10 +305,10 @@ appropriate exception message.
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
order_placed = EventPluginSignal(
|
||||
providing_args=["order"]
|
||||
)
|
||||
order_placed = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``order``
|
||||
|
||||
This signal is sent out every time an order is placed. The order object is given
|
||||
as the first argument. This signal is *not* sent out if an order is created through
|
||||
splitting an existing order, so you can not expect to see all orders by listening
|
||||
@@ -340,10 +317,10 @@ to this signal.
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
order_paid = EventPluginSignal(
|
||||
providing_args=["order"]
|
||||
)
|
||||
order_paid = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``order``
|
||||
|
||||
This signal is sent out every time an order is paid. The order object is given
|
||||
as the first argument. This signal is *not* sent out if an order is marked as paid
|
||||
because an already-paid order has been split.
|
||||
@@ -351,80 +328,80 @@ because an already-paid order has been split.
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
order_canceled = EventPluginSignal(
|
||||
providing_args=["order"]
|
||||
)
|
||||
order_canceled = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``order``
|
||||
|
||||
This signal is sent out every time an order is canceled. The order object is given
|
||||
as the first argument.
|
||||
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
order_reactivated = EventPluginSignal(
|
||||
providing_args=["order"]
|
||||
)
|
||||
order_reactivated = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``order``
|
||||
|
||||
This signal is sent out every time a canceled order is reactivated. The order object is given
|
||||
as the first argument.
|
||||
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
order_expired = EventPluginSignal(
|
||||
providing_args=["order"]
|
||||
)
|
||||
order_expired = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``order``
|
||||
|
||||
This signal is sent out every time an order is marked as expired. The order object is given
|
||||
as the first argument.
|
||||
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
order_modified = EventPluginSignal(
|
||||
providing_args=["order"]
|
||||
)
|
||||
order_modified = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``order``
|
||||
|
||||
This signal is sent out every time an order's information is modified. The order object is given
|
||||
as the first argument.
|
||||
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
order_changed = EventPluginSignal(
|
||||
providing_args=["order"]
|
||||
)
|
||||
order_changed = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``order``
|
||||
|
||||
This signal is sent out every time an order's content is changed. The order object is given
|
||||
as the first argument.
|
||||
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
order_approved = EventPluginSignal(
|
||||
providing_args=["order"]
|
||||
)
|
||||
order_approved = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``order``
|
||||
|
||||
This signal is sent out every time an order is being approved. The order object is given
|
||||
as the first argument.
|
||||
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
order_denied = EventPluginSignal(
|
||||
providing_args=["order"]
|
||||
)
|
||||
order_denied = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``order``
|
||||
|
||||
This signal is sent out every time an order is being denied. The order object is given
|
||||
as the first argument.
|
||||
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
order_gracefully_delete = EventPluginSignal(
|
||||
providing_args=["order"]
|
||||
)
|
||||
order_gracefully_delete = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``order``
|
||||
|
||||
This signal is sent out every time a test-mode order is being deleted. The order object
|
||||
is given as the first argument.
|
||||
|
||||
@@ -435,10 +412,10 @@ the deletion of the order.
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
checkin_created = EventPluginSignal(
|
||||
providing_args=["checkin"],
|
||||
)
|
||||
checkin_created = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``checkin``
|
||||
|
||||
This signal is sent out every time a check-in is created (i.e. an order position is marked as
|
||||
checked in). It is not send if the position was already checked in and is force-checked-in a second time.
|
||||
The check-in object is given as the first argument
|
||||
@@ -446,10 +423,10 @@ The check-in object is given as the first argument
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
logentry_display = EventPluginSignal(
|
||||
providing_args=["logentry"]
|
||||
)
|
||||
logentry_display = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``logentry``
|
||||
|
||||
To display an instance of the ``LogEntry`` model to a human user,
|
||||
``pretix.base.signals.logentry_display`` will be sent out with a ``logentry`` argument.
|
||||
|
||||
@@ -459,10 +436,10 @@ to the user. The receivers are expected to return plain text.
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
logentry_object_link = EventPluginSignal(
|
||||
providing_args=["logentry"]
|
||||
)
|
||||
logentry_object_link = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``logentry``
|
||||
|
||||
To display the relationship of an instance of the ``LogEntry`` model to another model
|
||||
to a human user, ``pretix.base.signals.logentry_object_link`` will be sent out with a
|
||||
``logentry`` argument.
|
||||
@@ -487,10 +464,10 @@ Make sure that any user content in the HTML code you return is properly escaped!
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
requiredaction_display = EventPluginSignal(
|
||||
providing_args=["action", "request"]
|
||||
)
|
||||
requiredaction_display = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``action``, ``request``
|
||||
|
||||
To display an instance of the ``RequiredAction`` model to a human user,
|
||||
``pretix.base.signals.requiredaction_display`` will be sent out with a ``action`` argument.
|
||||
You will also get the current ``request`` in a different argument.
|
||||
@@ -501,10 +478,10 @@ to the user. The receivers are expected to return HTML code.
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
event_copy_data = EventPluginSignal(
|
||||
providing_args=["other", "tax_map", "category_map", "item_map", "question_map", "variation_map", "checkin_list_map"]
|
||||
)
|
||||
event_copy_data = EventPluginSignal()
|
||||
"""
|
||||
Arguments: "other", ``tax_map``, ``category_map``, ``item_map``, ``question_map``, ``variation_map``, ``checkin_list_map``
|
||||
|
||||
This signal is sent out when a new event is created as a clone of an existing event, i.e.
|
||||
the settings from the older event are copied to the newer one. You can listen to this
|
||||
signal to copy data or configuration stored within your plugin's models as well.
|
||||
@@ -519,10 +496,10 @@ keyword argument will contain the event to **copy from**. The keyword arguments
|
||||
in the new event of the respective types.
|
||||
"""
|
||||
|
||||
item_copy_data = EventPluginSignal(
|
||||
providing_args=["source", "target"]
|
||||
)
|
||||
item_copy_data = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``source``, ``target``
|
||||
|
||||
This signal is sent out when a new product is created as a clone of an existing product, i.e.
|
||||
the settings from the older product are copied to the newer one. You can listen to this
|
||||
signal to copy data or configuration stored within your plugin's models as well.
|
||||
@@ -546,10 +523,10 @@ All plugins that are installed may send fields for the global settings form, as
|
||||
an OrderedDict of (setting name, form field).
|
||||
"""
|
||||
|
||||
order_fee_calculation = EventPluginSignal(
|
||||
providing_args=['positions', 'invoice_address', 'meta_info', 'total', 'gift_cards']
|
||||
)
|
||||
order_fee_calculation = EventPluginSignal()
|
||||
"""
|
||||
Arguments: 'positions', 'invoice_address', 'meta_info', 'total', 'gift_cards'
|
||||
|
||||
This signals allows you to add fees to an order while it is being created. You are expected to
|
||||
return a list of ``OrderFee`` objects that are not yet saved to the database
|
||||
(because there is no order yet).
|
||||
@@ -562,10 +539,10 @@ keyword argument will contain the total cart sum without any fees. You should no
|
||||
the gift cards in use.
|
||||
"""
|
||||
|
||||
order_fee_type_name = EventPluginSignal(
|
||||
providing_args=['request', 'fee']
|
||||
)
|
||||
order_fee_type_name = EventPluginSignal()
|
||||
"""
|
||||
Arguments: 'request', 'fee'
|
||||
|
||||
This signals allows you to return a human-readable description for a fee type based on the ``fee_type``
|
||||
and ``internal_type`` attributes of the ``OrderFee`` model that you get as keyword arguments. You are
|
||||
expected to return a string or None, if you don't know about this fee.
|
||||
@@ -573,20 +550,20 @@ expected to return a string or None, if you don't know about this fee.
|
||||
As with all plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
allow_ticket_download = EventPluginSignal(
|
||||
providing_args=['order']
|
||||
)
|
||||
allow_ticket_download = EventPluginSignal()
|
||||
"""
|
||||
Arguments: 'order'
|
||||
|
||||
This signal is sent out to check if tickets for an order can be downloaded. If any receiver returns false,
|
||||
a download will not be offered.
|
||||
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
email_filter = EventPluginSignal(
|
||||
providing_args=['message', 'order', 'user']
|
||||
)
|
||||
email_filter = EventPluginSignal()
|
||||
"""
|
||||
Arguments: 'message', 'order', 'user'
|
||||
|
||||
This signal allows you to implement a middleware-style filter on all outgoing emails. You are expected to
|
||||
return a (possibly modified) copy of the message object passed to you.
|
||||
|
||||
@@ -598,10 +575,10 @@ If the email is associated with a specific user, e.g. a notification email, the
|
||||
well, otherwise it will be ``None``.
|
||||
"""
|
||||
|
||||
global_email_filter = GlobalSignal(
|
||||
providing_args=['message', 'order', 'user']
|
||||
)
|
||||
global_email_filter = GlobalSignal()
|
||||
"""
|
||||
Arguments: 'message', 'order', 'user'
|
||||
|
||||
This signal allows you to implement a middleware-style filter on all outgoing emails. You are expected to
|
||||
return a (possibly modified) copy of the message object passed to you.
|
||||
|
||||
@@ -666,10 +643,10 @@ a ``subevent`` argument which might be none and you are expected to return a lis
|
||||
"""
|
||||
|
||||
|
||||
quota_availability = EventPluginSignal(
|
||||
providing_args=['quota', 'result', 'count_waitinglist']
|
||||
)
|
||||
quota_availability = EventPluginSignal()
|
||||
"""
|
||||
Arguments: 'quota', 'result', 'count_waitinglist'
|
||||
|
||||
This signal allows you to modify the availability of a quota. You are passed the ``quota`` and an
|
||||
``availability`` result calculated by pretix code or other plugins. ``availability`` is a tuple
|
||||
with the first entry being one of the ``Quota.AVAILABILITY_*`` constants and the second entry being
|
||||
@@ -682,25 +659,23 @@ system really bad.** Also, keep in mind that your response is subject to caching
|
||||
quotas might be used for display (not for actual order processing).
|
||||
"""
|
||||
|
||||
order_split = EventPluginSignal(
|
||||
providing_args=["original", "split_order"]
|
||||
)
|
||||
order_split = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``original``, ``split_order``
|
||||
|
||||
This signal is sent out when an order is split into two orders and allows you to copy related models
|
||||
to the new order. You will be passed the old order as ``original`` and the new order as ``split_order``.
|
||||
"""
|
||||
|
||||
invoice_line_text = EventPluginSignal(
|
||||
providing_args=["position"]
|
||||
)
|
||||
invoice_line_text = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``position``
|
||||
|
||||
This signal is sent out when an invoice is built for an order. You can return additional text that
|
||||
should be shown on the invoice for the given ``position``.
|
||||
"""
|
||||
|
||||
order_import_columns = EventPluginSignal(
|
||||
providing_args=[]
|
||||
)
|
||||
order_import_columns = EventPluginSignal()
|
||||
"""
|
||||
This signal is sent out if the user performs an import of orders from an external source. You can use this
|
||||
to define additional columns that can be read during import. You are expected to return a list of instances of
|
||||
@@ -709,10 +684,10 @@ to define additional columns that can be read during import. You are expected to
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
validate_event_settings = EventPluginSignal(
|
||||
providing_args=["settings_dict"]
|
||||
)
|
||||
validate_event_settings = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``settings_dict``
|
||||
|
||||
This signal is sent out if the user performs an update of event settings through the API or web interface.
|
||||
You are passed a ``settings_dict`` dictionary with the new state of the event settings object and are expected
|
||||
to raise a ``django.core.exceptions.ValidationError`` if the new state is not valid.
|
||||
@@ -723,9 +698,7 @@ serializer field instead.
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
api_event_settings_fields = EventPluginSignal(
|
||||
providing_args=[]
|
||||
)
|
||||
api_event_settings_fields = EventPluginSignal()
|
||||
"""
|
||||
This signal is sent out to collect serializable settings fields for the API. You are expected to
|
||||
return a dictionary mapping names of attributes in the settings store to DRF serializer field instances.
|
||||
|
||||
@@ -11,7 +11,7 @@ register = template.Library()
|
||||
|
||||
@register.filter("money")
|
||||
def money_filter(value: Decimal, arg='', hide_currency=False):
|
||||
if isinstance(value, (float, int)):
|
||||
if isinstance(value, float) or isinstance(value, int):
|
||||
value = Decimal(value)
|
||||
if not isinstance(value, Decimal):
|
||||
if value == '':
|
||||
@@ -47,7 +47,7 @@ def money_filter(value: Decimal, arg='', hide_currency=False):
|
||||
|
||||
@register.filter("money_numberfield")
|
||||
def money_numberfield_filter(value: Decimal, arg=''):
|
||||
if isinstance(value, (float, int)):
|
||||
if isinstance(value, float) or isinstance(value, int):
|
||||
value = Decimal(value)
|
||||
if not isinstance(value, Decimal):
|
||||
raise TypeError("Invalid data type passed to money filter: %r" % type(value))
|
||||
|
||||
@@ -153,9 +153,9 @@ def markdown_compile_email(source):
|
||||
|
||||
class SnippetExtension(markdown.extensions.Extension):
|
||||
def extendMarkdown(self, md, *args, **kwargs):
|
||||
del md.parser.blockprocessors['olist']
|
||||
del md.parser.blockprocessors['ulist']
|
||||
del md.parser.blockprocessors['quote']
|
||||
md.parser.blockprocessors.deregister('olist')
|
||||
md.parser.blockprocessors.deregister('ulist')
|
||||
md.parser.blockprocessors.deregister('quote')
|
||||
|
||||
|
||||
def markdown_compile(source, snippet=False):
|
||||
|
||||
@@ -48,7 +48,7 @@ def page_not_found(request, exception):
|
||||
except (AttributeError, IndexError):
|
||||
pass
|
||||
else:
|
||||
if isinstance(message, (str, Promise)):
|
||||
if isinstance(message, str) or isinstance(message, Promise):
|
||||
exception_repr = str(message)
|
||||
context = {
|
||||
'request_path': request.path,
|
||||
|
||||
@@ -4,25 +4,43 @@ import celery.exceptions
|
||||
from celery.result import AsyncResult
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.http import JsonResponse
|
||||
from django.shortcuts import redirect, render
|
||||
from django.test import RequestFactory
|
||||
from django.utils.translation import gettext as _
|
||||
from django.views.generic import FormView
|
||||
|
||||
from pretix.base.models import User
|
||||
from pretix.base.services.tasks import ProfiledEventTask
|
||||
from pretix.celery_app import app
|
||||
|
||||
logger = logging.getLogger('pretix.base.tasks')
|
||||
|
||||
|
||||
class AsyncMixin:
|
||||
class AsyncAction:
|
||||
task = None
|
||||
success_url = None
|
||||
error_url = None
|
||||
known_errortypes = []
|
||||
|
||||
def do(self, *args, **kwargs):
|
||||
if not isinstance(self.task, app.Task):
|
||||
raise TypeError('Method has no task attached')
|
||||
|
||||
try:
|
||||
res = self.task.apply_async(args=args, kwargs=kwargs)
|
||||
except ConnectionError:
|
||||
# Task very likely not yet sent, due to redis restarting etc. Let's try once agan
|
||||
res = self.task.apply_async(args=args, kwargs=kwargs)
|
||||
|
||||
if 'ajax' in self.request.GET or 'ajax' in self.request.POST:
|
||||
data = self._return_ajax_result(res)
|
||||
data['check_url'] = self.get_check_url(res.id, True)
|
||||
return JsonResponse(data)
|
||||
else:
|
||||
if res.ready():
|
||||
if res.successful() and not isinstance(res.info, Exception):
|
||||
return self.success(res.info)
|
||||
else:
|
||||
return self.error(res.info)
|
||||
return redirect(self.get_check_url(res.id, False))
|
||||
|
||||
def get_success_url(self, value):
|
||||
return self.success_url
|
||||
|
||||
@@ -32,6 +50,11 @@ class AsyncMixin:
|
||||
def get_check_url(self, task_id, ajax):
|
||||
return self.request.path + '?async_id=%s' % task_id + ('&ajax=1' if ajax else '')
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
if 'async_id' in request.GET and settings.HAS_CELERY:
|
||||
return self.get_result(request)
|
||||
return self.http_method_not_allowed(request)
|
||||
|
||||
def _ajax_response_data(self):
|
||||
return {}
|
||||
|
||||
@@ -63,7 +86,7 @@ class AsyncMixin:
|
||||
if smes:
|
||||
messages.success(self.request, smes)
|
||||
# TODO: Do not store message if the ajax client states that it will not redirect
|
||||
# but handle the message itself
|
||||
# but handle the mssage itself
|
||||
data.update({
|
||||
'redirect': self.get_success_url(res.info),
|
||||
'success': True,
|
||||
@@ -72,7 +95,7 @@ class AsyncMixin:
|
||||
else:
|
||||
messages.error(self.request, self.get_error_message(res.info))
|
||||
# TODO: Do not store message if the ajax client states that it will not redirect
|
||||
# but handle the message itself
|
||||
# but handle the mssage itself
|
||||
data.update({
|
||||
'redirect': self.get_error_url(),
|
||||
'success': False,
|
||||
@@ -136,124 +159,3 @@ class AsyncMixin:
|
||||
|
||||
def get_success_message(self, value):
|
||||
return _('The task has been completed.')
|
||||
|
||||
|
||||
class AsyncAction(AsyncMixin):
|
||||
task = None
|
||||
|
||||
def do(self, *args, **kwargs):
|
||||
if not isinstance(self.task, app.Task):
|
||||
raise TypeError('Method has no task attached')
|
||||
|
||||
try:
|
||||
res = self.task.apply_async(args=args, kwargs=kwargs)
|
||||
except ConnectionError:
|
||||
# Task very likely not yet sent, due to redis restarting etc. Let's try once again
|
||||
res = self.task.apply_async(args=args, kwargs=kwargs)
|
||||
|
||||
if 'ajax' in self.request.GET or 'ajax' in self.request.POST:
|
||||
data = self._return_ajax_result(res)
|
||||
data['check_url'] = self.get_check_url(res.id, True)
|
||||
return JsonResponse(data)
|
||||
else:
|
||||
if res.ready():
|
||||
if res.successful() and not isinstance(res.info, Exception):
|
||||
return self.success(res.info)
|
||||
else:
|
||||
return self.error(res.info)
|
||||
return redirect(self.get_check_url(res.id, False))
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
if 'async_id' in request.GET and settings.HAS_CELERY:
|
||||
return self.get_result(request)
|
||||
return self.http_method_not_allowed(request)
|
||||
|
||||
|
||||
class AsyncFormView(AsyncMixin, FormView):
|
||||
"""
|
||||
FormView variant in which instead of ``form_valid``, an ``async_form_valid``
|
||||
is executed in a celery task. Note that this places some severe limitations
|
||||
on the form and the view, e.g. neither ``get_form*`` nor the form itself
|
||||
may depend on the request object unless specifically supported by this class.
|
||||
Also, all form keyword arguments except ``instance`` need to be serializable.
|
||||
"""
|
||||
known_errortypes = ['ValidationError']
|
||||
|
||||
def __init_subclass__(cls):
|
||||
def async_execute(self, request_path, form_kwargs, organizer=None, event=None, user=None):
|
||||
view_instance = cls()
|
||||
view_instance.request = RequestFactory().post(request_path)
|
||||
if organizer:
|
||||
view_instance.request.event = event
|
||||
if organizer:
|
||||
view_instance.request.organizer = organizer
|
||||
if user:
|
||||
view_instance.request.user = User.objects.get(pk=user)
|
||||
|
||||
form_class = view_instance.get_form_class()
|
||||
if form_kwargs.get('instance'):
|
||||
cls.model.objects.get(pk=form_kwargs['instance'])
|
||||
|
||||
form_kwargs = view_instance.get_async_form_kwargs(form_kwargs, organizer, event)
|
||||
|
||||
form = form_class(**form_kwargs)
|
||||
return view_instance.async_form_valid(self, form)
|
||||
|
||||
cls.async_execute = app.task(
|
||||
base=ProfiledEventTask,
|
||||
bind=True,
|
||||
name=cls.__module__ + '.' + cls.__name__ + '.async_execute',
|
||||
throws=(ValidationError,)
|
||||
)(async_execute)
|
||||
|
||||
def async_form_valid(self, task, form):
|
||||
pass
|
||||
|
||||
def get_async_form_kwargs(self, form_kwargs, organizer=None, event=None):
|
||||
return form_kwargs
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
if 'async_id' in request.GET and settings.HAS_CELERY:
|
||||
return self.get_result(request)
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
def form_valid(self, form):
|
||||
if form.files:
|
||||
raise TypeError('File upload currently not supported in AsyncFormView')
|
||||
form_kwargs = {
|
||||
k: v for k, v in self.get_form_kwargs().items()
|
||||
}
|
||||
if form_kwargs.get('instance'):
|
||||
if form_kwargs['instance'].pk:
|
||||
form_kwargs['instance'] = form_kwargs['instance'].pk
|
||||
else:
|
||||
form_kwargs['instance'] = None
|
||||
form_kwargs.setdefault('data', {})
|
||||
kwargs = {
|
||||
'request_path': self.request.path,
|
||||
'form_kwargs': form_kwargs,
|
||||
}
|
||||
if hasattr(self.request, 'organizer'):
|
||||
kwargs['organizer'] = self.request.organizer.pk
|
||||
if self.request.user.is_authenticated:
|
||||
kwargs['user'] = self.request.user.pk
|
||||
if hasattr(self.request, 'event'):
|
||||
kwargs['event'] = self.request.event.pk
|
||||
|
||||
try:
|
||||
res = type(self).async_execute.apply_async(kwargs=kwargs)
|
||||
except ConnectionError:
|
||||
# Task very likely not yet sent, due to redis restarting etc. Let's try once again
|
||||
res = type(self).async_execute.apply_async(kwargs=kwargs)
|
||||
|
||||
if 'ajax' in self.request.GET or 'ajax' in self.request.POST:
|
||||
data = self._return_ajax_result(res)
|
||||
data['check_url'] = self.get_check_url(res.id, True)
|
||||
return JsonResponse(data)
|
||||
else:
|
||||
if res.ready():
|
||||
if res.successful() and not isinstance(res.info, Exception):
|
||||
return self.success(res.info)
|
||||
else:
|
||||
return self.error(res.info)
|
||||
return redirect(self.get_check_url(res.id, False))
|
||||
|
||||
@@ -1439,8 +1439,6 @@ class VoucherFilterForm(FilterForm):
|
||||
s = fdata.get('tag').strip()
|
||||
if s == '<>':
|
||||
qs = qs.filter(Q(tag__isnull=True) | Q(tag=''))
|
||||
elif s[0] == '"' and s[-1] == '"':
|
||||
qs = qs.filter(tag__iexact=s[1:-1])
|
||||
else:
|
||||
qs = qs.filter(tag__icontains=s)
|
||||
|
||||
|
||||
@@ -337,7 +337,7 @@ class ItemCreateForm(I18nModelForm):
|
||||
setattr(self.instance, f, getattr(self.cleaned_data['copy_from'], f))
|
||||
else:
|
||||
# Add to all sales channels by default
|
||||
self.instance.sales_channels = list(get_all_sales_channels().keys())
|
||||
self.instance.sales_channels = [k for k in get_all_sales_channels().keys()]
|
||||
|
||||
self.instance.position = (self.event.items.aggregate(p=Max('position'))['p'] or 0) + 1
|
||||
instance = super().save(*args, **kwargs)
|
||||
|
||||
@@ -75,7 +75,7 @@ class ExtendForm(I18nModelForm):
|
||||
return super().save(commit)
|
||||
|
||||
|
||||
class ForceQuotaConfirmationForm(forms.Form):
|
||||
class ConfirmPaymentForm(forms.Form):
|
||||
force = forms.BooleanField(
|
||||
label=_('Overbook quota and ignore late payment'),
|
||||
help_text=_('If you check this box, this operation will be performed even if it leads to an overbooked quota '
|
||||
@@ -101,15 +101,7 @@ class ForceQuotaConfirmationForm(forms.Form):
|
||||
del self.fields['force']
|
||||
|
||||
|
||||
class ConfirmPaymentForm(ForceQuotaConfirmationForm):
|
||||
pass
|
||||
|
||||
|
||||
class ReactivateOrderForm(ForceQuotaConfirmationForm):
|
||||
pass
|
||||
|
||||
|
||||
class CancelForm(ForceQuotaConfirmationForm):
|
||||
class CancelForm(ConfirmPaymentForm):
|
||||
send_email = forms.BooleanField(
|
||||
required=False,
|
||||
label=_('Notify customer by email'),
|
||||
|
||||
@@ -5,7 +5,7 @@ from io import StringIO
|
||||
from django import forms
|
||||
from django.core.exceptions import ObjectDoesNotExist, ValidationError
|
||||
from django.core.validators import EmailValidator
|
||||
from django.db.models.functions import Upper
|
||||
from django.db.models.functions import Lower
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext_lazy as _, pgettext_lazy
|
||||
from django_scopes.forms import SafeModelChoiceField
|
||||
@@ -346,8 +346,8 @@ class VoucherBulkForm(VoucherForm):
|
||||
data = super().clean()
|
||||
|
||||
vouchers = self.instance.event.vouchers.annotate(
|
||||
code_upper=Upper('code')
|
||||
).filter(code_upper__in=[c.upper() for c in data['codes']])
|
||||
code_lower=Lower('code')
|
||||
).filter(code_lower__in=[c.lower() for c in data['codes']])
|
||||
if vouchers.exists():
|
||||
raise ValidationError(_('A voucher with one of these codes already exists.'))
|
||||
|
||||
@@ -377,5 +377,26 @@ class VoucherBulkForm(VoucherForm):
|
||||
|
||||
return data
|
||||
|
||||
def post_bulk_save(self, objs):
|
||||
pass
|
||||
def save(self, event, *args, **kwargs):
|
||||
objs = []
|
||||
for code in self.cleaned_data['codes']:
|
||||
obj = modelcopy(self.instance)
|
||||
obj.event = event
|
||||
obj.code = code
|
||||
try:
|
||||
obj.seat = self.cleaned_data['seats'].pop()
|
||||
obj.item = obj.seat.product
|
||||
except IndexError:
|
||||
pass
|
||||
data = dict(self.cleaned_data)
|
||||
data['code'] = code
|
||||
data['bulk'] = True
|
||||
del data['codes']
|
||||
objs.append(obj)
|
||||
Voucher.objects.bulk_create(objs, batch_size=200)
|
||||
objs = []
|
||||
for v in event.vouchers.filter(code__in=self.cleaned_data['codes']):
|
||||
# We need to query them again as bulk_create does not fill in .pk values on databases
|
||||
# other than PostgreSQL
|
||||
objs.append(v)
|
||||
return objs
|
||||
|
||||
@@ -7,7 +7,7 @@ from django.utils.translation import gettext as _
|
||||
|
||||
|
||||
def current_url(request):
|
||||
if request.GET:
|
||||
if len(request.GET):
|
||||
return request.path + '?' + request.GET.urlencode()
|
||||
else:
|
||||
return request.path
|
||||
|
||||
@@ -2,9 +2,7 @@ from django.dispatch import Signal
|
||||
|
||||
from pretix.base.signals import DeprecatedSignal, EventPluginSignal
|
||||
|
||||
html_page_start = Signal(
|
||||
providing_args=[]
|
||||
)
|
||||
html_page_start = Signal()
|
||||
"""
|
||||
This signal allows you to put code in the beginning of the main page for every
|
||||
page in the backend. You are expected to return HTML.
|
||||
@@ -12,10 +10,10 @@ page in the backend. You are expected to return HTML.
|
||||
The ``sender`` keyword argument will contain the request.
|
||||
"""
|
||||
|
||||
html_head = EventPluginSignal(
|
||||
providing_args=["request"]
|
||||
)
|
||||
html_head = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``request``
|
||||
|
||||
This signal allows you to put code inside the HTML ``<head>`` tag
|
||||
of every page in the backend. You will get the request as the keyword argument
|
||||
``request`` and are expected to return plain HTML.
|
||||
@@ -23,10 +21,10 @@ of every page in the backend. You will get the request as the keyword argument
|
||||
As with all plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
nav_event = EventPluginSignal(
|
||||
providing_args=["request"]
|
||||
)
|
||||
nav_event = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``request``
|
||||
|
||||
This signal allows you to add additional views to the admin panel
|
||||
navigation. You will get the request as a keyword argument ``request``.
|
||||
Receivers are expected to return a list of dictionaries. The dictionaries
|
||||
@@ -48,10 +46,10 @@ in pretix.
|
||||
As with all plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
nav_topbar = Signal(
|
||||
providing_args=["request"]
|
||||
)
|
||||
nav_topbar = Signal()
|
||||
"""
|
||||
Arguments: ``request``
|
||||
|
||||
This signal allows you to add additional views to the top navigation bar.
|
||||
You will get the request as a keyword argument ``request``.
|
||||
Receivers are expected to return a list of dictionaries. The dictionaries
|
||||
@@ -67,10 +65,10 @@ This is no ``EventPluginSignal``, so you do not get the event in the ``sender``
|
||||
and you may get the signal regardless of whether your plugin is active.
|
||||
"""
|
||||
|
||||
nav_global = Signal(
|
||||
providing_args=["request"]
|
||||
)
|
||||
nav_global = Signal()
|
||||
"""
|
||||
Arguments: ``request``
|
||||
|
||||
This signal allows you to add additional views to the navigation bar when no event is
|
||||
selected. You will get the request as a keyword argument ``request``.
|
||||
Receivers are expected to return a list of dictionaries. The dictionaries
|
||||
@@ -92,10 +90,10 @@ This is no ``EventPluginSignal``, so you do not get the event in the ``sender``
|
||||
and you may get the signal regardless of whether your plugin is active.
|
||||
"""
|
||||
|
||||
event_dashboard_top = EventPluginSignal(
|
||||
providing_args=['request']
|
||||
)
|
||||
event_dashboard_top = EventPluginSignal()
|
||||
"""
|
||||
Arguments: 'request'
|
||||
|
||||
This signal is sent out to include custom HTML in the top part of the the event dashboard.
|
||||
Receivers should return HTML.
|
||||
|
||||
@@ -103,9 +101,7 @@ As with all plugin signals, the ``sender`` keyword argument will contain the eve
|
||||
An additional keyword argument ``subevent`` *can* contain a sub-event.
|
||||
"""
|
||||
|
||||
event_dashboard_widgets = EventPluginSignal(
|
||||
providing_args=[]
|
||||
)
|
||||
event_dashboard_widgets = EventPluginSignal()
|
||||
"""
|
||||
This signal is sent out to include widgets in the event dashboard. Receivers
|
||||
should return a list of dictionaries, where each dictionary can have the keys:
|
||||
@@ -120,10 +116,10 @@ As with all plugin signals, the ``sender`` keyword argument will contain the eve
|
||||
An additional keyword argument ``subevent`` *can* contain a sub-event.
|
||||
"""
|
||||
|
||||
user_dashboard_widgets = Signal(
|
||||
providing_args=['user']
|
||||
)
|
||||
user_dashboard_widgets = Signal()
|
||||
"""
|
||||
Arguments: 'user'
|
||||
|
||||
This signal is sent out to include widgets in the personal user dashboard. Receivers
|
||||
should return a list of dictionaries, where each dictionary can have the keys:
|
||||
|
||||
@@ -136,36 +132,31 @@ should return a list of dictionaries, where each dictionary can have the keys:
|
||||
This is a regular django signal (no pretix event signal).
|
||||
"""
|
||||
|
||||
voucher_form_html = EventPluginSignal(
|
||||
providing_args=['form']
|
||||
)
|
||||
voucher_form_html = EventPluginSignal()
|
||||
"""
|
||||
Arguments: 'form'
|
||||
|
||||
This signal allows you to add additional HTML to the form that is used for modifying vouchers.
|
||||
You receive the form object in the ``form`` keyword argument.
|
||||
|
||||
As with all plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
voucher_form_class = EventPluginSignal(
|
||||
providing_args=['cls']
|
||||
)
|
||||
voucher_form_class = EventPluginSignal()
|
||||
"""
|
||||
Arguments: 'cls'
|
||||
|
||||
This signal allows you to replace the form class that is used for modifying vouchers.
|
||||
You will receive the default form class (or the class set by a previous plugin) in the
|
||||
``cls`` argument so that you can inherit from it.
|
||||
|
||||
Note that this is also called for the voucher bulk creation form, which is executed in
|
||||
an asynchronous context. For the bulk creation form, ``save()`` is not called. Instead,
|
||||
you can implement ``post_bulk_save(saved_vouchers)`` which may be called multiple times
|
||||
for every batch persisted to the database.
|
||||
|
||||
As with all plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
voucher_form_validation = EventPluginSignal(
|
||||
providing_args=['form']
|
||||
)
|
||||
voucher_form_validation = EventPluginSignal()
|
||||
"""
|
||||
Arguments: 'form'
|
||||
|
||||
This signal allows you to add additional validation to the form that is used for
|
||||
creating and modifying vouchers. You will receive the form instance in the ``form``
|
||||
argument and the current data state in the ``data`` argument.
|
||||
@@ -173,28 +164,28 @@ argument and the current data state in the ``data`` argument.
|
||||
As with all plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
quota_detail_html = EventPluginSignal(
|
||||
providing_args=['quota']
|
||||
)
|
||||
quota_detail_html = EventPluginSignal()
|
||||
"""
|
||||
Arguments: 'quota'
|
||||
|
||||
This signal allows you to append HTML to a Quota's detail view. You receive the
|
||||
quota as argument in the ``quota`` keyword argument.
|
||||
|
||||
As with all plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
organizer_edit_tabs = DeprecatedSignal(
|
||||
providing_args=['organizer', 'request']
|
||||
)
|
||||
organizer_edit_tabs = DeprecatedSignal()
|
||||
"""
|
||||
Arguments: 'organizer', 'request'
|
||||
|
||||
Deprecated signal, no longer works. We just keep the definition so old plugins don't
|
||||
break the installation.
|
||||
"""
|
||||
|
||||
nav_organizer = Signal(
|
||||
providing_args=['organizer', 'request']
|
||||
)
|
||||
nav_organizer = Signal()
|
||||
"""
|
||||
Arguments: 'organizer', 'request'
|
||||
|
||||
This signal is sent out to include tab links on the detail page of an organizer.
|
||||
Receivers are expected to return a list of dictionaries. The dictionaries
|
||||
should contain at least the keys ``label`` and ``url``. You should also return
|
||||
@@ -215,30 +206,30 @@ This is a regular django signal (no pretix event signal). Receivers will be pass
|
||||
the keyword arguments ``organizer`` and ``request``.
|
||||
"""
|
||||
|
||||
order_info = EventPluginSignal(
|
||||
providing_args=["order", "request"]
|
||||
)
|
||||
order_info = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``order``, ``request``
|
||||
|
||||
This signal is sent out to display additional information on the order detail page
|
||||
|
||||
As with all plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
Additionally, the argument ``order`` and ``request`` are available.
|
||||
"""
|
||||
|
||||
order_position_buttons = EventPluginSignal(
|
||||
providing_args=["order", "position", "request"]
|
||||
)
|
||||
order_position_buttons = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``order``, ``position``, ``request``
|
||||
|
||||
This signal is sent out to display additional buttons for a single position of an order.
|
||||
|
||||
As with all plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
Additionally, the argument ``order`` and ``request`` are available.
|
||||
"""
|
||||
|
||||
nav_event_settings = EventPluginSignal(
|
||||
providing_args=['request']
|
||||
)
|
||||
nav_event_settings = EventPluginSignal()
|
||||
"""
|
||||
Arguments: 'request'
|
||||
|
||||
This signal is sent out to include tab links on the settings page of an event.
|
||||
Receivers are expected to return a list of dictionaries. The dictionaries
|
||||
should contain at least the keys ``label`` and ``url``. You should also return
|
||||
@@ -253,10 +244,10 @@ As with all plugin signals, the ``sender`` keyword argument will contain the eve
|
||||
A second keyword argument ``request`` will contain the request object.
|
||||
"""
|
||||
|
||||
event_settings_widget = EventPluginSignal(
|
||||
providing_args=['request']
|
||||
)
|
||||
event_settings_widget = EventPluginSignal()
|
||||
"""
|
||||
Arguments: 'request'
|
||||
|
||||
This signal is sent out to include template snippets on the settings page of an event
|
||||
that allows generating a pretix Widget code.
|
||||
|
||||
@@ -264,10 +255,10 @@ As with all plugin signals, the ``sender`` keyword argument will contain the eve
|
||||
A second keyword argument ``request`` will contain the request object.
|
||||
"""
|
||||
|
||||
item_forms = EventPluginSignal(
|
||||
providing_args=['request', 'item']
|
||||
)
|
||||
item_forms = EventPluginSignal()
|
||||
"""
|
||||
Arguments: 'request', 'item'
|
||||
|
||||
This signal allows you to return additional forms that should be rendered on the product
|
||||
modification page. You are passed ``request`` and ``item`` arguments and are expected to return
|
||||
an instance of a form class that you bind yourself when appropriate. Your form will be executed
|
||||
@@ -277,10 +268,10 @@ styles. It is advisable to set a prefix for your form to avoid clashes with othe
|
||||
As with all plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
item_formsets = EventPluginSignal(
|
||||
providing_args=['request', 'item']
|
||||
)
|
||||
item_formsets = EventPluginSignal()
|
||||
"""
|
||||
Arguments: 'request', 'item'
|
||||
|
||||
This signal allows you to return additional formsets that should be rendered on the product
|
||||
modification page. You are passed ``request`` and ``item`` arguments and are expected to return
|
||||
an instance of a formset class that you bind yourself when appropriate. Your formset will be
|
||||
@@ -295,10 +286,10 @@ will be passed a ``formset`` variable with your formset.
|
||||
As with all plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
subevent_forms = EventPluginSignal(
|
||||
providing_args=['request', 'subevent', 'copy_from']
|
||||
)
|
||||
subevent_forms = EventPluginSignal()
|
||||
"""
|
||||
Arguments: 'request', 'subevent', 'copy_from'
|
||||
|
||||
This signal allows you to return additional forms that should be rendered on the subevent creation
|
||||
or modification page. You are passed ``request`` and ``subevent`` arguments and are expected to return
|
||||
an instance of a form class that you bind yourself when appropriate. Your form will be executed
|
||||
@@ -312,17 +303,17 @@ creation, ``copy_from`` can be a subevent that is being copied from.
|
||||
As with all plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
oauth_application_registered = Signal(
|
||||
providing_args=["user", "application"]
|
||||
)
|
||||
oauth_application_registered = Signal()
|
||||
"""
|
||||
Arguments: ``user``, ``application``
|
||||
|
||||
This signal will be called whenever a user registers a new OAuth application.
|
||||
"""
|
||||
|
||||
order_search_filter_q = Signal(
|
||||
providing_args=["query"]
|
||||
)
|
||||
order_search_filter_q = Signal()
|
||||
"""
|
||||
Arguments: ``query``
|
||||
|
||||
This signal will be called whenever a free-text order search is performed. You are expected to return one
|
||||
Q object that will be OR-ed with existing search queries. As order search exists on a global level as well,
|
||||
this is not an Event signal and will be called even if your plugin is not active. ``sender`` will contain the
|
||||
@@ -330,10 +321,10 @@ event if the search is performed within an event, and ``None`` otherwise. The se
|
||||
``query``.
|
||||
"""
|
||||
|
||||
order_search_forms = EventPluginSignal(
|
||||
providing_args=['request']
|
||||
)
|
||||
order_search_forms = EventPluginSignal()
|
||||
"""
|
||||
Arguments: 'request'
|
||||
|
||||
This signal allows you to return additional forms that should be rendered in the advanced order search.
|
||||
You are passed ``request`` argument and are expected to return an instance of a form class that you bind
|
||||
yourself when appropriate. Your form will be executed as part of the standard validation and rendering
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
{% if request.event.has_subevents %}
|
||||
<form class="form-inline helper-display-inline" action="" method="get">
|
||||
<form class="form-inline helper-display-inline" action="" method="get">
|
||||
{% include "pretixcontrol/event/fragment_subevent_choice_simple.html" with auto_submit=True %}
|
||||
{% include "pretixcontrol/event/fragment_subevent_choice_simple.html" %}
|
||||
</form>
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% load i18n %}
|
||||
<p>
|
||||
<select name="subevent" class="form-control{% if auto_submit %} simple-subevent-choice{% endif %}" data-model-select2="event"
|
||||
<select name="subevent" class="form-control simple-subevent-choice" data-model-select2="event"
|
||||
data-select2-url="{% url "control:event.subevents.select2" organizer=request.event.organizer.slug event=request.event.slug %}"
|
||||
data-placeholder="{% trans "All dates" context "subevent" %}">
|
||||
{% for se in selected_subevents %}
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
|
||||
{% if request.event.has_subevents %}
|
||||
<form class="form-inline helper-display-inline" action="" method="get">
|
||||
{% include "pretixcontrol/event/fragment_subevent_choice_simple.html" with auto_submit=True %}
|
||||
{% include "pretixcontrol/event/fragment_subevent_choice_simple.html" %}
|
||||
</form>
|
||||
{% endif %}
|
||||
{% if not request.event.has_subevents or subevent %}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
</p>
|
||||
{% if request.event.has_subevents %}
|
||||
<form class="form-inline helper-display-inline" action="" method="get">
|
||||
{% include "pretixcontrol/event/fragment_subevent_choice_simple.html" with auto_submit=True %}
|
||||
{% include "pretixcontrol/event/fragment_subevent_choice_simple.html" %}
|
||||
</form>
|
||||
{% endif %}
|
||||
{% if quotas|length == 0 %}
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
|
||||
<form method="post" class="form-horizontal" href="">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form form layout='horizontal' horizontal_label_class='sr-only' horizontal_field_class='col-md-12' %}
|
||||
<div class="form-group submit-group">
|
||||
<a class="btn btn-default btn-lg"
|
||||
href="{% url "control:event.order" event=request.event.slug organizer=request.event.organizer.slug code=order.code %}">
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
{% block title %}{% trans "Voucher" %}{% endblock %}
|
||||
{% block inside %}
|
||||
<h1>{% trans "Create multiple vouchers" %}</h1>
|
||||
<form action="" method="post" class="form-horizontal" data-asynctask>
|
||||
<form action="" method="post" class="form-horizontal">
|
||||
{% csrf_token %}
|
||||
{% bootstrap_form_errors form %}
|
||||
<fieldset>
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
<td>
|
||||
<strong>
|
||||
{% if t.tag %}
|
||||
<a href="{% url "control:event.vouchers" organizer=request.event.organizer.slug event=request.event.slug %}?tag={{ '"'|add:t.tag|add:'"'|urlencode }}">
|
||||
<a href="{% url "control:event.vouchers" organizer=request.event.organizer.slug event=request.event.slug %}?tag={{ t.tag|urlencode }}">
|
||||
{{ t.tag }}
|
||||
</a>
|
||||
{% else %}
|
||||
|
||||
@@ -48,9 +48,15 @@
|
||||
</p>
|
||||
{% endif %}
|
||||
{% if request.event.has_subevents %}
|
||||
<div class="col-md-6">
|
||||
{% include "pretixcontrol/event/fragment_subevent_choice_simple.html" %}
|
||||
</div>
|
||||
<select name="subevent" class="form-control">
|
||||
<option value="">{% trans "All dates" context "subevent" %}</option>
|
||||
{% for se in request.event.subevents.all %}
|
||||
<option value="{{ se.id }}"
|
||||
{% if request.GET.subevent|add:0 == se.id %}selected="selected"{% endif %}>
|
||||
{{ se.name }} – {{ se.get_date_range_display }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% endif %}
|
||||
<button class="btn btn-large btn-primary" type="submit">
|
||||
{% trans "Send as many vouchers as possible" %}
|
||||
@@ -74,50 +80,52 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form class="row filter-form" action="" method="get">
|
||||
<div class="col-lg-2 col-md-3 col-xs-6">
|
||||
<select name="status" class="form-control">
|
||||
<option value="a"
|
||||
{% if request.GET.status == "p" %}selected="selected"{% endif %}>{% trans "All entries" %}</option>
|
||||
<option value="w"
|
||||
{% if request.GET.status == "w" or not request.GET.status %}selected="selected"{% endif %}>
|
||||
{% trans "Waiting for a voucher" %}</option>
|
||||
<option value="s"
|
||||
{% if request.GET.status == "s" %}selected="selected"{% endif %}>{% trans "Voucher assigned" %}</option>
|
||||
<option value="v"
|
||||
{% if request.GET.status == "v" %}selected="selected"{% endif %}>
|
||||
{% trans "Waiting for redemption" %}</option>
|
||||
<option value="r"
|
||||
{% if request.GET.status == "r" %}selected="selected"{% endif %}>
|
||||
{% trans "Successfully redeemed" %}</option>
|
||||
<option value="e"
|
||||
{% if request.GET.status == "e" %}selected="selected"{% endif %}>
|
||||
{% trans "Voucher expired" %}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-lg-2 col-md-3 col-xs-6">
|
||||
<select name="item" class="form-control">
|
||||
<option value="">{% trans "All products" %}</option>
|
||||
{% for item in items %}
|
||||
<option value="{{ item.id }}"
|
||||
{% if request.GET.item|add:0 == item.id %}selected="selected"{% endif %}>
|
||||
{{ item }}
|
||||
<p>
|
||||
<form class="form-inline helper-display-inline" action="" method="get">
|
||||
<select name="status" class="form-control">
|
||||
<option value="a"
|
||||
{% if request.GET.status == "p" %}selected="selected"{% endif %}>{% trans "All entries" %}</option>
|
||||
<option value="w"
|
||||
{% if request.GET.status == "w" or not request.GET.status %}selected="selected"{% endif %}>
|
||||
{% trans "Waiting for a voucher" %}</option>
|
||||
<option value="s"
|
||||
{% if request.GET.status == "s" %}selected="selected"{% endif %}>{% trans "Voucher assigned" %}</option>
|
||||
<option value="v"
|
||||
{% if request.GET.status == "v" %}selected="selected"{% endif %}>
|
||||
{% trans "Waiting for redemption" %}</option>
|
||||
<option value="r"
|
||||
{% if request.GET.status == "r" %}selected="selected"{% endif %}>
|
||||
{% trans "Successfully redeemed" %}</option>
|
||||
<option value="e"
|
||||
{% if request.GET.status == "e" %}selected="selected"{% endif %}>
|
||||
{% trans "Voucher expired" %}</option>
|
||||
</select>
|
||||
<select name="item" class="form-control">
|
||||
<option value="">{% trans "All products" %}</option>
|
||||
{% for item in items %}
|
||||
<option value="{{ item.id }}"
|
||||
{% if request.GET.item|add:0 == item.id %}selected="selected"{% endif %}>
|
||||
{{ item }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% if request.event.has_subevents %}
|
||||
<select name="subevent" class="form-control">
|
||||
<option value="">{% trans "All dates" context "subevent" %}</option>
|
||||
{% for se in request.event.subevents.all %}
|
||||
<option value="{{ se.id }}"
|
||||
{% if request.GET.subevent|add:0 == se.id %}selected="selected"{% endif %}>
|
||||
{{ se.name }} – {{ se.get_date_range_display }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
{% if request.event.has_subevents %}
|
||||
<div class="col-lg-4 col-md-6 col-sm-12 col-xs-12">
|
||||
{% include "pretixcontrol/event/fragment_subevent_choice_simple.html" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="col-lg-4 col-md-6 col-sm-12 col-xs-12">
|
||||
<button class="btn btn-primary" type="submit"><span class="fa fa-filter"></span> {% trans "Filter" %}</button>
|
||||
<a href="?{% url_replace request "download" "yes" %}"
|
||||
<button class="btn btn-primary" type="submit">{% trans "Filter" %}</button>
|
||||
<a href="?{% url_replace request "download" "yes" %}"
|
||||
class="btn btn-default"><i class="fa fa-download"></i>
|
||||
{% trans "Download list" %}</a>
|
||||
</div>
|
||||
{% trans "Download list" %}</a>
|
||||
</form>
|
||||
</p>
|
||||
<form method="post" action="?next={{ request.get_full_path|urlencode }}">
|
||||
{% csrf_token %}
|
||||
<div class="table-responsive">
|
||||
@@ -158,7 +166,7 @@
|
||||
{% endif %}
|
||||
</td>
|
||||
{% if request.event.has_subevents %}
|
||||
<td>{{ e.subevent.name }} – {{ e.subevent.get_date_range_display }} {{ e.subevent.date_from|date:"TIME_FORMAT" }}</td>
|
||||
<td>{{ e.subevent.name }} – {{ e.subevent.get_date_range_display }}</td>
|
||||
{% endif %}
|
||||
<td>
|
||||
{{ e.created|date:"SHORT_DATETIME_FORMAT" }}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from django.conf.urls import include, url
|
||||
from django.conf.urls import include, re_path
|
||||
from django.views.generic.base import RedirectView
|
||||
|
||||
from pretix.control.views import (
|
||||
@@ -8,310 +8,327 @@ from pretix.control.views import (
|
||||
)
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^logout$', auth.logout, name='auth.logout'),
|
||||
url(r'^login$', auth.login, name='auth.login'),
|
||||
url(r'^login/2fa$', auth.Login2FAView.as_view(), name='auth.login.2fa'),
|
||||
url(r'^register$', auth.register, name='auth.register'),
|
||||
url(r'^invite/(?P<token>[a-zA-Z0-9]+)$', auth.invite, name='auth.invite'),
|
||||
url(r'^forgot$', auth.Forgot.as_view(), name='auth.forgot'),
|
||||
url(r'^forgot/recover$', auth.Recover.as_view(), name='auth.forgot.recover'),
|
||||
url(r'^$', dashboards.user_index, name='index'),
|
||||
url(r'^widgets.json$', dashboards.user_index_widgets_lazy, name='index.widgets'),
|
||||
url(r'^global/settings/$', global_settings.GlobalSettingsView.as_view(), name='global.settings'),
|
||||
url(r'^global/update/$', global_settings.UpdateCheckView.as_view(), name='global.update'),
|
||||
url(r'^global/message/$', global_settings.MessageView.as_view(), name='global.message'),
|
||||
url(r'^logdetail/$', global_settings.LogDetailView.as_view(), name='global.logdetail'),
|
||||
url(r'^logdetail/payment/$', global_settings.PaymentDetailView.as_view(), name='global.paymentdetail'),
|
||||
url(r'^logdetail/refund/$', global_settings.RefundDetailView.as_view(), name='global.refunddetail'),
|
||||
url(r'^geocode/$', geo.GeoCodeView.as_view(), name='global.geocode'),
|
||||
url(r'^reauth/$', user.ReauthView.as_view(), name='user.reauth'),
|
||||
url(r'^sudo/$', user.StartStaffSession.as_view(), name='user.sudo'),
|
||||
url(r'^sudo/stop/$', user.StopStaffSession.as_view(), name='user.sudo.stop'),
|
||||
url(r'^sudo/(?P<id>\d+)/$', user.EditStaffSession.as_view(), name='user.sudo.edit'),
|
||||
url(r'^sudo/sessions/$', user.StaffSessionList.as_view(), name='user.sudo.list'),
|
||||
url(r'^users/$', users.UserListView.as_view(), name='users'),
|
||||
url(r'^users/select2$', typeahead.users_select2, name='users.select2'),
|
||||
url(r'^users/add$', users.UserCreateView.as_view(), name='users.add'),
|
||||
url(r'^users/impersonate/stop', users.UserImpersonateStopView.as_view(), name='users.impersonate.stop'),
|
||||
url(r'^users/(?P<id>\d+)/$', users.UserEditView.as_view(), name='users.edit'),
|
||||
url(r'^users/(?P<id>\d+)/reset$', users.UserResetView.as_view(), name='users.reset'),
|
||||
url(r'^users/(?P<id>\d+)/impersonate', users.UserImpersonateView.as_view(), name='users.impersonate'),
|
||||
url(r'^users/(?P<id>\d+)/anonymize', users.UserAnonymizeView.as_view(), name='users.anonymize'),
|
||||
url(r'^pdf/editor/webfonts.css', pdf.FontsCSSView.as_view(), name='pdf.css'),
|
||||
url(r'^settings/?$', user.UserSettings.as_view(), name='user.settings'),
|
||||
url(r'^settings/history/$', user.UserHistoryView.as_view(), name='user.settings.history'),
|
||||
url(r'^settings/notifications/$', user.UserNotificationsEditView.as_view(), name='user.settings.notifications'),
|
||||
url(r'^settings/notifications/off/(?P<id>\d+)/(?P<token>[^/]+)/$', user.UserNotificationsDisableView.as_view(),
|
||||
name='user.settings.notifications.off'),
|
||||
url(r'^settings/oauth/authorized/$', oauth.AuthorizationListView.as_view(),
|
||||
name='user.settings.oauth.list'),
|
||||
url(r'^settings/oauth/authorized/(?P<pk>\d+)/revoke$', oauth.AuthorizationRevokeView.as_view(),
|
||||
name='user.settings.oauth.revoke'),
|
||||
url(r'^settings/oauth/apps/$', oauth.OAuthApplicationListView.as_view(),
|
||||
name='user.settings.oauth.apps'),
|
||||
url(r'^settings/oauth/apps/add$', oauth.OAuthApplicationRegistrationView.as_view(),
|
||||
name='user.settings.oauth.apps.register'),
|
||||
url(r'^settings/oauth/apps/(?P<pk>\d+)/$', oauth.OAuthApplicationUpdateView.as_view(),
|
||||
name='user.settings.oauth.app'),
|
||||
url(r'^settings/oauth/apps/(?P<pk>\d+)/disable$', oauth.OAuthApplicationDeleteView.as_view(),
|
||||
name='user.settings.oauth.app.disable'),
|
||||
url(r'^settings/oauth/apps/(?P<pk>\d+)/roll$', oauth.OAuthApplicationRollView.as_view(),
|
||||
name='user.settings.oauth.app.roll'),
|
||||
url(r'^settings/2fa/$', user.User2FAMainView.as_view(), name='user.settings.2fa'),
|
||||
url(r'^settings/2fa/add$', user.User2FADeviceAddView.as_view(), name='user.settings.2fa.add'),
|
||||
url(r'^settings/2fa/enable', user.User2FAEnableView.as_view(), name='user.settings.2fa.enable'),
|
||||
url(r'^settings/2fa/disable', user.User2FADisableView.as_view(), name='user.settings.2fa.disable'),
|
||||
url(r'^settings/2fa/regenemergency', user.User2FARegenerateEmergencyView.as_view(),
|
||||
name='user.settings.2fa.regenemergency'),
|
||||
url(r'^settings/2fa/totp/(?P<device>[0-9]+)/confirm', user.User2FADeviceConfirmTOTPView.as_view(),
|
||||
name='user.settings.2fa.confirm.totp'),
|
||||
url(r'^settings/2fa/webauthn/(?P<device>[0-9]+)/confirm', user.User2FADeviceConfirmWebAuthnView.as_view(),
|
||||
name='user.settings.2fa.confirm.webauthn'),
|
||||
url(r'^settings/2fa/(?P<devicetype>[^/]+)/(?P<device>[0-9]+)/delete', user.User2FADeviceDeleteView.as_view(),
|
||||
name='user.settings.2fa.delete'),
|
||||
url(r'^organizers/$', organizer.OrganizerList.as_view(), name='organizers'),
|
||||
url(r'^organizers/add$', organizer.OrganizerCreate.as_view(), name='organizers.add'),
|
||||
url(r'^organizers/select2$', typeahead.organizer_select2, name='organizers.select2'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/$', organizer.OrganizerDetail.as_view(), name='organizer'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/edit$', organizer.OrganizerUpdate.as_view(), name='organizer.edit'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/delete$', organizer.OrganizerDelete.as_view(), name='organizer.delete'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/settings/display$', organizer.OrganizerDisplaySettings.as_view(),
|
||||
name='organizer.display'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/properties$', organizer.EventMetaPropertyListView.as_view(), name='organizer.properties'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/property/add$', organizer.EventMetaPropertyCreateView.as_view(),
|
||||
name='organizer.property.add'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/property/(?P<property>[^/]+)/edit$', organizer.EventMetaPropertyUpdateView.as_view(),
|
||||
name='organizer.property.edit'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/property/(?P<property>[^/]+)/delete$', organizer.EventMetaPropertyDeleteView.as_view(),
|
||||
name='organizer.property.delete'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/giftcards$', organizer.GiftCardListView.as_view(), name='organizer.giftcards'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/giftcard/add$', organizer.GiftCardCreateView.as_view(), name='organizer.giftcard.add'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/giftcard/(?P<giftcard>[^/]+)/$', organizer.GiftCardDetailView.as_view(), name='organizer.giftcard'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/giftcard/(?P<giftcard>[^/]+)/edit$', organizer.GiftCardUpdateView.as_view(),
|
||||
name='organizer.giftcard.edit'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/webhooks$', organizer.WebHookListView.as_view(), name='organizer.webhooks'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/webhook/add$', organizer.WebHookCreateView.as_view(),
|
||||
name='organizer.webhook.add'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/webhook/(?P<webhook>[^/]+)/edit$', organizer.WebHookUpdateView.as_view(),
|
||||
name='organizer.webhook.edit'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/webhook/(?P<webhook>[^/]+)/logs$', organizer.WebHookLogsView.as_view(),
|
||||
name='organizer.webhook.logs'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/devices$', organizer.DeviceListView.as_view(), name='organizer.devices'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/device/add$', organizer.DeviceCreateView.as_view(),
|
||||
name='organizer.device.add'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/device/(?P<device>[^/]+)/edit$', organizer.DeviceUpdateView.as_view(),
|
||||
name='organizer.device.edit'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/device/(?P<device>[^/]+)/connect$', organizer.DeviceConnectView.as_view(),
|
||||
name='organizer.device.connect'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/device/(?P<device>[^/]+)/revoke$', organizer.DeviceRevokeView.as_view(),
|
||||
name='organizer.device.revoke'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/device/(?P<device>[^/]+)/logs$', organizer.DeviceLogView.as_view(),
|
||||
name='organizer.device.logs'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/gates$', organizer.GateListView.as_view(), name='organizer.gates'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/gate/add$', organizer.GateCreateView.as_view(), name='organizer.gate.add'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/gate/(?P<gate>[^/]+)/edit$', organizer.GateUpdateView.as_view(),
|
||||
name='organizer.gate.edit'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/gate/(?P<gate>[^/]+)/delete$', organizer.GateDeleteView.as_view(),
|
||||
name='organizer.gate.delete'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/teams$', organizer.TeamListView.as_view(), name='organizer.teams'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/team/add$', organizer.TeamCreateView.as_view(), name='organizer.team.add'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/team/(?P<team>[^/]+)/$', organizer.TeamMemberView.as_view(),
|
||||
name='organizer.team'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/team/(?P<team>[^/]+)/edit$', organizer.TeamUpdateView.as_view(),
|
||||
name='organizer.team.edit'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/team/(?P<team>[^/]+)/delete$', organizer.TeamDeleteView.as_view(),
|
||||
name='organizer.team.delete'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/slugrng', main.SlugRNG.as_view(), name='events.add.slugrng'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/logs', organizer.LogView.as_view(), name='organizer.log'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/export/$', organizer.ExportView.as_view(), name='organizer.export'),
|
||||
url(r'^organizer/(?P<organizer>[^/]+)/export/do$', organizer.ExportDoView.as_view(), name='organizer.export.do'),
|
||||
url(r'^nav/typeahead/$', typeahead.nav_context_list, name='nav.typeahead'),
|
||||
url(r'^events/$', main.EventList.as_view(), name='events'),
|
||||
url(r'^events/add$', main.EventWizard.as_view(), name='events.add'),
|
||||
url(r'^events/typeahead/$', typeahead.event_list, name='events.typeahead'),
|
||||
url(r'^events/typeahead/meta/$', typeahead.meta_values, name='events.meta.typeahead'),
|
||||
url(r'^search/orders/$', search.OrderSearch.as_view(), name='search.orders'),
|
||||
url(r'^event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/', include([
|
||||
url(r'^$', dashboards.event_index, name='event.index'),
|
||||
url(r'^widgets.json$', dashboards.event_index_widgets_lazy, name='event.index.widgets'),
|
||||
url(r'^live/$', event.EventLive.as_view(), name='event.live'),
|
||||
url(r'^logs/$', event.EventLog.as_view(), name='event.log'),
|
||||
url(r'^delete/$', event.EventDelete.as_view(), name='event.delete'),
|
||||
url(r'^requiredactions/$', event.EventActions.as_view(), name='event.requiredactions'),
|
||||
url(r'^requiredactions/(?P<id>\d+)/discard$', event.EventActionDiscard.as_view(),
|
||||
name='event.requiredaction.discard'),
|
||||
url(r'^comment/$', event.EventComment.as_view(),
|
||||
name='event.comment'),
|
||||
url(r'^quickstart/$', event.QuickSetupView.as_view(), name='event.quick'),
|
||||
url(r'^settings/$', event.EventUpdate.as_view(), name='event.settings'),
|
||||
url(r'^settings/plugins$', event.EventPlugins.as_view(), name='event.settings.plugins'),
|
||||
url(r'^settings/payment/(?P<provider>[^/]+)$', event.PaymentProviderSettings.as_view(),
|
||||
name='event.settings.payment.provider'),
|
||||
url(r'^settings/payment$', event.PaymentSettings.as_view(), name='event.settings.payment'),
|
||||
url(r'^settings/tickets$', event.TicketSettings.as_view(), name='event.settings.tickets'),
|
||||
url(r'^settings/tickets/preview/(?P<output>[^/]+)$', event.TicketSettingsPreview.as_view(),
|
||||
name='event.settings.tickets.preview'),
|
||||
url(r'^settings/email$', event.MailSettings.as_view(), name='event.settings.mail'),
|
||||
url(r'^settings/email/preview$', event.MailSettingsPreview.as_view(), name='event.settings.mail.preview'),
|
||||
url(r'^settings/email/layoutpreview$', event.MailSettingsRendererPreview.as_view(),
|
||||
name='event.settings.mail.preview.layout'),
|
||||
url(r'^settings/cancel', event.CancelSettings.as_view(), name='event.settings.cancel'),
|
||||
url(r'^settings/invoice$', event.InvoiceSettings.as_view(), name='event.settings.invoice'),
|
||||
url(r'^settings/invoice/preview$', event.InvoicePreview.as_view(), name='event.settings.invoice.preview'),
|
||||
url(r'^settings/display', event.DisplaySettings.as_view(), name='event.settings.display'),
|
||||
url(r'^settings/tax/$', event.TaxList.as_view(), name='event.settings.tax'),
|
||||
url(r'^settings/tax/(?P<rule>\d+)/$', event.TaxUpdate.as_view(), name='event.settings.tax.edit'),
|
||||
url(r'^settings/tax/add$', event.TaxCreate.as_view(), name='event.settings.tax.add'),
|
||||
url(r'^settings/tax/(?P<rule>\d+)/delete$', event.TaxDelete.as_view(), name='event.settings.tax.delete'),
|
||||
url(r'^settings/widget$', event.WidgetSettings.as_view(), name='event.settings.widget'),
|
||||
url(r'^pdf/editor/webfonts.css', pdf.FontsCSSView.as_view(), name='pdf.css'),
|
||||
url(r'^pdf/editor/(?P<filename>[^/]+).pdf$', pdf.PdfView.as_view(), name='pdf.background'),
|
||||
url(r'^subevents/$', subevents.SubEventList.as_view(), name='event.subevents'),
|
||||
url(r'^subevents/select2$', typeahead.subevent_select2, name='event.subevents.select2'),
|
||||
url(r'^subevents/(?P<subevent>\d+)/$', subevents.SubEventUpdate.as_view(), name='event.subevent'),
|
||||
url(r'^subevents/(?P<subevent>\d+)/delete$', subevents.SubEventDelete.as_view(),
|
||||
name='event.subevent.delete'),
|
||||
url(r'^subevents/add$', subevents.SubEventCreate.as_view(), name='event.subevents.add'),
|
||||
url(r'^subevents/bulk_add$', subevents.SubEventBulkCreate.as_view(), name='event.subevents.bulk'),
|
||||
url(r'^subevents/bulk_action$', subevents.SubEventBulkAction.as_view(), name='event.subevents.bulkaction'),
|
||||
url(r'^subevents/bulk_edit$', subevents.SubEventBulkEdit.as_view(), name='event.subevents.bulkedit'),
|
||||
url(r'^items/$', item.ItemList.as_view(), name='event.items'),
|
||||
url(r'^items/add$', item.ItemCreate.as_view(), name='event.items.add'),
|
||||
url(r'^items/(?P<item>\d+)/$', item.ItemUpdateGeneral.as_view(), name='event.item'),
|
||||
url(r'^items/(?P<item>\d+)/up$', item.item_move_up, name='event.items.up'),
|
||||
url(r'^items/(?P<item>\d+)/down$', item.item_move_down, name='event.items.down'),
|
||||
url(r'^items/(?P<item>\d+)/delete$', item.ItemDelete.as_view(), name='event.items.delete'),
|
||||
url(r'^items/typeahead/meta/$', typeahead.item_meta_values, name='event.items.meta.typeahead'),
|
||||
url(r'^items/select2$', typeahead.items_select2, name='event.items.select2'),
|
||||
url(r'^items/select2/variation$', typeahead.variations_select2, name='event.items.variations.select2'),
|
||||
url(r'^categories/$', item.CategoryList.as_view(), name='event.items.categories'),
|
||||
url(r'^categories/select2$', typeahead.category_select2, name='event.items.categories.select2'),
|
||||
url(r'^categories/(?P<category>\d+)/delete$', item.CategoryDelete.as_view(),
|
||||
name='event.items.categories.delete'),
|
||||
url(r'^categories/(?P<category>\d+)/up$', item.category_move_up, name='event.items.categories.up'),
|
||||
url(r'^categories/(?P<category>\d+)/down$', item.category_move_down,
|
||||
name='event.items.categories.down'),
|
||||
url(r'^categories/(?P<category>\d+)/$', item.CategoryUpdate.as_view(),
|
||||
name='event.items.categories.edit'),
|
||||
url(r'^categories/add$', item.CategoryCreate.as_view(), name='event.items.categories.add'),
|
||||
url(r'^questions/$', item.QuestionList.as_view(), name='event.items.questions'),
|
||||
url(r'^questions/reorder$', item.reorder_questions, name='event.items.questions.reorder'),
|
||||
url(r'^questions/(?P<question>\d+)/delete$', item.QuestionDelete.as_view(),
|
||||
name='event.items.questions.delete'),
|
||||
url(r'^questions/(?P<question>\d+)/$', item.QuestionView.as_view(),
|
||||
name='event.items.questions.show'),
|
||||
url(r'^questions/(?P<question>\d+)/change$', item.QuestionUpdate.as_view(),
|
||||
name='event.items.questions.edit'),
|
||||
url(r'^questions/add$', item.QuestionCreate.as_view(), name='event.items.questions.add'),
|
||||
url(r'^quotas/$', item.QuotaList.as_view(), name='event.items.quotas'),
|
||||
url(r'^quotas/(?P<quota>\d+)/$', item.QuotaView.as_view(), name='event.items.quotas.show'),
|
||||
url(r'^quotas/select$', typeahead.quotas_select2, name='event.items.quotas.select2'),
|
||||
url(r'^quotas/(?P<quota>\d+)/change$', item.QuotaUpdate.as_view(), name='event.items.quotas.edit'),
|
||||
url(r'^quotas/(?P<quota>\d+)/delete$', item.QuotaDelete.as_view(),
|
||||
name='event.items.quotas.delete'),
|
||||
url(r'^quotas/add$', item.QuotaCreate.as_view(), name='event.items.quotas.add'),
|
||||
url(r'^vouchers/$', vouchers.VoucherList.as_view(), name='event.vouchers'),
|
||||
url(r'^vouchers/tags/$', vouchers.VoucherTags.as_view(), name='event.vouchers.tags'),
|
||||
url(r'^vouchers/rng$', vouchers.VoucherRNG.as_view(), name='event.vouchers.rng'),
|
||||
url(r'^vouchers/item_select$', typeahead.itemvarquota_select2, name='event.vouchers.itemselect2'),
|
||||
url(r'^vouchers/(?P<voucher>\d+)/$', vouchers.VoucherUpdate.as_view(), name='event.voucher'),
|
||||
url(r'^vouchers/(?P<voucher>\d+)/delete$', vouchers.VoucherDelete.as_view(),
|
||||
name='event.voucher.delete'),
|
||||
url(r'^vouchers/add$', vouchers.VoucherCreate.as_view(), name='event.vouchers.add'),
|
||||
url(r'^vouchers/go$', vouchers.VoucherGo.as_view(), name='event.vouchers.go'),
|
||||
url(r'^vouchers/bulk_add$', vouchers.VoucherBulkCreate.as_view(), name='event.vouchers.bulk'),
|
||||
url(r'^vouchers/bulk_action$', vouchers.VoucherBulkAction.as_view(), name='event.vouchers.bulkaction'),
|
||||
url(r'^orders/(?P<code>[0-9A-Z]+)/transition$', orders.OrderTransition.as_view(),
|
||||
name='event.order.transition'),
|
||||
url(r'^orders/(?P<code>[0-9A-Z]+)/resend$', orders.OrderResendLink.as_view(),
|
||||
name='event.order.resendlink'),
|
||||
url(r'^orders/(?P<code>[0-9A-Z]+)/(?P<position>\d+)/resend$', orders.OrderResendLink.as_view(),
|
||||
name='event.order.resendlink'),
|
||||
url(r'^orders/(?P<code>[0-9A-Z]+)/invoice$', orders.OrderInvoiceCreate.as_view(),
|
||||
name='event.order.geninvoice'),
|
||||
url(r'^orders/(?P<code>[0-9A-Z]+)/invoices/(?P<id>\d+)/regenerate$', orders.OrderInvoiceRegenerate.as_view(),
|
||||
name='event.order.regeninvoice'),
|
||||
url(r'^orders/(?P<code>[0-9A-Z]+)/invoices/(?P<id>\d+)/reissue$', orders.OrderInvoiceReissue.as_view(),
|
||||
name='event.order.reissueinvoice'),
|
||||
url(r'^orders/(?P<code>[0-9A-Z]+)/download/(?P<position>\d+)/(?P<output>[^/]+)/$',
|
||||
orders.OrderDownload.as_view(),
|
||||
name='event.order.download.ticket'),
|
||||
url(r'^orders/(?P<code>[0-9A-Z]+)/answer/(?P<answer>[^/]+)/$',
|
||||
orders.AnswerDownload.as_view(),
|
||||
name='event.order.download.answer'),
|
||||
url(r'^orders/(?P<code>[0-9A-Z]+)/checkvatid', orders.OrderCheckVATID.as_view(),
|
||||
name='event.order.checkvatid'),
|
||||
url(r'^orders/(?P<code>[0-9A-Z]+)/extend$', orders.OrderExtend.as_view(),
|
||||
name='event.order.extend'),
|
||||
url(r'^orders/(?P<code>[0-9A-Z]+)/reactivate$', orders.OrderReactivate.as_view(),
|
||||
name='event.order.reactivate'),
|
||||
url(r'^orders/(?P<code>[0-9A-Z]+)/contact$', orders.OrderContactChange.as_view(),
|
||||
name='event.order.contact'),
|
||||
url(r'^orders/(?P<code>[0-9A-Z]+)/locale', orders.OrderLocaleChange.as_view(),
|
||||
name='event.order.locale'),
|
||||
url(r'^orders/(?P<code>[0-9A-Z]+)/comment$', orders.OrderComment.as_view(),
|
||||
name='event.order.comment'),
|
||||
url(r'^orders/(?P<code>[0-9A-Z]+)/change$', orders.OrderChange.as_view(),
|
||||
name='event.order.change'),
|
||||
url(r'^orders/(?P<code>[0-9A-Z]+)/approve', orders.OrderApprove.as_view(),
|
||||
name='event.order.approve'),
|
||||
url(r'^orders/(?P<code>[0-9A-Z]+)/deny$', orders.OrderDeny.as_view(),
|
||||
name='event.order.deny'),
|
||||
url(r'^orders/(?P<code>[0-9A-Z]+)/delete$', orders.OrderDelete.as_view(),
|
||||
name='event.order.delete'),
|
||||
url(r'^orders/(?P<code>[0-9A-Z]+)/info', orders.OrderModifyInformation.as_view(),
|
||||
name='event.order.info'),
|
||||
url(r'^orders/(?P<code>[0-9A-Z]+)/sendmail$', orders.OrderSendMail.as_view(),
|
||||
name='event.order.sendmail'),
|
||||
url(r'^orders/(?P<code>[0-9A-Z]+)/(?P<position>[0-9A-Z]+)/sendmail$', orders.OrderPositionSendMail.as_view(),
|
||||
name='event.order.position.sendmail'),
|
||||
url(r'^orders/(?P<code>[0-9A-Z]+)/mail_history$', orders.OrderEmailHistory.as_view(),
|
||||
name='event.order.mail_history'),
|
||||
url(r'^orders/(?P<code>[0-9A-Z]+)/payments/(?P<payment>\d+)/cancel$', orders.OrderPaymentCancel.as_view(),
|
||||
name='event.order.payments.cancel'),
|
||||
url(r'^orders/(?P<code>[0-9A-Z]+)/payments/(?P<payment>\d+)/confirm$', orders.OrderPaymentConfirm.as_view(),
|
||||
name='event.order.payments.confirm'),
|
||||
url(r'^orders/(?P<code>[0-9A-Z]+)/refund$', orders.OrderRefundView.as_view(),
|
||||
name='event.order.refunds.start'),
|
||||
url(r'^orders/(?P<code>[0-9A-Z]+)/refunds/(?P<refund>\d+)/cancel$', orders.OrderRefundCancel.as_view(),
|
||||
name='event.order.refunds.cancel'),
|
||||
url(r'^orders/(?P<code>[0-9A-Z]+)/refunds/(?P<refund>\d+)/process$', orders.OrderRefundProcess.as_view(),
|
||||
name='event.order.refunds.process'),
|
||||
url(r'^orders/(?P<code>[0-9A-Z]+)/refunds/(?P<refund>\d+)/done$', orders.OrderRefundDone.as_view(),
|
||||
name='event.order.refunds.done'),
|
||||
url(r'^orders/(?P<code>[0-9A-Z]+)/cancellationrequests/(?P<req>\d+)/delete$',
|
||||
orders.OrderCancellationRequestDelete.as_view(),
|
||||
name='event.order.cancellationrequests.delete'),
|
||||
url(r'^orders/(?P<code>[0-9A-Z]+)/$', orders.OrderDetail.as_view(), name='event.order'),
|
||||
url(r'^invoice/(?P<invoice>[^/]+)$', orders.InvoiceDownload.as_view(),
|
||||
name='event.invoice.download'),
|
||||
url(r'^orders/overview/$', orders.OverView.as_view(), name='event.orders.overview'),
|
||||
url(r'^orders/import/$', orderimport.ImportView.as_view(), name='event.orders.import'),
|
||||
url(r'^orders/import/(?P<file>[^/]+)/$', orderimport.ProcessView.as_view(), name='event.orders.import.process'),
|
||||
url(r'^orders/export/$', orders.ExportView.as_view(), name='event.orders.export'),
|
||||
url(r'^orders/export/do$', orders.ExportDoView.as_view(), name='event.orders.export.do'),
|
||||
url(r'^orders/refunds/$', orders.RefundList.as_view(), name='event.orders.refunds'),
|
||||
url(r'^orders/go$', orders.OrderGo.as_view(), name='event.orders.go'),
|
||||
url(r'^orders/$', orders.OrderList.as_view(), name='event.orders'),
|
||||
url(r'^orders/search$', orders.OrderSearch.as_view(), name='event.orders.search'),
|
||||
url(r'^dangerzone/$', event.DangerZone.as_view(), name='event.dangerzone'),
|
||||
url(r'^cancel/$', orders.EventCancel.as_view(), name='event.cancel'),
|
||||
url(r'^shredder/$', shredder.StartShredView.as_view(), name='event.shredder.start'),
|
||||
url(r'^shredder/export$', shredder.ShredExportView.as_view(), name='event.shredder.export'),
|
||||
url(r'^shredder/download/(?P<file>[^/]+)/$', shredder.ShredDownloadView.as_view(), name='event.shredder.download'),
|
||||
url(r'^shredder/shred', shredder.ShredDoView.as_view(), name='event.shredder.shred'),
|
||||
url(r'^waitinglist/$', waitinglist.WaitingListView.as_view(), name='event.orders.waitinglist'),
|
||||
url(r'^waitinglist/auto_assign$', waitinglist.AutoAssign.as_view(), name='event.orders.waitinglist.auto'),
|
||||
url(r'^waitinglist/(?P<entry>\d+)/delete$', waitinglist.EntryDelete.as_view(),
|
||||
name='event.orders.waitinglist.delete'),
|
||||
url(r'^checkinlists/$', checkin.CheckinListList.as_view(), name='event.orders.checkinlists'),
|
||||
url(r'^checkinlists/add$', checkin.CheckinListCreate.as_view(), name='event.orders.checkinlists.add'),
|
||||
url(r'^checkinlists/select2$', typeahead.checkinlist_select2, name='event.orders.checkinlists.select2'),
|
||||
url(r'^checkinlists/(?P<list>\d+)/$', checkin.CheckInListShow.as_view(), name='event.orders.checkinlists.show'),
|
||||
url(r'^checkinlists/(?P<list>\d+)/change$', checkin.CheckinListUpdate.as_view(),
|
||||
name='event.orders.checkinlists.edit'),
|
||||
url(r'^checkinlists/(?P<list>\d+)/delete$', checkin.CheckinListDelete.as_view(),
|
||||
name='event.orders.checkinlists.delete'),
|
||||
re_path(r'^logout$', auth.logout, name='auth.logout'),
|
||||
re_path(r'^login$', auth.login, name='auth.login'),
|
||||
re_path(r'^login/2fa$', auth.Login2FAView.as_view(), name='auth.login.2fa'),
|
||||
re_path(r'^register$', auth.register, name='auth.register'),
|
||||
re_path(r'^invite/(?P<token>[a-zA-Z0-9]+)$', auth.invite, name='auth.invite'),
|
||||
re_path(r'^forgot$', auth.Forgot.as_view(), name='auth.forgot'),
|
||||
re_path(r'^forgot/recover$', auth.Recover.as_view(), name='auth.forgot.recover'),
|
||||
re_path(r'^$', dashboards.user_index, name='index'),
|
||||
re_path(r'^widgets.json$', dashboards.user_index_widgets_lazy, name='index.widgets'),
|
||||
re_path(r'^global/settings/$', global_settings.GlobalSettingsView.as_view(), name='global.settings'),
|
||||
re_path(r'^global/update/$', global_settings.UpdateCheckView.as_view(), name='global.update'),
|
||||
re_path(r'^global/message/$', global_settings.MessageView.as_view(), name='global.message'),
|
||||
re_path(r'^logdetail/$', global_settings.LogDetailView.as_view(), name='global.logdetail'),
|
||||
re_path(r'^logdetail/payment/$', global_settings.PaymentDetailView.as_view(), name='global.paymentdetail'),
|
||||
re_path(r'^logdetail/refund/$', global_settings.RefundDetailView.as_view(), name='global.refunddetail'),
|
||||
re_path(r'^geocode/$', geo.GeoCodeView.as_view(), name='global.geocode'),
|
||||
re_path(r'^reauth/$', user.ReauthView.as_view(), name='user.reauth'),
|
||||
re_path(r'^sudo/$', user.StartStaffSession.as_view(), name='user.sudo'),
|
||||
re_path(r'^sudo/stop/$', user.StopStaffSession.as_view(), name='user.sudo.stop'),
|
||||
re_path(r'^sudo/(?P<id>\d+)/$', user.EditStaffSession.as_view(), name='user.sudo.edit'),
|
||||
re_path(r'^sudo/sessions/$', user.StaffSessionList.as_view(), name='user.sudo.list'),
|
||||
re_path(r'^users/$', users.UserListView.as_view(), name='users'),
|
||||
re_path(r'^users/select2$', typeahead.users_select2, name='users.select2'),
|
||||
re_path(r'^users/add$', users.UserCreateView.as_view(), name='users.add'),
|
||||
re_path(r'^users/impersonate/stop', users.UserImpersonateStopView.as_view(), name='users.impersonate.stop'),
|
||||
re_path(r'^users/(?P<id>\d+)/$', users.UserEditView.as_view(), name='users.edit'),
|
||||
re_path(r'^users/(?P<id>\d+)/reset$', users.UserResetView.as_view(), name='users.reset'),
|
||||
re_path(r'^users/(?P<id>\d+)/impersonate', users.UserImpersonateView.as_view(), name='users.impersonate'),
|
||||
re_path(r'^users/(?P<id>\d+)/anonymize', users.UserAnonymizeView.as_view(), name='users.anonymize'),
|
||||
re_path(r'^pdf/editor/webfonts.css', pdf.FontsCSSView.as_view(), name='pdf.css'),
|
||||
re_path(r'^settings/?$', user.UserSettings.as_view(), name='user.settings'),
|
||||
re_path(r'^settings/history/$', user.UserHistoryView.as_view(), name='user.settings.history'),
|
||||
re_path(r'^settings/notifications/$', user.UserNotificationsEditView.as_view(), name='user.settings.notifications'),
|
||||
re_path(r'^settings/notifications/off/(?P<id>\d+)/(?P<token>[^/]+)/$', user.UserNotificationsDisableView.as_view(),
|
||||
name='user.settings.notifications.off'),
|
||||
re_path(r'^settings/oauth/authorized/$', oauth.AuthorizationListView.as_view(),
|
||||
name='user.settings.oauth.list'),
|
||||
re_path(r'^settings/oauth/authorized/(?P<pk>\d+)/revoke$', oauth.AuthorizationRevokeView.as_view(),
|
||||
name='user.settings.oauth.revoke'),
|
||||
re_path(r'^settings/oauth/apps/$', oauth.OAuthApplicationListView.as_view(),
|
||||
name='user.settings.oauth.apps'),
|
||||
re_path(r'^settings/oauth/apps/add$', oauth.OAuthApplicationRegistrationView.as_view(),
|
||||
name='user.settings.oauth.apps.register'),
|
||||
re_path(r'^settings/oauth/apps/(?P<pk>\d+)/$', oauth.OAuthApplicationUpdateView.as_view(),
|
||||
name='user.settings.oauth.app'),
|
||||
re_path(r'^settings/oauth/apps/(?P<pk>\d+)/disable$', oauth.OAuthApplicationDeleteView.as_view(),
|
||||
name='user.settings.oauth.app.disable'),
|
||||
re_path(r'^settings/oauth/apps/(?P<pk>\d+)/roll$', oauth.OAuthApplicationRollView.as_view(),
|
||||
name='user.settings.oauth.app.roll'),
|
||||
re_path(r'^settings/2fa/$', user.User2FAMainView.as_view(), name='user.settings.2fa'),
|
||||
re_path(r'^settings/2fa/add$', user.User2FADeviceAddView.as_view(), name='user.settings.2fa.add'),
|
||||
re_path(r'^settings/2fa/enable', user.User2FAEnableView.as_view(), name='user.settings.2fa.enable'),
|
||||
re_path(r'^settings/2fa/disable', user.User2FADisableView.as_view(), name='user.settings.2fa.disable'),
|
||||
re_path(r'^settings/2fa/regenemergency', user.User2FARegenerateEmergencyView.as_view(),
|
||||
name='user.settings.2fa.regenemergency'),
|
||||
re_path(r'^settings/2fa/totp/(?P<device>[0-9]+)/confirm', user.User2FADeviceConfirmTOTPView.as_view(),
|
||||
name='user.settings.2fa.confirm.totp'),
|
||||
re_path(r'^settings/2fa/webauthn/(?P<device>[0-9]+)/confirm', user.User2FADeviceConfirmWebAuthnView.as_view(),
|
||||
name='user.settings.2fa.confirm.webauthn'),
|
||||
re_path(r'^settings/2fa/(?P<devicetype>[^/]+)/(?P<device>[0-9]+)/delete', user.User2FADeviceDeleteView.as_view(),
|
||||
name='user.settings.2fa.delete'),
|
||||
re_path(r'^organizers/$', organizer.OrganizerList.as_view(), name='organizers'),
|
||||
re_path(r'^organizers/add$', organizer.OrganizerCreate.as_view(), name='organizers.add'),
|
||||
re_path(r'^organizers/select2$', typeahead.organizer_select2, name='organizers.select2'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/$', organizer.OrganizerDetail.as_view(), name='organizer'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/edit$', organizer.OrganizerUpdate.as_view(), name='organizer.edit'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/delete$', organizer.OrganizerDelete.as_view(), name='organizer.delete'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/settings/display$', organizer.OrganizerDisplaySettings.as_view(),
|
||||
name='organizer.display'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/properties$', organizer.EventMetaPropertyListView.as_view(),
|
||||
name='organizer.properties'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/property/add$', organizer.EventMetaPropertyCreateView.as_view(),
|
||||
name='organizer.property.add'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/property/(?P<property>[^/]+)/edit$',
|
||||
organizer.EventMetaPropertyUpdateView.as_view(),
|
||||
name='organizer.property.edit'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/property/(?P<property>[^/]+)/delete$',
|
||||
organizer.EventMetaPropertyDeleteView.as_view(),
|
||||
name='organizer.property.delete'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/giftcards$', organizer.GiftCardListView.as_view(),
|
||||
name='organizer.giftcards'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/giftcard/add$', organizer.GiftCardCreateView.as_view(),
|
||||
name='organizer.giftcard.add'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/giftcard/(?P<giftcard>[^/]+)/$', organizer.GiftCardDetailView.as_view(),
|
||||
name='organizer.giftcard'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/giftcard/(?P<giftcard>[^/]+)/edit$',
|
||||
organizer.GiftCardUpdateView.as_view(),
|
||||
name='organizer.giftcard.edit'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/webhooks$', organizer.WebHookListView.as_view(),
|
||||
name='organizer.webhooks'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/webhook/add$', organizer.WebHookCreateView.as_view(),
|
||||
name='organizer.webhook.add'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/webhook/(?P<webhook>[^/]+)/edit$', organizer.WebHookUpdateView.as_view(),
|
||||
name='organizer.webhook.edit'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/webhook/(?P<webhook>[^/]+)/logs$', organizer.WebHookLogsView.as_view(),
|
||||
name='organizer.webhook.logs'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/devices$', organizer.DeviceListView.as_view(), name='organizer.devices'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/device/add$', organizer.DeviceCreateView.as_view(),
|
||||
name='organizer.device.add'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/device/(?P<device>[^/]+)/edit$', organizer.DeviceUpdateView.as_view(),
|
||||
name='organizer.device.edit'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/device/(?P<device>[^/]+)/connect$', organizer.DeviceConnectView.as_view(),
|
||||
name='organizer.device.connect'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/device/(?P<device>[^/]+)/revoke$', organizer.DeviceRevokeView.as_view(),
|
||||
name='organizer.device.revoke'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/device/(?P<device>[^/]+)/logs$', organizer.DeviceLogView.as_view(),
|
||||
name='organizer.device.logs'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/gates$', organizer.GateListView.as_view(), name='organizer.gates'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/gate/add$', organizer.GateCreateView.as_view(),
|
||||
name='organizer.gate.add'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/gate/(?P<gate>[^/]+)/edit$', organizer.GateUpdateView.as_view(),
|
||||
name='organizer.gate.edit'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/gate/(?P<gate>[^/]+)/delete$', organizer.GateDeleteView.as_view(),
|
||||
name='organizer.gate.delete'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/teams$', organizer.TeamListView.as_view(), name='organizer.teams'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/team/add$', organizer.TeamCreateView.as_view(),
|
||||
name='organizer.team.add'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/team/(?P<team>[^/]+)/$', organizer.TeamMemberView.as_view(),
|
||||
name='organizer.team'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/team/(?P<team>[^/]+)/edit$', organizer.TeamUpdateView.as_view(),
|
||||
name='organizer.team.edit'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/team/(?P<team>[^/]+)/delete$', organizer.TeamDeleteView.as_view(),
|
||||
name='organizer.team.delete'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/slugrng', main.SlugRNG.as_view(), name='events.add.slugrng'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/logs', organizer.LogView.as_view(), name='organizer.log'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/export/$', organizer.ExportView.as_view(), name='organizer.export'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/export/do$', organizer.ExportDoView.as_view(),
|
||||
name='organizer.export.do'),
|
||||
re_path(r'^nav/typeahead/$', typeahead.nav_context_list, name='nav.typeahead'),
|
||||
re_path(r'^events/$', main.EventList.as_view(), name='events'),
|
||||
re_path(r'^events/add$', main.EventWizard.as_view(), name='events.add'),
|
||||
re_path(r'^events/typeahead/$', typeahead.event_list, name='events.typeahead'),
|
||||
re_path(r'^events/typeahead/meta/$', typeahead.meta_values, name='events.meta.typeahead'),
|
||||
re_path(r'^search/orders/$', search.OrderSearch.as_view(), name='search.orders'),
|
||||
re_path(r'^event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/', include([
|
||||
re_path(r'^$', dashboards.event_index, name='event.index'),
|
||||
re_path(r'^widgets.json$', dashboards.event_index_widgets_lazy, name='event.index.widgets'),
|
||||
re_path(r'^live/$', event.EventLive.as_view(), name='event.live'),
|
||||
re_path(r'^logs/$', event.EventLog.as_view(), name='event.log'),
|
||||
re_path(r'^delete/$', event.EventDelete.as_view(), name='event.delete'),
|
||||
re_path(r'^requiredactions/$', event.EventActions.as_view(), name='event.requiredactions'),
|
||||
re_path(r'^requiredactions/(?P<id>\d+)/discard$', event.EventActionDiscard.as_view(),
|
||||
name='event.requiredaction.discard'),
|
||||
re_path(r'^comment/$', event.EventComment.as_view(),
|
||||
name='event.comment'),
|
||||
re_path(r'^quickstart/$', event.QuickSetupView.as_view(), name='event.quick'),
|
||||
re_path(r'^settings/$', event.EventUpdate.as_view(), name='event.settings'),
|
||||
re_path(r'^settings/plugins$', event.EventPlugins.as_view(), name='event.settings.plugins'),
|
||||
re_path(r'^settings/payment/(?P<provider>[^/]+)$', event.PaymentProviderSettings.as_view(),
|
||||
name='event.settings.payment.provider'),
|
||||
re_path(r'^settings/payment$', event.PaymentSettings.as_view(), name='event.settings.payment'),
|
||||
re_path(r'^settings/tickets$', event.TicketSettings.as_view(), name='event.settings.tickets'),
|
||||
re_path(r'^settings/tickets/preview/(?P<output>[^/]+)$', event.TicketSettingsPreview.as_view(),
|
||||
name='event.settings.tickets.preview'),
|
||||
re_path(r'^settings/email$', event.MailSettings.as_view(), name='event.settings.mail'),
|
||||
re_path(r'^settings/email/preview$', event.MailSettingsPreview.as_view(), name='event.settings.mail.preview'),
|
||||
re_path(r'^settings/email/layoutpreview$', event.MailSettingsRendererPreview.as_view(),
|
||||
name='event.settings.mail.preview.layout'),
|
||||
re_path(r'^settings/cancel', event.CancelSettings.as_view(), name='event.settings.cancel'),
|
||||
re_path(r'^settings/invoice$', event.InvoiceSettings.as_view(), name='event.settings.invoice'),
|
||||
re_path(r'^settings/invoice/preview$', event.InvoicePreview.as_view(), name='event.settings.invoice.preview'),
|
||||
re_path(r'^settings/display', event.DisplaySettings.as_view(), name='event.settings.display'),
|
||||
re_path(r'^settings/tax/$', event.TaxList.as_view(), name='event.settings.tax'),
|
||||
re_path(r'^settings/tax/(?P<rule>\d+)/$', event.TaxUpdate.as_view(), name='event.settings.tax.edit'),
|
||||
re_path(r'^settings/tax/add$', event.TaxCreate.as_view(), name='event.settings.tax.add'),
|
||||
re_path(r'^settings/tax/(?P<rule>\d+)/delete$', event.TaxDelete.as_view(), name='event.settings.tax.delete'),
|
||||
re_path(r'^settings/widget$', event.WidgetSettings.as_view(), name='event.settings.widget'),
|
||||
re_path(r'^pdf/editor/webfonts.css', pdf.FontsCSSView.as_view(), name='pdf.css'),
|
||||
re_path(r'^pdf/editor/(?P<filename>[^/]+).pdf$', pdf.PdfView.as_view(), name='pdf.background'),
|
||||
re_path(r'^subevents/$', subevents.SubEventList.as_view(), name='event.subevents'),
|
||||
re_path(r'^subevents/select2$', typeahead.subevent_select2, name='event.subevents.select2'),
|
||||
re_path(r'^subevents/(?P<subevent>\d+)/$', subevents.SubEventUpdate.as_view(), name='event.subevent'),
|
||||
re_path(r'^subevents/(?P<subevent>\d+)/delete$', subevents.SubEventDelete.as_view(),
|
||||
name='event.subevent.delete'),
|
||||
re_path(r'^subevents/add$', subevents.SubEventCreate.as_view(), name='event.subevents.add'),
|
||||
re_path(r'^subevents/bulk_add$', subevents.SubEventBulkCreate.as_view(), name='event.subevents.bulk'),
|
||||
re_path(r'^subevents/bulk_action$', subevents.SubEventBulkAction.as_view(), name='event.subevents.bulkaction'),
|
||||
re_path(r'^subevents/bulk_edit$', subevents.SubEventBulkEdit.as_view(), name='event.subevents.bulkedit'),
|
||||
re_path(r'^items/$', item.ItemList.as_view(), name='event.items'),
|
||||
re_path(r'^items/add$', item.ItemCreate.as_view(), name='event.items.add'),
|
||||
re_path(r'^items/(?P<item>\d+)/$', item.ItemUpdateGeneral.as_view(), name='event.item'),
|
||||
re_path(r'^items/(?P<item>\d+)/up$', item.item_move_up, name='event.items.up'),
|
||||
re_path(r'^items/(?P<item>\d+)/down$', item.item_move_down, name='event.items.down'),
|
||||
re_path(r'^items/(?P<item>\d+)/delete$', item.ItemDelete.as_view(), name='event.items.delete'),
|
||||
re_path(r'^items/typeahead/meta/$', typeahead.item_meta_values, name='event.items.meta.typeahead'),
|
||||
re_path(r'^items/select2$', typeahead.items_select2, name='event.items.select2'),
|
||||
re_path(r'^items/select2/variation$', typeahead.variations_select2, name='event.items.variations.select2'),
|
||||
re_path(r'^categories/$', item.CategoryList.as_view(), name='event.items.categories'),
|
||||
re_path(r'^categories/select2$', typeahead.category_select2, name='event.items.categories.select2'),
|
||||
re_path(r'^categories/(?P<category>\d+)/delete$', item.CategoryDelete.as_view(),
|
||||
name='event.items.categories.delete'),
|
||||
re_path(r'^categories/(?P<category>\d+)/up$', item.category_move_up, name='event.items.categories.up'),
|
||||
re_path(r'^categories/(?P<category>\d+)/down$', item.category_move_down,
|
||||
name='event.items.categories.down'),
|
||||
re_path(r'^categories/(?P<category>\d+)/$', item.CategoryUpdate.as_view(),
|
||||
name='event.items.categories.edit'),
|
||||
re_path(r'^categories/add$', item.CategoryCreate.as_view(), name='event.items.categories.add'),
|
||||
re_path(r'^questions/$', item.QuestionList.as_view(), name='event.items.questions'),
|
||||
re_path(r'^questions/reorder$', item.reorder_questions, name='event.items.questions.reorder'),
|
||||
re_path(r'^questions/(?P<question>\d+)/delete$', item.QuestionDelete.as_view(),
|
||||
name='event.items.questions.delete'),
|
||||
re_path(r'^questions/(?P<question>\d+)/$', item.QuestionView.as_view(),
|
||||
name='event.items.questions.show'),
|
||||
re_path(r'^questions/(?P<question>\d+)/change$', item.QuestionUpdate.as_view(),
|
||||
name='event.items.questions.edit'),
|
||||
re_path(r'^questions/add$', item.QuestionCreate.as_view(), name='event.items.questions.add'),
|
||||
re_path(r'^quotas/$', item.QuotaList.as_view(), name='event.items.quotas'),
|
||||
re_path(r'^quotas/(?P<quota>\d+)/$', item.QuotaView.as_view(), name='event.items.quotas.show'),
|
||||
re_path(r'^quotas/select$', typeahead.quotas_select2, name='event.items.quotas.select2'),
|
||||
re_path(r'^quotas/(?P<quota>\d+)/change$', item.QuotaUpdate.as_view(), name='event.items.quotas.edit'),
|
||||
re_path(r'^quotas/(?P<quota>\d+)/delete$', item.QuotaDelete.as_view(),
|
||||
name='event.items.quotas.delete'),
|
||||
re_path(r'^quotas/add$', item.QuotaCreate.as_view(), name='event.items.quotas.add'),
|
||||
re_path(r'^vouchers/$', vouchers.VoucherList.as_view(), name='event.vouchers'),
|
||||
re_path(r'^vouchers/tags/$', vouchers.VoucherTags.as_view(), name='event.vouchers.tags'),
|
||||
re_path(r'^vouchers/rng$', vouchers.VoucherRNG.as_view(), name='event.vouchers.rng'),
|
||||
re_path(r'^vouchers/item_select$', typeahead.itemvarquota_select2, name='event.vouchers.itemselect2'),
|
||||
re_path(r'^vouchers/(?P<voucher>\d+)/$', vouchers.VoucherUpdate.as_view(), name='event.voucher'),
|
||||
re_path(r'^vouchers/(?P<voucher>\d+)/delete$', vouchers.VoucherDelete.as_view(),
|
||||
name='event.voucher.delete'),
|
||||
re_path(r'^vouchers/add$', vouchers.VoucherCreate.as_view(), name='event.vouchers.add'),
|
||||
re_path(r'^vouchers/go$', vouchers.VoucherGo.as_view(), name='event.vouchers.go'),
|
||||
re_path(r'^vouchers/bulk_add$', vouchers.VoucherBulkCreate.as_view(), name='event.vouchers.bulk'),
|
||||
re_path(r'^vouchers/bulk_action$', vouchers.VoucherBulkAction.as_view(), name='event.vouchers.bulkaction'),
|
||||
re_path(r'^orders/(?P<code>[0-9A-Z]+)/transition$', orders.OrderTransition.as_view(),
|
||||
name='event.order.transition'),
|
||||
re_path(r'^orders/(?P<code>[0-9A-Z]+)/resend$', orders.OrderResendLink.as_view(),
|
||||
name='event.order.resendlink'),
|
||||
re_path(r'^orders/(?P<code>[0-9A-Z]+)/(?P<position>\d+)/resend$', orders.OrderResendLink.as_view(),
|
||||
name='event.order.resendlink'),
|
||||
re_path(r'^orders/(?P<code>[0-9A-Z]+)/invoice$', orders.OrderInvoiceCreate.as_view(),
|
||||
name='event.order.geninvoice'),
|
||||
re_path(r'^orders/(?P<code>[0-9A-Z]+)/invoices/(?P<id>\d+)/regenerate$',
|
||||
orders.OrderInvoiceRegenerate.as_view(),
|
||||
name='event.order.regeninvoice'),
|
||||
re_path(r'^orders/(?P<code>[0-9A-Z]+)/invoices/(?P<id>\d+)/reissue$', orders.OrderInvoiceReissue.as_view(),
|
||||
name='event.order.reissueinvoice'),
|
||||
re_path(r'^orders/(?P<code>[0-9A-Z]+)/download/(?P<position>\d+)/(?P<output>[^/]+)/$',
|
||||
orders.OrderDownload.as_view(),
|
||||
name='event.order.download.ticket'),
|
||||
re_path(r'^orders/(?P<code>[0-9A-Z]+)/answer/(?P<answer>[^/]+)/$',
|
||||
orders.AnswerDownload.as_view(),
|
||||
name='event.order.download.answer'),
|
||||
re_path(r'^orders/(?P<code>[0-9A-Z]+)/checkvatid', orders.OrderCheckVATID.as_view(),
|
||||
name='event.order.checkvatid'),
|
||||
re_path(r'^orders/(?P<code>[0-9A-Z]+)/extend$', orders.OrderExtend.as_view(),
|
||||
name='event.order.extend'),
|
||||
re_path(r'^orders/(?P<code>[0-9A-Z]+)/reactivate$', orders.OrderReactivate.as_view(),
|
||||
name='event.order.reactivate'),
|
||||
re_path(r'^orders/(?P<code>[0-9A-Z]+)/contact$', orders.OrderContactChange.as_view(),
|
||||
name='event.order.contact'),
|
||||
re_path(r'^orders/(?P<code>[0-9A-Z]+)/locale', orders.OrderLocaleChange.as_view(),
|
||||
name='event.order.locale'),
|
||||
re_path(r'^orders/(?P<code>[0-9A-Z]+)/comment$', orders.OrderComment.as_view(),
|
||||
name='event.order.comment'),
|
||||
re_path(r'^orders/(?P<code>[0-9A-Z]+)/change$', orders.OrderChange.as_view(),
|
||||
name='event.order.change'),
|
||||
re_path(r'^orders/(?P<code>[0-9A-Z]+)/approve', orders.OrderApprove.as_view(),
|
||||
name='event.order.approve'),
|
||||
re_path(r'^orders/(?P<code>[0-9A-Z]+)/deny$', orders.OrderDeny.as_view(),
|
||||
name='event.order.deny'),
|
||||
re_path(r'^orders/(?P<code>[0-9A-Z]+)/delete$', orders.OrderDelete.as_view(),
|
||||
name='event.order.delete'),
|
||||
re_path(r'^orders/(?P<code>[0-9A-Z]+)/info', orders.OrderModifyInformation.as_view(),
|
||||
name='event.order.info'),
|
||||
re_path(r'^orders/(?P<code>[0-9A-Z]+)/sendmail$', orders.OrderSendMail.as_view(),
|
||||
name='event.order.sendmail'),
|
||||
re_path(r'^orders/(?P<code>[0-9A-Z]+)/(?P<position>[0-9A-Z]+)/sendmail$',
|
||||
orders.OrderPositionSendMail.as_view(),
|
||||
name='event.order.position.sendmail'),
|
||||
re_path(r'^orders/(?P<code>[0-9A-Z]+)/mail_history$', orders.OrderEmailHistory.as_view(),
|
||||
name='event.order.mail_history'),
|
||||
re_path(r'^orders/(?P<code>[0-9A-Z]+)/payments/(?P<payment>\d+)/cancel$', orders.OrderPaymentCancel.as_view(),
|
||||
name='event.order.payments.cancel'),
|
||||
re_path(r'^orders/(?P<code>[0-9A-Z]+)/payments/(?P<payment>\d+)/confirm$', orders.OrderPaymentConfirm.as_view(),
|
||||
name='event.order.payments.confirm'),
|
||||
re_path(r'^orders/(?P<code>[0-9A-Z]+)/refund$', orders.OrderRefundView.as_view(),
|
||||
name='event.order.refunds.start'),
|
||||
re_path(r'^orders/(?P<code>[0-9A-Z]+)/refunds/(?P<refund>\d+)/cancel$', orders.OrderRefundCancel.as_view(),
|
||||
name='event.order.refunds.cancel'),
|
||||
re_path(r'^orders/(?P<code>[0-9A-Z]+)/refunds/(?P<refund>\d+)/process$', orders.OrderRefundProcess.as_view(),
|
||||
name='event.order.refunds.process'),
|
||||
re_path(r'^orders/(?P<code>[0-9A-Z]+)/refunds/(?P<refund>\d+)/done$', orders.OrderRefundDone.as_view(),
|
||||
name='event.order.refunds.done'),
|
||||
re_path(r'^orders/(?P<code>[0-9A-Z]+)/cancellationrequests/(?P<req>\d+)/delete$',
|
||||
orders.OrderCancellationRequestDelete.as_view(),
|
||||
name='event.order.cancellationrequests.delete'),
|
||||
re_path(r'^orders/(?P<code>[0-9A-Z]+)/$', orders.OrderDetail.as_view(), name='event.order'),
|
||||
re_path(r'^invoice/(?P<invoice>[^/]+)$', orders.InvoiceDownload.as_view(),
|
||||
name='event.invoice.download'),
|
||||
re_path(r'^orders/overview/$', orders.OverView.as_view(), name='event.orders.overview'),
|
||||
re_path(r'^orders/import/$', orderimport.ImportView.as_view(), name='event.orders.import'),
|
||||
re_path(r'^orders/import/(?P<file>[^/]+)/$', orderimport.ProcessView.as_view(),
|
||||
name='event.orders.import.process'),
|
||||
re_path(r'^orders/export/$', orders.ExportView.as_view(), name='event.orders.export'),
|
||||
re_path(r'^orders/export/do$', orders.ExportDoView.as_view(), name='event.orders.export.do'),
|
||||
re_path(r'^orders/refunds/$', orders.RefundList.as_view(), name='event.orders.refunds'),
|
||||
re_path(r'^orders/go$', orders.OrderGo.as_view(), name='event.orders.go'),
|
||||
re_path(r'^orders/$', orders.OrderList.as_view(), name='event.orders'),
|
||||
re_path(r'^orders/search$', orders.OrderSearch.as_view(), name='event.orders.search'),
|
||||
re_path(r'^dangerzone/$', event.DangerZone.as_view(), name='event.dangerzone'),
|
||||
re_path(r'^cancel/$', orders.EventCancel.as_view(), name='event.cancel'),
|
||||
re_path(r'^shredder/$', shredder.StartShredView.as_view(), name='event.shredder.start'),
|
||||
re_path(r'^shredder/export$', shredder.ShredExportView.as_view(), name='event.shredder.export'),
|
||||
re_path(r'^shredder/download/(?P<file>[^/]+)/$', shredder.ShredDownloadView.as_view(),
|
||||
name='event.shredder.download'),
|
||||
re_path(r'^shredder/shred', shredder.ShredDoView.as_view(), name='event.shredder.shred'),
|
||||
re_path(r'^waitinglist/$', waitinglist.WaitingListView.as_view(), name='event.orders.waitinglist'),
|
||||
re_path(r'^waitinglist/auto_assign$', waitinglist.AutoAssign.as_view(), name='event.orders.waitinglist.auto'),
|
||||
re_path(r'^waitinglist/(?P<entry>\d+)/delete$', waitinglist.EntryDelete.as_view(),
|
||||
name='event.orders.waitinglist.delete'),
|
||||
re_path(r'^checkinlists/$', checkin.CheckinListList.as_view(), name='event.orders.checkinlists'),
|
||||
re_path(r'^checkinlists/add$', checkin.CheckinListCreate.as_view(), name='event.orders.checkinlists.add'),
|
||||
re_path(r'^checkinlists/select2$', typeahead.checkinlist_select2, name='event.orders.checkinlists.select2'),
|
||||
re_path(r'^checkinlists/(?P<list>\d+)/$', checkin.CheckInListShow.as_view(),
|
||||
name='event.orders.checkinlists.show'),
|
||||
re_path(r'^checkinlists/(?P<list>\d+)/change$', checkin.CheckinListUpdate.as_view(),
|
||||
name='event.orders.checkinlists.edit'),
|
||||
re_path(r'^checkinlists/(?P<list>\d+)/delete$', checkin.CheckinListDelete.as_view(),
|
||||
name='event.orders.checkinlists.delete'),
|
||||
])),
|
||||
url(r'^event/(?P<organizer>[^/]+)/$', RedirectView.as_view(pattern_name='control:organizer'), name='event.organizerredirect'),
|
||||
re_path(r'^event/(?P<organizer>[^/]+)/$', RedirectView.as_view(pattern_name='control:organizer'),
|
||||
name='event.organizerredirect'),
|
||||
]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import collections
|
||||
import collections.abc
|
||||
import warnings
|
||||
|
||||
from django.core.paginator import (
|
||||
@@ -65,7 +65,7 @@ class PaginationMixin:
|
||||
return ctx
|
||||
|
||||
|
||||
class LargeResultSetPage(collections.Sequence):
|
||||
class LargeResultSetPage(collections.abc.Sequence):
|
||||
|
||||
def __init__(self, object_list, number, paginator):
|
||||
self.object_list = object_list
|
||||
|
||||
@@ -955,10 +955,11 @@ class EventDelete(RecentAuthenticationRequiredMixin, EventPermissionRequiredMixi
|
||||
return reverse('control:index')
|
||||
|
||||
|
||||
class EventLog(EventPermissionRequiredMixin, PaginationMixin, ListView):
|
||||
class EventLog(EventPermissionRequiredMixin, ListView):
|
||||
template_name = 'pretixcontrol/event/logs.html'
|
||||
model = LogEntry
|
||||
context_object_name = 'logs'
|
||||
paginate_by = 20
|
||||
|
||||
def get_queryset(self):
|
||||
qs = self.request.event.logentry_set.all().select_related(
|
||||
@@ -1362,7 +1363,7 @@ class QuickSetupView(FormView):
|
||||
tax_rule=tax_rule,
|
||||
admission=True,
|
||||
position=i,
|
||||
sales_channels=list(get_all_sales_channels().keys())
|
||||
sales_channels=[k for k in get_all_sales_channels().keys()]
|
||||
)
|
||||
item.log_action('pretix.event.item.added', user=self.request.user, data=dict(f.cleaned_data))
|
||||
if f.cleaned_data['quota'] or not form.cleaned_data['total_quota']:
|
||||
|
||||
@@ -83,7 +83,7 @@ from pretix.control.forms.orders import (
|
||||
ExtendForm, MarkPaidForm, OrderContactForm, OrderFeeChangeForm,
|
||||
OrderLocaleForm, OrderMailForm, OrderPositionAddForm,
|
||||
OrderPositionAddFormset, OrderPositionChangeForm, OrderPositionMailForm,
|
||||
OrderRefundForm, OtherOperationsForm, ReactivateOrderForm,
|
||||
OrderRefundForm, OtherOperationsForm,
|
||||
)
|
||||
from pretix.control.permissions import EventPermissionRequiredMixin
|
||||
from pretix.control.signals import order_search_forms
|
||||
@@ -1424,24 +1424,11 @@ class OrderExtend(OrderView):
|
||||
class OrderReactivate(OrderView):
|
||||
permission = 'can_change_orders'
|
||||
|
||||
@cached_property
|
||||
def reactivate_form(self):
|
||||
return ReactivateOrderForm(
|
||||
instance=self.order,
|
||||
data=self.request.POST if self.request.method == "POST" else None,
|
||||
)
|
||||
|
||||
def post(self, *args, **kwargs):
|
||||
if not self.reactivate_form.is_valid():
|
||||
return render(self.request, 'pretixcontrol/order/reactivate.html', {
|
||||
'form': self.reactivate_form,
|
||||
'order': self.order,
|
||||
})
|
||||
try:
|
||||
reactivate_order(
|
||||
self.order,
|
||||
user=self.request.user,
|
||||
force=self.reactivate_form.cleaned_data.get('force', False)
|
||||
user=self.request.user
|
||||
)
|
||||
messages.success(self.request, _('The order has been reactivated.'))
|
||||
except OrderError as e:
|
||||
@@ -1466,7 +1453,6 @@ class OrderReactivate(OrderView):
|
||||
|
||||
def get(self, *args, **kwargs):
|
||||
return render(self.request, 'pretixcontrol/order/reactivate.html', {
|
||||
'form': self.reactivate_form,
|
||||
'order': self.order,
|
||||
})
|
||||
|
||||
|
||||
@@ -1438,11 +1438,12 @@ class EventMetaPropertyDeleteView(OrganizerDetailViewMixin, OrganizerPermissionR
|
||||
return redirect(success_url)
|
||||
|
||||
|
||||
class LogView(OrganizerPermissionRequiredMixin, PaginationMixin, ListView):
|
||||
class LogView(OrganizerPermissionRequiredMixin, ListView):
|
||||
template_name = 'pretixcontrol/organizers/logs.html'
|
||||
permission = 'can_change_organizer_settings'
|
||||
model = LogEntry
|
||||
context_object_name = 'logs'
|
||||
paginate_by = 20
|
||||
|
||||
def get_queryset(self):
|
||||
qs = self.request.organizer.all_logentries().select_related(
|
||||
|
||||
@@ -3,8 +3,7 @@ import io
|
||||
from defusedcsv import csv
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import connection, transaction
|
||||
from django.db import transaction
|
||||
from django.db.models import Sum
|
||||
from django.http import (
|
||||
Http404, HttpResponse, HttpResponseBadRequest, HttpResponseRedirect,
|
||||
@@ -22,9 +21,7 @@ from django.views.generic import (
|
||||
|
||||
from pretix.base.models import CartPosition, LogEntry, OrderPosition, Voucher
|
||||
from pretix.base.models.vouchers import _generate_random_code
|
||||
from pretix.base.services.locking import NoLockManager
|
||||
from pretix.base.services.vouchers import vouchers_send
|
||||
from pretix.base.views.tasks import AsyncFormView
|
||||
from pretix.control.forms.filter import VoucherFilterForm, VoucherTagFilterForm
|
||||
from pretix.control.forms.vouchers import VoucherBulkForm, VoucherForm
|
||||
from pretix.control.permissions import EventPermissionRequiredMixin
|
||||
@@ -290,19 +287,13 @@ class VoucherGo(EventPermissionRequiredMixin, View):
|
||||
return redirect('control:event.vouchers', event=request.event.slug, organizer=request.event.organizer.slug)
|
||||
|
||||
|
||||
class VoucherBulkCreate(EventPermissionRequiredMixin, AsyncFormView):
|
||||
class VoucherBulkCreate(EventPermissionRequiredMixin, CreateView):
|
||||
model = Voucher
|
||||
template_name = 'pretixcontrol/vouchers/bulk.html'
|
||||
permission = 'can_change_vouchers'
|
||||
context_object_name = 'voucher'
|
||||
|
||||
def get_success_url(self, value) -> str:
|
||||
return reverse('control:event.vouchers', kwargs={
|
||||
'organizer': self.request.event.organizer.slug,
|
||||
'event': self.request.event.slug,
|
||||
})
|
||||
|
||||
def get_error_url(self):
|
||||
def get_success_url(self) -> str:
|
||||
return reverse('control:event.vouchers', kwargs={
|
||||
'organizer': self.request.event.organizer.slug,
|
||||
'event': self.request.event.slug,
|
||||
@@ -325,84 +316,34 @@ class VoucherBulkCreate(EventPermissionRequiredMixin, AsyncFormView):
|
||||
i.redeemed = 0
|
||||
kwargs['instance'] = i
|
||||
else:
|
||||
kwargs['instance'] = Voucher(event=self.request.event, code=None)
|
||||
kwargs['instance'] = Voucher(event=self.request.event)
|
||||
return kwargs
|
||||
|
||||
def get_async_form_kwargs(self, form_kwargs, organizer=None, event=None):
|
||||
if not form_kwargs.get('instance'):
|
||||
form_kwargs['instance'] = Voucher(event=self.request.event, code=None)
|
||||
return form_kwargs
|
||||
|
||||
def async_form_valid(self, task, form):
|
||||
lockfn = NoLockManager
|
||||
if form.data.get('block_quota'):
|
||||
lockfn = self.request.event.lock
|
||||
batch_size = 500
|
||||
total_num = 1 # will be set later
|
||||
|
||||
def set_progress(percent):
|
||||
if not task.request.called_directly:
|
||||
task.update_state(
|
||||
state='PROGRESS',
|
||||
meta={'value': percent}
|
||||
)
|
||||
|
||||
def process_batch(batch_vouchers, voucherids):
|
||||
Voucher.objects.bulk_create(batch_vouchers)
|
||||
if not connection.features.can_return_rows_from_bulk_insert:
|
||||
batch_vouchers = list(self.request.event.vouchers.filter(code__in=[v.code for v in batch_vouchers]))
|
||||
|
||||
log_entries = []
|
||||
for v in batch_vouchers:
|
||||
voucherids.append(v.pk)
|
||||
data = dict(form.cleaned_data)
|
||||
data['code'] = code
|
||||
data['bulk'] = True
|
||||
del data['codes']
|
||||
log_entries.append(
|
||||
v.log_action('pretix.voucher.added', data=data, user=self.request.user, save=False)
|
||||
)
|
||||
LogEntry.objects.bulk_create(log_entries)
|
||||
form.post_bulk_save(batch_vouchers)
|
||||
batch_vouchers.clear()
|
||||
set_progress(len(voucherids) / total_num * (50. if form.cleaned_data['send'] else 100.))
|
||||
|
||||
@transaction.atomic
|
||||
def form_valid(self, form):
|
||||
log_entries = []
|
||||
objs = form.save(self.request.event)
|
||||
voucherids = []
|
||||
with lockfn(), transaction.atomic():
|
||||
if not form.is_valid():
|
||||
raise ValidationError(form.errors)
|
||||
total_num = len(form.cleaned_data['codes'])
|
||||
|
||||
batch_vouchers = []
|
||||
for code in form.cleaned_data['codes']:
|
||||
if len(batch_vouchers) > batch_size:
|
||||
process_batch(batch_vouchers, voucherids)
|
||||
|
||||
obj = modelcopy(form.instance, code=None)
|
||||
obj.event = self.request.event
|
||||
obj.code = code
|
||||
try:
|
||||
obj.seat = form.cleaned_data['seats'].pop()
|
||||
obj.item = obj.seat.product
|
||||
except IndexError:
|
||||
pass
|
||||
batch_vouchers.append(obj)
|
||||
|
||||
process_batch(batch_vouchers, voucherids)
|
||||
for v in objs:
|
||||
log_entries.append(
|
||||
v.log_action('pretix.voucher.added', data=form.cleaned_data, user=self.request.user, save=False)
|
||||
)
|
||||
voucherids.append(v.pk)
|
||||
LogEntry.objects.bulk_create(log_entries, batch_size=200)
|
||||
|
||||
if form.cleaned_data['send']:
|
||||
vouchers_send(
|
||||
event=self.request.event,
|
||||
vouchers=voucherids,
|
||||
subject=form.cleaned_data['send_subject'],
|
||||
message=form.cleaned_data['send_message'],
|
||||
recipients=[r._asdict() for r in form.cleaned_data['send_recipients']],
|
||||
user=self.request.user.pk,
|
||||
progress=lambda p: set_progress(50. + p * 50.)
|
||||
)
|
||||
|
||||
def get_success_message(self, value):
|
||||
return _('The new vouchers have been created.')
|
||||
vouchers_send.apply_async(kwargs={
|
||||
'event': self.request.event.pk,
|
||||
'vouchers': voucherids,
|
||||
'subject': form.cleaned_data['send_subject'],
|
||||
'message': form.cleaned_data['send_message'],
|
||||
'recipients': [r._asdict() for r in form.cleaned_data['send_recipients']],
|
||||
'user': self.request.user.pk,
|
||||
})
|
||||
messages.success(self.request, _('The new vouchers have been created and will be sent out shortly.'))
|
||||
else:
|
||||
messages.success(self.request, _('The new vouchers have been created.'))
|
||||
return HttpResponseRedirect(self.get_success_url())
|
||||
|
||||
def get_form_class(self):
|
||||
form_class = VoucherBulkForm
|
||||
@@ -416,6 +357,11 @@ class VoucherBulkCreate(EventPermissionRequiredMixin, AsyncFormView):
|
||||
ctx['code_length'] = settings.ENTROPY['voucher_code']
|
||||
return ctx
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
# TODO: Transform this into an asynchronous call?
|
||||
with request.event.lock():
|
||||
return super().post(request, *args, **kwargs)
|
||||
|
||||
|
||||
class VoucherRNG(EventPermissionRequiredMixin, View):
|
||||
permission = 'can_change_vouchers'
|
||||
|
||||
@@ -94,7 +94,7 @@ def merge(*args):
|
||||
"""Implements the 'merge' operator for merging lists."""
|
||||
ret = []
|
||||
for arg in args:
|
||||
if isinstance(arg, (list, tuple)):
|
||||
if isinstance(arg, list) or isinstance(arg, tuple):
|
||||
ret += list(arg)
|
||||
else:
|
||||
ret.append(arg)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import copy
|
||||
|
||||
from django.core.files import File
|
||||
from django.db import models
|
||||
|
||||
|
||||
@@ -12,11 +13,12 @@ class Thumbnail(models.Model):
|
||||
unique_together = (('source', 'size'),)
|
||||
|
||||
|
||||
def modelcopy(obj: models.Model, **kwargs):
|
||||
n = obj.__class__(**kwargs)
|
||||
def modelcopy(obj: models.Model):
|
||||
n = obj.__class__()
|
||||
for f in obj._meta.fields:
|
||||
val = getattr(obj, f.name)
|
||||
if isinstance(val, models.Model):
|
||||
print(f, f.name, val)
|
||||
if isinstance(val, (models.Model, File)):
|
||||
setattr(n, f.name, copy.copy(val))
|
||||
else:
|
||||
setattr(n, f.name, copy.deepcopy(val))
|
||||
|
||||
@@ -7,16 +7,16 @@ msgstr ""
|
||||
"Project-Id-Version: 1\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-03-08 16:39+0000\n"
|
||||
"PO-Revision-Date: 2021-03-14 17:33+0000\n"
|
||||
"Last-Translator: Raphael Michel <michel@rami.io>\n"
|
||||
"Language-Team: Dutch <https://translate.pretix.eu/projects/pretix/pretix/nl/>"
|
||||
"\n"
|
||||
"PO-Revision-Date: 2021-01-29 11:23+0000\n"
|
||||
"Last-Translator: Maarten van den Berg <maartenberg1@gmail.com>\n"
|
||||
"Language-Team: Dutch <https://translate.pretix.eu/projects/pretix/pretix/nl/"
|
||||
">\n"
|
||||
"Language: nl\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 4.4.2\n"
|
||||
"X-Generator: Weblate 3.10.3\n"
|
||||
|
||||
#: htmlcov/pretix_control_views_dashboards_py.html:898
|
||||
#: pretix/control/templates/pretixcontrol/events/index.html:144
|
||||
@@ -154,10 +154,10 @@ msgid "Meta data property '{name}' does not exist."
|
||||
msgstr "Metadataeigenschap '{name}' bestaat niet."
|
||||
|
||||
#: pretix/api/serializers/event.py:182 pretix/api/serializers/event.py:466
|
||||
#, python-brace-format
|
||||
#, fuzzy, python-brace-format
|
||||
#| msgid "Meta data property '{name}' does not exist."
|
||||
msgid "Meta data property '{name}' does not allow value '{value}'."
|
||||
msgstr ""
|
||||
"De waarde '{value}' is niet toegestaan voor de metadataeigenschap '{name}'."
|
||||
msgstr "Metadataeigenschap '{name}' bestaat niet."
|
||||
|
||||
#: pretix/api/serializers/event.py:225
|
||||
#, python-brace-format
|
||||
@@ -2246,7 +2246,7 @@ msgstr "U moet ten minste één quotum instellen om iets te verkopen."
|
||||
#: pretix/base/models/event.py:960
|
||||
#, python-brace-format
|
||||
msgid "You need to fill the meta parameter \"{property}\"."
|
||||
msgstr "U moet de meta-eigenschap \"{property}\" invullen."
|
||||
msgstr ""
|
||||
|
||||
#: pretix/base/models/event.py:1065
|
||||
msgid ""
|
||||
@@ -2324,49 +2324,50 @@ msgstr ""
|
||||
"onderstrepingstekens bevatten."
|
||||
|
||||
#: pretix/base/models/event.py:1379
|
||||
#, fuzzy
|
||||
#| msgid "Default language"
|
||||
msgid "Default value"
|
||||
msgstr "Standaardwaarde"
|
||||
msgstr "Standaardtaal"
|
||||
|
||||
#: pretix/base/models/event.py:1381
|
||||
#, fuzzy
|
||||
#| msgid "Can change organizer settings"
|
||||
msgid "Can only be changed by organizer-level administrators"
|
||||
msgstr "Kan alleen worden gewijzigd door beheerders van deze organisator"
|
||||
msgstr "Kan organisatorinstellingen wijzigen"
|
||||
|
||||
#: pretix/base/models/event.py:1383
|
||||
#, fuzzy
|
||||
#| msgid "Search for events"
|
||||
msgid "Required for events"
|
||||
msgstr "Verplicht voor evenementen"
|
||||
msgstr "Zoek naar evenementen"
|
||||
|
||||
#: pretix/base/models/event.py:1384
|
||||
msgid ""
|
||||
"If checked, an event can only be taken live if the property is set. In event "
|
||||
"series, its always optional to set a value for individual dates"
|
||||
msgstr ""
|
||||
"Als deze optie is ingeschakeld kan een evenement alleen live worden gezet "
|
||||
"als deze eigenschap een waarde heeft. In evenementenreeksen is het altijd "
|
||||
"optioneel om een waarde voor individuele datums in te stellen."
|
||||
|
||||
#: pretix/base/models/event.py:1389
|
||||
#, fuzzy
|
||||
#| msgid "Total value"
|
||||
msgid "Valid values"
|
||||
msgstr "Toegestane waarden"
|
||||
msgstr "Totaalwaarde"
|
||||
|
||||
#: pretix/base/models/event.py:1390
|
||||
msgid ""
|
||||
"If you keep this empty, any value is allowed. Otherwise, enter one possible "
|
||||
"value per line."
|
||||
msgstr ""
|
||||
"Voer hier een toegestane waarde per regel in. Als u dit veld leeg laat wordt "
|
||||
"iedere waarde toegestaan."
|
||||
|
||||
#: pretix/base/models/event.py:1396
|
||||
msgid "A property can either be required or have a default value, not both."
|
||||
msgstr ""
|
||||
"Een eigenschap kan niet verplicht zijn en tegelijkertijd een standaardwaarde "
|
||||
"hebben."
|
||||
|
||||
#: pretix/base/models/event.py:1398
|
||||
#, fuzzy
|
||||
#| msgid "You cannot select a quota that belongs to a different event."
|
||||
msgid "You cannot set a default value that is not a valid value."
|
||||
msgstr ""
|
||||
"U kunt geen standaardwaarde instellen die niet in de lijst met toegestane "
|
||||
"waarden staat."
|
||||
msgstr "U kunt geen quotum selecteren dat bij een ander evenement hoort."
|
||||
|
||||
#: pretix/base/models/fields.py:12
|
||||
msgid "No value can contain the delimiter character."
|
||||
@@ -4420,7 +4421,12 @@ msgid "Payment process description in order confirmation emails"
|
||||
msgstr "Beschrijving van betalingsproces in bevestigingsmails"
|
||||
|
||||
#: pretix/base/payment.py:971
|
||||
#, python-brace-format
|
||||
#, fuzzy, python-brace-format
|
||||
#| msgid ""
|
||||
#| "This text will be included for the {payment_info} placeholder in order "
|
||||
#| "confirmation mails. It should instruct the user on how to proceed with "
|
||||
#| "the payment. You can use the placeholders {order}, {total}, {currency} "
|
||||
#| "and {total_with_currency}."
|
||||
msgid ""
|
||||
"This text will be included for the {payment_info} placeholder in order "
|
||||
"confirmation mails. It should instruct the user on how to proceed with the "
|
||||
@@ -4430,7 +4436,7 @@ msgstr ""
|
||||
"Deze tekst zal worden ingevoegd op de plaats van de {payment_info}-"
|
||||
"plaatsaanduiding in bevestigingsmails voor een bestelling. De tekst moet de "
|
||||
"gebruiker informeren hoe verder te gaan met de betaling. U kunt hier de "
|
||||
"plaatsaanduidingen {order}, {amount}, {currency} en {amount_with_currency} "
|
||||
"plaatsaanduidingen {order}, {total}, {currency} en {total_with_currency} "
|
||||
"gebruiken."
|
||||
|
||||
#: pretix/base/payment.py:978
|
||||
@@ -4438,7 +4444,12 @@ msgid "Payment process description for pending orders"
|
||||
msgstr "Beschrijving van betalingsproces voor openstaande bestellingen"
|
||||
|
||||
#: pretix/base/payment.py:979
|
||||
#, python-brace-format
|
||||
#, fuzzy, python-brace-format
|
||||
#| msgid ""
|
||||
#| "This text will be shown on the order confirmation page for pending "
|
||||
#| "orders. It should instruct the user on how to proceed with the payment. "
|
||||
#| "You can use the placeholders {order}, {total}, {currency} and "
|
||||
#| "{total_with_currency}."
|
||||
msgid ""
|
||||
"This text will be shown on the order confirmation page for pending orders. "
|
||||
"It should instruct the user on how to proceed with the payment. You can use "
|
||||
@@ -4446,8 +4457,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Deze tekst zal worden getoond op de bevestigingspagina van openstaande "
|
||||
"bestellingen. De tekst moet de gebruiker informeren hoe verder te gaan met "
|
||||
"de betaling. U kunt hier de plaatsaanduidingen {order}, {amount}, {currency} "
|
||||
"en {amount_with_currency} gebruiken."
|
||||
"de betaling. U kunt hier de plaatsaanduidingen {order}, {total}, {currency} "
|
||||
"en {total_with_currency} gebruiken."
|
||||
|
||||
#: pretix/base/payment.py:1028
|
||||
msgid "Offsetting"
|
||||
@@ -4793,11 +4804,13 @@ msgstr "Informatietekst organisator"
|
||||
|
||||
#: pretix/base/pdf.py:298
|
||||
msgid "Event organizer info text"
|
||||
msgstr "Informatie over de organisator van het evenement"
|
||||
msgstr "Informatietekst van de organisator van het evenement"
|
||||
|
||||
#: pretix/base/pdf.py:302 pretix/base/pdf.py:303
|
||||
#, fuzzy
|
||||
#| msgid "Event organizer info text"
|
||||
msgid "Event info text"
|
||||
msgstr "Informatie over het evenement"
|
||||
msgstr "Informatietekst van de organisator van het evenement"
|
||||
|
||||
#: pretix/base/pdf.py:307
|
||||
msgid "Printing date"
|
||||
@@ -6441,52 +6454,64 @@ msgstr ""
|
||||
"aan de volgende persoon op de lijst."
|
||||
|
||||
#: pretix/base/settings.py:984
|
||||
#, fuzzy
|
||||
#| msgid "Ask for attendee names"
|
||||
msgid "Ask for a name"
|
||||
msgstr "Vraag om namen"
|
||||
msgstr "Vraag om namen van gasten"
|
||||
|
||||
#: pretix/base/settings.py:985
|
||||
#, fuzzy
|
||||
#| msgid "An entry has been changed on the waiting list."
|
||||
msgid "Ask for a name when signing up to the waiting list."
|
||||
msgstr "Vraag om een naam bij het aanmelden voor de wachtlijst."
|
||||
msgstr "Een inschrijving op de wachtlijst is aangepast."
|
||||
|
||||
#: pretix/base/settings.py:994
|
||||
#, fuzzy
|
||||
#| msgid "Require customer name"
|
||||
msgid "Require name"
|
||||
msgstr "Verplicht namen"
|
||||
msgstr "Verplicht klantnaam"
|
||||
|
||||
#: pretix/base/settings.py:995
|
||||
#, fuzzy
|
||||
#| msgid "An entry has been changed on the waiting list."
|
||||
msgid "Require a name when signing up to the waiting list.."
|
||||
msgstr ""
|
||||
"Maakt het opgeven van een naam verplicht om in te schrijven voor de "
|
||||
"wachtlijst."
|
||||
msgstr "Een inschrijving op de wachtlijst is aangepast."
|
||||
|
||||
#: pretix/base/settings.py:1005
|
||||
#, fuzzy
|
||||
#| msgid "Ask for a phone number per order"
|
||||
msgid "Ask for a phone number"
|
||||
msgstr "Vraag om een telefoonnummer"
|
||||
msgstr "Vraag om een telefoonnummer bij bestelling"
|
||||
|
||||
#: pretix/base/settings.py:1006
|
||||
#, fuzzy
|
||||
#| msgid "An entry has been changed on the waiting list."
|
||||
msgid "Ask for a phone number when signing up to the waiting list."
|
||||
msgstr "Vraag om een telefoonnummer bij het inschrijven voor de wachtlijst."
|
||||
msgstr "Een inschrijving op de wachtlijst is aangepast."
|
||||
|
||||
#: pretix/base/settings.py:1015
|
||||
#, fuzzy
|
||||
#| msgid "Require a phone number per order"
|
||||
msgid "Require phone number"
|
||||
msgstr "Verplicht telefoonnummer"
|
||||
msgstr "Verplicht het opgeven van een telefoonnummer"
|
||||
|
||||
#: pretix/base/settings.py:1016
|
||||
#, fuzzy
|
||||
#| msgid "An entry has been changed on the waiting list."
|
||||
msgid "Require a phone number when signing up to the waiting list.."
|
||||
msgstr ""
|
||||
"Maakt het opgeven van een telefoonnummer verplicht bij het inschrijven voor "
|
||||
"de wachtlijst."
|
||||
msgstr "Een inschrijving op de wachtlijst is aangepast."
|
||||
|
||||
#: pretix/base/settings.py:1026
|
||||
#, fuzzy
|
||||
#| msgid "Voucher explanation"
|
||||
msgid "Phone number explanation"
|
||||
msgstr "Uitleg voor telefoonnummer"
|
||||
msgstr "Voucher-uitleg"
|
||||
|
||||
#: pretix/base/settings.py:1029
|
||||
msgid ""
|
||||
"If you ask for a phone number, explain why you do so and what you will use "
|
||||
"the phone number for."
|
||||
msgstr ""
|
||||
"Als u om een telefoonnummer vraagt kunt u in dit veld uitleggen waarom en "
|
||||
"hoe u de verzamelde telefoonnummers zult gebruiken."
|
||||
|
||||
#: pretix/base/settings.py:1039
|
||||
msgid "Allow users to download tickets"
|
||||
@@ -6616,7 +6641,6 @@ msgstr ""
|
||||
#: pretix/base/settings.py:1147
|
||||
msgid "Allow customers to modify their information after they checked in."
|
||||
msgstr ""
|
||||
"Sta klanten toe om hun informatie aan te passen nadat ze ingecheckt zijn."
|
||||
|
||||
#: pretix/base/settings.py:1156
|
||||
msgid "Last date of modifications"
|
||||
@@ -6812,8 +6836,10 @@ msgstr ""
|
||||
"contactinformatie en eventuele wettelijk verplichte informatie bevat."
|
||||
|
||||
#: pretix/base/settings.py:1387
|
||||
#, fuzzy
|
||||
#| msgid "Cached ticket files"
|
||||
msgid "Attach ticket files"
|
||||
msgstr "Ticketbestanden bijvoegen bij e-mails"
|
||||
msgstr "Gecachete ticketbestanden"
|
||||
|
||||
#: pretix/base/settings.py:1389
|
||||
#, python-brace-format
|
||||
@@ -6821,8 +6847,6 @@ msgid ""
|
||||
"Tickets will never be attached if they're larger than {size} to avoid email "
|
||||
"delivery problems."
|
||||
msgstr ""
|
||||
"Tickets worden nooit bijgevoegd bij een e-mail als ze groter zijn dan {size}"
|
||||
", om problemen met het versturen van de e-mail te voorkomen."
|
||||
|
||||
#: pretix/base/settings.py:1400
|
||||
msgid "Attach calendar files"
|
||||
@@ -7559,16 +7583,22 @@ msgstr ""
|
||||
"informatie vraagt."
|
||||
|
||||
#: pretix/base/settings.py:2073
|
||||
#, fuzzy
|
||||
#| msgid "Additional fee"
|
||||
msgid "Additional success message"
|
||||
msgstr "Extra succesbericht na het plaatsen van een bestelling"
|
||||
msgstr "Extra kosten"
|
||||
|
||||
#: pretix/base/settings.py:2074
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "This text will be shown on the order confirmation page for pending orders "
|
||||
#| "in addition to the standard text."
|
||||
msgid ""
|
||||
"This message will be shown after an order has been created successfully. It "
|
||||
"will be shown in additional to the default text."
|
||||
msgstr ""
|
||||
"Deze tekst zal worden getoond nadat een klant een bestelling heeft "
|
||||
"geplaatst. Deze tekst wordt samen met de standaardtekst getoond."
|
||||
"Deze tekst zal naast de standaardtekst worden getoond op de "
|
||||
"bevestigingspagina voor openstaande bestellingen."
|
||||
|
||||
#: pretix/base/settings.py:2086
|
||||
msgid "Help text of the phone number field"
|
||||
@@ -7853,12 +7883,12 @@ msgstr ""
|
||||
"met opgeslagen emailinhoud."
|
||||
|
||||
#: pretix/base/shredder.py:206
|
||||
#, fuzzy
|
||||
#| msgid "This will remove all email addresses from the waiting list."
|
||||
msgid ""
|
||||
"This will remove all names, email addresses, and phone numbers from the "
|
||||
"waiting list."
|
||||
msgstr ""
|
||||
"Dit zal alle namen, e-mailadressen en telefoonnummers van de wachtlijst "
|
||||
"verwijderen."
|
||||
msgstr "Dit zal alle e-mailadressen van de wachtlijst verwijderen."
|
||||
|
||||
#: pretix/base/shredder.py:239
|
||||
msgid "Attendee info"
|
||||
@@ -8063,18 +8093,25 @@ msgid "Order code:"
|
||||
msgstr "Bestelcode:"
|
||||
|
||||
#: pretix/base/templates/pretixbase/email/order_details.html:30
|
||||
#, fuzzy
|
||||
#| msgctxt "payment_state"
|
||||
#| msgid "created"
|
||||
msgid "created by"
|
||||
msgstr "aangemaakt door"
|
||||
msgstr "aangemaakt"
|
||||
|
||||
#: pretix/base/templates/pretixbase/email/order_details.html:36
|
||||
#: pretix/base/templates/pretixbase/email/order_details.html:92
|
||||
#, fuzzy
|
||||
#| msgid "Order status"
|
||||
msgid "Order status:"
|
||||
msgstr "Bestelstatus:"
|
||||
msgstr "Bestelstatus"
|
||||
|
||||
#: pretix/base/templates/pretixbase/email/order_details.html:44
|
||||
#: pretix/base/templates/pretixbase/email/order_details.html:140
|
||||
#, fuzzy
|
||||
#| msgid "Organizer"
|
||||
msgid "Organizer:"
|
||||
msgstr "Organisator:"
|
||||
msgstr "Organisator"
|
||||
|
||||
#: pretix/base/templates/pretixbase/email/order_details.html:59
|
||||
msgid "View registration details"
|
||||
@@ -8089,8 +8126,10 @@ msgstr ""
|
||||
"geplaatst:"
|
||||
|
||||
#: pretix/base/templates/pretixbase/email/order_details.html:101
|
||||
#, fuzzy
|
||||
#| msgid "Details"
|
||||
msgid "Details:"
|
||||
msgstr "Details:"
|
||||
msgstr "Details"
|
||||
|
||||
#: pretix/base/templates/pretixbase/forms/widgets/reldate.html:15
|
||||
#: pretix/base/templates/pretixbase/forms/widgets/reldatetime.html:19
|
||||
@@ -8340,9 +8379,10 @@ msgid "Do not copy"
|
||||
msgstr "Niet kopiëren"
|
||||
|
||||
#: pretix/control/forms/event.py:274 pretix/control/forms/subevents.py:309
|
||||
#, python-brace-format
|
||||
#, fuzzy, python-brace-format
|
||||
#| msgid "Default language"
|
||||
msgid "Default ({value})"
|
||||
msgstr "Standaard ({value})"
|
||||
msgstr "Standaardtaal"
|
||||
|
||||
#: pretix/control/forms/event.py:326 pretix/control/forms/organizer.py:84
|
||||
msgid "Custom domain"
|
||||
@@ -8862,7 +8902,7 @@ msgstr "Annulering aangevraagd"
|
||||
|
||||
#: pretix/control/forms/filter.py:158
|
||||
msgid "Fully canceled but invoice not canceled"
|
||||
msgstr "Compleet geannuleerd, maar factuur niet geannuleerd"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/control/forms/filter.py:160
|
||||
msgid "Payment process"
|
||||
@@ -9492,8 +9532,10 @@ msgstr ""
|
||||
"betalingen worden uitgevoerd."
|
||||
|
||||
#: pretix/control/forms/orders.py:107 pretix/control/forms/orders.py:151
|
||||
#, fuzzy
|
||||
#| msgid "Notify user by e-mail"
|
||||
msgid "Notify customer by email"
|
||||
msgstr "Stel de klant per e-mail op de hoogte"
|
||||
msgstr "Stel de gebruiker per e-mail op de hoogte"
|
||||
|
||||
#: pretix/control/forms/orders.py:114
|
||||
msgid "Keep a cancellation fee of"
|
||||
@@ -9514,8 +9556,10 @@ msgstr ""
|
||||
"betalen. Voer een bruto bedrag in, belasting zal automatisch worden berekend."
|
||||
|
||||
#: pretix/control/forms/orders.py:121
|
||||
#, fuzzy
|
||||
#| msgid "Generate cancellation"
|
||||
msgid "Generate cancellation for invoice"
|
||||
msgstr "Genereer annulering voor factuur"
|
||||
msgstr "Genereer annulering"
|
||||
|
||||
#: pretix/control/forms/orders.py:158
|
||||
msgid "Payment amount"
|
||||
@@ -9890,17 +9934,21 @@ msgstr "Optioneel"
|
||||
#: pretix/control/templates/pretixcontrol/subevents/bulk_edit.html:48
|
||||
#: pretix/control/templates/pretixcontrol/subevents/bulk_edit.html:181
|
||||
#: pretix/control/templates/pretixcontrol/subevents/bulk_edit.html:266
|
||||
#, fuzzy
|
||||
#| msgid "Change"
|
||||
msgctxt "form_bulk"
|
||||
msgid "change"
|
||||
msgstr "veranderen"
|
||||
msgstr "Veranderen"
|
||||
|
||||
#: pretix/control/forms/subevents.py:96
|
||||
#, fuzzy
|
||||
#| msgid "Current value"
|
||||
msgid "Keep the current values"
|
||||
msgstr "Houd huidige waarden"
|
||||
msgstr "Huidige waarde"
|
||||
|
||||
#: pretix/control/forms/subevents.py:113 pretix/control/forms/subevents.py:121
|
||||
msgid "Selection contains various values"
|
||||
msgstr "Selectie bevat verschillende waarden"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/control/forms/subevents.py:369
|
||||
msgid "Exclude these dates instead of adding them."
|
||||
@@ -10311,28 +10359,40 @@ msgid "This object has been created by cloning."
|
||||
msgstr "Dit object is aangemaakt via kopiëren."
|
||||
|
||||
#: pretix/control/logdisplay.py:276
|
||||
#, fuzzy
|
||||
#| msgid "The order has been changed."
|
||||
msgid "The organizer has been changed."
|
||||
msgstr "De organisator is veranderd."
|
||||
msgstr "De bestelling is aangepast."
|
||||
|
||||
#: pretix/control/logdisplay.py:277
|
||||
#, fuzzy
|
||||
#| msgid "The team settings have been changed."
|
||||
msgid "The organizer settings have been changed."
|
||||
msgstr "De instellingen van de organisator zijn aangepast."
|
||||
msgstr "De teaminstellingen zijn aangepast."
|
||||
|
||||
#: pretix/control/logdisplay.py:278
|
||||
#, fuzzy
|
||||
#| msgid "The new organizer has been created."
|
||||
msgid "Gift card acceptance for another organizer has been added."
|
||||
msgstr "Cadeaubonacceptatie voor een andere organisator is toegevoegd."
|
||||
msgstr "De nieuwe organisator is aangemaakt."
|
||||
|
||||
#: pretix/control/logdisplay.py:279
|
||||
#, fuzzy
|
||||
#| msgid "The new organizer has been created."
|
||||
msgid "Gift card acceptance for another organizer has been removed."
|
||||
msgstr "Cadeaubonacceptatie voor een andere organisator is verwijderd."
|
||||
msgstr "De nieuwe organisator is aangemaakt."
|
||||
|
||||
#: pretix/control/logdisplay.py:280
|
||||
#, fuzzy
|
||||
#| msgid "The user has been created."
|
||||
msgid "The webhook has been created."
|
||||
msgstr "De webhook is aangemaakt."
|
||||
msgstr "De gebruiker is aangemaakt."
|
||||
|
||||
#: pretix/control/logdisplay.py:281
|
||||
#, fuzzy
|
||||
#| msgid "The gate has been changed."
|
||||
msgid "The webhook has been changed."
|
||||
msgstr "De webhook is aangepast."
|
||||
msgstr "De toegangslocatie is aangepast."
|
||||
|
||||
#: pretix/control/logdisplay.py:282
|
||||
msgid "The event's internal comment has been updated."
|
||||
@@ -10343,8 +10403,10 @@ msgid "The event has been canceled."
|
||||
msgstr "Het evenement is geannuleerd."
|
||||
|
||||
#: pretix/control/logdisplay.py:284
|
||||
#, fuzzy
|
||||
#| msgid "The event has been deleted."
|
||||
msgid "An event has been deleted."
|
||||
msgstr "Een webhook is verwijderd."
|
||||
msgstr "Dit evenement is verwijderd."
|
||||
|
||||
#: pretix/control/logdisplay.py:285
|
||||
msgid "The order details have been changed."
|
||||
@@ -12375,19 +12437,25 @@ msgstr "Geocoding-data © OpenStreetMap"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/event/fragment_geodata_autoupdate.html:4
|
||||
msgid "Failed to retrieve geo coordinates"
|
||||
msgstr "Geo-coördinaten ophalen mislukt"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/event/fragment_geodata_autoupdate.html:5
|
||||
#, fuzzy
|
||||
#| msgid "Geo coordinates"
|
||||
msgid "Retrieving geo coordinates …"
|
||||
msgstr "Geo-coördinaten ophalen…"
|
||||
msgstr "Geo-coördinaten"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/event/fragment_geodata_autoupdate.html:6
|
||||
#, fuzzy
|
||||
#| msgid "Geo coordinates"
|
||||
msgid "Geo coordinates updated"
|
||||
msgstr "Geo-coördinaten bijgewerkt"
|
||||
msgstr "Geo-coördinaten"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/event/fragment_geodata_autoupdate.html:7
|
||||
#, fuzzy
|
||||
#| msgid "Update comment"
|
||||
msgid "Update map?"
|
||||
msgstr "Kaart bijwerken?"
|
||||
msgstr "Commentaar bijwerken"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/event/fragment_timeline.html:5
|
||||
msgid "Your timeline"
|
||||
@@ -15496,7 +15564,7 @@ msgstr "VOLLEDIG BETAALD"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/orders/index.html:175
|
||||
msgid "INVOICE NOT CANCELED"
|
||||
msgstr "FACTUUR NIET GEANNULEERD"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/orders/index.html:186
|
||||
msgid "Sum over all pages"
|
||||
@@ -15882,8 +15950,10 @@ msgstr ""
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/organizers/logs.html:4
|
||||
#: pretix/control/templates/pretixcontrol/organizers/logs.html:6
|
||||
#, fuzzy
|
||||
#| msgid "Organizers"
|
||||
msgid "Organizer logs"
|
||||
msgstr "Organisatorlogs"
|
||||
msgstr "Organisatoren"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/organizers/properties.html:7
|
||||
msgid ""
|
||||
@@ -15897,24 +15967,34 @@ msgstr ""
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/organizers/properties.html:15
|
||||
#: pretix/control/templates/pretixcontrol/organizers/property_edit.html:8
|
||||
#, fuzzy
|
||||
#| msgid "Create a new product"
|
||||
msgid "Create a new property"
|
||||
msgstr "Nieuwe eigenschap aanmaken"
|
||||
msgstr "Nieuw product aanmaken"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/organizers/properties.html:20
|
||||
#, fuzzy
|
||||
#| msgid "Add property"
|
||||
msgid "Property"
|
||||
msgstr "Eigenschap"
|
||||
msgstr "Eigenschap toevoegen"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/organizers/property_delete.html:5
|
||||
#, fuzzy
|
||||
#| msgid "Delete product"
|
||||
msgid "Delete property:"
|
||||
msgstr "Verwijder eigenschap:"
|
||||
msgstr "Product verwijderen"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/organizers/property_delete.html:8
|
||||
#, fuzzy
|
||||
#| msgid "Are you sure you want to delete the gate?"
|
||||
msgid "Are you sure you want to delete the property?"
|
||||
msgstr "Weet u zeker dat u de eigenschap wilt verwijderen?"
|
||||
msgstr "Weet u zeker dat u de toegangslocatie wilt verwijderen?"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/organizers/property_edit.html:6
|
||||
#, fuzzy
|
||||
#| msgid "Add property"
|
||||
msgid "Property:"
|
||||
msgstr "Eigenschap:"
|
||||
msgstr "Eigenschap toevoegen"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/organizers/team_delete.html:5
|
||||
msgid "Delete team:"
|
||||
@@ -16294,8 +16374,10 @@ msgid "Light"
|
||||
msgstr "Licht"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/pdf/index.html:349
|
||||
#, fuzzy
|
||||
#| msgid "E-mail content"
|
||||
msgid "Image content"
|
||||
msgstr "Afbeeldingsinhoud"
|
||||
msgstr "E-mailinhoud"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/pdf/index.html:360
|
||||
msgid "Text content"
|
||||
@@ -16331,7 +16413,7 @@ msgstr "pretix-logo"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/pdf/index.html:410
|
||||
msgid "Dynamic image"
|
||||
msgstr "Dynamische afbeelding"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/search/orders.html:104
|
||||
msgid ""
|
||||
@@ -16584,14 +16666,18 @@ msgstr "Voeg een nieuwe inchecklijst toe"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/subevents/bulk_edit.html:8
|
||||
#: pretix/control/templates/pretixcontrol/subevents/bulk_edit.html:11
|
||||
#, fuzzy
|
||||
#| msgctxt "subevent"
|
||||
#| msgid "Create multiple dates"
|
||||
msgctxt "subevent"
|
||||
msgid "Change multiple dates"
|
||||
msgstr "Meerdere datums veranderen"
|
||||
msgstr "Maak meerdere datums aan"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/subevents/bulk_edit.html:13
|
||||
#, python-format
|
||||
#, fuzzy, python-format
|
||||
#| msgid "Enable selected"
|
||||
msgid "%(number)s selected"
|
||||
msgstr "%(number)s geselecteerd"
|
||||
msgstr "Schakel geselecteerde in"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/subevents/bulk_edit.html:171
|
||||
msgid ""
|
||||
@@ -16600,18 +16686,12 @@ msgid ""
|
||||
"new set of quotas to <strong>replace</strong> the quota setup of all "
|
||||
"selected dates."
|
||||
msgstr ""
|
||||
"De quotuminstellingen van de gekozen datums verschillen en kunnen hierom "
|
||||
"niet in één keer aangepast worden. Als u dit wilt kunt u wel nieuwe quota "
|
||||
"definiëren om de quotuminstellingen van de geselecteerde datums "
|
||||
"<strong>vervangen</strong>."
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/subevents/bulk_edit.html:257
|
||||
msgid ""
|
||||
"You selected a set of dates that currently have different check-in list "
|
||||
"setups. You can therefore not change their check-in lists in bulk."
|
||||
msgstr ""
|
||||
"De inchecklijstinstellingen van de gekozen datums verschillen en kunnen "
|
||||
"hierom niet in één keer aangepast worden."
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/subevents/delete.html:4
|
||||
#: pretix/control/templates/pretixcontrol/subevents/delete.html:6
|
||||
@@ -16671,7 +16751,7 @@ msgstr "Maak meerdere nieuwe datums"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/subevents/index.html:70
|
||||
msgid "select all rows for batch-operation"
|
||||
msgstr "Selecteer alle rijen voor batch-handeling"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/subevents/index.html:77
|
||||
msgid "Begin"
|
||||
@@ -16679,11 +16759,11 @@ msgstr "Begin"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/subevents/index.html:100
|
||||
msgid "Select all results on other pages as well"
|
||||
msgstr "Selecteer ook alle resultaten op andere pagina's"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/subevents/index.html:111
|
||||
msgid "select row for batch-operation"
|
||||
msgstr "Selecteer rij voor batch-handeling"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/subevents/index.html:152
|
||||
msgctxt "subevent"
|
||||
@@ -16701,16 +16781,23 @@ msgid "Delete selected"
|
||||
msgstr "Verwijder geselecteerde"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/subevents/index.html:176
|
||||
#, fuzzy
|
||||
#| msgctxt "subevent"
|
||||
#| msgid "No date selected."
|
||||
msgid "Edit selected"
|
||||
msgstr "Bewerk geselecteerde"
|
||||
msgstr "Geen datum geselecteerd."
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/subevents/index.html:179
|
||||
#, fuzzy
|
||||
#| msgid "Disable selected"
|
||||
msgid "Activate selected"
|
||||
msgstr "Activeer geselecteerde"
|
||||
msgstr "Schakel geselecteerde uit"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/subevents/index.html:182
|
||||
#, fuzzy
|
||||
#| msgid "Delete selected"
|
||||
msgid "Deactivate selected"
|
||||
msgstr "Deactiveer geselecteerde"
|
||||
msgstr "Verwijder geselecteerde"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/user/2fa_add.html:4
|
||||
#: pretix/control/templates/pretixcontrol/user/2fa_add.html:6
|
||||
@@ -18608,12 +18695,16 @@ msgid "The selected gate has been deleted."
|
||||
msgstr "De geselecteerde toegangslocatie is verwijderd."
|
||||
|
||||
#: pretix/control/views/organizer.py:1375
|
||||
#, fuzzy
|
||||
#| msgid "The product has been created."
|
||||
msgid "The property has been created."
|
||||
msgstr "De eigenschap is aangemaakt."
|
||||
msgstr "Het product is aangemaakt."
|
||||
|
||||
#: pretix/control/views/organizer.py:1437
|
||||
#, fuzzy
|
||||
#| msgid "The selected product has been deleted."
|
||||
msgid "The selected property has been deleted."
|
||||
msgstr "De eigenschap is verwijderd."
|
||||
msgstr "Het gekozen product is verwijderd."
|
||||
|
||||
#: pretix/control/views/pdf.py:53
|
||||
msgid "The uploaded PDF file is too large."
|
||||
@@ -20366,14 +20457,19 @@ msgid "Only send to customers of dates starting before"
|
||||
msgstr "Stuur alleen naar klanten van subevenementen die beginnen voor"
|
||||
|
||||
#: pretix/plugins/sendmail/forms.py:70
|
||||
#, fuzzy
|
||||
#| msgid "Send to customers with order status"
|
||||
msgctxt "subevent"
|
||||
msgid "Only send to customers with orders created after"
|
||||
msgstr "Stuur alleen naar klanten met bestellingen geplaatst na"
|
||||
msgstr "Stuur naar klanten met bestelstatus"
|
||||
|
||||
#: pretix/plugins/sendmail/forms.py:75
|
||||
#, fuzzy
|
||||
#| msgctxt "subevent"
|
||||
#| msgid "Only send to customers of dates starting before"
|
||||
msgctxt "subevent"
|
||||
msgid "Only send to customers with orders created before"
|
||||
msgstr "Stuur alleen naar klanten met bestellingen geplaatst voor"
|
||||
msgstr "Stuur alleen naar klanten van subevenementen die beginnen voor"
|
||||
|
||||
#: pretix/plugins/sendmail/forms.py:108
|
||||
msgid "Everyone who created a ticket order"
|
||||
@@ -20457,13 +20553,16 @@ msgid "There are no orders matching this selection."
|
||||
msgstr "Er zijn geen bestellingen die overeenkomen met deze selectie."
|
||||
|
||||
#: pretix/plugins/sendmail/views.py:180
|
||||
#, python-format
|
||||
#, fuzzy, python-format
|
||||
#| msgid ""
|
||||
#| "Your message has been queued and will be sent to the contact addresses of "
|
||||
#| "%d orders in the next minutes."
|
||||
msgid ""
|
||||
"Your message has been queued and will be sent to the contact addresses of %d "
|
||||
"orders in the next few minutes."
|
||||
msgstr ""
|
||||
"Uw bericht is in de wachtrij gezet en zal binnenkort naar de e-mailadressen "
|
||||
"van %d bestellingen worden verstuurd."
|
||||
"Uw bericht is in de wachtrij gezet, en zal in de komende minuten naar de e-"
|
||||
"mailadressen van %d bestellingen worden verstuurd."
|
||||
|
||||
#: pretix/plugins/statistics/__init__.py:9
|
||||
#: pretix/plugins/statistics/__init__.py:12
|
||||
@@ -21454,9 +21553,12 @@ msgid "No other variations of this product exist."
|
||||
msgstr "Er bestaan geen andere varianten van dit product."
|
||||
|
||||
#: pretix/presale/forms/renderers.py:32
|
||||
#, fuzzy
|
||||
#| msgctxt "attendee_data"
|
||||
#| msgid "Required"
|
||||
msgctxt "form"
|
||||
msgid "required"
|
||||
msgstr "verplicht"
|
||||
msgstr "Verplicht"
|
||||
|
||||
#: pretix/presale/ical.py:54
|
||||
#, python-brace-format
|
||||
@@ -21474,8 +21576,10 @@ msgid "Organizer: {organizer}"
|
||||
msgstr "Organisator: {organizer}"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/base.html:59
|
||||
#, fuzzy
|
||||
#| msgid "Toggle navigation"
|
||||
msgid "Footer Navigation"
|
||||
msgstr "Footer-navigatie"
|
||||
msgstr "Navigatie schakelen"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/base_footer.html:36
|
||||
#, python-format
|
||||
@@ -21492,8 +21596,10 @@ msgstr "Zet uw winkel nu live"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/base.html:40
|
||||
#: pretix/presale/templates/pretixpresale/event/base.html:86
|
||||
#, fuzzy
|
||||
#| msgid "Use languages"
|
||||
msgid "select language"
|
||||
msgstr "taal kiezen"
|
||||
msgstr "Gebruik talen"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/base.html:52
|
||||
#, python-format
|
||||
@@ -21652,7 +21758,7 @@ msgstr "Ga terug"
|
||||
#: pretix/presale/templates/pretixpresale/event/checkout_base.html:7
|
||||
#, python-format
|
||||
msgid "Step %(current)s of %(total)s: %(label)s"
|
||||
msgstr "Stap %(current)s van %(total)s: %(label)s"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/checkout_base.html:12
|
||||
#: pretix/presale/templates/pretixpresale/event/checkout_base.html:57
|
||||
@@ -21924,12 +22030,16 @@ msgid "Redeem voucher"
|
||||
msgstr "Voucher inwisselen"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_checkoutflow.html:13
|
||||
#, fuzzy
|
||||
#| msgid "Completion date"
|
||||
msgid "Completed:"
|
||||
msgstr "Voltooid:"
|
||||
msgstr "Voltooiingsdatum"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_checkoutflow.html:15
|
||||
#, fuzzy
|
||||
#| msgid "Currency"
|
||||
msgid "Current:"
|
||||
msgstr "Huidig:"
|
||||
msgstr "Munteenheid"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_checkoutflow.html:29
|
||||
msgctxt "checkoutflow"
|
||||
@@ -21943,27 +22053,39 @@ msgstr ""
|
||||
"tickets te ontvangen."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_downloads.html:16
|
||||
#, fuzzy
|
||||
#| msgid "Please check your email account, we've sent you your tickets."
|
||||
msgid "Please check your email account, we've sent you an email."
|
||||
msgstr "We hebben een e-mail naar u verzonden."
|
||||
msgstr ""
|
||||
"We hebben uw tickets per e-mail naar u verzonden. Kijk in uw inbox om uw "
|
||||
"tickets te ontvangen."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_downloads.html:21
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "You can also download them right here as soon as the person who placed "
|
||||
#| "the order clicked the link in the email they received to confirm the "
|
||||
#| "email address is valid."
|
||||
msgid ""
|
||||
"You can download your tickets right here as soon as the person who placed "
|
||||
"the order clicked the link in the email they received to confirm the email "
|
||||
"address is valid."
|
||||
msgstr ""
|
||||
"De persoon die de bestelling heeft geplaatst heeft een e-mail ontvangen met "
|
||||
"een link om het opgegeven e-mailadres te controleren. U kunt uw tickets op "
|
||||
"deze pagina downloaden zodra de persoon die de bestelling heeft geplaatst op "
|
||||
"deze link heeft geklikt."
|
||||
"U kunt uw tickets ook op deze pagina downloaden zodra het opgegeven e-"
|
||||
"mailadres is bevestigd. Dit kan de persoon die de bestelling heeft geplaatst "
|
||||
"doen door te klikken op de link in de toegezonden email."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_downloads.html:26
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "If the email has no attachment, click the link in our email and you will "
|
||||
#| "be able to download them from here."
|
||||
msgid ""
|
||||
"If you click the link in our email, you will be able to download your "
|
||||
"tickets here."
|
||||
msgstr ""
|
||||
"U kunt uw tickets op deze pagina downloaden zodra u op de link in onze e-"
|
||||
"mail klikt."
|
||||
"Als de email geen bijlage heeft kunt u op de link in de mail klikken om de "
|
||||
"tickets te downloaden."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_downloads.html:30
|
||||
msgid ""
|
||||
@@ -22017,14 +22139,17 @@ msgid "Confirmed"
|
||||
msgstr "Bevestigd"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_product_list.html:9
|
||||
#, fuzzy
|
||||
#| msgid "Uncategorized"
|
||||
msgid "Uncategorized products"
|
||||
msgstr "Ongecategoriseerde producten"
|
||||
msgstr "Ongecategoriseerd"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_product_list.html:28
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_product_list.html:187
|
||||
#, python-format
|
||||
#, fuzzy, python-format
|
||||
#| msgid "Show all events of %(name)s"
|
||||
msgid "Show full-size image of %(item)s"
|
||||
msgstr "Toon volledige afbeelding van %(item)s"
|
||||
msgstr "Toon alle evenementen van %(name)s"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_product_list.html:63
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_product_list.html:120
|
||||
@@ -22092,12 +22217,10 @@ msgstr "Nog niet in de verkoop"
|
||||
#: pretix/presale/templates/pretixpresale/event/index.html:27
|
||||
msgid "Your cart, general information, add products to your cart"
|
||||
msgstr ""
|
||||
"Uw winkelwagen, algemene informatie, nieuwe producten aan winkelwagen "
|
||||
"toevoegen"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/index.html:27
|
||||
msgid "General information, add products to your cart"
|
||||
msgstr "Algemene informatie, nieuwe producten aan winkelwagen toevoegen"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/index.html:65
|
||||
#: pretix/presale/templates/pretixpresale/event/index.html:82
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import importlib.util
|
||||
|
||||
from django.apps import apps
|
||||
from django.conf.urls import include, url
|
||||
from django.conf.urls import include, re_path
|
||||
|
||||
from pretix.multidomain.plugin_handler import plugin_event_urls
|
||||
from pretix.presale.urls import event_patterns, locale_patterns
|
||||
from pretix.urls import common_patterns
|
||||
|
||||
presale_patterns = [
|
||||
url(r'', include((locale_patterns + [
|
||||
url(r'', include(event_patterns)),
|
||||
re_path(r'', include((locale_patterns + [
|
||||
re_path(r'', include(event_patterns)),
|
||||
], 'presale')))
|
||||
]
|
||||
|
||||
@@ -21,11 +21,11 @@ for app in apps.get_app_configs():
|
||||
if hasattr(urlmod, 'event_patterns'):
|
||||
patterns = plugin_event_urls(urlmod.event_patterns, plugin=app.name)
|
||||
raw_plugin_patterns.append(
|
||||
url(r'', include((patterns, app.label)))
|
||||
re_path(r'', include((patterns, app.label)))
|
||||
)
|
||||
|
||||
plugin_patterns = [
|
||||
url(r'', include((raw_plugin_patterns, 'plugins')))
|
||||
re_path(r'', include((raw_plugin_patterns, 'plugins')))
|
||||
]
|
||||
|
||||
# The presale namespace comes last, because it contains a wildcard catch
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import importlib.util
|
||||
|
||||
from django.apps import apps
|
||||
from django.conf.urls import include, url
|
||||
from django.conf.urls import include, re_path
|
||||
from django.views.generic import TemplateView
|
||||
|
||||
from pretix.multidomain.plugin_handler import plugin_event_urls
|
||||
@@ -11,10 +11,10 @@ from pretix.presale.urls import (
|
||||
from pretix.urls import common_patterns
|
||||
|
||||
presale_patterns_main = [
|
||||
url(r'', include((locale_patterns + [
|
||||
url(r'^(?P<organizer>[^/]+)/', include(organizer_patterns)),
|
||||
url(r'^(?P<organizer>[^/]+)/(?P<event>[^/]+)/', include(event_patterns)),
|
||||
url(r'^$', TemplateView.as_view(template_name='pretixpresale/index.html'), name="index")
|
||||
re_path(r'', include((locale_patterns + [
|
||||
re_path(r'^(?P<organizer>[^/]+)/', include(organizer_patterns)),
|
||||
re_path(r'^(?P<organizer>[^/]+)/(?P<event>[^/]+)/', include(event_patterns)),
|
||||
re_path(r'^$', TemplateView.as_view(template_name='pretixpresale/index.html'), name="index")
|
||||
], 'presale')))
|
||||
]
|
||||
|
||||
@@ -28,18 +28,18 @@ for app in apps.get_app_configs():
|
||||
single_plugin_patterns += urlmod.urlpatterns
|
||||
if hasattr(urlmod, 'event_patterns'):
|
||||
patterns = plugin_event_urls(urlmod.event_patterns, plugin=app.name)
|
||||
single_plugin_patterns.append(url(r'^(?P<organizer>[^/]+)/(?P<event>[^/]+)/',
|
||||
include(patterns)))
|
||||
single_plugin_patterns.append(re_path(r'^(?P<organizer>[^/]+)/(?P<event>[^/]+)/',
|
||||
include(patterns)))
|
||||
if hasattr(urlmod, 'organizer_patterns'):
|
||||
patterns = urlmod.organizer_patterns
|
||||
single_plugin_patterns.append(url(r'^(?P<organizer>[^/]+)/',
|
||||
include(patterns)))
|
||||
single_plugin_patterns.append(re_path(r'^(?P<organizer>[^/]+)/',
|
||||
include(patterns)))
|
||||
raw_plugin_patterns.append(
|
||||
url(r'', include((single_plugin_patterns, app.label)))
|
||||
re_path(r'', include((single_plugin_patterns, app.label)))
|
||||
)
|
||||
|
||||
plugin_patterns = [
|
||||
url(r'', include((raw_plugin_patterns, 'plugins')))
|
||||
re_path(r'', include((raw_plugin_patterns, 'plugins')))
|
||||
]
|
||||
|
||||
# The presale namespace comes last, because it contains a wildcard catch
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import importlib.util
|
||||
|
||||
from django.apps import apps
|
||||
from django.conf.urls import include, url
|
||||
from django.conf.urls import include, re_path
|
||||
|
||||
from pretix.multidomain.plugin_handler import plugin_event_urls
|
||||
from pretix.presale.urls import (
|
||||
@@ -10,9 +10,9 @@ from pretix.presale.urls import (
|
||||
from pretix.urls import common_patterns
|
||||
|
||||
presale_patterns = [
|
||||
url(r'', include((locale_patterns + [
|
||||
url(r'', include(organizer_patterns)),
|
||||
url(r'^(?P<event>[^/]+)/', include(event_patterns)),
|
||||
re_path(r'', include((locale_patterns + [
|
||||
re_path(r'', include(organizer_patterns)),
|
||||
re_path(r'^(?P<event>[^/]+)/', include(event_patterns)),
|
||||
], 'presale')))
|
||||
]
|
||||
|
||||
@@ -24,16 +24,16 @@ for app in apps.get_app_configs():
|
||||
if hasattr(urlmod, 'event_patterns'):
|
||||
patterns = plugin_event_urls(urlmod.event_patterns, plugin=app.name)
|
||||
raw_plugin_patterns.append(
|
||||
url(r'^(?P<event>[^/]+)/', include((patterns, app.label)))
|
||||
re_path(r'^(?P<event>[^/]+)/', include((patterns, app.label)))
|
||||
)
|
||||
if hasattr(urlmod, 'organizer_patterns'):
|
||||
patterns = urlmod.organizer_patterns
|
||||
raw_plugin_patterns.append(
|
||||
url(r'', include((patterns, app.label)))
|
||||
re_path(r'', include((patterns, app.label)))
|
||||
)
|
||||
|
||||
plugin_patterns = [
|
||||
url(r'', include((raw_plugin_patterns, 'plugins')))
|
||||
re_path(r'', include((raw_plugin_patterns, 'plugins')))
|
||||
]
|
||||
|
||||
# The presale namespace comes last, because it contains a wildcard catch
|
||||
|
||||
@@ -63,7 +63,7 @@ def eventurl(parser, token, absolute=False):
|
||||
asvar = bits[-1]
|
||||
bits = bits[:-2]
|
||||
|
||||
if bits:
|
||||
if len(bits):
|
||||
for bit in bits:
|
||||
match = kwarg_re.match(bit)
|
||||
if not match:
|
||||
|
||||
@@ -5,14 +5,12 @@ from io import BytesIO
|
||||
from typing import Tuple
|
||||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.contrib.staticfiles import finders
|
||||
from django.core.files import File
|
||||
from django.core.files.storage import default_storage
|
||||
from django.db.models import Exists, OuterRef
|
||||
from django.db.models.functions import Coalesce
|
||||
from django.utils.translation import gettext as _, gettext_lazy
|
||||
from jsonfallback.functions import JSONExtract
|
||||
from reportlab.lib import pagesizes
|
||||
from reportlab.lib.units import mm
|
||||
from reportlab.pdfgen import canvas
|
||||
@@ -242,10 +240,10 @@ class BadgeExporter(BaseExporter):
|
||||
choices=[
|
||||
('name', _('Attendee name')),
|
||||
('code', _('Order code')),
|
||||
] + ([
|
||||
] + [
|
||||
('name:{}'.format(k), _('Attendee name: {part}').format(part=label))
|
||||
for k, label, w in name_scheme['fields']
|
||||
] if settings.JSON_FIELD_AVAILABLE and len(name_scheme['fields']) > 1 else []),
|
||||
],
|
||||
)),
|
||||
]
|
||||
)
|
||||
@@ -275,10 +273,8 @@ class BadgeExporter(BaseExporter):
|
||||
qs = qs.annotate(
|
||||
resolved_name=Coalesce('attendee_name_parts', 'addon_to__attendee_name_parts',
|
||||
'order__invoice_address__name_parts')
|
||||
).annotate(
|
||||
resolved_name_part=JSONExtract('resolved_name', part)
|
||||
).order_by(
|
||||
'resolved_name_part'
|
||||
f'resolved_name__{part}'
|
||||
)
|
||||
|
||||
outbuffer = render_pdf(self.event, qs, OPTIONS[form_data.get('rendering', 'one')])
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from django.conf.urls import url
|
||||
from django.conf.urls import re_path
|
||||
|
||||
from pretix.api.urls import event_router
|
||||
from pretix.plugins.badges.api import BadgeItemViewSet, BadgeLayoutViewSet
|
||||
@@ -9,18 +9,18 @@ from .views import (
|
||||
)
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/badges/$',
|
||||
LayoutListView.as_view(), name='index'),
|
||||
url(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/badges/print$',
|
||||
OrderPrintDo.as_view(), name='print'),
|
||||
url(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/badges/add$',
|
||||
LayoutCreate.as_view(), name='add'),
|
||||
url(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/badges/(?P<layout>\d+)/default$',
|
||||
LayoutSetDefault.as_view(), name='default'),
|
||||
url(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/badges/(?P<layout>\d+)/delete$',
|
||||
LayoutDelete.as_view(), name='delete'),
|
||||
url(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/badges/(?P<layout>\d+)/editor',
|
||||
LayoutEditorView.as_view(), name='edit'),
|
||||
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/badges/$',
|
||||
LayoutListView.as_view(), name='index'),
|
||||
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/badges/print$',
|
||||
OrderPrintDo.as_view(), name='print'),
|
||||
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/badges/add$',
|
||||
LayoutCreate.as_view(), name='add'),
|
||||
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/badges/(?P<layout>\d+)/default$',
|
||||
LayoutSetDefault.as_view(), name='default'),
|
||||
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/badges/(?P<layout>\d+)/delete$',
|
||||
LayoutDelete.as_view(), name='delete'),
|
||||
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/badges/(?P<layout>\d+)/editor',
|
||||
LayoutEditorView.as_view(), name='edit'),
|
||||
]
|
||||
event_router.register('badgelayouts', BadgeLayoutViewSet)
|
||||
event_router.register('badgeitems', BadgeItemViewSet)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from django.conf.urls import url
|
||||
from django.conf.urls import re_path
|
||||
|
||||
from pretix.api.urls import orga_router
|
||||
from pretix.plugins.banktransfer.api import BankImportJobViewSet
|
||||
@@ -6,38 +6,38 @@ from pretix.plugins.banktransfer.api import BankImportJobViewSet
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^control/organizer/(?P<organizer>[^/]+)/banktransfer/import/',
|
||||
views.OrganizerImportView.as_view(),
|
||||
name='import'),
|
||||
url(r'^control/organizer/(?P<organizer>[^/]+)/banktransfer/job/(?P<job>\d+)/',
|
||||
views.OrganizerJobDetailView.as_view(), name='import.job'),
|
||||
url(r'^control/organizer/(?P<organizer>[^/]+)/banktransfer/action/',
|
||||
views.OrganizerActionView.as_view(), name='import.action'),
|
||||
url(r'^control/organizer/(?P<organizer>[^/]+)/banktransfer/refunds/',
|
||||
views.OrganizerRefundExportListView.as_view(), name='refunds.list'),
|
||||
url(r'^control/organizer/(?P<organizer>[^/]+)/banktransfer/export/(?P<id>\d+)/$',
|
||||
views.OrganizerDownloadRefundExportView.as_view(),
|
||||
name='refunds.download'),
|
||||
url(r'^control/organizer/(?P<organizer>[^/]+)/banktransfer/sepa-export/(?P<id>\d+)/$',
|
||||
views.OrganizerSepaXMLExportView.as_view(),
|
||||
name='refunds.sepa'),
|
||||
re_path(r'^control/organizer/(?P<organizer>[^/]+)/banktransfer/import/',
|
||||
views.OrganizerImportView.as_view(),
|
||||
name='import'),
|
||||
re_path(r'^control/organizer/(?P<organizer>[^/]+)/banktransfer/job/(?P<job>\d+)/',
|
||||
views.OrganizerJobDetailView.as_view(), name='import.job'),
|
||||
re_path(r'^control/organizer/(?P<organizer>[^/]+)/banktransfer/action/',
|
||||
views.OrganizerActionView.as_view(), name='import.action'),
|
||||
re_path(r'^control/organizer/(?P<organizer>[^/]+)/banktransfer/refunds/',
|
||||
views.OrganizerRefundExportListView.as_view(), name='refunds.list'),
|
||||
re_path(r'^control/organizer/(?P<organizer>[^/]+)/banktransfer/export/(?P<id>\d+)/$',
|
||||
views.OrganizerDownloadRefundExportView.as_view(),
|
||||
name='refunds.download'),
|
||||
re_path(r'^control/organizer/(?P<organizer>[^/]+)/banktransfer/sepa-export/(?P<id>\d+)/$',
|
||||
views.OrganizerSepaXMLExportView.as_view(),
|
||||
name='refunds.sepa'),
|
||||
|
||||
url(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/banktransfer/import/',
|
||||
views.EventImportView.as_view(),
|
||||
name='import'),
|
||||
url(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/banktransfer/job/(?P<job>\d+)/',
|
||||
views.EventJobDetailView.as_view(), name='import.job'),
|
||||
url(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/banktransfer/action/',
|
||||
views.EventActionView.as_view(), name='import.action'),
|
||||
url(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/banktransfer/refunds/',
|
||||
views.EventRefundExportListView.as_view(),
|
||||
name='refunds.list'),
|
||||
url(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/banktransfer/export/(?P<id>\d+)/$',
|
||||
views.EventDownloadRefundExportView.as_view(),
|
||||
name='refunds.download'),
|
||||
url(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/banktransfer/sepa-export/(?P<id>\d+)/$',
|
||||
views.EventSepaXMLExportView.as_view(),
|
||||
name='refunds.sepa'),
|
||||
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/banktransfer/import/',
|
||||
views.EventImportView.as_view(),
|
||||
name='import'),
|
||||
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/banktransfer/job/(?P<job>\d+)/',
|
||||
views.EventJobDetailView.as_view(), name='import.job'),
|
||||
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/banktransfer/action/',
|
||||
views.EventActionView.as_view(), name='import.action'),
|
||||
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/banktransfer/refunds/',
|
||||
views.EventRefundExportListView.as_view(),
|
||||
name='refunds.list'),
|
||||
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/banktransfer/export/(?P<id>\d+)/$',
|
||||
views.EventDownloadRefundExportView.as_view(),
|
||||
name='refunds.download'),
|
||||
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/banktransfer/sepa-export/(?P<id>\d+)/$',
|
||||
views.EventSepaXMLExportView.as_view(),
|
||||
name='refunds.sepa'),
|
||||
]
|
||||
|
||||
orga_router.register('bankimportjobs', BankImportJobViewSet)
|
||||
|
||||
@@ -3,16 +3,14 @@ from datetime import datetime, time, timedelta
|
||||
|
||||
import dateutil.parser
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.db.models import (
|
||||
Case, Exists, Max, OuterRef, Q, Subquery, Value, When,
|
||||
Case, Exists, Max, OuterRef, Q, Subquery, Value, When, F,
|
||||
)
|
||||
from django.db.models.functions import Coalesce, NullIf
|
||||
from django.urls import reverse
|
||||
from django.utils.formats import date_format
|
||||
from django.utils.timezone import is_aware, make_aware
|
||||
from django.utils.translation import gettext as _, gettext_lazy, pgettext
|
||||
from jsonfallback.functions import JSONExtract
|
||||
from pytz import UTC
|
||||
from reportlab.lib.units import mm
|
||||
from reportlab.platypus import Flowable, Paragraph, Spacer, Table, TableStyle
|
||||
@@ -73,10 +71,10 @@ class CheckInListMixin(BaseExporter):
|
||||
choices=[
|
||||
('name', _('Attendee name')),
|
||||
('code', _('Order code')),
|
||||
] + ([
|
||||
] + [
|
||||
('name:{}'.format(k), _('Attendee name: {part}').format(part=label))
|
||||
for k, label, w in name_scheme['fields']
|
||||
] if settings.JSON_FIELD_AVAILABLE and len(name_scheme['fields']) > 1 else []),
|
||||
],
|
||||
widget=forms.RadioSelect,
|
||||
required=False
|
||||
)),
|
||||
@@ -159,7 +157,7 @@ class CheckInListMixin(BaseExporter):
|
||||
), self.event.timezone)
|
||||
qs = qs.filter(subevent__date_from__lt=dt)
|
||||
|
||||
o = ()
|
||||
o = tuple()
|
||||
if self.event.has_subevents and not cl.subevent:
|
||||
o = ('subevent__date_from', 'subevent__name')
|
||||
|
||||
@@ -180,15 +178,17 @@ class CheckInListMixin(BaseExporter):
|
||||
part = sort[5:]
|
||||
qs = qs.annotate(
|
||||
resolved_name=Case(
|
||||
When(attendee_name_cached__ne='', then='attendee_name_parts'),
|
||||
When(addon_to__attendee_name_cached__isnull=False, addon_to__attendee_name_cached__ne='', then='addon_to__attendee_name_parts'),
|
||||
default='order__invoice_address__name_parts',
|
||||
)
|
||||
When(attendee_name_cached__isnull=False, attendee_name_cached__ne='',
|
||||
then='attendee_name_parts'),
|
||||
When(addon_to__attendee_name_cached__isnull=False, addon_to__attendee_name_cached__ne='',
|
||||
then='addon_to__attendee_name_parts'),
|
||||
default='order__invoice_address__name_parts',
|
||||
),
|
||||
).annotate(
|
||||
resolved_name_part=JSONExtract('resolved_name', part)
|
||||
resolved_name_part=F(f'resolved_name__{part}')
|
||||
).order_by(
|
||||
*o,
|
||||
'resolved_name_part'
|
||||
f'resolved_name__{part}'
|
||||
)
|
||||
|
||||
if form_data.get('attention_only'):
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from django.conf.urls import include, url
|
||||
from django.conf.urls import include, re_path
|
||||
|
||||
from pretix.multidomain import event_url
|
||||
|
||||
@@ -7,22 +7,21 @@ from .views import (
|
||||
)
|
||||
|
||||
event_patterns = [
|
||||
url(r'^paypal/', include([
|
||||
url(r'^abort/$', abort, name='abort'),
|
||||
url(r'^return/$', success, name='return'),
|
||||
url(r'^redirect/$', redirect_view, name='redirect'),
|
||||
re_path(r'^paypal/', include([
|
||||
re_path(r'^abort/$', abort, name='abort'),
|
||||
re_path(r'^return/$', success, name='return'),
|
||||
re_path(r'^redirect/$', redirect_view, name='redirect'),
|
||||
|
||||
url(r'w/(?P<cart_namespace>[a-zA-Z0-9]{16})/abort/', abort, name='abort'),
|
||||
url(r'w/(?P<cart_namespace>[a-zA-Z0-9]{16})/return/', success, name='return'),
|
||||
re_path(r'w/(?P<cart_namespace>[a-zA-Z0-9]{16})/abort/', abort, name='abort'),
|
||||
re_path(r'w/(?P<cart_namespace>[a-zA-Z0-9]{16})/return/', success, name='return'),
|
||||
|
||||
event_url(r'^webhook/$', webhook, name='webhook', require_live=False),
|
||||
])),
|
||||
]
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/paypal/disconnect/',
|
||||
oauth_disconnect, name='oauth.disconnect'),
|
||||
url(r'^_paypal/webhook/$', webhook, name='webhook'),
|
||||
url(r'^_paypal/oauth_return/$', oauth_return, name='oauth.return'),
|
||||
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/paypal/disconnect/',
|
||||
oauth_disconnect, name='oauth.disconnect'),
|
||||
re_path(r'^_paypal/webhook/$', webhook, name='webhook'),
|
||||
re_path(r'^_paypal/oauth_return/$', oauth_return, name='oauth.return'),
|
||||
]
|
||||
|
||||
@@ -616,7 +616,7 @@ class OrderTaxListReport(MultiSheetListExporter):
|
||||
elif sheet == 'companies':
|
||||
yield from self.iterate_companies(form_data)
|
||||
|
||||
def _combine(self, *qs, keys=()):
|
||||
def _combine(self, *qs, keys=tuple()):
|
||||
cache = {}
|
||||
|
||||
def kf(r):
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
from django.conf.urls import url
|
||||
from django.conf.urls import re_path
|
||||
|
||||
from .views import ReturnSettings
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/returnurl/settings$',
|
||||
ReturnSettings.as_view(), name='settings'),
|
||||
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/returnurl/settings$',
|
||||
ReturnSettings.as_view(), name='settings'),
|
||||
]
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
from django.conf.urls import url
|
||||
from django.conf.urls import re_path
|
||||
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/sendmail/$', views.SenderView.as_view(),
|
||||
name='send'),
|
||||
url(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/sendmail/history/', views.EmailHistoryView.as_view(), name='history')
|
||||
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/sendmail/$', views.SenderView.as_view(),
|
||||
name='send'),
|
||||
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/sendmail/history/', views.EmailHistoryView.as_view(),
|
||||
name='history')
|
||||
]
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<h1>{% trans "Statistics" %}</h1>
|
||||
{% if request.event.has_subevents %}
|
||||
<form class="form-inline helper-display-inline" action="" method="get">
|
||||
{% include "pretixcontrol/event/fragment_subevent_choice_simple.html" with auto_submit=True %}
|
||||
{% include "pretixcontrol/event/fragment_subevent_choice_simple.html" %}
|
||||
</form>
|
||||
{% endif %}
|
||||
{% if has_orders %}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
from django.conf.urls import url
|
||||
from django.conf.urls import re_path
|
||||
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/statistics/', views.IndexView.as_view(),
|
||||
name='index'),
|
||||
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/statistics/', views.IndexView.as_view(),
|
||||
name='index'),
|
||||
]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from django.conf.urls import include, url
|
||||
from django.conf.urls import include, re_path
|
||||
|
||||
from pretix.multidomain import event_url
|
||||
|
||||
@@ -9,30 +9,30 @@ from .views import (
|
||||
)
|
||||
|
||||
event_patterns = [
|
||||
url(r'^stripe/', include([
|
||||
re_path(r'^stripe/', include([
|
||||
event_url(r'^webhook/$', webhook, name='webhook', require_live=False),
|
||||
url(r'^redirect/$', redirect_view, name='redirect'),
|
||||
url(r'^return/(?P<order>[^/]+)/(?P<hash>[^/]+)/(?P<payment>[0-9]+)/$', ReturnView.as_view(), name='return'),
|
||||
url(r'^sca/(?P<order>[^/]+)/(?P<hash>[^/]+)/(?P<payment>[0-9]+)/$', ScaView.as_view(), name='sca'),
|
||||
url(r'^sca/(?P<order>[^/]+)/(?P<hash>[^/]+)/(?P<payment>[0-9]+)/return/$',
|
||||
ScaReturnView.as_view(), name='sca.return'),
|
||||
re_path(r'^redirect/$', redirect_view, name='redirect'),
|
||||
re_path(r'^return/(?P<order>[^/]+)/(?P<hash>[^/]+)/(?P<payment>[0-9]+)/$', ReturnView.as_view(), name='return'),
|
||||
re_path(r'^sca/(?P<order>[^/]+)/(?P<hash>[^/]+)/(?P<payment>[0-9]+)/$', ScaView.as_view(), name='sca'),
|
||||
re_path(r'^sca/(?P<order>[^/]+)/(?P<hash>[^/]+)/(?P<payment>[0-9]+)/return/$',
|
||||
ScaReturnView.as_view(), name='sca.return'),
|
||||
])),
|
||||
url(r'^.well-known/apple-developer-merchantid-domain-association$',
|
||||
applepay_association, name='applepay.association'),
|
||||
re_path(r'^.well-known/apple-developer-merchantid-domain-association$',
|
||||
applepay_association, name='applepay.association'),
|
||||
]
|
||||
|
||||
organizer_patterns = [
|
||||
url(r'^.well-known/apple-developer-merchantid-domain-association$',
|
||||
applepay_association, name='applepay.association'),
|
||||
re_path(r'^.well-known/apple-developer-merchantid-domain-association$',
|
||||
applepay_association, name='applepay.association'),
|
||||
]
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/stripe/disconnect/',
|
||||
oauth_disconnect, name='oauth.disconnect'),
|
||||
url(r'^control/organizer/(?P<organizer>[^/]+)/stripeconnect/',
|
||||
OrganizerSettingsFormView.as_view(), name='settings.connect'),
|
||||
url(r'^_stripe/webhook/$', webhook, name='webhook'),
|
||||
url(r'^_stripe/oauth_return/$', oauth_return, name='oauth.return'),
|
||||
url(r'^.well-known/apple-developer-merchantid-domain-association$',
|
||||
applepay_association, name='applepay.association'),
|
||||
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/stripe/disconnect/',
|
||||
oauth_disconnect, name='oauth.disconnect'),
|
||||
re_path(r'^control/organizer/(?P<organizer>[^/]+)/stripeconnect/',
|
||||
OrganizerSettingsFormView.as_view(), name='settings.connect'),
|
||||
re_path(r'^_stripe/webhook/$', webhook, name='webhook'),
|
||||
re_path(r'^_stripe/oauth_return/$', oauth_return, name='oauth.return'),
|
||||
re_path(r'^.well-known/apple-developer-merchantid-domain-association$',
|
||||
applepay_association, name='applepay.association'),
|
||||
]
|
||||
|
||||
@@ -2,11 +2,9 @@ from collections import OrderedDict
|
||||
from io import BytesIO
|
||||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.core.files.base import ContentFile
|
||||
from django.db.models.functions import Coalesce
|
||||
from django.utils.translation import gettext as _, gettext_lazy
|
||||
from jsonfallback.functions import JSONExtract
|
||||
from PyPDF2.merger import PdfFileMerger
|
||||
|
||||
from pretix.base.exporter import BaseExporter
|
||||
@@ -41,7 +39,7 @@ class AllTicketsPDF(BaseExporter):
|
||||
] + ([
|
||||
('name:{}'.format(k), _('Attendee name: {part}').format(part=label))
|
||||
for k, label, w in name_scheme['fields']
|
||||
] if settings.JSON_FIELD_AVAILABLE and name_scheme and len(name_scheme['fields']) > 1 else []),
|
||||
] if name_scheme else [])
|
||||
)),
|
||||
]
|
||||
)
|
||||
@@ -68,10 +66,8 @@ class AllTicketsPDF(BaseExporter):
|
||||
part = form_data['order_by'][5:]
|
||||
qs = qs.annotate(
|
||||
resolved_name=Coalesce('attendee_name_parts', 'addon_to__attendee_name_parts', 'order__invoice_address__name_parts')
|
||||
).annotate(
|
||||
resolved_name_part=JSONExtract('resolved_name', part)
|
||||
).order_by(
|
||||
'resolved_name_part'
|
||||
f'resolved_name__{part}'
|
||||
)
|
||||
|
||||
o = PdfTicketOutput(Event.objects.none())
|
||||
|
||||
@@ -131,10 +131,10 @@ def pdf_logentry_object_link(sender, logentry, **kwargs):
|
||||
return a_text.format_map(a_map)
|
||||
|
||||
|
||||
override_layout = EventPluginSignal(
|
||||
providing_args=["layout", "orderposition"]
|
||||
)
|
||||
override_layout = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``layout``, ``orderposition``
|
||||
|
||||
This signal allows you to forcefully override the ticket layout that is being used to create the ticket PDF. Use with
|
||||
care, as this will render any specifically by the organizer selected templates useless.
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from django.conf.urls import url
|
||||
from django.conf.urls import re_path
|
||||
|
||||
from pretix.api.urls import event_router
|
||||
from pretix.plugins.ticketoutputpdf.api import (
|
||||
@@ -10,18 +10,18 @@ from pretix.plugins.ticketoutputpdf.views import (
|
||||
)
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/pdfoutput/$',
|
||||
LayoutListView.as_view(), name='index'),
|
||||
url(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/pdfoutput/add$',
|
||||
LayoutCreate.as_view(), name='add'),
|
||||
url(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/pdfoutput/(?P<layout>\d+)/default$',
|
||||
LayoutSetDefault.as_view(), name='default'),
|
||||
url(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/pdfoutput/default$',
|
||||
LayoutGetDefault.as_view(), name='getdefault'),
|
||||
url(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/pdfoutput/(?P<layout>\d+)/delete$',
|
||||
LayoutDelete.as_view(), name='delete'),
|
||||
url(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/pdfoutput/(?P<layout>\d+)/editor',
|
||||
LayoutEditorView.as_view(), name='edit'),
|
||||
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/pdfoutput/$',
|
||||
LayoutListView.as_view(), name='index'),
|
||||
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/pdfoutput/add$',
|
||||
LayoutCreate.as_view(), name='add'),
|
||||
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/pdfoutput/(?P<layout>\d+)/default$',
|
||||
LayoutSetDefault.as_view(), name='default'),
|
||||
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/pdfoutput/default$',
|
||||
LayoutGetDefault.as_view(), name='getdefault'),
|
||||
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/pdfoutput/(?P<layout>\d+)/delete$',
|
||||
LayoutDelete.as_view(), name='delete'),
|
||||
re_path(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/pdfoutput/(?P<layout>\d+)/editor',
|
||||
LayoutEditorView.as_view(), name='edit'),
|
||||
]
|
||||
event_router.register('ticketlayouts', TicketLayoutViewSet)
|
||||
event_router.register('ticketlayoutitems', TicketLayoutItemViewSet)
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
from bootstrap3.renderers import FieldRenderer
|
||||
from bootstrap3.text import text_value
|
||||
from bootstrap3.utils import add_css_class
|
||||
from django.forms import CheckboxInput, CheckboxSelectMultiple, RadioSelect
|
||||
from django.forms import CheckboxInput
|
||||
from django.forms.utils import flatatt
|
||||
from django.utils.html import escape, format_html, strip_tags
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import pgettext
|
||||
|
||||
|
||||
def render_label(content, label_for=None, label_class=None, label_title='', label_id='', optional=False, is_valid=None):
|
||||
def render_label(content, label_for=None, label_class=None, label_title='', optional=False):
|
||||
"""
|
||||
Render a label with content
|
||||
"""
|
||||
@@ -19,17 +19,6 @@ def render_label(content, label_for=None, label_class=None, label_title='', labe
|
||||
attrs['class'] = label_class
|
||||
if label_title:
|
||||
attrs['title'] = label_title
|
||||
if label_id:
|
||||
attrs['id'] = label_id
|
||||
|
||||
opt = ""
|
||||
|
||||
if is_valid is not None:
|
||||
if is_valid:
|
||||
validation_text = pgettext('form', 'is valid')
|
||||
else:
|
||||
validation_text = pgettext('form', 'has errors')
|
||||
opt += '<strong class="sr-only"> {}</strong>'.format(validation_text)
|
||||
|
||||
if text_value(content) == ' ':
|
||||
# Empty label, e.g. checkbox
|
||||
@@ -37,17 +26,17 @@ def render_label(content, label_for=None, label_class=None, label_title='', labe
|
||||
attrs['class'] += ' label-empty'
|
||||
# usually checkboxes have overall empty labels and special labels per checkbox
|
||||
# => remove for-attribute as well as "required"-text appended to label
|
||||
if 'for' in attrs:
|
||||
del(attrs['for'])
|
||||
del(attrs['for'])
|
||||
opt = ""
|
||||
else:
|
||||
opt += '<i class="sr-only label-required">, {}</i>'.format(pgettext('form', 'required')) if not optional else ''
|
||||
opt = mark_safe('<i class="sr-only"> {}</i>'.format(pgettext('form', 'required'))) if not optional else ''
|
||||
|
||||
builder = '<{tag}{attrs}>{content}{opt}</{tag}>'
|
||||
return format_html(
|
||||
builder,
|
||||
tag='label',
|
||||
attrs=mark_safe(flatatt(attrs)) if attrs else '',
|
||||
opt=mark_safe(opt),
|
||||
opt=opt,
|
||||
content=text_value(content),
|
||||
)
|
||||
|
||||
@@ -56,7 +45,6 @@ class CheckoutFieldRenderer(FieldRenderer):
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs['layout'] = 'horizontal'
|
||||
super().__init__(*args, **kwargs)
|
||||
self.is_group_widget = isinstance(self.widget, (CheckboxSelectMultiple, RadioSelect, )) or (self.is_multi_widget and len(self.widget.widgets) > 1)
|
||||
|
||||
def get_form_group_class(self):
|
||||
form_group_class = self.form_group_class
|
||||
@@ -76,26 +64,6 @@ class CheckoutFieldRenderer(FieldRenderer):
|
||||
)
|
||||
return form_group_class
|
||||
|
||||
def append_to_field(self, html):
|
||||
help_text_and_errors = []
|
||||
help_text_and_errors += self.field_errors
|
||||
if self.field_help:
|
||||
help_text_and_errors.append(self.field_help)
|
||||
for idx, text in enumerate(help_text_and_errors):
|
||||
html += '<div class="help-block" id="help-for-{id}-{idx}">{text}</div>'.format(id=self.field.id_for_label, text=text, idx=idx)
|
||||
return html
|
||||
|
||||
def add_help_attrs(self, widget=None):
|
||||
super().add_help_attrs(widget)
|
||||
if widget is None:
|
||||
widget = self.widget
|
||||
help_cnt = len(self.field_errors)
|
||||
if self.field_help:
|
||||
help_cnt += 1
|
||||
if help_cnt > 0:
|
||||
help_ids = ["help-for-{id}-{idx}".format(id=self.field.id_for_label, idx=idx) for idx in range(help_cnt)]
|
||||
widget.attrs["aria-describedby"] = " ".join(help_ids)
|
||||
|
||||
def add_label(self, html):
|
||||
label = self.get_label()
|
||||
|
||||
@@ -105,25 +73,11 @@ class CheckoutFieldRenderer(FieldRenderer):
|
||||
else:
|
||||
required = self.field.field.required
|
||||
|
||||
if self.field.form.is_bound:
|
||||
is_valid = len(self.field.errors) == 0
|
||||
else:
|
||||
is_valid = None
|
||||
|
||||
if self.is_group_widget:
|
||||
label_for = ""
|
||||
label_id = "legend-{}".format(self.field.html_name)
|
||||
else:
|
||||
label_for = self.field.id_for_label
|
||||
label_id = ""
|
||||
|
||||
html = render_label(
|
||||
label,
|
||||
label_for=label_for,
|
||||
label_for=self.field.id_for_label,
|
||||
label_class=self.get_label_class(),
|
||||
label_id=label_id,
|
||||
optional=not required and not isinstance(self.widget, CheckboxInput),
|
||||
is_valid=is_valid
|
||||
optional=not required and not isinstance(self.widget, CheckboxInput)
|
||||
) + html
|
||||
return html
|
||||
|
||||
@@ -134,10 +88,3 @@ class CheckoutFieldRenderer(FieldRenderer):
|
||||
label_for=self.field.id_for_label,
|
||||
label_title=escape(strip_tags(self.field_help)),
|
||||
)
|
||||
|
||||
def wrap_label_and_field(self, html):
|
||||
if self.is_group_widget:
|
||||
attrs = ' role="group" aria-labelledby="legend-{}"'.format(self.field.html_name)
|
||||
else:
|
||||
attrs = ''
|
||||
return '<div class="{klass}"{attrs}>{html}</div>'.format(klass=self.get_form_group_class(), html=html, attrs=attrs)
|
||||
|
||||
@@ -2,10 +2,10 @@ from django.dispatch import Signal
|
||||
|
||||
from pretix.base.signals import EventPluginSignal
|
||||
|
||||
global_html_head = Signal(
|
||||
providing_args=["request"]
|
||||
)
|
||||
global_html_head = Signal()
|
||||
"""
|
||||
Arguments: ``request``
|
||||
|
||||
This signal allows you to put code inside the HTML ``<head>`` tag
|
||||
of every page in the frontend. You will get the request as the keyword argument
|
||||
``request`` and are expected to return plain HTML.
|
||||
@@ -13,10 +13,10 @@ of every page in the frontend. You will get the request as the keyword argument
|
||||
This signal is called regardless of whether your plugin is active for all pages of the system.
|
||||
"""
|
||||
|
||||
global_html_page_header = Signal(
|
||||
providing_args=["request"]
|
||||
)
|
||||
global_html_page_header = Signal()
|
||||
"""
|
||||
Arguments: ``request``
|
||||
|
||||
This signal allows you to put code right in the beginning of the HTML ``<body>`` tag
|
||||
of every page in the frontend. You will get the request as the keyword argument
|
||||
``request`` and are expected to return plain HTML.
|
||||
@@ -24,10 +24,10 @@ of every page in the frontend. You will get the request as the keyword argument
|
||||
This signal is called regardless of whether your plugin is active for all pages of the system.
|
||||
"""
|
||||
|
||||
global_html_footer = Signal(
|
||||
providing_args=["request"]
|
||||
)
|
||||
global_html_footer = Signal()
|
||||
"""
|
||||
Arguments: ``request``
|
||||
|
||||
This signal allows you to put code before the end of the HTML ``<body>`` tag
|
||||
of every page in the frontend. You will get the request as the keyword argument
|
||||
``request`` and are expected to return plain HTML.
|
||||
@@ -35,10 +35,10 @@ of every page in the frontend. You will get the request as the keyword argument
|
||||
This signal is called regardless of whether your plugin is active for all pages of the system.
|
||||
"""
|
||||
|
||||
html_head = EventPluginSignal(
|
||||
providing_args=["request"]
|
||||
)
|
||||
html_head = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``request``
|
||||
|
||||
This signal allows you to put code inside the HTML ``<head>`` tag
|
||||
of every page in the frontend. You will get the request as the keyword argument
|
||||
``request`` and are expected to return plain HTML.
|
||||
@@ -46,10 +46,10 @@ of every page in the frontend. You will get the request as the keyword argument
|
||||
As with all plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
html_page_header = EventPluginSignal(
|
||||
providing_args=["request"]
|
||||
)
|
||||
html_page_header = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``request``
|
||||
|
||||
This signal allows you to put code right in the beginning of the HTML ``<body>`` tag
|
||||
of every page in the frontend. You will get the request as the keyword argument
|
||||
``request`` and are expected to return plain HTML.
|
||||
@@ -57,10 +57,10 @@ of every page in the frontend. You will get the request as the keyword argument
|
||||
As with all plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
html_footer = EventPluginSignal(
|
||||
providing_args=["request"]
|
||||
)
|
||||
html_footer = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``request``
|
||||
|
||||
This signal allows you to put code before the end of the HTML ``<body>`` tag
|
||||
of every page in the frontend. You will get the request as the keyword argument
|
||||
``request`` and are expected to return plain HTML.
|
||||
@@ -68,10 +68,10 @@ of every page in the frontend. You will get the request as the keyword argument
|
||||
As with all plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
sass_preamble = EventPluginSignal(
|
||||
providing_args=["filename"]
|
||||
)
|
||||
sass_preamble = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``filename``
|
||||
|
||||
This signal allows you to put SASS code at the beginning of the event-specific
|
||||
stylesheet. Keep in mind that this will only be called/rebuilt when the user changes
|
||||
display settings or pretix gets updated. You will get the filename that is being
|
||||
@@ -82,10 +82,10 @@ code.
|
||||
As with all plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
sass_postamble = EventPluginSignal(
|
||||
providing_args=["filename"]
|
||||
)
|
||||
sass_postamble = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``filename``
|
||||
|
||||
This signal allows you to put SASS code at the end of the event-specific
|
||||
stylesheet. Keep in mind that this will only be called/rebuilt when the user changes
|
||||
display settings or pretix gets updated. You will get the filename that is being
|
||||
@@ -95,20 +95,20 @@ all of pretix' SASS code.
|
||||
As with all plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
footer_link = EventPluginSignal(
|
||||
providing_args=["request"]
|
||||
)
|
||||
footer_link = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``request``
|
||||
|
||||
The signal ``pretix.presale.signals.footer_link`` allows you to add links to the footer of an event page. You
|
||||
are expected to return a dictionary containing the keys ``label`` and ``url``.
|
||||
|
||||
As with all plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
global_footer_link = Signal(
|
||||
providing_args=["request"]
|
||||
)
|
||||
global_footer_link = Signal()
|
||||
"""
|
||||
Arguments: ``request``
|
||||
|
||||
The signal ``pretix.presale.signals.global_footer_link`` allows you to add links to the footer of any page. You
|
||||
are expected to return a dictionary containing the keys ``label`` and ``url``.
|
||||
"""
|
||||
@@ -131,29 +131,29 @@ a subclass of ``pretix.presale.checkoutflow.BaseCheckoutFlowStep``.
|
||||
As with all plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
voucher_redeem_info = EventPluginSignal(
|
||||
providing_args=["voucher"]
|
||||
)
|
||||
voucher_redeem_info = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``voucher``
|
||||
|
||||
This signal is sent out to display additional information on the "redeem a voucher" page
|
||||
|
||||
As with all plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
order_meta_from_request = EventPluginSignal(
|
||||
providing_args=["request"]
|
||||
)
|
||||
order_meta_from_request = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``request``
|
||||
|
||||
This signal is sent before an order is created through the pretixpresale frontend. It allows you
|
||||
to return a dictionary that will be merged in the meta_info attribute of the order.
|
||||
You will receive the request triggering the order creation as the ``request`` keyword argument.
|
||||
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
checkout_confirm_page_content = EventPluginSignal(
|
||||
providing_args=['request']
|
||||
)
|
||||
checkout_confirm_page_content = EventPluginSignal()
|
||||
"""
|
||||
Arguments: 'request'
|
||||
|
||||
This signals allows you to add HTML content to the confirmation page that is presented at the
|
||||
end of the checkout process, just before the order is being created.
|
||||
|
||||
@@ -161,10 +161,10 @@ As with all plugin signals, the ``sender`` keyword argument will contain the eve
|
||||
argument will contain the request object.
|
||||
"""
|
||||
|
||||
fee_calculation_for_cart = EventPluginSignal(
|
||||
providing_args=['request', 'invoice_address', 'total', 'positions']
|
||||
)
|
||||
fee_calculation_for_cart = EventPluginSignal()
|
||||
"""
|
||||
Arguments: 'request', 'invoice_address', 'total', 'positions'
|
||||
|
||||
This signals allows you to add fees to a cart. You are expected to return a list of ``OrderFee``
|
||||
objects that are not yet saved to the database (because there is no order yet).
|
||||
|
||||
@@ -175,9 +175,7 @@ You should not rely on this ``total`` value for fee calculations as other fees m
|
||||
The ``positions`` argument will contain a list or queryset of ``CartPosition`` objects.
|
||||
"""
|
||||
|
||||
contact_form_fields = EventPluginSignal(
|
||||
providing_args=[]
|
||||
)
|
||||
contact_form_fields = EventPluginSignal()
|
||||
"""
|
||||
This signals allows you to add form fields to the contact form that is presented during checkout
|
||||
and by default only asks for the email address. You are supposed to return a dictionary of
|
||||
@@ -188,10 +186,10 @@ As with all plugin signals, the ``sender`` keyword argument will contain the eve
|
||||
argument will contain the request object.
|
||||
"""
|
||||
|
||||
contact_form_fields_overrides = EventPluginSignal(
|
||||
providing_args=["request", "order"]
|
||||
)
|
||||
contact_form_fields_overrides = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``request``, ``order``
|
||||
|
||||
This signal allows you to override fields of the contact form that is presented during checkout
|
||||
and by default only asks for the email address. It is also being used for the invoice address
|
||||
form. You are supposed to return a dictionary of dictionaries with globally unique keys. The
|
||||
@@ -203,10 +201,10 @@ argument will contain the request object. The ``order`` argument is ``None`` dur
|
||||
process and contains an order if the customer is trying to change an existing order.
|
||||
"""
|
||||
|
||||
question_form_fields = EventPluginSignal(
|
||||
providing_args=["position"]
|
||||
)
|
||||
question_form_fields = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``position``
|
||||
|
||||
This signals allows you to add form fields to the questions form that is presented during checkout
|
||||
and by default asks for the questions configured in the backend. You are supposed to return a dictionary
|
||||
of form fields with globally unique keys. The validated form results will be saved into the
|
||||
@@ -219,10 +217,10 @@ later.
|
||||
As with all plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
question_form_fields_overrides = EventPluginSignal(
|
||||
providing_args=["position", "request"]
|
||||
)
|
||||
question_form_fields_overrides = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``position``, ``request``
|
||||
|
||||
This signal allows you to override fields of the questions form that is presented during checkout
|
||||
and by default only asks for the questions configured in the backend. You are supposed to return a
|
||||
dictionary of dictionaries with globally unique keys. The value-dictionary should contain one or
|
||||
@@ -235,46 +233,46 @@ As with all plugin signals, the ``sender`` keyword argument will contain the eve
|
||||
argument will contain the request object.
|
||||
"""
|
||||
|
||||
order_info = EventPluginSignal(
|
||||
providing_args=["order", "request"]
|
||||
)
|
||||
order_info = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``order``, ``request``
|
||||
|
||||
This signal is sent out to display additional information on the order detail page
|
||||
|
||||
As with all plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
position_info = EventPluginSignal(
|
||||
providing_args=["order", "position", "request"]
|
||||
)
|
||||
position_info = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``order``, ``position``, ``request``
|
||||
|
||||
This signal is sent out to display additional information on the position detail page
|
||||
|
||||
As with all plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
order_info_top = EventPluginSignal(
|
||||
providing_args=["order", "request"]
|
||||
)
|
||||
order_info_top = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``order``, ``request``
|
||||
|
||||
This signal is sent out to display additional information on top of the order detail page
|
||||
|
||||
As with all plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
position_info_top = EventPluginSignal(
|
||||
providing_args=["order", "position", "request"]
|
||||
)
|
||||
position_info_top = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``order``, ``position``, ``request``
|
||||
|
||||
This signal is sent out to display additional information on top of the position detail page
|
||||
|
||||
As with all plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
process_request = EventPluginSignal(
|
||||
providing_args=["request"]
|
||||
)
|
||||
process_request = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``request``
|
||||
|
||||
This signal is sent out whenever a request is made to a event presale page. Most of the
|
||||
time, this will be called from the middleware layer (except on plugin-provided pages
|
||||
this will be called by the @event_view decorator). Similarly to Django's process_request
|
||||
@@ -287,10 +285,10 @@ easy to cause serious performance problems.
|
||||
As with all plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
process_response = EventPluginSignal(
|
||||
providing_args=["request", "response"]
|
||||
)
|
||||
process_response = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``request``, ``response``
|
||||
|
||||
This signal is sent out whenever a response is sent from a event presale page. Most of
|
||||
the time, this will be called from the middleware layer (except on plugin-provided pages
|
||||
this will be called by the @event_view decorator). Similarly to Django's process_response
|
||||
@@ -304,10 +302,10 @@ easy to cause serious performance problems.
|
||||
As with all plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
"""
|
||||
|
||||
front_page_top = EventPluginSignal(
|
||||
providing_args=["request", "subevent"]
|
||||
)
|
||||
front_page_top = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``request``, ``subevent``
|
||||
|
||||
This signal is sent out to display additional information on the frontpage above the list
|
||||
of products and but below a custom frontpage text.
|
||||
|
||||
@@ -315,10 +313,10 @@ As with all plugin signals, the ``sender`` keyword argument will contain the eve
|
||||
receivers are expected to return HTML.
|
||||
"""
|
||||
|
||||
render_seating_plan = EventPluginSignal(
|
||||
providing_args=["request", "subevent", "voucher"]
|
||||
)
|
||||
render_seating_plan = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``request``, ``subevent``, ``voucher``
|
||||
|
||||
This signal is sent out to render a seating plan, if one is configured for the specific event.
|
||||
You will be passed the ``request`` as a keyword argument. If applicable, a ``subevent`` or
|
||||
``voucher`` argument might be given.
|
||||
@@ -327,10 +325,10 @@ As with all plugin signals, the ``sender`` keyword argument will contain the eve
|
||||
receivers are expected to return HTML.
|
||||
"""
|
||||
|
||||
front_page_bottom = EventPluginSignal(
|
||||
providing_args=["request", "subevent"]
|
||||
)
|
||||
front_page_bottom = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``request``, ``subevent``
|
||||
|
||||
This signal is sent out to display additional information on the frontpage below the list
|
||||
of products.
|
||||
|
||||
@@ -338,10 +336,10 @@ As with all plugin signals, the ``sender`` keyword argument will contain the eve
|
||||
receivers are expected to return HTML.
|
||||
"""
|
||||
|
||||
front_page_bottom_widget = EventPluginSignal(
|
||||
providing_args=["request", "subevent"]
|
||||
)
|
||||
front_page_bottom_widget = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``request``, ``subevent``
|
||||
|
||||
This signal is sent out to display additional information on the frontpage below the list
|
||||
of products if the front page is shown in the widget.
|
||||
|
||||
@@ -349,10 +347,10 @@ As with all plugin signals, the ``sender`` keyword argument will contain the eve
|
||||
receivers are expected to return HTML.
|
||||
"""
|
||||
|
||||
checkout_all_optional = EventPluginSignal(
|
||||
providing_args=['request']
|
||||
)
|
||||
checkout_all_optional = EventPluginSignal()
|
||||
"""
|
||||
Arguments: 'request'
|
||||
|
||||
If any receiver of this signal returns ``True``, all input fields during checkout (contact data,
|
||||
invoice address, confirmations) will be optional, except for questions. Use with care!
|
||||
|
||||
@@ -360,10 +358,10 @@ As with all plugin signals, the ``sender`` keyword argument will contain the eve
|
||||
argument will contain the request object.
|
||||
"""
|
||||
|
||||
item_description = EventPluginSignal(
|
||||
providing_args=["item", "variation"]
|
||||
)
|
||||
item_description = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``item``, ``variation``
|
||||
|
||||
This signal is sent out when the description of an item or variation is rendered and allows you to append
|
||||
additional text to the description. You are passed the ``item`` and ``variation`` and expected to return
|
||||
HTML.
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
<div class="panel-heading">
|
||||
{% if payment_provider.identifier != "free" %}
|
||||
<div class="pull-right flip">
|
||||
<a href="{% eventurl request.event "presale:event.checkout" step="payment" cart_namespace=cart_namespace|default_if_none:"" %}" aria-label="{% trans "Modify payment" %}">
|
||||
<a href="{% eventurl request.event "presale:event.checkout" step="payment" cart_namespace=cart_namespace|default_if_none:"" %}">
|
||||
<span class="fa fa-edit" aria-hidden="true"></span>
|
||||
{% trans "Modify" %}
|
||||
</a>
|
||||
@@ -79,7 +79,7 @@
|
||||
<div class="panel panel-primary panel-contact">
|
||||
<div class="panel-heading">
|
||||
<div class="pull-right flip">
|
||||
<a href="{% eventurl request.event "presale:event.checkout" step="questions" cart_namespace=cart_namespace|default_if_none:"" %}?invoice=1" aria-label="{% trans "Modify invoice information" %}">
|
||||
<a href="{% eventurl request.event "presale:event.checkout" step="questions" cart_namespace=cart_namespace|default_if_none:"" %}?invoice=1">
|
||||
<span class="fa fa-edit" aria-hidden="true"></span>
|
||||
{% trans "Modify" %}
|
||||
</a>
|
||||
@@ -129,7 +129,7 @@
|
||||
<div class="panel panel-primary panel-contact">
|
||||
<div class="panel-heading">
|
||||
<div class="pull-right flip">
|
||||
<a href="{% eventurl request.event "presale:event.checkout" step="questions" cart_namespace=cart_namespace|default_if_none:"" %}" aria-label="{% trans "Modify contact information" %}">
|
||||
<a href="{% eventurl request.event "presale:event.checkout" step="questions" cart_namespace=cart_namespace|default_if_none:"" %}">
|
||||
<span class="fa fa-edit" aria-hidden="true"></span>
|
||||
{% trans "Modify" %}
|
||||
</a>
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
</summary>
|
||||
<div id="contact">
|
||||
<div class="panel-body">
|
||||
{% bootstrap_form contact_form layout="checkout" %}
|
||||
{% bootstrap_form contact_form layout="horizontal" %}
|
||||
{% if not invoice_address_asked and event.settings.invoice_name_required %}
|
||||
{% bootstrap_form invoice_form layout="checkout" %}
|
||||
{% bootstrap_form invoice_form layout="horizontal" %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
@@ -46,7 +46,7 @@
|
||||
{{ event.settings.invoice_address_explanation_text|rich_text }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% bootstrap_form invoice_form layout="checkout" %}
|
||||
{% bootstrap_form invoice_form layout="horizontal" %}
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
@@ -51,47 +51,49 @@
|
||||
</dt>
|
||||
<dd class="toplevel">
|
||||
<span data-toggle="tooltip" title="{% trans "Attendee name" %}">
|
||||
{% if line.attendee_name %}{{ line.attendee_name }}{% else %}<em>{% trans "No attendee name provided" %}</em>{% endif %}
|
||||
{% if line.attendee_name %}{{ line.attendee_name }}{% else %}<em>{% trans "not answered" %}</em>{% endif %}
|
||||
</span>
|
||||
</dd>
|
||||
{% endif %}
|
||||
{% if line.item.admission and event.settings.attendee_emails_asked and line.attendee_email %}
|
||||
{% if line.item.admission and event.settings.attendee_emails_asked %}
|
||||
<dt class="sr-only">
|
||||
{% trans "Attendee email" %}
|
||||
</dt>
|
||||
<dd class="toplevel">
|
||||
<span data-toggle="tooltip" title="{% trans "Attendee email" %}">
|
||||
{{ line.attendee_email }}
|
||||
{% if line.attendee_email %}{{ line.attendee_email }}{% else %}<em>{% trans "not answered" %}</em>{% endif %}
|
||||
</span>
|
||||
</dd>
|
||||
{% endif %}
|
||||
{% if line.item.admission and event.settings.attendee_addresses_asked %}
|
||||
<br>
|
||||
{% endif %}
|
||||
{% if line.item.admission and event.settings.attendee_company_asked and line.company %}
|
||||
{% if line.item.admission and event.settings.attendee_company_asked %}
|
||||
<dt class="sr-only">
|
||||
{% trans "Attendee company" %}
|
||||
</dt>
|
||||
<dd class="toplevel">
|
||||
<span data-toggle="tooltip" title="{% trans "Attendee company" %}">
|
||||
{{ line.company }}
|
||||
{% if line.company %}{{ line.company }}{% else %}<em>{% trans "not answered" %}</em>{% endif %}
|
||||
</span>
|
||||
</dd>
|
||||
{% endif %}
|
||||
{% if line.item.admission and event.settings.attendee_addresses_asked %}
|
||||
{% if line.street or line.zipcode or line.city %}
|
||||
<dt class="sr-only">
|
||||
{% trans "Attendee address" %}
|
||||
</dt>
|
||||
<dd class="toplevel">
|
||||
<span data-toggle="tooltip" title="{% trans "Attendee address" %}">
|
||||
<dt class="sr-only">
|
||||
{% trans "Attendee address" %}
|
||||
</dt>
|
||||
<dd class="toplevel">
|
||||
<span data-toggle="tooltip" title="{% trans "Attendee address" %}">
|
||||
{% if line.street or line.zipcode or line.city or line.country %}
|
||||
{{ line.street|default_if_none:""|linebreaksbr }}<br>
|
||||
{{ line.zipcode|default_if_none:"" }} {{ line.city|default_if_none:"" }}<br>
|
||||
{{ line.country.name|default_if_none:"" }}
|
||||
{% if line.state %}<br>{{ line.state }}{% endif %}
|
||||
</span>
|
||||
</dd>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<em>{% trans "not answered" %}</em>
|
||||
{% endif %}
|
||||
</span>
|
||||
</dd>
|
||||
{% endif %}
|
||||
{% for q in line.questions %}
|
||||
<dt>{{ q.question }}</dt>
|
||||
@@ -138,7 +140,6 @@
|
||||
{% elif line.addon_to %}
|
||||
<div class="count"> </div>
|
||||
<div class="singleprice price">
|
||||
<span class="sr-only">{% trans "price per item" %}</span>
|
||||
{% if event.settings.display_net_prices %}
|
||||
{{ line.net_price|money:event.currency }}
|
||||
{% else %}
|
||||
@@ -162,7 +163,6 @@
|
||||
</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
<span class="sr-only">{% trans "quantity" %}</span>
|
||||
{{ line.count }}
|
||||
{% if editable %}
|
||||
<form action="{% eventurl event "presale:event.cart.add" cart_namespace=cart_namespace|default_if_none:"" %}"
|
||||
@@ -189,7 +189,6 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="singleprice price">
|
||||
<span class="sr-only">{% trans "price per item" %}</span>
|
||||
{% if event.settings.display_net_prices %}
|
||||
{{ line.net_price|money:event.currency }}
|
||||
{% else %}
|
||||
@@ -198,7 +197,6 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="totalprice price">
|
||||
<span class="sr-only">{% trans "price" %}</span>
|
||||
{% if event.settings.display_net_prices %}
|
||||
<strong>{{ line.net_total|money:event.currency }}</strong>
|
||||
{% if line.tax_rate and line.total %}
|
||||
@@ -308,12 +306,11 @@
|
||||
data-asynctask-headline="{% trans "We're applying this voucher to your cart..." %}"
|
||||
method="post" data-asynctask class="apply-voucher">
|
||||
{% csrf_token %}
|
||||
<label for="voucher_code" class="sr-only">{% trans "Voucher code" %}</label>
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" name="voucher" id="voucher_code" placeholder="{% trans "Voucher code" %}" aria-label="{% trans "Voucher code" %}">
|
||||
<input type="text" class="form-control" name="voucher" placeholder="{% trans "Voucher code" %}" aria-label="{% trans "Voucher code" %}">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-primary" type="submit">
|
||||
<span class="fa fa-check" aria-hidden="true"></span><span class="sr-only"> {% trans "Redeem voucher" %}</span>
|
||||
<button class="btn btn-primary" type="submit" aria-label="{% trans "Redeem voucher" %}">
|
||||
<span class="fa fa-check" aria-hidden="true"></span>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -6,14 +6,12 @@
|
||||
{% load eventsignal %}
|
||||
{% load rich_text %}
|
||||
{% for tup in items_by_category %}
|
||||
<section aria-labelledby="category-{% if tup.0 %}{{ tup.0.id }}{% else %}none{% endif %}"{% if tup.0.description %} aria-describedby="category-info-{{ tup.0.id }}"{% endif %}>
|
||||
<section{% if tup.0 %} aria-labelledby="category-{{ tup.0.id }}"{% else %} aria-label="{% trans "Uncategorized products" %}"{% endif %}{% if tup.0.description %} aria-describedby="category-info-{{ tup.0.id }}"{% endif %}>
|
||||
{% if tup.0 %}
|
||||
<h3 id="category-{{ tup.0.id }}">{{ tup.0.name }}</h3>
|
||||
{% if tup.0.description %}
|
||||
<div id="category-info-{{ tup.0.id }}">{{ tup.0.description|localize|rich_text }}</div>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<h3 id="category-none" class="sr-only">{% trans "Uncategorized products" %}</h3>
|
||||
{% endif %}
|
||||
{% for item in tup.1 %}
|
||||
{% if item.has_variations %}
|
||||
|
||||
@@ -105,19 +105,19 @@
|
||||
|
||||
{% if subevent and "year" not in request.GET %}
|
||||
{% if show_cart %}
|
||||
<a class="subevent-toggle btn btn-primary btn-block btn-lg" href="#subevent-list">
|
||||
<a class="subevent-toggle btn btn-primary btn-block btn-lg">
|
||||
<span class="fa fa-reply" aria-hidden="true"></span>
|
||||
{% trans "Add tickets for a different date" %}
|
||||
</a>
|
||||
{% else %}
|
||||
<a class="subevent-toggle btn btn-default btn-block" href="#subevent-list">
|
||||
<a class="subevent-toggle btn btn-default btn-block">
|
||||
{% trans "View other date" %}
|
||||
</a>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<h3>{% trans "Choose date to book a ticket" %}</h3>
|
||||
{% endif %}
|
||||
<div class="panel panel-default subevent-list" id="subevent-list">
|
||||
<div class="panel panel-default subevent-list">
|
||||
<div class="panel-heading">
|
||||
{% if subevent %}
|
||||
{% trans "Other dates" context "subevent" %}
|
||||
@@ -298,11 +298,10 @@
|
||||
<form method="get" action="{% eventurl event "presale:event.redeem" cart_namespace=cart_namespace %}">
|
||||
<div class="row-voucher">
|
||||
<div class="col-md-8 col-sm-6 col-xs-12">
|
||||
<label for="voucher" class="sr-only">{% trans "Voucher code" %}</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><i class="fa fa-ticket fa-fw" aria-hidden="true"></i></span>
|
||||
<input type="text" class="form-control" name="voucher" id="voucher"
|
||||
placeholder="{% trans "Voucher code" %}">
|
||||
placeholder="{% trans "Voucher code" %}" aria-label="{% trans "Voucher code" %}">
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" name="subevent" value="{{ subevent.id|default_if_none:"" }}" />
|
||||
|
||||
@@ -186,7 +186,7 @@
|
||||
<div class="panel-heading">
|
||||
{% if order.can_modify_answers %}
|
||||
<div class="pull-right flip">
|
||||
<a href="{% eventurl event "presale:event.order.modify" secret=order.secret order=order.code %}" aria-label="{% trans "Change ordered items" %}">
|
||||
<a href="{% eventurl event "presale:event.order.modify" secret=order.secret order=order.code %}">
|
||||
<span class="fa fa-edit" aria-hidden="true"></span>
|
||||
{% trans "Change details" %}
|
||||
</a>
|
||||
@@ -280,7 +280,7 @@
|
||||
{% if invoice_address_asked or request.event.settings.invoice_name_required %}
|
||||
{% if order.can_modify_answers %}
|
||||
<div class="pull-right flip">
|
||||
<a href="{% eventurl event "presale:event.order.modify" secret=order.secret order=order.code %}" aria-label="{% trans "Change your information" %}">
|
||||
<a href="{% eventurl event "presale:event.order.modify" secret=order.secret order=order.code %}">
|
||||
<span class="fa fa-edit" aria-hidden="true"></span>
|
||||
{% trans "Change details" %}
|
||||
</a>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from django.conf.urls import include, url
|
||||
from django.conf.urls import include, re_path
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
|
||||
import pretix.presale.views.cart
|
||||
@@ -17,126 +17,129 @@ import pretix.presale.views.widget
|
||||
# configuration is done by the pretix.multidomain package.
|
||||
|
||||
frame_wrapped_urls = [
|
||||
url(r'^cart/remove$', pretix.presale.views.cart.CartRemove.as_view(), name='event.cart.remove'),
|
||||
url(r'^cart/voucher$', pretix.presale.views.cart.CartApplyVoucher.as_view(), name='event.cart.voucher'),
|
||||
url(r'^cart/clear$', pretix.presale.views.cart.CartClear.as_view(), name='event.cart.clear'),
|
||||
url(r'^cart/answer/(?P<answer>[^/]+)/$',
|
||||
pretix.presale.views.cart.AnswerDownload.as_view(),
|
||||
name='event.cart.download.answer'),
|
||||
url(r'^checkout/start$', pretix.presale.views.checkout.CheckoutView.as_view(), name='event.checkout.start'),
|
||||
url(r'^checkout/(?P<step>[^/]+)/$', pretix.presale.views.checkout.CheckoutView.as_view(),
|
||||
name='event.checkout'),
|
||||
url(r'^redeem/?$', pretix.presale.views.cart.RedeemView.as_view(),
|
||||
name='event.redeem'),
|
||||
url(r'^seatingframe/$', pretix.presale.views.event.SeatingPlanView.as_view(),
|
||||
name='event.seatingplan'),
|
||||
url(r'^(?P<subevent>[0-9]+)/seatingframe/$', pretix.presale.views.event.SeatingPlanView.as_view(),
|
||||
name='event.seatingplan'),
|
||||
url(r'^(?P<subevent>[0-9]+)/$', pretix.presale.views.event.EventIndex.as_view(), name='event.index'),
|
||||
url(r'^waitinglist', pretix.presale.views.waiting.WaitingView.as_view(), name='event.waitinglist'),
|
||||
url(r'^$', pretix.presale.views.event.EventIndex.as_view(), name='event.index'),
|
||||
re_path(r'^cart/remove$', pretix.presale.views.cart.CartRemove.as_view(), name='event.cart.remove'),
|
||||
re_path(r'^cart/voucher$', pretix.presale.views.cart.CartApplyVoucher.as_view(), name='event.cart.voucher'),
|
||||
re_path(r'^cart/clear$', pretix.presale.views.cart.CartClear.as_view(), name='event.cart.clear'),
|
||||
re_path(r'^cart/answer/(?P<answer>[^/]+)/$',
|
||||
pretix.presale.views.cart.AnswerDownload.as_view(),
|
||||
name='event.cart.download.answer'),
|
||||
re_path(r'^checkout/start$', pretix.presale.views.checkout.CheckoutView.as_view(), name='event.checkout.start'),
|
||||
re_path(r'^checkout/(?P<step>[^/]+)/$', pretix.presale.views.checkout.CheckoutView.as_view(),
|
||||
name='event.checkout'),
|
||||
re_path(r'^redeem/?$', pretix.presale.views.cart.RedeemView.as_view(),
|
||||
name='event.redeem'),
|
||||
re_path(r'^seatingframe/$', pretix.presale.views.event.SeatingPlanView.as_view(),
|
||||
name='event.seatingplan'),
|
||||
re_path(r'^(?P<subevent>[0-9]+)/seatingframe/$', pretix.presale.views.event.SeatingPlanView.as_view(),
|
||||
name='event.seatingplan'),
|
||||
re_path(r'^(?P<subevent>[0-9]+)/$', pretix.presale.views.event.EventIndex.as_view(), name='event.index'),
|
||||
re_path(r'^waitinglist', pretix.presale.views.waiting.WaitingView.as_view(), name='event.waitinglist'),
|
||||
re_path(r'^$', pretix.presale.views.event.EventIndex.as_view(), name='event.index'),
|
||||
]
|
||||
event_patterns = [
|
||||
# Cart/checkout patterns are a bit more complicated, as they should have simple URLs like cart/clear in normal
|
||||
# cases, but need to have versions with unguessable URLs like w/8l4Y83XNonjLxoBb/cart/clear to be used in widget
|
||||
# mode. This is required to prevent all clickjacking and CSRF attacks that would otherwise be possible.
|
||||
# First, we define the normal version. The docstring of get_or_create_cart_id() has more information on this.
|
||||
url(r'', include(frame_wrapped_urls)),
|
||||
re_path(r'', include(frame_wrapped_urls)),
|
||||
# Second, the widget version
|
||||
url(r'w/(?P<cart_namespace>[a-zA-Z0-9]{16})/', include(frame_wrapped_urls)),
|
||||
re_path(r'w/(?P<cart_namespace>[a-zA-Z0-9]{16})/', include(frame_wrapped_urls)),
|
||||
# Third, a fake version that is defined like the first (and never gets called), but makes reversing URLs easier
|
||||
url(r'(?P<cart_namespace>[_]{0})', include(frame_wrapped_urls)),
|
||||
re_path(r'(?P<cart_namespace>[_]{0})', include(frame_wrapped_urls)),
|
||||
# CartAdd goes extra since it also gets a csrf_exempt decorator in one of the cases
|
||||
url(r'^cart/add$', pretix.presale.views.cart.CartAdd.as_view(), name='event.cart.add'),
|
||||
url(r'^(?P<cart_namespace>[_]{0})cart/add$', pretix.presale.views.cart.CartAdd.as_view(), name='event.cart.add'),
|
||||
url(r'w/(?P<cart_namespace>[a-zA-Z0-9]{16})/cart/add',
|
||||
csrf_exempt(pretix.presale.views.cart.CartAdd.as_view()),
|
||||
name='event.cart.add'),
|
||||
re_path(r'^cart/add$', pretix.presale.views.cart.CartAdd.as_view(), name='event.cart.add'),
|
||||
re_path(r'^(?P<cart_namespace>[_]{0})cart/add$', pretix.presale.views.cart.CartAdd.as_view(),
|
||||
name='event.cart.add'),
|
||||
re_path(r'w/(?P<cart_namespace>[a-zA-Z0-9]{16})/cart/add',
|
||||
csrf_exempt(pretix.presale.views.cart.CartAdd.as_view()),
|
||||
name='event.cart.add'),
|
||||
|
||||
url(r'unlock/(?P<hash>[a-z0-9]{64})/$', pretix.presale.views.user.UnlockHashView.as_view(),
|
||||
name='event.payment.unlock'),
|
||||
url(r'resend/$', pretix.presale.views.user.ResendLinkView.as_view(), name='event.resend_link'),
|
||||
re_path(r'unlock/(?P<hash>[a-z0-9]{64})/$', pretix.presale.views.user.UnlockHashView.as_view(),
|
||||
name='event.payment.unlock'),
|
||||
re_path(r'resend/$', pretix.presale.views.user.ResendLinkView.as_view(), name='event.resend_link'),
|
||||
|
||||
url(r'^order/(?P<order>[^/]+)/(?P<secret>[A-Za-z0-9]+)/open/(?P<hash>[a-z0-9]+)/$', pretix.presale.views.order.OrderOpen.as_view(),
|
||||
name='event.order.open'),
|
||||
url(r'^order/(?P<order>[^/]+)/(?P<secret>[A-Za-z0-9]+)/$', pretix.presale.views.order.OrderDetails.as_view(),
|
||||
name='event.order'),
|
||||
url(r'^order/(?P<order>[^/]+)/(?P<secret>[A-Za-z0-9]+)/invoice$',
|
||||
pretix.presale.views.order.OrderInvoiceCreate.as_view(),
|
||||
name='event.order.geninvoice'),
|
||||
url(r'^order/(?P<order>[^/]+)/(?P<secret>[A-Za-z0-9]+)/change$',
|
||||
pretix.presale.views.order.OrderChange.as_view(),
|
||||
name='event.order.change'),
|
||||
url(r'^order/(?P<order>[^/]+)/(?P<secret>[A-Za-z0-9]+)/cancel$',
|
||||
pretix.presale.views.order.OrderCancel.as_view(),
|
||||
name='event.order.cancel'),
|
||||
url(r'^order/(?P<order>[^/]+)/(?P<secret>[A-Za-z0-9]+)/cancel/do$',
|
||||
pretix.presale.views.order.OrderCancelDo.as_view(),
|
||||
name='event.order.cancel.do'),
|
||||
url(r'^order/(?P<order>[^/]+)/(?P<secret>[A-Za-z0-9]+)/modify$',
|
||||
pretix.presale.views.order.OrderModify.as_view(),
|
||||
name='event.order.modify'),
|
||||
url(r'^order/(?P<order>[^/]+)/(?P<secret>[A-Za-z0-9]+)/pay/(?P<payment>[0-9]+)/$',
|
||||
pretix.presale.views.order.OrderPaymentStart.as_view(),
|
||||
name='event.order.pay'),
|
||||
url(r'^order/(?P<order>[^/]+)/(?P<secret>[A-Za-z0-9]+)/pay/(?P<payment>[0-9]+)/confirm$',
|
||||
pretix.presale.views.order.OrderPaymentConfirm.as_view(),
|
||||
name='event.order.pay.confirm'),
|
||||
url(r'^order/(?P<order>[^/]+)/(?P<secret>[A-Za-z0-9]+)/pay/(?P<payment>[0-9]+)/complete$',
|
||||
pretix.presale.views.order.OrderPaymentComplete.as_view(),
|
||||
name='event.order.pay.complete'),
|
||||
url(r'^order/(?P<order>[^/]+)/(?P<secret>[A-Za-z0-9]+)/pay/change',
|
||||
pretix.presale.views.order.OrderPayChangeMethod.as_view(),
|
||||
name='event.order.pay.change'),
|
||||
url(r'^order/(?P<order>[^/]+)/(?P<secret>[A-Za-z0-9]+)/answer/(?P<answer>[^/]+)/$',
|
||||
pretix.presale.views.order.AnswerDownload.as_view(),
|
||||
name='event.order.download.answer'),
|
||||
url(r'^order/(?P<order>[^/]+)/(?P<secret>[A-Za-z0-9]+)/download/(?P<output>[^/]+)$',
|
||||
pretix.presale.views.order.OrderDownload.as_view(),
|
||||
name='event.order.download.combined'),
|
||||
url(r'^order/(?P<order>[^/]+)/(?P<secret>[A-Za-z0-9]+)/download/(?P<position>[0-9]+)/(?P<output>[^/]+)$',
|
||||
pretix.presale.views.order.OrderDownload.as_view(),
|
||||
name='event.order.download'),
|
||||
url(r'^order/(?P<order>[^/]+)/(?P<secret>[A-Za-z0-9]+)/invoice/(?P<invoice>[0-9]+)$',
|
||||
pretix.presale.views.order.InvoiceDownload.as_view(),
|
||||
name='event.invoice.download'),
|
||||
re_path(r'^order/(?P<order>[^/]+)/(?P<secret>[A-Za-z0-9]+)/open/(?P<hash>[a-z0-9]+)/$',
|
||||
pretix.presale.views.order.OrderOpen.as_view(),
|
||||
name='event.order.open'),
|
||||
re_path(r'^order/(?P<order>[^/]+)/(?P<secret>[A-Za-z0-9]+)/$', pretix.presale.views.order.OrderDetails.as_view(),
|
||||
name='event.order'),
|
||||
re_path(r'^order/(?P<order>[^/]+)/(?P<secret>[A-Za-z0-9]+)/invoice$',
|
||||
pretix.presale.views.order.OrderInvoiceCreate.as_view(),
|
||||
name='event.order.geninvoice'),
|
||||
re_path(r'^order/(?P<order>[^/]+)/(?P<secret>[A-Za-z0-9]+)/change$',
|
||||
pretix.presale.views.order.OrderChange.as_view(),
|
||||
name='event.order.change'),
|
||||
re_path(r'^order/(?P<order>[^/]+)/(?P<secret>[A-Za-z0-9]+)/cancel$',
|
||||
pretix.presale.views.order.OrderCancel.as_view(),
|
||||
name='event.order.cancel'),
|
||||
re_path(r'^order/(?P<order>[^/]+)/(?P<secret>[A-Za-z0-9]+)/cancel/do$',
|
||||
pretix.presale.views.order.OrderCancelDo.as_view(),
|
||||
name='event.order.cancel.do'),
|
||||
re_path(r'^order/(?P<order>[^/]+)/(?P<secret>[A-Za-z0-9]+)/modify$',
|
||||
pretix.presale.views.order.OrderModify.as_view(),
|
||||
name='event.order.modify'),
|
||||
re_path(r'^order/(?P<order>[^/]+)/(?P<secret>[A-Za-z0-9]+)/pay/(?P<payment>[0-9]+)/$',
|
||||
pretix.presale.views.order.OrderPaymentStart.as_view(),
|
||||
name='event.order.pay'),
|
||||
re_path(r'^order/(?P<order>[^/]+)/(?P<secret>[A-Za-z0-9]+)/pay/(?P<payment>[0-9]+)/confirm$',
|
||||
pretix.presale.views.order.OrderPaymentConfirm.as_view(),
|
||||
name='event.order.pay.confirm'),
|
||||
re_path(r'^order/(?P<order>[^/]+)/(?P<secret>[A-Za-z0-9]+)/pay/(?P<payment>[0-9]+)/complete$',
|
||||
pretix.presale.views.order.OrderPaymentComplete.as_view(),
|
||||
name='event.order.pay.complete'),
|
||||
re_path(r'^order/(?P<order>[^/]+)/(?P<secret>[A-Za-z0-9]+)/pay/change',
|
||||
pretix.presale.views.order.OrderPayChangeMethod.as_view(),
|
||||
name='event.order.pay.change'),
|
||||
re_path(r'^order/(?P<order>[^/]+)/(?P<secret>[A-Za-z0-9]+)/answer/(?P<answer>[^/]+)/$',
|
||||
pretix.presale.views.order.AnswerDownload.as_view(),
|
||||
name='event.order.download.answer'),
|
||||
re_path(r'^order/(?P<order>[^/]+)/(?P<secret>[A-Za-z0-9]+)/download/(?P<output>[^/]+)$',
|
||||
pretix.presale.views.order.OrderDownload.as_view(),
|
||||
name='event.order.download.combined'),
|
||||
re_path(r'^order/(?P<order>[^/]+)/(?P<secret>[A-Za-z0-9]+)/download/(?P<position>[0-9]+)/(?P<output>[^/]+)$',
|
||||
pretix.presale.views.order.OrderDownload.as_view(),
|
||||
name='event.order.download'),
|
||||
re_path(r'^order/(?P<order>[^/]+)/(?P<secret>[A-Za-z0-9]+)/invoice/(?P<invoice>[0-9]+)$',
|
||||
pretix.presale.views.order.InvoiceDownload.as_view(),
|
||||
name='event.invoice.download'),
|
||||
|
||||
url(r'^ticket/(?P<order>[^/]+)/(?P<position>\d+)/(?P<secret>[A-Za-z0-9]+)/$',
|
||||
pretix.presale.views.order.OrderPositionDetails.as_view(),
|
||||
name='event.order.position'),
|
||||
url(r'^ticket/(?P<order>[^/]+)/(?P<position>\d+)/(?P<secret>[A-Za-z0-9]+)/download/(?P<pid>[0-9]+)/(?P<output>[^/]+)$',
|
||||
re_path(r'^ticket/(?P<order>[^/]+)/(?P<position>\d+)/(?P<secret>[A-Za-z0-9]+)/$',
|
||||
pretix.presale.views.order.OrderPositionDetails.as_view(),
|
||||
name='event.order.position'),
|
||||
re_path(
|
||||
r'^ticket/(?P<order>[^/]+)/(?P<position>\d+)/(?P<secret>[A-Za-z0-9]+)/download/(?P<pid>[0-9]+)/(?P<output>[^/]+)$',
|
||||
pretix.presale.views.order.OrderPositionDownload.as_view(),
|
||||
name='event.order.position.download'),
|
||||
|
||||
url(r'^ical/?$',
|
||||
pretix.presale.views.event.EventIcalDownload.as_view(),
|
||||
name='event.ical.download'),
|
||||
url(r'^ical/(?P<subevent>[0-9]+)/$',
|
||||
pretix.presale.views.event.EventIcalDownload.as_view(),
|
||||
name='event.ical.download'),
|
||||
url(r'^auth/$', pretix.presale.views.event.EventAuth.as_view(), name='event.auth'),
|
||||
re_path(r'^ical/?$',
|
||||
pretix.presale.views.event.EventIcalDownload.as_view(),
|
||||
name='event.ical.download'),
|
||||
re_path(r'^ical/(?P<subevent>[0-9]+)/$',
|
||||
pretix.presale.views.event.EventIcalDownload.as_view(),
|
||||
name='event.ical.download'),
|
||||
re_path(r'^auth/$', pretix.presale.views.event.EventAuth.as_view(), name='event.auth'),
|
||||
|
||||
url(r'^widget/product_list$', pretix.presale.views.widget.WidgetAPIProductList.as_view(),
|
||||
name='event.widget.productlist'),
|
||||
url(r'^widget/v1.css$', pretix.presale.views.widget.widget_css, name='event.widget.css'),
|
||||
url(r'^(?P<subevent>\d+)/widget/product_list$', pretix.presale.views.widget.WidgetAPIProductList.as_view(),
|
||||
name='event.widget.productlist'),
|
||||
re_path(r'^widget/product_list$', pretix.presale.views.widget.WidgetAPIProductList.as_view(),
|
||||
name='event.widget.productlist'),
|
||||
re_path(r'^widget/v1.css$', pretix.presale.views.widget.widget_css, name='event.widget.css'),
|
||||
re_path(r'^(?P<subevent>\d+)/widget/product_list$', pretix.presale.views.widget.WidgetAPIProductList.as_view(),
|
||||
name='event.widget.productlist'),
|
||||
]
|
||||
|
||||
organizer_patterns = [
|
||||
url(r'^$', pretix.presale.views.organizer.OrganizerIndex.as_view(), name='organizer.index'),
|
||||
url(r'^events/ical/$',
|
||||
pretix.presale.views.organizer.OrganizerIcalDownload.as_view(),
|
||||
name='organizer.ical'),
|
||||
url(r'^widget/product_list$', pretix.presale.views.widget.WidgetAPIProductList.as_view(),
|
||||
name='organizer.widget.productlist'),
|
||||
url(r'^widget/v1.css$', pretix.presale.views.widget.widget_css, name='organizer.widget.css'),
|
||||
re_path(r'^$', pretix.presale.views.organizer.OrganizerIndex.as_view(), name='organizer.index'),
|
||||
re_path(r'^events/ical/$',
|
||||
pretix.presale.views.organizer.OrganizerIcalDownload.as_view(),
|
||||
name='organizer.ical'),
|
||||
re_path(r'^widget/product_list$', pretix.presale.views.widget.WidgetAPIProductList.as_view(),
|
||||
name='organizer.widget.productlist'),
|
||||
re_path(r'^widget/v1.css$', pretix.presale.views.widget.widget_css, name='organizer.widget.css'),
|
||||
]
|
||||
|
||||
locale_patterns = [
|
||||
url(r'^locale/set$', pretix.presale.views.locale.LocaleSet.as_view(), name='locale.set'),
|
||||
url(r'^robots.txt$', pretix.presale.views.robots.robots_txt, name='robots.txt'),
|
||||
url(r'^browserconfig.xml$', pretix.presale.views.theme.browserconfig_xml, name='browserconfig.xml'),
|
||||
url(r'^site.webmanifest$', pretix.presale.views.theme.webmanifest, name='site.webmanifest'),
|
||||
url(r'^widget/v1\.(?P<lang>[a-zA-Z0-9_\-]+)\.js$', pretix.presale.views.widget.widget_js, name='widget.js'),
|
||||
re_path(r'^locale/set$', pretix.presale.views.locale.LocaleSet.as_view(), name='locale.set'),
|
||||
re_path(r'^robots.txt$', pretix.presale.views.robots.robots_txt, name='robots.txt'),
|
||||
re_path(r'^browserconfig.xml$', pretix.presale.views.theme.browserconfig_xml, name='browserconfig.xml'),
|
||||
re_path(r'^site.webmanifest$', pretix.presale.views.theme.webmanifest, name='site.webmanifest'),
|
||||
re_path(r'^widget/v1\.(?P<lang>[a-zA-Z0-9_\-]+)\.js$', pretix.presale.views.widget.widget_js, name='widget.js'),
|
||||
]
|
||||
|
||||
@@ -100,7 +100,7 @@ def _detect_event(request, require_live=True, require_plugin=None):
|
||||
|
||||
if hasattr(request, 'event'):
|
||||
# Restrict locales to the ones available for this event
|
||||
LocaleMiddleware().process_request(request)
|
||||
LocaleMiddleware(NotImplementedError).process_request(request)
|
||||
|
||||
if require_live and not request.event.live:
|
||||
can_access = (
|
||||
|
||||
@@ -81,7 +81,6 @@ else:
|
||||
|
||||
if 'mysql' in db_backend:
|
||||
db_options['charset'] = 'utf8mb4'
|
||||
JSON_FIELD_AVAILABLE = db_backend in ('mysql', 'postgresql')
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
@@ -653,7 +652,7 @@ LOGGING = {
|
||||
'django.db.backends': {
|
||||
'handlers': ['file', 'console'],
|
||||
'level': 'INFO', # Do not output all the queries
|
||||
'propagate': False,
|
||||
'propagate': True,
|
||||
},
|
||||
'asyncio': {
|
||||
'handlers': ['file', 'console'],
|
||||
|
||||
@@ -208,7 +208,7 @@ $input-border-radius-small: $border-radius-small !default;
|
||||
$input-border-focus: #66afe9 !default;
|
||||
|
||||
//** Placeholder text color
|
||||
$input-color-placeholder: #767676 !default;
|
||||
$input-color-placeholder: #999 !default;
|
||||
|
||||
//** Default `.form-control` height
|
||||
$input-height-base: ($line-height-computed + ($padding-base-vertical * 2) + 2) !default;
|
||||
|
||||
@@ -9,19 +9,19 @@
|
||||
$gray-darker: lighten(#000, 13.5%);
|
||||
$gray-dark: lighten(#000, 20%);
|
||||
$gray: lighten(#000, 33.5%);
|
||||
$gray-light: lighten(#000, 55%);
|
||||
$gray-light: lighten(#000, 60%);
|
||||
$gray-lighter: lighten(#000, 93.5%);
|
||||
$gray-lightest: lighten(#000, 97.25%);
|
||||
|
||||
$font-family-sans-serif: "Open Sans", "OpenSans", "Helvetica Neue", Helvetica, Arial, sans-serif !default;
|
||||
$text-color: #222222 !default;
|
||||
$text-muted: #767676 !default;
|
||||
$text-muted: #999999 !default;
|
||||
|
||||
$brand-primary: #7f5a91 !default;
|
||||
$brand-success: #50a167 !default;
|
||||
$brand-info: #5f9cd4 !default;
|
||||
$brand-warning: #ffb419 !default;
|
||||
$brand-danger: #c44f4f !default;
|
||||
$brand-danger: #d36060 !default;
|
||||
|
||||
$btn-default-border: #CCCCCC;
|
||||
|
||||
|
||||
@@ -45,9 +45,9 @@ $(function () {
|
||||
if (data_type === 'B') {
|
||||
var colors;
|
||||
if (data[0].answer_bool) {
|
||||
colors = ['#50A167', '#C44F4F'];
|
||||
colors = ['#50A167', '#D36060'];
|
||||
} else {
|
||||
colors = ['#C44F4F', '#50A167'];
|
||||
colors = ['#D36060', '#50A167'];
|
||||
}
|
||||
new Morris.Donut({
|
||||
element: 'question_chart',
|
||||
@@ -65,7 +65,7 @@ $(function () {
|
||||
'#50A167',
|
||||
'#FFB419',
|
||||
'#5F9CD4',
|
||||
'#C44F4F',
|
||||
'#D36060',
|
||||
'#83FFFA',
|
||||
'#FF6C38',
|
||||
'#1f5b8e',
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
.help-block {
|
||||
color: $text-muted;
|
||||
}
|
||||
|
||||
td > .form-group {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ $(function () {
|
||||
$(".apply-voucher-toggle").click(function (e) {
|
||||
$(".apply-voucher-toggle").hide();
|
||||
$(".apply-voucher").show();
|
||||
$(".apply-voucher input[type=text]").first().focus();
|
||||
$(".apply-voucher input[ŧype=text]").first().focus();
|
||||
e.preventDefault();
|
||||
return true;
|
||||
});
|
||||
|
||||
@@ -292,7 +292,6 @@ $(function () {
|
||||
|
||||
$("input[data-required-if], select[data-required-if], textarea[data-required-if]").each(function () {
|
||||
var dependent = $(this),
|
||||
dependentLabel = $("label[for="+this.id+"]"),
|
||||
dependency = $($(this).attr("data-required-if")),
|
||||
update = function (ev) {
|
||||
var enabled = (dependency.attr("type") === 'checkbox' || dependency.attr("type") === 'radio') ? dependency.prop('checked') : !!dependency.val();
|
||||
@@ -300,12 +299,6 @@ $(function () {
|
||||
dependent.prop('required', enabled);
|
||||
}
|
||||
dependent.closest('.form-group').toggleClass('required', enabled);
|
||||
if (enabled) {
|
||||
dependentLabel.append('<i class="sr-only label-required">, ' + gettext('required') + '</i>');
|
||||
}
|
||||
else {
|
||||
dependentLabel.find(".label-required").remove();
|
||||
}
|
||||
};
|
||||
update();
|
||||
dependency.closest('.form-group').find('input[name=' + dependency.attr("name") + ']').on("change", update);
|
||||
|
||||
@@ -229,9 +229,7 @@ Vue.component('availbox', {
|
||||
},
|
||||
amount_selected: {
|
||||
get: function () {
|
||||
var selected = this.item.has_variations ? this.variation.amount_selected : this.item.amount_selected
|
||||
if (selected === 0) return undefined;
|
||||
return selected
|
||||
return this.item.has_variations ? this.variation.amount_selected : this.item.amount_selected
|
||||
},
|
||||
set: function (value) {
|
||||
// Unary operator to force boolean to integer conversion, as the HTML form submission
|
||||
@@ -614,12 +612,7 @@ var shared_methods = {
|
||||
},
|
||||
resume: function () {
|
||||
var redirect_url;
|
||||
redirect_url = this.$root.target_url + 'w/' + widget_id + '/';
|
||||
if (this.$root.subevent && !this.$root.cart_id) {
|
||||
// button with subevent but no items
|
||||
redirect_url += this.$root.subevent + '/';
|
||||
}
|
||||
redirect_url += '?iframe=1&locale=' + lang;
|
||||
redirect_url = this.$root.target_url + 'w/' + widget_id + '/?iframe=1&locale=' + lang;
|
||||
if (this.$root.cart_id) {
|
||||
redirect_url += '&take_cart_id=' + this.$root.cart_id;
|
||||
}
|
||||
@@ -666,9 +659,7 @@ var shared_iframe_fragment = (
|
||||
+ ' :name="$root.parent.widget_id" src="about:blank" v-once>'
|
||||
+ 'Please enable frames in your browser!'
|
||||
+ '</iframe>'
|
||||
+ '<div class="pretix-widget-frame-close"><a href="#" @click.prevent="close">'
|
||||
+ '<svg height="16px" viewBox="0 0 512 512" width="16px" xmlns="http://www.w3.org/2000/svg"><path fill="#fff" d="M437.5,386.6L306.9,256l130.6-130.6c14.1-14.1,14.1-36.8,0-50.9c-14.1-14.1-36.8-14.1-50.9,0L256,205.1L125.4,74.5 c-14.1-14.1-36.8-14.1-50.9,0c-14.1,14.1-14.1,36.8,0,50.9L205.1,256L74.5,386.6c-14.1,14.1-14.1,36.8,0,50.9 c14.1,14.1,36.8,14.1,50.9,0L256,306.9l130.6,130.6c14.1,14.1,36.8,14.1,50.9,0C451.5,423.4,451.5,400.6,437.5,386.6z"/></svg>'
|
||||
+ '</a></div>'
|
||||
+ '<div class="pretix-widget-frame-close"><a href="#" @click.prevent="close">X</a></div>'
|
||||
+ '</div>'
|
||||
+ '</div>'
|
||||
);
|
||||
@@ -1347,7 +1338,7 @@ var shared_root_methods = {
|
||||
url += '&voucher=' + encodeURIComponent(this.$root.voucher_code);
|
||||
}
|
||||
if (cart_id) {
|
||||
url += "&cart_id=" + encodeURIComponent(cart_id);
|
||||
url += "&cart_id=" + cart_id;
|
||||
}
|
||||
if (this.$root.date !== null) {
|
||||
url += "&year=" + this.$root.date.substr(0, 4) + "&month=" + this.$root.date.substr(5, 2);
|
||||
@@ -1355,21 +1346,18 @@ var shared_root_methods = {
|
||||
url += "&year=" + this.$root.week[0] + "&week=" + this.$root.week[1];
|
||||
}
|
||||
if (this.$root.style !== null) {
|
||||
url = url + '&style=' + encodeURIComponent(this.$root.style);
|
||||
url = url + '&style=' + this.$root.style;
|
||||
}
|
||||
var root = this.$root;
|
||||
api._getJSON(url, function (data, xhr) {
|
||||
if (typeof xhr.responseURL !== "undefined") {
|
||||
if (typeof xhr.responseURL !== "undefined" && xhr.responseURL !== url) {
|
||||
var new_url = xhr.responseURL.substr(0, xhr.responseURL.indexOf("/widget/product_list?") + 1);
|
||||
var old_url = url.substr(0, url.indexOf("/widget/product_list?") + 1);
|
||||
if (new_url !== old_url) {
|
||||
if (root.subevent) {
|
||||
new_url = new_url.substr(0, new_url.lastIndexOf("/", new_url.length - 1) + 1);
|
||||
}
|
||||
root.target_url = new_url;
|
||||
root.reload();
|
||||
return;
|
||||
if (root.subevent) {
|
||||
new_url = new_url.substr(0, new_url.lastIndexOf("/", new_url.length - 1) + 1);
|
||||
}
|
||||
root.target_url = new_url;
|
||||
root.reload();
|
||||
return;
|
||||
}
|
||||
if (data.weeks !== undefined) {
|
||||
root.weeks = data.weeks;
|
||||
@@ -1515,7 +1503,7 @@ var shared_root_computed = {
|
||||
return form_target
|
||||
},
|
||||
useIframe: function () {
|
||||
return !this.disable_iframe && (this.skip_ssl || site_is_secure());
|
||||
return !this.disable_iframe && Math.min(screen.width, window.innerWidth) >= 800 && (this.skip_ssl || site_is_secure());
|
||||
},
|
||||
showPrices: function () {
|
||||
var has_priced = false;
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
.help-block {
|
||||
color: $text-muted;
|
||||
}
|
||||
|
||||
a.btn, button.btn {
|
||||
max-width: 100%;
|
||||
white-space: normal;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user