Compare commits

...

39 Commits

Author SHA1 Message Date
Lukas Bockstaller
a050506072 styling 2026-02-23 16:09:55 +01:00
Lukas Bockstaller
1d3a9b0345 handle products with only inactive variations 2026-02-23 16:05:57 +01:00
Lukas Bockstaller
2b852e40d9 Merge branch 'master' into lbo-waitinglist-edit 2026-02-23 15:47:25 +01:00
Lukas Bockstaller
4f02b607e5 small review changes 2026-02-20 17:51:52 +01:00
Lukas Bockstaller
14b2c84627 add validation tests 2026-01-12 13:02:56 +01:00
Lukas Bockstaller
ed1d86f411 cleanup 2026-01-12 10:51:04 +01:00
Lukas Bockstaller
3e18ee6311 propper use of WrappedPhoneNumberPrefixWidget 2026-01-12 10:50:52 +01:00
Lukas Bockstaller
784a48d28a add queryset to prefetch only active ItemVariations 2026-01-12 10:50:03 +01:00
Lukas Bockstaller
f0ddebda6c add queryset to prefetch only active ItemVariations 2026-01-12 10:49:59 +01:00
Lukas Bockstaller
50f02f1ff8 add test for the different edit form variations 2026-01-12 10:48:32 +01:00
Lukas Bockstaller
551b286c31 add better assertions 2026-01-09 17:38:03 +01:00
Lukas Bockstaller
7ff286d2c2 implement small review items 2026-01-09 17:37:53 +01:00
Lukas Bockstaller
3255753222 replace widget 2026-01-09 17:37:11 +01:00
Lukas Bockstaller
a400040f06 remove validations 2026-01-09 17:36:49 +01:00
Lukas Bockstaller
a227037bb5 remove validations 2026-01-09 17:36:35 +01:00
Lukas Bockstaller
87c2a958f0 Update src/pretix/control/views/waitinglist.py
Co-authored-by: Richard Schreiber <schreiber@pretix.eu>
2025-12-19 13:57:46 +01:00
Lukas Bockstaller
a39d57f2b8 Update src/pretix/control/views/waitinglist.py
Co-authored-by: Richard Schreiber <schreiber@pretix.eu>
2025-12-19 13:56:46 +01:00
Lukas Bockstaller
b5889e0b13 Update src/pretix/control/views/waitinglist.py
Co-authored-by: Richard Schreiber <schreiber@pretix.eu>
2025-12-19 13:55:15 +01:00
Lukas Bockstaller
d402e1d8f5 Update src/pretix/control/templates/pretixcontrol/waitinglist/index.html
Co-authored-by: Richard Schreiber <schreiber@pretix.eu>
2025-12-19 13:50:44 +01:00
Lukas Bockstaller
7db5669813 Update src/pretix/control/templates/pretixcontrol/waitinglist/edit.html
Co-authored-by: Richard Schreiber <schreiber@pretix.eu>
2025-12-19 13:50:29 +01:00
Lukas Bockstaller
fef4f3c5a7 Update src/pretix/control/urls.py
Co-authored-by: Richard Schreiber <schreiber@pretix.eu>
2025-12-19 13:49:33 +01:00
Lukas Bockstaller
3e92d509fd Update src/pretix/control/forms/waitinglist.py
Co-authored-by: Richard Schreiber <schreiber@pretix.eu>
2025-12-19 13:48:48 +01:00
Lukas Bockstaller
2f4fc10575 Update src/pretix/control/forms/waitinglist.py
Co-authored-by: Richard Schreiber <schreiber@pretix.eu>
2025-12-19 13:48:32 +01:00
Lukas Bockstaller
125670537b code style 2025-12-18 12:42:50 +01:00
Lukas Bockstaller
aa680391ec add tests 2025-12-18 12:34:58 +01:00
Lukas Bockstaller
730a60ba45 change transfer to edit 2025-12-18 12:33:52 +01:00
Lukas Bockstaller
e226bfb8d5 combine edit.html and transfer.html 2025-12-17 17:14:08 +01:00
Lukas Bockstaller
1deb867734 include only products with an enabled waitinglist in the product field 2025-12-16 14:20:33 +01:00
Lukas Bockstaller
8fa492d82f change label from "Item and Variation" to "Product" 2025-12-16 12:52:08 +01:00
Lukas Bockstaller
7c21aed1a7 remove item and variation fields from form
rather set those values during clean
2025-12-16 12:51:36 +01:00
Lukas Bockstaller
f26d260471 make name and phone field optional by removing them 2025-12-16 12:50:49 +01:00
Lukas Bockstaller
308e0d83a6 repair settings check
Co-authored-by: Richard Schreiber <schreiber@pretix.eu>
2025-12-11 13:51:13 +01:00
Lukas Bockstaller
01f5872607 add search to the waitinglist view 2025-12-11 10:12:22 +01:00
Lukas Bockstaller
2962f41f13 fix linting 2025-12-10 18:49:34 +01:00
Lukas Bockstaller
4f61c4c889 fix test 2025-12-10 17:53:31 +01:00
Lukas Bockstaller
ab250bcb19 add testcases for new edit view 2025-12-10 17:34:42 +01:00
Lukas Bockstaller
cc57fab671 fix linting 2025-12-10 16:19:33 +01:00
Lukas Bockstaller
9663306c3f add test and fix behaviour when name isn't asked for 2025-12-10 16:17:13 +01:00
Lukas Bockstaller
d5fda6d319 add edit view for waitinglist entry 2025-12-10 15:40:40 +01:00
7 changed files with 320 additions and 67 deletions

