forked from CGM_Public/pretix_original
Allow to bulk-select many tickets to check in or out (#2678)
* Allow to bulk-select many tickets to check in or out * Update tests * Add permission test * Update src/pretix/control/templates/pretixcontrol/checkin/index.html Co-authored-by: Richard Schreiber <wiffbi@gmail.com> * Update src/pretix/static/pretixbase/js/asynctask.js Co-authored-by: Richard Schreiber <wiffbi@gmail.com> * Remove console.warn * Simplify stuff * minor refactor * fix missing checked-out success message Co-authored-by: Richard Schreiber <wiffbi@gmail.com> Co-authored-by: Richard Schreiber <schreiber@rami.io>
This commit is contained in:
@@ -29,12 +29,13 @@ from celery.result import AsyncResult
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.http import JsonResponse, QueryDict
|
from django.http import HttpResponse, JsonResponse, QueryDict
|
||||||
from django.shortcuts import redirect, render
|
from django.shortcuts import redirect, render
|
||||||
from django.test import RequestFactory
|
from django.test import RequestFactory
|
||||||
from django.utils import timezone, translation
|
from django.utils import timezone, translation
|
||||||
from django.utils.timezone import get_current_timezone
|
from django.utils.timezone import get_current_timezone
|
||||||
from django.utils.translation import get_language, gettext as _
|
from django.utils.translation import get_language, gettext as _
|
||||||
|
from django.views import View
|
||||||
from django.views.generic import FormView
|
from django.views.generic import FormView
|
||||||
from redis import ResponseError
|
from redis import ResponseError
|
||||||
|
|
||||||
@@ -312,3 +313,94 @@ class AsyncFormView(AsyncMixin, FormView):
|
|||||||
else:
|
else:
|
||||||
return self.error(res.info)
|
return self.error(res.info)
|
||||||
return redirect(self.get_check_url(res.id, False))
|
return redirect(self.get_check_url(res.id, False))
|
||||||
|
|
||||||
|
|
||||||
|
class AsyncPostView(AsyncMixin, View):
|
||||||
|
"""
|
||||||
|
View variant in which instead of ``post``, an ``async_post`` is executed in a celery task.
|
||||||
|
Note that this places some severe limitations on the form and the view, e.g. ``async_post`` may not
|
||||||
|
depend on the request object unless specifically supported by this class. File upload is currently also
|
||||||
|
not supported.
|
||||||
|
"""
|
||||||
|
known_errortypes = ['ValidationError']
|
||||||
|
expected_exceptions = (ValidationError,)
|
||||||
|
task_base = ProfiledEventTask
|
||||||
|
|
||||||
|
def __init_subclass__(cls):
|
||||||
|
def async_execute(self, *, request_path, url_args, url_kwargs, query_string, post_data, locale, tz,
|
||||||
|
organizer=None, event=None, user=None, session_key=None):
|
||||||
|
view_instance = cls()
|
||||||
|
req = RequestFactory().post(
|
||||||
|
request_path + '?' + query_string,
|
||||||
|
data=post_data,
|
||||||
|
content_type='application/x-www-form-urlencoded'
|
||||||
|
)
|
||||||
|
view_instance.request = req
|
||||||
|
if event:
|
||||||
|
view_instance.request.event = event
|
||||||
|
view_instance.request.organizer = event.organizer
|
||||||
|
elif organizer:
|
||||||
|
view_instance.request.organizer = organizer
|
||||||
|
if user:
|
||||||
|
view_instance.request.user = User.objects.get(pk=user) if isinstance(user, int) else user
|
||||||
|
if session_key:
|
||||||
|
engine = import_module(settings.SESSION_ENGINE)
|
||||||
|
self.SessionStore = engine.SessionStore
|
||||||
|
view_instance.request.session = self.SessionStore(session_key)
|
||||||
|
|
||||||
|
with translation.override(locale), timezone.override(pytz.timezone(tz)):
|
||||||
|
return view_instance.async_post(view_instance.request, *url_args, **url_kwargs)
|
||||||
|
|
||||||
|
cls.async_execute = app.task(
|
||||||
|
base=cls.task_base,
|
||||||
|
bind=True,
|
||||||
|
name=cls.__module__ + '.' + cls.__name__ + '.async_execute',
|
||||||
|
throws=cls.expected_exceptions
|
||||||
|
)(async_execute)
|
||||||
|
|
||||||
|
def async_post(self, request, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get(self, request, *args, **kwargs):
|
||||||
|
if 'async_id' in request.GET and settings.HAS_CELERY:
|
||||||
|
return self.get_result(request)
|
||||||
|
return HttpResponse(status=405)
|
||||||
|
|
||||||
|
def post(self, request, *args, **kwargs):
|
||||||
|
if request.FILES:
|
||||||
|
raise TypeError('File upload currently not supported in AsyncPostView')
|
||||||
|
kwargs = {
|
||||||
|
'request_path': self.request.path,
|
||||||
|
'query_string': self.request.GET.urlencode(),
|
||||||
|
'post_data': self.request.POST.urlencode(),
|
||||||
|
'locale': get_language(),
|
||||||
|
'url_args': args,
|
||||||
|
'url_kwargs': kwargs,
|
||||||
|
'tz': get_current_timezone().zone,
|
||||||
|
}
|
||||||
|
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
|
||||||
|
if hasattr(self.request, 'session'):
|
||||||
|
kwargs['session_key'] = self.request.session.session_key
|
||||||
|
|
||||||
|
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))
|
||||||
|
|||||||
@@ -71,13 +71,20 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<form method="post" action="">
|
<form method="post" action="{% url "control:event.orders.checkinlists.bulk_action" event=request.event.slug organizer=request.event.organizer.slug list=checkinlist.pk %}" data-asynctask>
|
||||||
|
<div class="hidden">
|
||||||
|
{{ filter_form.as_p }}
|
||||||
|
<input name="returnquery" type="hidden" value="{{ request.META.QUERY_STRING }}">
|
||||||
|
</div>
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-condensed table-hover">
|
<table class="table table-condensed table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th></th>
|
<th>
|
||||||
|
<label aria-label="{% trans "select all rows for batch-operation" %}"
|
||||||
|
class="batch-select-label"><input type="checkbox" data-toggle-table/></label>
|
||||||
|
</th>
|
||||||
<th>{% trans "Order code" %} <a href="?{% url_replace request 'ordering' '-code'%}"><i class="fa fa-caret-down"></i></a>
|
<th>{% trans "Order code" %} <a href="?{% url_replace request 'ordering' '-code'%}"><i class="fa fa-caret-down"></i></a>
|
||||||
<a href="?{% url_replace request 'ordering' 'code'%}"><i class="fa fa-caret-up"></i></a></th>
|
<a href="?{% url_replace request 'ordering' 'code'%}"><i class="fa fa-caret-up"></i></a></th>
|
||||||
<th>{% trans "Item" %} <a href="?{% url_replace request 'ordering' '-item'%}"><i class="fa fa-caret-down"></i></a>
|
<th>{% trans "Item" %} <a href="?{% url_replace request 'ordering' '-item'%}"><i class="fa fa-caret-down"></i></a>
|
||||||
@@ -100,6 +107,19 @@
|
|||||||
<th>{% trans "Timestamp" %} <a href="?{% url_replace request 'ordering' '-timestamp'%}"><i class="fa fa-caret-down"></i></a>
|
<th>{% trans "Timestamp" %} <a href="?{% url_replace request 'ordering' '-timestamp'%}"><i class="fa fa-caret-down"></i></a>
|
||||||
<a href="?{% url_replace request 'ordering' 'timestamp'%}"><i class="fa fa-caret-up"></i></a></th>
|
<a href="?{% url_replace request 'ordering' 'timestamp'%}"><i class="fa fa-caret-up"></i></a></th>
|
||||||
</tr>
|
</tr>
|
||||||
|
{% if page_obj.paginator.num_pages > 1 %}
|
||||||
|
<tr class="table-select-all warning hidden">
|
||||||
|
<td>
|
||||||
|
<input type="checkbox" name="__ALL" id="__all"
|
||||||
|
data-results-total="{{ page_obj.paginator.count }}">
|
||||||
|
</td>
|
||||||
|
<td colspan="8">
|
||||||
|
<label for="__all">
|
||||||
|
{% trans "Select all results on other pages as well" %}
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for e in entries %}
|
{% for e in entries %}
|
||||||
@@ -180,13 +200,16 @@
|
|||||||
</div>
|
</div>
|
||||||
{% if "can_change_orders" in request.eventpermset %}
|
{% if "can_change_orders" in request.eventpermset %}
|
||||||
<button type="submit" class="btn btn-primary btn-save">
|
<button type="submit" class="btn btn-primary btn-save">
|
||||||
|
<span class="fa fa-sign-in" aria-hidden="true"></span>
|
||||||
{% trans "Check-In selected attendees" %}
|
{% trans "Check-In selected attendees" %}
|
||||||
</button>
|
</button>
|
||||||
<button type="submit" class="btn btn-default btn-save" name="checkout" value="true">
|
<button type="submit" class="btn btn-default btn-save" name="checkout" value="true">
|
||||||
|
<span class="fa fa-sign-out" aria-hidden="true"></span>
|
||||||
{% trans "Check-Out selected attendees" %}
|
{% trans "Check-Out selected attendees" %}
|
||||||
</button>
|
</button>
|
||||||
<button type="submit" class="btn btn-default btn-save" name="revert" value="true">
|
<button type="submit" class="btn btn-danger btn-save" name="revert" value="true">
|
||||||
{% trans "Revert selected check-ins" %}
|
<span class="fa fa-trash" aria-hidden="true"></span>
|
||||||
|
{% trans "Delete all check-ins of selected attendees" %}
|
||||||
</button>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -392,6 +392,7 @@ urlpatterns = [
|
|||||||
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'),
|
||||||
re_path(r'^checkinlists/select2$', typeahead.checkinlist_select2, name='event.orders.checkinlists.select2'),
|
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+)/$', checkin.CheckInListShow.as_view(), name='event.orders.checkinlists.show'),
|
||||||
|
re_path(r'^checkinlists/(?P<list>\d+)/bulk_action$', checkin.CheckInListBulkActionView.as_view(), name='event.orders.checkinlists.bulk_action'),
|
||||||
re_path(r'^checkinlists/(?P<list>\d+)/change$', checkin.CheckinListUpdate.as_view(),
|
re_path(r'^checkinlists/(?P<list>\d+)/change$', checkin.CheckinListUpdate.as_view(),
|
||||||
name='event.orders.checkinlists.edit'),
|
name='event.orders.checkinlists.edit'),
|
||||||
re_path(r'^checkinlists/(?P<list>\d+)/delete$', checkin.CheckinListDelete.as_view(),
|
re_path(r'^checkinlists/(?P<list>\d+)/delete$', checkin.CheckinListDelete.as_view(),
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ from django.contrib import messages
|
|||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.db.models import Exists, Max, OuterRef, Prefetch, Subquery
|
from django.db.models import Exists, Max, OuterRef, Prefetch, Subquery
|
||||||
from django.http import Http404, HttpResponseRedirect
|
from django.http import Http404, HttpResponseRedirect
|
||||||
from django.shortcuts import get_object_or_404, redirect
|
from django.shortcuts import get_object_or_404
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from django.utils.timezone import is_aware, make_aware, now
|
from django.utils.timezone import is_aware, make_aware, now
|
||||||
@@ -49,6 +49,7 @@ from pretix.base.channels import get_all_sales_channels
|
|||||||
from pretix.base.models import Checkin, Order, OrderPosition
|
from pretix.base.models import Checkin, Order, OrderPosition
|
||||||
from pretix.base.models.checkin import CheckinList
|
from pretix.base.models.checkin import CheckinList
|
||||||
from pretix.base.signals import checkin_created
|
from pretix.base.signals import checkin_created
|
||||||
|
from pretix.base.views.tasks import AsyncPostView
|
||||||
from pretix.control.forms.checkin import CheckinListForm
|
from pretix.control.forms.checkin import CheckinListForm
|
||||||
from pretix.control.forms.filter import (
|
from pretix.control.forms.filter import (
|
||||||
CheckinFilterForm, CheckinListAttendeeFilterForm,
|
CheckinFilterForm, CheckinListAttendeeFilterForm,
|
||||||
@@ -58,11 +59,13 @@ from pretix.control.views import CreateView, PaginationMixin, UpdateView
|
|||||||
from pretix.helpers.models import modelcopy
|
from pretix.helpers.models import modelcopy
|
||||||
|
|
||||||
|
|
||||||
class CheckInListShow(EventPermissionRequiredMixin, PaginationMixin, ListView):
|
class CheckInListQueryMixin:
|
||||||
model = Checkin
|
|
||||||
context_object_name = 'entries'
|
@cached_property
|
||||||
template_name = 'pretixcontrol/checkin/index.html'
|
def request_data(self):
|
||||||
permission = 'can_view_orders'
|
if self.request.method == "POST":
|
||||||
|
return self.request.POST
|
||||||
|
return self.request.GET
|
||||||
|
|
||||||
def get_queryset(self, filter=True):
|
def get_queryset(self, filter=True):
|
||||||
cqs = Checkin.objects.filter(
|
cqs = Checkin.objects.filter(
|
||||||
@@ -105,16 +108,28 @@ class CheckInListShow(EventPermissionRequiredMixin, PaginationMixin, ListView):
|
|||||||
if filter and self.filter_form.is_valid():
|
if filter and self.filter_form.is_valid():
|
||||||
qs = self.filter_form.filter_qs(qs)
|
qs = self.filter_form.filter_qs(qs)
|
||||||
|
|
||||||
|
if 'checkin' in self.request_data and '__ALL' not in self.request_data:
|
||||||
|
qs = qs.filter(
|
||||||
|
id__in=self.request_data.getlist('checkin')
|
||||||
|
)
|
||||||
|
|
||||||
return qs
|
return qs
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def filter_form(self):
|
def filter_form(self):
|
||||||
return CheckinListAttendeeFilterForm(
|
return CheckinListAttendeeFilterForm(
|
||||||
data=self.request.GET,
|
data=self.request_data,
|
||||||
event=self.request.event,
|
event=self.request.event,
|
||||||
list=self.list
|
list=self.list
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class CheckInListShow(EventPermissionRequiredMixin, PaginationMixin, CheckInListQueryMixin, ListView):
|
||||||
|
model = Checkin
|
||||||
|
context_object_name = 'entries'
|
||||||
|
template_name = 'pretixcontrol/checkin/index.html'
|
||||||
|
permission = 'can_view_orders'
|
||||||
|
|
||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
self.list = get_object_or_404(self.request.event.checkin_lists.all(), pk=kwargs.get("list"))
|
self.list = get_object_or_404(self.request.event.checkin_lists.all(), pk=kwargs.get("list"))
|
||||||
return super().dispatch(request, *args, **kwargs)
|
return super().dispatch(request, *args, **kwargs)
|
||||||
@@ -153,18 +168,23 @@ class CheckInListShow(EventPermissionRequiredMixin, PaginationMixin, ListView):
|
|||||||
e.last_exit_aware = e.last_exit
|
e.last_exit_aware = e.last_exit
|
||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
|
||||||
if "can_change_orders" not in request.eventpermset:
|
|
||||||
messages.error(request, _('You do not have permission to perform this action.'))
|
|
||||||
return redirect(reverse('control:event.orders.checkins', kwargs={
|
|
||||||
'event': self.request.event.slug,
|
|
||||||
'organizer': self.request.event.organizer.slug
|
|
||||||
}) + '?' + request.GET.urlencode())
|
|
||||||
|
|
||||||
positions = self.get_queryset(filter=False).filter(
|
class CheckInListBulkActionView(CheckInListQueryMixin, EventPermissionRequiredMixin, AsyncPostView):
|
||||||
pk__in=request.POST.getlist('checkin')
|
template_name = 'pretixcontrol/organizers/device_bulk_edit.html'
|
||||||
)
|
permission = 'can_change_orders'
|
||||||
|
context_object_name = 'device'
|
||||||
|
|
||||||
|
def dispatch(self, request, *args, **kwargs):
|
||||||
|
self.list = get_object_or_404(self.request.event.checkin_lists.all(), pk=kwargs.get("list"))
|
||||||
|
return super().dispatch(request, *args, **kwargs)
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
return super().get_queryset().prefetch_related(None).order_by()
|
||||||
|
|
||||||
|
@transaction.atomic()
|
||||||
|
def async_post(self, request, *args, **kwargs):
|
||||||
|
self.list = get_object_or_404(request.event.checkin_lists.all(), pk=kwargs.get("list"))
|
||||||
|
positions = self.get_queryset()
|
||||||
if request.POST.get('revert') == 'true':
|
if request.POST.get('revert') == 'true':
|
||||||
for op in positions:
|
for op in positions:
|
||||||
if op.order.status == Order.STATUS_PAID or (self.list.include_pending and op.order.status == Order.STATUS_PENDING):
|
if op.order.status == Order.STATUS_PAID or (self.list.include_pending and op.order.status == Order.STATUS_PENDING):
|
||||||
@@ -177,7 +197,7 @@ class CheckInListShow(EventPermissionRequiredMixin, PaginationMixin, ListView):
|
|||||||
}, user=request.user)
|
}, user=request.user)
|
||||||
op.order.touch()
|
op.order.touch()
|
||||||
|
|
||||||
messages.success(request, _('The selected check-ins have been reverted.'))
|
return 'reverted', request.POST.get('returnquery')
|
||||||
else:
|
else:
|
||||||
for op in positions:
|
for op in positions:
|
||||||
if op.order.status == Order.STATUS_PAID or (self.list.include_pending and op.order.status == Order.STATUS_PENDING):
|
if op.order.status == Order.STATUS_PAID or (self.list.include_pending and op.order.status == Order.STATUS_PENDING):
|
||||||
@@ -206,14 +226,22 @@ class CheckInListShow(EventPermissionRequiredMixin, PaginationMixin, ListView):
|
|||||||
'web': True
|
'web': True
|
||||||
}, user=request.user)
|
}, user=request.user)
|
||||||
checkin_created.send(op.order.event, checkin=ci)
|
checkin_created.send(op.order.event, checkin=ci)
|
||||||
|
return 'checked-out' if t == Checkin.TYPE_EXIT else 'checked-in', request.POST.get('returnquery')
|
||||||
|
|
||||||
messages.success(request, _('The selected tickets have been marked as checked in.'))
|
def get_success_message(self, value):
|
||||||
|
if value[0] == 'reverted':
|
||||||
|
return _('The selected check-ins have been reverted.')
|
||||||
|
elif value[0] == 'checked-out':
|
||||||
|
return _('The selected tickets have been marked as checked out.')
|
||||||
|
else:
|
||||||
|
return _('The selected tickets have been marked as checked in.')
|
||||||
|
|
||||||
return redirect(reverse('control:event.orders.checkinlists.show', kwargs={
|
def get_success_url(self, value):
|
||||||
|
return reverse('control:event.orders.checkinlists.show', kwargs={
|
||||||
'event': self.request.event.slug,
|
'event': self.request.event.slug,
|
||||||
'organizer': self.request.event.organizer.slug,
|
'organizer': self.request.event.organizer.slug,
|
||||||
'list': self.list.pk
|
'list': self.list.pk
|
||||||
}) + '?' + request.GET.urlencode())
|
}) + ('?' + value[1] if value[1] else '')
|
||||||
|
|
||||||
|
|
||||||
class CheckinListList(EventPermissionRequiredMixin, PaginationMixin, ListView):
|
class CheckinListList(EventPermissionRequiredMixin, PaginationMixin, ListView):
|
||||||
|
|||||||
@@ -830,7 +830,7 @@ class DeviceQueryMixin:
|
|||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def filter_form(self):
|
def filter_form(self):
|
||||||
return DeviceFilterForm(data=self.request.GET, request=self.request)
|
return DeviceFilterForm(data=self.request_data, request=self.request)
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
qs = self.request.organizer.devices.prefetch_related(
|
qs = self.request.organizer.devices.prefetch_related(
|
||||||
|
|||||||
@@ -218,14 +218,17 @@ $(function () {
|
|||||||
'this page and try again.'
|
'this page and try again.'
|
||||||
));
|
));
|
||||||
|
|
||||||
|
var formData = new FormData(this);
|
||||||
console.log($(this).get(0))
|
|
||||||
var formData = new FormData($(this).get(0))
|
|
||||||
formData.append('ajax', '1');
|
formData.append('ajax', '1');
|
||||||
|
// Not supported on IE, may lead to wrong results, but we don't support IE in the backend anymore
|
||||||
|
var submitter = e.originalEvent.submitter;
|
||||||
|
if (submitter && submitter.name) {
|
||||||
|
formData.append(submitter.name, submitter.value);
|
||||||
|
}
|
||||||
$.ajax(
|
$.ajax(
|
||||||
{
|
{
|
||||||
'type': 'POST',
|
'type': 'POST',
|
||||||
'url': $(this).attr('action'),
|
'url': this.action,
|
||||||
'data': formData,
|
'data': formData,
|
||||||
processData: false,
|
processData: false,
|
||||||
contentType: false,
|
contentType: false,
|
||||||
|
|||||||
@@ -297,7 +297,7 @@ def test_manual_checkins(client, checkin_list_env):
|
|||||||
client.login(email='dummy@dummy.dummy', password='dummy')
|
client.login(email='dummy@dummy.dummy', password='dummy')
|
||||||
with scopes_disabled():
|
with scopes_disabled():
|
||||||
assert not checkin_list_env[5][3].checkins.exists()
|
assert not checkin_list_env[5][3].checkins.exists()
|
||||||
client.post('/control/event/dummy/dummy/checkinlists/{}/'.format(checkin_list_env[6].pk), {
|
client.post('/control/event/dummy/dummy/checkinlists/{}/bulk_action'.format(checkin_list_env[6].pk), {
|
||||||
'checkin': [checkin_list_env[5][3].pk]
|
'checkin': [checkin_list_env[5][3].pk]
|
||||||
})
|
})
|
||||||
with scopes_disabled():
|
with scopes_disabled():
|
||||||
@@ -312,10 +312,10 @@ def test_manual_checkins_revert(client, checkin_list_env):
|
|||||||
client.login(email='dummy@dummy.dummy', password='dummy')
|
client.login(email='dummy@dummy.dummy', password='dummy')
|
||||||
with scopes_disabled():
|
with scopes_disabled():
|
||||||
assert not checkin_list_env[5][3].checkins.exists()
|
assert not checkin_list_env[5][3].checkins.exists()
|
||||||
client.post('/control/event/dummy/dummy/checkinlists/{}/'.format(checkin_list_env[6].pk), {
|
client.post('/control/event/dummy/dummy/checkinlists/{}/bulk_action'.format(checkin_list_env[6].pk), {
|
||||||
'checkin': [checkin_list_env[5][3].pk]
|
'checkin': [checkin_list_env[5][3].pk]
|
||||||
})
|
})
|
||||||
client.post('/control/event/dummy/dummy/checkinlists/{}/'.format(checkin_list_env[6].pk), {
|
client.post('/control/event/dummy/dummy/checkinlists/{}/bulk_action'.format(checkin_list_env[6].pk), {
|
||||||
'checkin': [checkin_list_env[5][3].pk],
|
'checkin': [checkin_list_env[5][3].pk],
|
||||||
'revert': 'true'
|
'revert': 'true'
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -169,6 +169,7 @@ event_urls = [
|
|||||||
"checkinlists/1/",
|
"checkinlists/1/",
|
||||||
"checkinlists/1/change",
|
"checkinlists/1/change",
|
||||||
"checkinlists/1/delete",
|
"checkinlists/1/delete",
|
||||||
|
"checkinlists/1/bulk_action",
|
||||||
"waitinglist/",
|
"waitinglist/",
|
||||||
"waitinglist/auto_assign",
|
"waitinglist/auto_assign",
|
||||||
"waitinglist/action",
|
"waitinglist/action",
|
||||||
@@ -380,6 +381,7 @@ event_permission_urls = [
|
|||||||
("can_view_orders", "checkins/", 200, HTTP_GET),
|
("can_view_orders", "checkins/", 200, HTTP_GET),
|
||||||
("can_view_orders", "checkinlists/", 200, HTTP_GET),
|
("can_view_orders", "checkinlists/", 200, HTTP_GET),
|
||||||
("can_view_orders", "checkinlists/1/", 404, HTTP_GET),
|
("can_view_orders", "checkinlists/1/", 404, HTTP_GET),
|
||||||
|
("can_change_orders", "checkinlists/1/bulk_action", 404, HTTP_POST),
|
||||||
("can_change_event_settings", "checkinlists/add", 200, HTTP_GET),
|
("can_change_event_settings", "checkinlists/add", 200, HTTP_GET),
|
||||||
("can_change_event_settings", "checkinlists/1/change", 404, HTTP_GET),
|
("can_change_event_settings", "checkinlists/1/change", 404, HTTP_GET),
|
||||||
("can_change_event_settings", "checkinlists/1/delete", 404, HTTP_GET),
|
("can_change_event_settings", "checkinlists/1/delete", 404, HTTP_GET),
|
||||||
|
|||||||
Reference in New Issue
Block a user