Allow to set multiple confirm texts (#1735)

This commit is contained in:
Felix Rindt
2020-08-04 10:20:55 +02:00
committed by GitHub
parent 896ba5b06b
commit 9b367cb28b
10 changed files with 216 additions and 64 deletions
+1 -1
View File
@@ -565,7 +565,7 @@ class EventSettingsSerializer(serializers.Serializer):
'attendee_addresses_required', 'attendee_addresses_required',
'attendee_company_asked', 'attendee_company_asked',
'attendee_company_required', 'attendee_company_required',
'confirm_text', 'confirm_texts',
'order_email_asked_twice', 'order_email_asked_twice',
'payment_term_days', 'payment_term_days',
'payment_term_last', 'payment_term_last',
@@ -0,0 +1,27 @@
# Generated by Django 3.0.8 on 2020-07-31 10:05
import json
from django.db import migrations
def migrate_confirm_text(apps, schema_editor):
# We now allow creating multiple confirm texts so we migrate the setting for that
# from `confirm_text` to `confirm_texts`
Event_SettingsStore = apps.get_model('pretixbase', 'Event_SettingsStore')
for store in Event_SettingsStore.objects.filter(key="confirm_text"):
values = json.dumps([json.loads(store.value)]) # convert single value to one-element list
store.key = "confirm_texts"
store.value = values
store.save()
class Migration(migrations.Migration):
dependencies = [
('pretixbase', '0159_mails_by_sales_channel'),
]
operations = [
migrations.RunPython(migrate_confirm_text, migrations.RunPython.noop),
]
+3 -3
View File
@@ -35,7 +35,7 @@ class RelativeDateWrapper:
def __init__(self, data: Union[datetime.datetime, RelativeDate]): def __init__(self, data: Union[datetime.datetime, RelativeDate]):
self.data = data self.data = data
def date(self, event) -> datetime.datetime: def date(self, event) -> datetime.date:
from .models import SubEvent from .models import SubEvent
if isinstance(self.data, datetime.date): if isinstance(self.data, datetime.date):
@@ -81,8 +81,8 @@ class RelativeDateWrapper:
second=self.data.time.second second=self.data.time.second
) )
new_date = new_date.astimezone(tz) new_date = new_date.astimezone(tz)
newoffset = new_date.utcoffset() new_offset = new_date.utcoffset()
new_date += oldoffset - newoffset new_date += oldoffset - new_offset
return new_date return new_date
def to_string(self) -> str: def to_string(self) -> str:
+4 -6
View File
@@ -27,7 +27,7 @@ from pretix.base.services.locking import LockTimeoutException, NoLockManager
from pretix.base.services.pricing import get_price from pretix.base.services.pricing import get_price
from pretix.base.services.quotas import QuotaAvailability from pretix.base.services.quotas import QuotaAvailability
from pretix.base.services.tasks import ProfiledEventTask from pretix.base.services.tasks import ProfiledEventTask
from pretix.base.settings import PERSON_NAME_SCHEMES from pretix.base.settings import PERSON_NAME_SCHEMES, LazyI18nStringList
from pretix.base.signals import validate_cart_addons from pretix.base.signals import validate_cart_addons
from pretix.base.templatetags.rich_text import rich_text from pretix.base.templatetags.rich_text import rich_text
from pretix.celery_app import app from pretix.celery_app import app
@@ -1240,9 +1240,7 @@ def set_cart_addons(self, event: Event, addons: List[dict], cart_id: str=None, l
@receiver(checkout_confirm_messages, dispatch_uid="cart_confirm_messages") @receiver(checkout_confirm_messages, dispatch_uid="cart_confirm_messages")
def confirm_messages(sender, *args, **kwargs): def confirm_messages(sender, *args, **kwargs):
if not sender.settings.confirm_text: if not sender.settings.confirm_texts:
return {} return {}
confirm_texts = sender.settings.get("confirm_texts", as_type=LazyI18nStringList)
return { return {'confirm_text_%i' % index: rich_text(str(text)) for index, text in enumerate(confirm_texts)}
'confirm_text': rich_text(str(sender.settings.confirm_text))
}
+24 -13
View File
@@ -1,5 +1,6 @@
import json import json
from collections import OrderedDict import operator
from collections import OrderedDict, UserList
from datetime import datetime from datetime import datetime
from decimal import Decimal from decimal import Decimal
from typing import Any from typing import Any
@@ -37,6 +38,20 @@ def country_choice_kwargs():
} }
class LazyI18nStringList(UserList):
def __init__(self, init_list=None):
super().__init__()
if init_list is not None:
self.data = [v if isinstance(v, LazyI18nString) else LazyI18nString(v) for v in init_list]
def serialize(self):
return json.dumps([s.data for s in self.data])
@classmethod
def unserialize(cls, s):
return cls(json.loads(s))
DEFAULTS = { DEFAULTS = {
'max_items_per_order': { 'max_items_per_order': {
'default': '10', 'default': '10',
@@ -1127,18 +1142,11 @@ DEFAULTS = {
), ),
'serializer_class': serializers.URLField, 'serializer_class': serializers.URLField,
}, },
'confirm_text': { 'confirm_texts': {
'default': None, 'default': LazyI18nStringList(),
'type': LazyI18nString, 'type': LazyI18nStringList,
'form_class': I18nFormField, 'serializer_class': serializers.ListField,
'serializer_class': I18nField, 'serializer_kwargs': lambda: dict(child=I18nField()),
'form_kwargs': dict(
label=_('Confirmation text'),
help_text=_('This text needs to be confirmed by the user before a purchase is possible. You could for example '
'link your terms of service here. If you use the Pages feature to publish your terms of service, '
'you don\'t need this setting since you can configure it there.'),
widget=I18nTextarea,
)
}, },
'mail_html_renderer': { 'mail_html_renderer': {
'default': 'classic', 'default': 'classic',
@@ -1939,6 +1947,9 @@ def i18n_uns(v):
settings_hierarkey.add_type(LazyI18nString, settings_hierarkey.add_type(LazyI18nString,
serialize=lambda s: json.dumps(s.data), serialize=lambda s: json.dumps(s.data),
unserialize=i18n_uns) unserialize=i18n_uns)
settings_hierarkey.add_type(LazyI18nStringList,
serialize=operator.methodcaller("serialize"),
unserialize=LazyI18nStringList.unserialize)
settings_hierarkey.add_type(RelativeDateWrapper, settings_hierarkey.add_type(RelativeDateWrapper,
serialize=lambda rdw: rdw.to_string(), serialize=lambda rdw: rdw.to_string(),
unserialize=lambda s: RelativeDateWrapper.from_string(s)) unserialize=lambda s: RelativeDateWrapper.from_string(s))
+22 -6
View File
@@ -518,7 +518,6 @@ class EventSettingsForm(SettingsForm):
'attendee_company_required', 'attendee_company_required',
'attendee_addresses_asked', 'attendee_addresses_asked',
'attendee_addresses_required', 'attendee_addresses_required',
'confirm_text',
'banner_text', 'banner_text',
'banner_text_bottom', 'banner_text_bottom',
'order_email_asked_twice', 'order_email_asked_twice',
@@ -535,11 +534,6 @@ class EventSettingsForm(SettingsForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.event = kwargs['obj'] self.event = kwargs['obj']
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.fields['confirm_text'].widget.attrs['rows'] = '3'
self.fields['confirm_text'].widget.attrs['placeholder'] = _(
'e.g. I hereby confirm that I have read and agree with the event organizer\'s terms of service '
'and agree with them.'
)
self.fields['name_scheme'].choices = ( self.fields['name_scheme'].choices = (
(k, _('Ask for {fields}, display like {example}').format( (k, _('Ask for {fields}, display like {example}').format(
fields=' + '.join(str(vv[1]) for vv in v['fields']), fields=' + '.join(str(vv[1]) for vv in v['fields']),
@@ -1342,3 +1336,25 @@ class ItemMetaPropertyForm(forms.ModelForm):
widgets = { widgets = {
'default': forms.TextInput() 'default': forms.TextInput()
} }
class ConfirmTextForm(I18nForm):
text = I18nFormField(
widget=I18nTextarea,
widget_kwargs={'attrs': {'rows': '2'}},
)
class BaseConfirmTextFormSet(I18nFormSetMixin, forms.BaseFormSet):
def __init__(self, *args, **kwargs):
event = kwargs.pop('event', None)
if event:
kwargs['locales'] = event.settings.get('locales')
super().__init__(*args, **kwargs)
ConfirmTextFormset = formset_factory(
ConfirmTextForm,
formset=BaseConfirmTextFormSet,
can_order=True, can_delete=True, extra=0
)
@@ -26,7 +26,11 @@
{% bootstrap_field form.date_to layout="control" %} {% bootstrap_field form.date_to layout="control" %}
<div class="geodata-section"> <div class="geodata-section">
{% bootstrap_field form.location layout="control" %} {% bootstrap_field form.location layout="control" %}
<div class="form-group geodata-group" data-tiles="{{ global_settings.leaflet_tiles|default_if_none:"" }}" data-attrib="{{ global_settings.leaflet_tiles_attribution }}" data-icon="{% static "leaflet/images/marker-icon.png" %}" data-shadow="{% static "leaflet/images/marker-shadow.png" %}"> <div class="form-group geodata-group"
data-tiles="{{ global_settings.leaflet_tiles|default_if_none:"" }}"
data-attrib="{{ global_settings.leaflet_tiles_attribution }}"
data-icon="{% static "leaflet/images/marker-icon.png" %}"
data-shadow="{% static "leaflet/images/marker-shadow.png" %}">
<label class="col-md-3 control-label"> <label class="col-md-3 control-label">
{% trans "Geo coordinates" %}<br> {% trans "Geo coordinates" %}<br>
<span class="optional">{% trans "Optional" %}</span> <span class="optional">{% trans "Optional" %}</span>
@@ -99,7 +103,77 @@
{% bootstrap_field sform.frontpage_text layout="control" %} {% bootstrap_field sform.frontpage_text layout="control" %}
{% bootstrap_field sform.presale_has_ended_text layout="control" %} {% bootstrap_field sform.presale_has_ended_text layout="control" %}
{% bootstrap_field sform.voucher_explanation_text layout="control" %} {% bootstrap_field sform.voucher_explanation_text layout="control" %}
{% bootstrap_field sform.confirm_text layout="control" %}
<div class="form-group">
<label class="col-md-3 control-label">
{% trans "Confirmation text" %}<br>
<span class="optional">{% trans "Optional" %}</span>
</label>
<div class="col-md-9">
<div class="help-block">
{% blocktrans trimmed %}
These texts need to be confirmed by the user before a purchase is possible. You could
for example link your terms of service here. If you use the Pages feature to publish
your terms of service, you don't need this setting since you can configure it there.
{% endblocktrans %}
</div>
<div class="formset" data-formset data-formset-prefix="{{ confirm_texts_formset.prefix }}">
{{ confirm_texts_formset.management_form }}
{% bootstrap_formset_errors confirm_texts_formset %}
<div data-formset-body>
{% for form in confirm_texts_formset %}
<div class="row formset-row" data-formset-form>
<div class="sr-only">
{{ form.id }}
{% bootstrap_field form.DELETE form_group_class="" layout="inline" %}
{% bootstrap_field form.ORDER form_group_class="" layout="inline" %}
</div>
<div class="col-md-10">
{% bootstrap_form_errors form %}
{% bootstrap_field form.text layout='inline' form_group_class="" %}
</div>
<div class="col-md-2 text-right flip">
<button type="button" class="btn" data-formset-move-up-button>
<i class="fa fa-arrow-up"></i></button>
<button type="button" class="btn" data-formset-move-down-button>
<i class="fa fa-arrow-down"></i></button>
<button type="button" class="btn btn-danger" data-formset-delete-button>
<i class="fa fa-trash"></i></button>
</div>
</div>
{% endfor %}
</div>
<script type="form-template" data-formset-empty-form>
{% escapescript %}
<div class="row formset-row" data-formset-form>
<div class="sr-only">
{{ confirm_texts_formset.empty_form.id }}
{% bootstrap_field confirm_texts_formset.empty_form.DELETE form_group_class="" layout="inline" %}
{% bootstrap_field confirm_texts_formset.empty_form.ORDER form_group_class="" layout="inline" %}
</div>
<div class="col-md-10">
{% bootstrap_field confirm_texts_formset.empty_form.text layout='inline' form_group_class="" %}
</div>
<div class="col-md-2 text-right flip">
<button type="button" class="btn" data-formset-move-up-button>
<i class="fa fa-arrow-up"></i></button>
<button type="button" class="btn" data-formset-move-down-button>
<i class="fa fa-arrow-down"></i></button>
<button type="button" class="btn btn-danger" data-formset-delete-button>
<i class="fa fa-trash"></i></button>
</div>
</div>
{% endescapescript %}
</script>
<p>
<button type="button" class="btn btn-default" data-formset-add>
<i class="fa fa-plus"></i> {% trans "Add confirmation text" %}</button>
</p>
</div>
</div>
</div>
{% bootstrap_field sform.checkout_email_helptext layout="control" %} {% bootstrap_field sform.checkout_email_helptext layout="control" %}
{% bootstrap_field sform.banner_text layout="control" %} {% bootstrap_field sform.banner_text layout="control" %}
{% bootstrap_field sform.banner_text_bottom layout="control" %} {% bootstrap_field sform.banner_text_bottom layout="control" %}
@@ -161,17 +235,18 @@
<legend>{% trans "Item metadata" %}</legend> <legend>{% trans "Item metadata" %}</legend>
<p> <p>
{% blocktrans trimmed %} {% blocktrans trimmed %}
You can here define a set of metadata properties (i.e. variables) that you can later set for your You can here define a set of metadata properties (i.e. variables) that you can later set for
items and re-use in places like ticket layouts. This is an useful timesaver if you create lots and your items and re-use in places like ticket layouts. This is an useful timesaver if you create
lots of items. lots and lots of items.
{% endblocktrans %} {% endblocktrans %}
</p> </p>
<div class="formset" data-formset data-formset-prefix="{{ formset.prefix }}"> <div class="formset" data-formset
{{ formset.management_form }} data-formset-prefix="{{ item_meta_property_formset.prefix }}">
{% bootstrap_formset_errors formset %} {{ item_meta_property_formset.management_form }}
{% bootstrap_formset_errors item_meta_property_formset %}
<div data-formset-body> <div data-formset-body>
{% for form in formset %} {% for form in item_meta_property_formset %}
<div class="row" data-formset-form> <div class="row formset-row" data-formset-form>
<div class="sr-only"> <div class="sr-only">
{{ form.id }} {{ form.id }}
{% bootstrap_field form.DELETE form_group_class="" layout="inline" %} {% bootstrap_field form.DELETE form_group_class="" layout="inline" %}
@@ -192,16 +267,16 @@
</div> </div>
<script type="form-template" data-formset-empty-form> <script type="form-template" data-formset-empty-form>
{% escapescript %} {% escapescript %}
<div class="row" data-formset-form> <div class="row formset-row" data-formset-form>
<div class="sr-only"> <div class="sr-only">
{{ formset.empty_form.id }} {{ item_meta_property_formset.empty_form.id }}
{% bootstrap_field formset.empty_form.DELETE form_group_class="" layout="inline" %} {% bootstrap_field item_meta_property_formset.empty_form.DELETE form_group_class="" layout="inline" %}
</div> </div>
<div class="col-md-5"> <div class="col-md-5">
{% bootstrap_field formset.empty_form.name layout='inline' form_group_class="" %} {% bootstrap_field item_meta_property_formset.empty_form.name layout='inline' form_group_class="" %}
</div> </div>
<div class="col-md-5 col-lg-6"> <div class="col-md-5 col-lg-6">
{% bootstrap_field formset.empty_form.default layout='inline' form_group_class="" %} {% bootstrap_field item_meta_property_formset.empty_form.default layout='inline' form_group_class="" %}
</div> </div>
<div class="col-md-2 col-lg-1 text-right flip"> <div class="col-md-2 col-lg-1 text-right flip">
<button type="button" class="btn btn-danger" data-formset-delete-button> <button type="button" class="btn btn-danger" data-formset-delete-button>
@@ -223,12 +298,12 @@
</button> </button>
<div class="pull-left"> <div class="pull-left">
<a href="{% url "control:event.dangerzone" organizer=request.organizer.slug event=request.event.slug %}" <a href="{% url "control:event.dangerzone" organizer=request.organizer.slug event=request.event.slug %}"
class="btn btn-danger btn-lg"> class="btn btn-danger btn-lg">
<span class="fa fa-trash"></span> <span class="fa fa-trash"></span>
{% trans "Cancel or delete event" %} {% trans "Cancel or delete event" %}
</a> </a>
<a href="{% url "control:events.add" %}?clone={{ request.event.pk }}" <a href="{% url "control:events.add" %}?clone={{ request.event.pk }}"
class="btn btn-default btn-lg"> class="btn btn-default btn-lg">
<span class="fa fa-copy"></span> <span class="fa fa-copy"></span>
{% trans "Clone event" %} {% trans "Clone event" %}
</a> </a>
+38 -18
View File
@@ -1,4 +1,5 @@
import json import json
import operator
import re import re
from collections import OrderedDict from collections import OrderedDict
from decimal import Decimal from decimal import Decimal
@@ -40,10 +41,11 @@ from pretix.base.services.invoices import build_preview_invoice_pdf
from pretix.base.signals import register_ticket_outputs from pretix.base.signals import register_ticket_outputs
from pretix.base.templatetags.rich_text import markdown_compile_email from pretix.base.templatetags.rich_text import markdown_compile_email
from pretix.control.forms.event import ( from pretix.control.forms.event import (
CancelSettingsForm, CommentForm, EventDeleteForm, EventMetaValueForm, CancelSettingsForm, CommentForm, ConfirmTextFormset, EventDeleteForm,
EventSettingsForm, EventUpdateForm, InvoiceSettingsForm, EventMetaValueForm, EventSettingsForm, EventUpdateForm,
ItemMetaPropertyForm, MailSettingsForm, PaymentSettingsForm, ProviderForm, InvoiceSettingsForm, ItemMetaPropertyForm, MailSettingsForm,
QuickSetupForm, QuickSetupProductFormSet, TaxRuleForm, TaxRuleLineFormSet, PaymentSettingsForm, ProviderForm, QuickSetupForm,
QuickSetupProductFormSet, TaxRuleForm, TaxRuleLineFormSet,
TicketSettingsForm, WidgetCodeForm, TicketSettingsForm, WidgetCodeForm,
) )
from pretix.control.permissions import EventPermissionRequiredMixin from pretix.control.permissions import EventPermissionRequiredMixin
@@ -54,6 +56,7 @@ from pretix.plugins.stripe.payment import StripeSettingsHolder
from pretix.presale.style import regenerate_css from pretix.presale.style import regenerate_css
from ...base.models.items import ItemMetaProperty from ...base.models.items import ItemMetaProperty
from ...base.settings import LazyI18nStringList
from ..logdisplay import OVERVIEW_BANLIST from ..logdisplay import OVERVIEW_BANLIST
from . import CreateView, PaginationMixin, UpdateView from . import CreateView, PaginationMixin, UpdateView
@@ -140,7 +143,8 @@ class EventUpdate(DecoupleMixin, EventSettingsViewMixin, EventPermissionRequired
context = super().get_context_data(*args, **kwargs) context = super().get_context_data(*args, **kwargs)
context['sform'] = self.sform context['sform'] = self.sform
context['meta_forms'] = self.meta_forms context['meta_forms'] = self.meta_forms
context['formset'] = self.formset context['item_meta_property_formset'] = self.item_meta_property_formset
context['confirm_texts_formset'] = self.confirm_texts_formset
return context return context
@transaction.atomic @transaction.atomic
@@ -148,13 +152,15 @@ class EventUpdate(DecoupleMixin, EventSettingsViewMixin, EventPermissionRequired
self._save_decoupled(self.sform) self._save_decoupled(self.sform)
self.sform.save() self.sform.save()
self.save_meta() self.save_meta()
self.save_formset(self.object) self.save_item_meta_property_formset(self.object)
self.save_confirm_texts_formset(self.object)
change_css = False change_css = False
if self.sform.has_changed(): if self.sform.has_changed() or self.confirm_texts_formset.has_changed():
self.request.event.log_action('pretix.event.settings', user=self.request.user, data={ data = {k: self.request.event.settings.get(k) for k in self.sform.changed_data}
k: self.request.event.settings.get(k) for k in self.sform.changed_data if self.confirm_texts_formset.has_changed():
}) data.update(confirm_texts=self.confirm_texts_formset.cleaned_data)
self.request.event.log_action('pretix.event.settings', user=self.request.user, data=data)
display_properties = ( display_properties = (
'primary_color', 'theme_color_success', 'theme_color_danger', 'primary_font', 'primary_color', 'theme_color_success', 'theme_color_danger', 'primary_font',
'theme_color_background', 'theme_round_borders', 'theme_color_background', 'theme_round_borders',
@@ -194,7 +200,7 @@ class EventUpdate(DecoupleMixin, EventSettingsViewMixin, EventPermissionRequired
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
form = self.get_form() form = self.get_form()
if form.is_valid() and self.sform.is_valid() and all([f.is_valid() for f in self.meta_forms]) and \ if form.is_valid() and self.sform.is_valid() and all([f.is_valid() for f in self.meta_forms]) and \
self.formset.is_valid(): self.item_meta_property_formset.is_valid() and self.confirm_texts_formset.is_valid():
# reset timezone # reset timezone
zone = timezone(self.sform.cleaned_data['timezone']) zone = timezone(self.sform.cleaned_data['timezone'])
event = form.instance event = form.instance
@@ -212,17 +218,17 @@ class EventUpdate(DecoupleMixin, EventSettingsViewMixin, EventPermissionRequired
return tz.localize(dt.replace(tzinfo=None)) if dt is not None else None return tz.localize(dt.replace(tzinfo=None)) if dt is not None else None
@cached_property @cached_property
def formset(self): def item_meta_property_formset(self):
formsetclass = inlineformset_factory( formsetclass = inlineformset_factory(
Event, ItemMetaProperty, Event, ItemMetaProperty,
form=ItemMetaPropertyForm, can_order=False, can_delete=True, extra=0 form=ItemMetaPropertyForm, can_order=False, can_delete=True, extra=0
) )
return formsetclass(self.request.POST if self.request.method == "POST" else None, return formsetclass(self.request.POST if self.request.method == "POST" else None, prefix="item-meta-property",
instance=self.object, queryset=self.object.item_meta_properties.all()) instance=self.object, queryset=self.object.item_meta_properties.all())
def save_formset(self, obj): def save_item_meta_property_formset(self, obj):
for form in self.formset.initial_forms: for form in self.item_meta_property_formset.initial_forms:
if form in self.formset.deleted_forms: if form in self.item_meta_property_formset.deleted_forms:
if not form.instance.pk: if not form.instance.pk:
continue continue
form.instance.delete() form.instance.delete()
@@ -230,14 +236,28 @@ class EventUpdate(DecoupleMixin, EventSettingsViewMixin, EventPermissionRequired
elif form.has_changed(): elif form.has_changed():
form.save() form.save()
for form in self.formset.extra_forms: for form in self.item_meta_property_formset.extra_forms:
if not form.has_changed(): if not form.has_changed():
continue continue
if self.formset._should_delete_form(form): if self.item_meta_property_formset._should_delete_form(form):
continue continue
form.instance.event = obj form.instance.event = obj
form.save() form.save()
@cached_property
def confirm_texts_formset(self):
initial = [{"text": text, "ORDER": order} for order, text in
enumerate(self.object.settings.get("confirm_texts", as_type=LazyI18nStringList))]
return ConfirmTextFormset(self.request.POST if self.request.method == "POST" else None, event=self.object,
prefix="confirm-texts", initial=initial)
def save_confirm_texts_formset(self, obj):
obj.settings.confirm_texts = LazyI18nStringList(
form_data['text'].data
for form_data in sorted(self.confirm_texts_formset.cleaned_data, key=operator.itemgetter("ORDER"))
if not form_data.get("DELETE", False)
)
class EventPlugins(EventSettingsViewMixin, EventPermissionRequiredMixin, TemplateView, SingleObjectMixin): class EventPlugins(EventSettingsViewMixin, EventPermissionRequiredMixin, TemplateView, SingleObjectMixin):
model = Event model = Event
@@ -54,6 +54,10 @@ div[data-formset-body], div[data-formset-form], div[data-nested-formset-form], d
margin: 0; margin: 0;
} }
.formset-row {
margin-bottom: 10px;
}
.submit-group { .submit-group {
margin: 15px 0 0 0 !important; margin: 15px 0 0 0 !important;
padding: 15px; padding: 15px;
@@ -11,6 +11,7 @@ from pretix.base.models import Event, Organizer, Team, User
class MailSettingPreviewTest(SoupTest): class MailSettingPreviewTest(SoupTest):
@scopes_disabled() @scopes_disabled()
def setUp(self): def setUp(self):
super().setUp()
self.user = User.objects.create_user('dummy@dummy.dummy', 'dummy') self.user = User.objects.create_user('dummy@dummy.dummy', 'dummy')
self.orga1 = Organizer.objects.create(name='CCC', slug='ccc') self.orga1 = Organizer.objects.create(name='CCC', slug='ccc')
self.orga2 = Organizer.objects.create(name='MRM', slug='mrm') self.orga2 = Organizer.objects.create(name='MRM', slug='mrm')