View File

@@ -19,17 +19,44 @@
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see # You should have received a copy of the GNU Affero General Public License along with this program. If not, see
# <https://www.gnu.org/licenses/>. # <https://www.gnu.org/licenses/>.
# #
from django import forms
from django.urls import reverse from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from django_scopes.forms import SafeModelChoiceField from django_scopes.forms import SafeModelChoiceField
from phonenumber_field.formfields import PhoneNumberField
from pretix.base.forms import I18nModelForm from pretix.base.forms import I18nModelForm
from pretix.base.forms.questions import (
NamePartsFormField, WrappedPhoneNumberPrefixWidget,
)
from pretix.base.models import WaitingListEntry from pretix.base.models import WaitingListEntry
from pretix.control.forms.widgets import Select2 from pretix.control.forms.widgets import Select2
class WaitingListEntryTransferForm(I18nModelForm): class WaitingListEntryEditForm(I18nModelForm):
itemvar = forms.ChoiceField(
error_messages={
'invalid_choice': _("Select a valid choice.")
}
)
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.instance = kwargs.get('instance', None)
initial = kwargs.get('initial', {})
choices = []
if self.instance and self.instance.pk and 'itemvar' not in initial:
if self.instance.variation is not None:
initial['itemvar'] = f'{self.instance.item.pk}-{self.instance.variation.pk}'
if self.instance.variation.active is False:
choices.append((initial['itemvar'], str(self.instance.variation)))
else:
initial['itemvar'] = self.instance.item.pk
if self.instance.item.active is False:
choices.append((initial['itemvar'], str(self.instance)))
kwargs['initial'] = initial
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
if self.event.has_subevents: if self.event.has_subevents:
@@ -45,12 +72,73 @@ class WaitingListEntryTransferForm(I18nModelForm):
} }
) )
self.fields['subevent'].widget.choices = self.fields['subevent'].choices self.fields['subevent'].widget.choices = self.fields['subevent'].choices
else:
del self.fields['subevent']
if self.event.settings.waiting_list_names_asked:
self.fields['name_parts'] = NamePartsFormField(
max_length=255,
required=self.event.settings.waiting_list_names_required,
scheme=self.event.organizer.settings.name_scheme,
titles=self.event.organizer.settings.name_scheme_titles,
label=_('Name'),
)
else:
del self.fields['name_parts']
if not self.event.settings.waiting_list_phones_asked:
del self.fields['phone']
items = self.event.items.filter(active=True).prefetch_related(
'variations'
)
for item in items:
if len(item.variations.all()) > 0:
for variation in item.variations.all():
if variation.active:
choices.append(
('{}-{}'.format(item.pk, variation.pk), '{} - {}'.format(str(item), str(variation)))
)
else:
choices.append(('{}'.format(item.pk), str(item)))
self.fields['itemvar'].label = _("Product")
self.fields['itemvar'].help_text = _("Only includes active products.")
self.fields['itemvar'].required = True
self.fields['itemvar'].choices = choices
def clean(self):
cleaned_data = super().clean()
if self.instance.voucher is not None:
raise forms.ValidationError(_('A voucher for this waiting list entry was already sent out.'))
itemvar = cleaned_data.get('itemvar')
if itemvar:
self.instance.item = self.event.items.get(pk=itemvar.split('-')[0])
if '-' in itemvar:
self.instance.variation = self.instance.item.variations.get(pk=itemvar.split('-')[1])
if ((self.instance.item and not self.instance.item.active) or
(self.instance.variation and not self.instance.variation.active)):
self.add_error('itemvar', _('The selected product is not active.'))
return cleaned_data
class Meta: class Meta:
model = WaitingListEntry model = WaitingListEntry
fields = [ fields = [
'email',
'name_parts',
'phone',
'subevent', 'subevent',
] ]
field_classes = { field_classes = {
'subevent': SafeModelChoiceField, 'subevent': SafeModelChoiceField,
'email': forms.EmailField,
'phone': PhoneNumberField,
}
widgets = {
'phone': WrappedPhoneNumberPrefixWidget,
} }

