managers: display filters on check page (#53238)

This commit is contained in:
Lauréline Guérin 2021-04-22 11:39:42 +02:00
parent 233c6e62ca
commit a4195b0dc2
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
5 changed files with 149 additions and 7 deletions

View File

@ -16,9 +16,11 @@
from __future__ import unicode_literals
import collections
import csv
import datetime
import django_filters
from django import forms
from django.conf import settings
from django.contrib.auth.models import Group
@ -240,6 +242,39 @@ class EventForm(forms.ModelForm):
return self.instance
class BookingCheckFilterSet(django_filters.FilterSet):
class Meta:
model = Booking
fields = []
def __init__(self, *args, **kwargs):
self.agenda = kwargs.pop('agenda')
super().__init__(*args, **kwargs)
# build filters from DB
agenda_filters = self.agenda.get_booking_check_filters()
filters = collections.defaultdict(set)
for extra_data in self.queryset.filter(extra_data__has_any_keys=agenda_filters).values_list(
'extra_data', flat=True
):
for k, v in extra_data.items():
if k in agenda_filters:
filters[k].add(v)
filters = sorted(filters.items())
filters = {k: sorted(list(v)) for k, v in filters}
# add filters to filterset
for key, values in filters.items():
self.filters[key] = django_filters.ChoiceFilter(
label=_('Filter by %s') % key,
field_name='extra_data__%s' % key,
lookup_expr='iexact',
choices=[(v, v) for v in values],
empty_label=_('all'),
widget=forms.RadioSelect,
)
class BookingAbsenceReasonForm(forms.Form):
reason = forms.ChoiceField(required=False)

View File

@ -408,6 +408,11 @@ table.check-bookings {
}
}
form.check-bookings-filters li {
display: inline;
margin-right: 10px;
}
// booking colors
$booking-colors: (
0: hsl(30, 100%, 46%),

View File

@ -14,6 +14,17 @@
{% blocktrans with places=object.places booked_places=booked|length %}Bookings ({{ booked_places }}/{{ places }}){% endblocktrans %}
</h3>
<div>
<form class="check-bookings-filters">
{{ filterset.form.as_p }}
<script>
$(function() {
$('form.check-bookings-filters input').on('change',
function() {
$(this).parents('form').submit();
});
});
</script>
</form>
<table class="main check-bookings">
<tbody>
{% if booked_without_status %}

View File

@ -90,6 +90,7 @@ from .forms import (
AgendasImportForm,
BookingAbsenceReasonForm,
BookingCancelForm,
BookingCheckFilterSet,
DeskForm,
EventCancelForm,
EventForm,
@ -1960,20 +1961,25 @@ class EventCheckView(ViewableAgendaMixin, DetailView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
event = self.object
context['booked'] = event.booking_set.filter(
cancellation_datetime__isnull=True, in_waiting_list=False
).order_by('user_last_name', 'user_first_name')
booked_qs = event.booking_set.filter(cancellation_datetime__isnull=True, in_waiting_list=False)
filterset = BookingCheckFilterSet(self.request.GET, queryset=booked_qs, agenda=self.agenda)
context['filterset'] = filterset
# build booking list
context['booked'] = filterset.qs.order_by('user_last_name', 'user_first_name')
context['booked_without_status'] = any(e.user_was_present is None for e in context['booked'])
if context['booked_without_status']:
context['absence_form'] = BookingAbsenceReasonForm(agenda=self.agenda)
context['waiting'] = event.booking_set.filter(
cancellation_datetime__isnull=True, in_waiting_list=True
).order_by('user_last_name', 'user_first_name')
for booking in context['booked']:
booking.form = BookingAbsenceReasonForm(
agenda=self.agenda, initial={'reason': booking.user_absence_reason}
)
context['waiting'] = event.booking_set.filter(
cancellation_datetime__isnull=True, in_waiting_list=True
).order_by('user_last_name', 'user_first_name')
return context

View File

@ -1091,7 +1091,7 @@ def test_event_check(app, admin_user):
assert '/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk) not in resp
app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk), status=404)
event.start_datetime = localtime(now()).replace(hour=22, minute=0) # it'os ok all the day
event.start_datetime = localtime(now()).replace(hour=22, minute=0) # it's ok all the day
event.save()
resp = app.get('/manage/agendas/%s/events/%s/' % (agenda.pk, event.pk))
assert '/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk) in resp
@ -1178,6 +1178,91 @@ def test_event_check(app, admin_user):
event.cancellation_datetime = None
def test_event_check_filters(app, admin_user):
agenda = Agenda.objects.create(label='Events', kind='events', booking_check_filters='foo,bar')
event = Event.objects.create(
label='xyz',
start_datetime=now() - datetime.timedelta(days=1),
places=10,
agenda=agenda,
)
Booking.objects.create(event=event, user_first_name='User', user_last_name='none')
Booking.objects.create(event=event, user_first_name='User', user_last_name='empty', extra_data={})
Booking.objects.create(
event=event, user_first_name='User', user_last_name='foo-val1 bar-none', extra_data={'foo': 'val1'}
)
Booking.objects.create(
event=event,
user_first_name='User',
user_last_name='foo-val2 bar-val1',
extra_data={'foo': 'val2', 'bar': 'val1'},
)
Booking.objects.create(
event=event,
user_first_name='User',
user_last_name='foo-val1 bar-val2',
extra_data={'foo': 'val1', 'bar': 'val2'},
)
Booking.objects.create(
event=event, user_first_name='User', user_last_name='foo-none bar-val2', extra_data={'bar': 'val2'}
)
login(app)
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
assert 'User none' in resp
assert 'User empty' in resp
assert 'User foo-val1' in resp
assert 'User foo-val2 bar-val1' in resp
assert 'User foo-val1 bar-val2' in resp
assert 'User foo-none bar-val2' in resp
resp = app.get(
'/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk), params={'unknown': 'unknown'}
)
assert 'User none' in resp
assert 'User empty' in resp
assert 'User foo-val1 bar-none' in resp
assert 'User foo-val2 bar-val1' in resp
assert 'User foo-val1 bar-val2' in resp
assert 'User foo-none bar-val2' in resp
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk), params={'foo': 'unknown'})
assert 'User none' in resp
assert 'User empty' in resp
assert 'User foo-val1 bar-none' in resp
assert 'User foo-val2 bar-val1' in resp
assert 'User foo-val1 bar-val2' in resp
assert 'User foo-none bar-val2' in resp
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk), params={'foo': 'val1'})
assert 'User none' not in resp
assert 'User empty' not in resp
assert 'User foo-val1 bar-none' in resp
assert 'User foo-val2 bar-val1' not in resp
assert 'User foo-val1 bar-val2' in resp
assert 'User foo-none bar-val2' not in resp
resp = app.get(
'/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk), params={'foo': 'val1', 'bar': 'val2'}
)
assert 'User none' not in resp
assert 'User empty' not in resp
assert 'User foo-val1 bar-none' not in resp
assert 'User foo-val2 bar-val1' not in resp
assert 'User foo-val1 bar-val2' in resp
assert 'User foo-none bar-val2' not in resp
resp = app.get(
'/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk), params={'foo': 'val2', 'bar': 'val2'}
)
assert 'User none' not in resp
assert 'User empty' not in resp
assert 'User foo-val1 bar-none' not in resp
assert 'User foo-val2 bar-val1' not in resp
assert 'User foo-val1 bar-val2' not in resp
assert 'User foo-none bar-val2' not in resp
def test_event_check_booking(app, admin_user):
group = AbsenceReasonGroup.objects.create(label='Foo bar')
agenda = Agenda.objects.create(label='Events', kind='events')