View File

@@ -0,0 +1,33 @@
{% extends "pretixcontrol/event/base.html" %}
{% load i18n %}
{% load bootstrap3 %}
{% block title %}{% trans "Edit entry" %}{% endblock %}
{% block content %}
<h1>{% trans "Edit entry" %}</h1>
<form action="" method="post" class="form-horizontal">
{% csrf_token %}
{% if form.subevent %}
{% bootstrap_field form.subevent layout="control" %}
{% endif %}
{% bootstrap_field form.email layout="control" %}
{% if form.name_parts %}
{% bootstrap_field form.name_parts layout="control" %}
{% endif %}
{% if form.phone %}
{% bootstrap_field form.phone layout="control" %}
{% endif %}
{% bootstrap_field form.itemvar layout="control" %}
<div class="form-group submit-group">
<a href="{% url "control:event.orders.waitinglist" organizer=request.event.organizer.slug event=request.event.slug %}" class="btn btn-default btn-cancel">
{% trans "Cancel" %}
</a>
<button type="submit" class="btn btn-primary btn-save">
{% trans "Save" %}
</button>
</div>
</form>
{% endblock %}

View File

@@ -124,6 +124,7 @@
</option> </option>
{% endfor %} {% endfor %}
</select> </select>
<input name="search" type="text" placeholder="{% trans "Search" %}" class="form-control" value="{{ request.GET.search }}">
{% if request.event.has_subevents %} {% if request.event.has_subevents %}
<select name="subevent" class="form-control"> <select name="subevent" class="form-control">
<option value="">{% trans "All dates" context "subevent" %}</option> <option value="">{% trans "All dates" context "subevent" %}</option>
@@ -267,13 +268,13 @@
data-toggle="tooltip" title="{% trans "Move to the end of the list" %}"> data-toggle="tooltip" title="{% trans "Move to the end of the list" %}">
<span class="fa fa-thumbs-down"></span> <span class="fa fa-thumbs-down"></span>
</button> </button>
{% if request.event.has_subevents %}
<a href="{% url "control:event.orders.waitinglist.transfer" organizer=request.event.organizer.slug event=request.event.slug entry=e.id %}" <a href="{% url "control:event.orders.waitinglist.edit" organizer=request.event.organizer.slug event=request.event.slug entry=e.id %}"
class="btn btn-default btn-sm" title="{% trans "Transfer to other date" context "subevent" %}" class="btn btn-default btn-sm" title="{% trans "Edit entry" %}"
data-toggle="tooltip"> data-toggle="tooltip">
<i class="fa fa-calendar" aria-hidden="true"></i> <i class="fa fa-edit" aria-hidden="true"></i>
</a> </a>
{% endif %}
<a href="{% url "control:event.orders.waitinglist.delete" organizer=request.event.organizer.slug event=request.event.slug entry=e.id %}?next={{ request.get_full_path|urlencode }}" class="btn btn-danger btn-sm"><i class="fa fa-trash"></i></a> <a href="{% url "control:event.orders.waitinglist.delete" organizer=request.event.organizer.slug event=request.event.slug entry=e.id %}?next={{ request.get_full_path|urlencode }}" class="btn btn-danger btn-sm"><i class="fa fa-trash"></i></a>
{% else %} {% else %}
<button class="btn btn-default btn-sm disabled"> <button class="btn btn-default btn-sm disabled">

View File

@@ -1,23 +0,0 @@
{% extends "pretixcontrol/event/base.html" %}
{% load i18n %}
{% load bootstrap3 %}
{% block title %}{% trans "Transfer entry" %}{% endblock %}
{% block content %}
<h1>{% trans "Transfer entry" %}</h1>
<form action="" method="post" class="form-horizontal">
{% csrf_token %}
<p>{% blocktrans trimmed context "subevent" %}
Please select the date to which the following waiting list entry should be
transferred: <strong>{{ entry }}</strong>?
{% endblocktrans %}</p>
{% bootstrap_field form.subevent layout="control" %}
<div class="form-group submit-group">
<a href="{% url "control:event.orders.waitinglist" organizer=request.event.organizer.slug event=request.event.slug %}" class="btn btn-default btn-cancel">
{% trans "Cancel" %}
</a>
<button type="submit" class="btn btn-primary btn-save">
{% trans "Transfer" %}
</button>
</div>
</form>
{% endblock %}

View File

@@ -480,8 +480,8 @@ urlpatterns = [
re_path(r'^waitinglist/auto_assign$', waitinglist.AutoAssign.as_view(), name='event.orders.waitinglist.auto'), 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(), re_path(r'^waitinglist/(?P<entry>\d+)/delete$', waitinglist.EntryDelete.as_view(),
name='event.orders.waitinglist.delete'), name='event.orders.waitinglist.delete'),
re_path(r'^waitinglist/(?P<entry>\d+)/transfer$', waitinglist.EntryTransfer.as_view(), re_path(r'^waitinglist/(?P<entry>\d+)/edit$', waitinglist.EntryEdit.as_view(),
name='event.orders.waitinglist.transfer'), name='event.orders.waitinglist.edit'),
re_path(r'^checkins/$', checkin.CheckinListView.as_view(), name='event.orders.checkins'), re_path(r'^checkins/$', checkin.CheckinListView.as_view(), name='event.orders.checkins'),
re_path(r'^checkinlists/$', checkin.CheckinListList.as_view(), name='event.orders.checkinlists'), 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/add$', checkin.CheckinListCreate.as_view(), name='event.orders.checkinlists.add'),

View File

@@ -53,7 +53,7 @@ from pretix.base.models import Item, LogEntry, Quota, WaitingListEntry
from pretix.base.models.waitinglist import WaitingListException from pretix.base.models.waitinglist import WaitingListException
from pretix.base.services.waitinglist import assign_automatically from pretix.base.services.waitinglist import assign_automatically
from pretix.base.views.tasks import AsyncAction from pretix.base.views.tasks import AsyncAction
from pretix.control.forms.waitinglist import WaitingListEntryTransferForm from pretix.control.forms.waitinglist import WaitingListEntryEditForm
from pretix.control.permissions import EventPermissionRequiredMixin from pretix.control.permissions import EventPermissionRequiredMixin
from pretix.control.views import PaginationMixin from pretix.control.views import PaginationMixin
@@ -138,6 +138,17 @@ class WaitingListQuerySetMixin:
elif force_filtered and '__ALL' not in self.request_data: elif force_filtered and '__ALL' not in self.request_data:
qs = qs.none() qs = qs.none()
if self.request_data.get("search", "") != "":
s = self.request_data.get("search", "")
search_q = Q(email__icontains=s)
if self.request.event.settings.waiting_list_names_asked:
search_q = search_q | Q(name_cached__icontains=s)
if self.request.event.settings.waiting_list_phones_asked:
search_q = search_q | Q(phone__icontains=s)
qs = qs.filter(search_q)
return qs return qs
@@ -238,7 +249,7 @@ class WaitingListView(EventPermissionRequiredMixin, WaitingListQuerySetMixin, Pa
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs) ctx = super().get_context_data(**kwargs)
ctx['items'] = Item.objects.filter(event=self.request.event) ctx['items'] = Item.objects.filter(event=self.request.event)
ctx['filtered'] = ("status" in self.request.GET or "item" in self.request.GET) ctx['filtered'] = any(param in self.request.GET for param in ("status", "item", "search"))
itemvar_cache = {} itemvar_cache = {}
quota_cache = {} quota_cache = {}
@@ -390,25 +401,20 @@ class EntryDelete(EventPermissionRequiredMixin, CompatDeleteView):
}) })
class EntryTransfer(EventPermissionRequiredMixin, UpdateView): class EntryEdit(EventPermissionRequiredMixin, UpdateView):
model = WaitingListEntry model = WaitingListEntry
template_name = 'pretixcontrol/waitinglist/transfer.html' template_name = 'pretixcontrol/waitinglist/edit.html'
permission = 'can_change_orders' permission = 'can_change_orders'
form_class = WaitingListEntryTransferForm form_class = WaitingListEntryEditForm
context_object_name = 'entry' context_object_name = 'entry'
def dispatch(self, request, *args, **kwargs):
if not self.request.event.has_subevents:
raise Http404(_("This is not an event series."))
return super().dispatch(request, *args, **kwargs)
def get_object(self, queryset=None) -> WaitingListEntry: def get_object(self, queryset=None) -> WaitingListEntry:
return get_object_or_404(WaitingListEntry, pk=self.kwargs['entry'], event=self.request.event, voucher__isnull=True) return get_object_or_404(WaitingListEntry, pk=self.kwargs['entry'], event=self.request.event, voucher__isnull=True)
@transaction.atomic @transaction.atomic
def form_valid(self, form): def form_valid(self, form):
messages.success(self.request, _('The waitinglist entry has been transferred.'))
if form.has_changed(): if form.has_changed():
messages.success(self.request, _('The waitinglist entry has been changed.'))
self.object.log_action( self.object.log_action(
'pretix.event.orders.waitinglist.changed', user=self.request.user, data={ 'pretix.event.orders.waitinglist.changed', user=self.request.user, data={
k: form.cleaned_data.get(k) for k in form.changed_data k: form.cleaned_data.get(k) for k in form.changed_data

View File

@@ -19,19 +19,6 @@
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see # You should have received a copy of the GNU Affero General Public License along with this program. If not, see
# <https://www.gnu.org/licenses/>. # <https://www.gnu.org/licenses/>.
# #
# This file is based on an earlier version of pretix which was released under the Apache License 2.0. The full text of
# the Apache License 2.0 can be obtained at <http://www.apache.org/licenses/LICENSE-2.0>.
#
# This file may have since been changed and any changes are released under the terms of AGPLv3 as described above. A
# full history of changes and contributors is available at <https://github.com/pretix/pretix>.
#
# This file contains Apache-licensed contributions copyrighted by: Daniel
#
# Unless required by applicable law or agreed to in writing, software distributed under the Apache License 2.0 is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under the License.
from datetime import timedelta from datetime import timedelta
import pytest import pytest
@@ -39,7 +26,8 @@ from django.utils.timezone import now
from django_scopes import scopes_disabled from django_scopes import scopes_disabled
from pretix.base.models import ( from pretix.base.models import (
Event, Item, Organizer, Quota, Team, User, Voucher, WaitingListEntry, Event, Item, ItemVariation, Organizer, Quota, Team, User, Voucher,
WaitingListEntry,
) )
from pretix.control.views.dashboards import waitinglist_widgets from pretix.control.views.dashboards import waitinglist_widgets
@@ -52,11 +40,12 @@ def env():
date_from=now(), plugins='pretix.plugins.banktransfer,tests.testdummy' date_from=now(), plugins='pretix.plugins.banktransfer,tests.testdummy'
) )
event.settings.set('ticketoutput_testdummy__enabled', True) event.settings.set('ticketoutput_testdummy__enabled', True)
event.settings.set('waiting_list_names_asked', False)
event.settings.set('waiting_list_names_required', False)
event.settings.set('waiting_list_phones_asked', False)
user = User.objects.create_user('dummy@dummy.dummy', 'dummy') user = User.objects.create_user('dummy@dummy.dummy', 'dummy')
item1 = Item.objects.create(event=event, name="Ticket", default_price=23, item1 = Item.objects.create(event=event, name="Ticket", default_price=23, admission=True, allow_waitinglist=True)
admission=True) item2 = Item.objects.create(event=event, name="Ticket", default_price=23, admission=True)
item2 = Item.objects.create(event=event, name="Ticket", default_price=23,
admission=True)
for i in range(5): for i in range(5):
WaitingListEntry.objects.create( WaitingListEntry.objects.create(
@@ -78,7 +67,16 @@ def env():
t = Team.objects.create(organizer=o, can_view_orders=True, can_change_orders=True) t = Team.objects.create(organizer=o, can_view_orders=True, can_change_orders=True)
t.members.add(user) t.members.add(user)
t.limit_events.add(event) t.limit_events.add(event)
return event, user, o, item1
wle = WaitingListEntry.objects.filter(item=item1).first()
variation = ItemVariation.objects.create(item=item1)
return {
"event": event,
"item1": item1,
"wle": wle,
"variation": variation,
}
@pytest.mark.django_db @pytest.mark.django_db
@@ -122,7 +120,7 @@ def test_list(client, env):
assert 'foo0@bar.com' not in response.content.decode() assert 'foo0@bar.com' not in response.content.decode()
assert 'valid@example.org' not in response.content.decode() assert 'valid@example.org' not in response.content.decode()
response = client.get('/control/event/dummy/dummy/waitinglist/?item=%d' % env[3].pk) response = client.get('/control/event/dummy/dummy/waitinglist/?item=%d' % env['item1'].pk)
assert 'item2@example.org' not in response.content.decode() assert 'item2@example.org' not in response.content.decode()
assert 'foo0@bar.com' in response.content.decode() assert 'foo0@bar.com' in response.content.decode()
@@ -191,11 +189,161 @@ def test_delete_bulk(client, env):
WaitingListEntry.objects.get(id=wle.id) WaitingListEntry.objects.get(id=wle.id)
@pytest.mark.django_db
def test_edit_settings(client, env):
event = env['event']
wle = env['wle']
client.login(email='dummy@dummy.dummy', password='dummy')
response = client.get('/control/event/dummy/dummy/waitinglist/%s/edit' % wle.id)
assert ['email', 'itemvar'] == list(response.context_data['form'].fields.keys())
event.settings.set('waiting_list_names_asked', True)
response = client.get('/control/event/dummy/dummy/waitinglist/%s/edit' % wle.id)
assert 'name_parts' in list(response.context_data['form'].fields.keys())
event.settings.set('waiting_list_names_required', True)
response = client.get('/control/event/dummy/dummy/waitinglist/%s/edit' % wle.id)
assert response.context_data['form'].fields['name_parts'].required is True
event.settings.set('waiting_list_phones_asked', True)
response = client.get('/control/event/dummy/dummy/waitinglist/%s/edit' % wle.id)
assert 'phone' in list(response.context_data['form'].fields.keys())
@pytest.mark.django_db
def test_edit_itemvariation(client, env):
item = env['item1']
variation = env['variation']
wle = env['wle']
client.login(email='dummy@dummy.dummy', password='dummy')
itemvar = f"{item.pk}-{variation.pk}"
client.post(
'/control/event/dummy/dummy/waitinglist/%s/edit' % wle.id,
data={
"email": f"1_{wle.email}",
"itemvar": itemvar
}
)
wle.refresh_from_db()
assert wle.variation == variation
@pytest.mark.django_db
def test_edit_validations_only_valid_item(client, env):
item = env['item1']
wle = env['wle']
client.login(email='dummy@dummy.dummy', password='dummy')
itemvar = f"{item.pk + 10000}"
response = client.post(
'/control/event/dummy/dummy/waitinglist/%s/edit' % wle.id,
data={
"email": f"1_{wle.email}",
"itemvar": itemvar
}
)
assert response.context_data['form'].errors['itemvar'] == ["Select a valid choice."]
@pytest.mark.django_db
def test_edit_validations_only_valid_variation(client, env):
item = env['item1']
wle = env['wle']
variation = env['variation']
client.login(email='dummy@dummy.dummy', password='dummy')
itemvar = f"{item.pk}-{variation.pk + 1}"
response = client.post(
'/control/event/dummy/dummy/waitinglist/%s/edit' % wle.id,
data={
"email": f"1_{wle.email}",
"itemvar": itemvar
}
)
assert response.context_data['form'].errors['itemvar'] == ["Select a valid choice."]
@pytest.mark.django_db
def test_edit_validations_inactive_item(client, env):
item = env['item1']
wle = env['wle']
item.active = False
item.save()
client.login(email='dummy@dummy.dummy', password='dummy')
response = client.post(
'/control/event/dummy/dummy/waitinglist/%s/edit' % wle.id,
data={
"email": f"1_{wle.email}",
"itemvar": f"{item.pk}"
}
)
assert response.context_data['form'].errors['itemvar'] == ["The selected product is not active."]
@pytest.mark.django_db
def test_edit_validations_inactive_variation(client, env):
item = env['item1']
wle = env['wle']
variation = env['variation']
wle.variation = variation
wle.save()
variation.active = False
variation.save()
client.login(email='dummy@dummy.dummy', password='dummy')
response = client.post(
'/control/event/dummy/dummy/waitinglist/%s/edit' % wle.id,
data={
"email": f"1_{wle.email}",
"itemvar": f"{item.pk}-{variation.pk}"
}
)
assert response.context_data['form'].errors['itemvar'] == ["The selected product is not active."]
@pytest.mark.django_db
def test_edit_voucher_send_out(client, env):
event = env['event']
item = env['item1']
wle = env['wle']
quota = Quota.objects.create(event=event, size=100)
quota.items.add(item)
client.login(email='dummy@dummy.dummy', password='dummy')
with scopes_disabled():
wle.send_voucher()
response = client.post(
'/control/event/dummy/dummy/waitinglist/%s/edit' % wle.id,
data={
"email": f"1_{wle.email}",
"itemvar": item.pk
},
follow=True
)
assert response.status_code == 404
@pytest.mark.django_db @pytest.mark.django_db
def test_dashboard(client, env): def test_dashboard(client, env):
with scopes_disabled(): with scopes_disabled():
quota = Quota.objects.create(name="Test", size=2, event=env[0]) quota = Quota.objects.create(name="Test", size=2, event=env['event'])
quota.items.add(env[3]) quota.items.add(env['item1'])
w = waitinglist_widgets(env[0]) w = waitinglist_widgets(env['event'])
assert '1' in w[0]['content'] assert '1' in w[0]['content']
assert '5' in w[1]['content'] assert '5' in w[1]['content']