agendas: Booking.user_check_type becomes a FK (#63847)

This commit is contained in:
Lauréline Guérin 2022-04-15 12:08:06 +02:00
parent a2350a6e36
commit e2cd0d6ad6
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
11 changed files with 275 additions and 114 deletions

View File

@ -0,0 +1,19 @@
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('agendas', '0120_check_types'),
]
operations = [
migrations.AddField(
model_name='booking',
name='new_user_check_type',
field=models.ForeignKey(
blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='agendas.CheckType'
),
),
]

View File

@ -0,0 +1,45 @@
from collections import defaultdict
from django.db import migrations
def forwards(apps, schema_editor):
Booking = apps.get_model('agendas', 'Booking')
Agenda = apps.get_model('agendas', 'Agenda')
check_types_by_agenda_id = defaultdict(list)
for agenda in Agenda.objects.filter(kind='events'):
if not agenda.check_type_group:
continue
for check_type in agenda.check_type_group.check_types.all():
check_types_by_agenda_id[agenda.pk].append(check_type)
for booking in Booking.objects.exclude(user_check_type='').filter(user_was_present__isnull=False):
if booking.event.agenda_id not in check_types_by_agenda_id:
# no check_types for this agenda
continue
for check_type in check_types_by_agenda_id[booking.event.agenda_id]:
if check_type.kind == 'absence' and booking.user_was_present is True:
continue
if check_type.kind == 'presence' and booking.user_was_present is False:
continue
if check_type.label == booking.user_check_type:
booking.new_user_check_type = check_type
booking.save()
break
def backwards(apps, schema_editor):
Booking = apps.get_model('agendas', 'Booking')
for booking in Booking.objects.filter(new_user_check_type__isnull=False):
booking.user_check_type = booking.new_user_check_type.label
booking.save()
class Migration(migrations.Migration):
dependencies = [
('agendas', '0121_user_check_type'),
]
operations = [
migrations.RunPython(forwards, reverse_code=backwards),
]

View File

@ -0,0 +1,20 @@
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('agendas', '0122_user_check_type'),
]
operations = [
migrations.RemoveField(
model_name='booking',
name='user_check_type',
),
migrations.RenameField(
model_name='booking',
old_name='new_user_check_type',
new_name='user_check_type',
),
]

View File

@ -1930,7 +1930,7 @@ class Booking(models.Model):
user_email = models.EmailField(blank=True)
user_phone_number = models.CharField(max_length=16, blank=True)
user_was_present = models.NullBooleanField()
user_check_type = models.CharField(max_length=250, blank=True)
user_check_type = models.ForeignKey('agendas.CheckType', on_delete=models.PROTECT, blank=True, null=True)
out_of_min_delay = models.BooleanField(default=False)
extra_emails = ArrayField(models.EmailField(), default=list)
@ -1982,7 +1982,7 @@ class Booking(models.Model):
self.save()
def mark_user_absence(self, check_type=None):
check_type = check_type or ''
check_type = check_type or None
self.user_check_type = check_type
self.user_was_present = False
with transaction.atomic():
@ -1992,7 +1992,7 @@ class Booking(models.Model):
self.event.set_is_checked()
def mark_user_presence(self, check_type=None):
check_type = check_type or ''
check_type = check_type or None
self.user_check_type = check_type
self.user_was_present = True
with transaction.atomic():

View File

@ -155,17 +155,14 @@ class BookingSerializer(serializers.ModelSerializer):
def to_representation(self, instance):
ret = super().to_representation(instance)
ret['user_absence_reason'] = (
self.instance.user_check_type if self.instance.user_was_present is False else ''
)
ret['user_presence_reason'] = (
self.instance.user_check_type if self.instance.user_was_present is True else ''
)
check_type_slug = self.instance.user_check_type.slug if self.instance.user_check_type else ''
ret['user_absence_reason'] = check_type_slug if self.instance.user_was_present is False else ''
ret['user_presence_reason'] = check_type_slug if self.instance.user_was_present is True else ''
return ret
def _validate_check_type(self, kind, value):
if not value:
return ''
return None
error_messages = {
'absence': _('unknown absence reason'),
@ -177,14 +174,13 @@ class BookingSerializer(serializers.ModelSerializer):
check_types_qs = self.instance.event.agenda.check_type_group.check_types.filter(kind=kind)
try:
check_type = check_types_qs.get(slug=value)
value = check_type.label
return check_types_qs.get(slug=value)
except CheckType.DoesNotExist:
if not check_types_qs.filter(label=value).exists():
try:
return check_types_qs.get(label=value)
except (CheckType.DoesNotExist, CheckType.MultipleObjectsReturned):
raise serializers.ValidationError(error_messages[kind])
return value
def validate_user_absence_reason(self, value):
return self._validate_check_type('absence', value)

View File

@ -2239,10 +2239,18 @@ class BookingFilter(filters.FilterSet):
return queryset.filter(Q(event__slug=value) | Q(event__primary_event__slug=value))
def filter_user_absence_reason(self, queryset, name, value):
return queryset.filter(user_check_type=value, user_was_present=False)
return queryset.filter(
Q(user_check_type__slug=value) | Q(user_check_type__label=value),
user_check_type__kind='absence',
user_was_present=False,
)
def filter_user_presence_reason(self, queryset, name, value):
return queryset.filter(user_check_type=value, user_was_present=True)
return queryset.filter(
Q(user_check_type__slug=value) | Q(user_check_type__label=value),
user_check_type__kind='presence',
user_was_present=True,
)
class Meta:
model = Booking

View File

@ -462,14 +462,16 @@ class BookingCheckFilterSet(django_filters.FilterSet):
]
if self.agenda.check_type_group:
status_choices += [
('presence-%s' % r.label, _('Presence (%s)') % r.label)
for r in self.agenda.check_type_group.check_types.presences()
('presence-%s' % r.pk, _('Presence (%s)') % r.label)
for r in self.agenda.check_type_group.check_types.all()
if r.kind == 'presence'
]
status_choices += [('absence', _('Absence'))]
if self.agenda.check_type_group:
status_choices += [
('absence-%s' % r.label, _('Absence (%s)') % r.label)
for r in self.agenda.check_type_group.check_types.absences()
('absence-%s' % r.pk, _('Absence (%s)') % r.label)
for r in self.agenda.check_type_group.check_types.all()
if r.kind == 'absence'
]
self.filters['booking-status'] = django_filters.ChoiceFilter(
label=_('Filter by status'),
@ -495,9 +497,9 @@ class BookingCheckFilterSet(django_filters.FilterSet):
if value == 'absence':
return queryset.filter(user_was_present=False)
if value.startswith('absence-'):
return queryset.filter(user_was_present=False, user_check_type=value[8:])
return queryset.filter(user_was_present=False, user_check_type=value.split('-')[1])
if value.startswith('presence-'):
return queryset.filter(user_was_present=True, user_check_type=value[9:])
return queryset.filter(user_was_present=True, user_check_type=value.split('-')[1])
return queryset
def do_nothing(self, queryset, name, value):
@ -516,26 +518,26 @@ class SubscriptionCheckFilterSet(BookingCheckFilterSet):
class BookingCheckAbsenceForm(forms.Form):
check_type = forms.ChoiceField(required=False)
check_type = forms.ChoiceField(required=False) # and not ModelChoiceField, to reduce querysets
def __init__(self, *args, **kwargs):
agenda = kwargs.pop('agenda')
super().__init__(*args, **kwargs)
if agenda.check_type_group:
self.fields['check_type'].choices = [('', '---------')] + [
(r.label, r.label) for r in agenda.check_type_group.check_types.absences()
(r.pk, r.label) for r in agenda.check_type_group.check_types.all() if r.kind == 'absence'
]
class BookingCheckPresenceForm(forms.Form):
check_type = forms.ChoiceField(required=False)
check_type = forms.ChoiceField(required=False) # and not ModelChoiceField, to reduce querysets
def __init__(self, *args, **kwargs):
agenda = kwargs.pop('agenda')
super().__init__(*args, **kwargs)
if agenda.check_type_group:
self.fields['check_type'].choices = [('', '---------')] + [
(r.label, r.label) for r in agenda.check_type_group.check_types.presences()
(r.pk, r.label) for r in agenda.check_type_group.check_types.all() if r.kind == 'presence'
]

View File

@ -2294,7 +2294,8 @@ class EventCheckView(ViewableAgendaMixin, DetailView):
booking_qs_kwargs = {}
if not self.agenda.subscriptions.exists():
booking_qs_kwargs = {'cancellation_datetime__isnull': True}
booked_qs = event.booking_set.filter(
booking_qs = event.booking_set.prefetch_related('user_check_type')
booked_qs = booking_qs.filter(
in_waiting_list=False, primary_booking__isnull=True, **booking_qs_kwargs
)
booked_qs = booked_qs.annotate(
@ -2302,7 +2303,7 @@ class EventCheckView(ViewableAgendaMixin, DetailView):
)
# waiting list queryset
waiting_qs = event.booking_set.filter(
waiting_qs = booking_qs.filter(
in_waiting_list=True, primary_booking__isnull=True, **booking_qs_kwargs
).order_by('user_last_name', 'user_first_name')
waiting_qs = waiting_qs.annotate(
@ -2339,11 +2340,11 @@ class EventCheckView(ViewableAgendaMixin, DetailView):
booked_without_status = True
booking.absence_form = BookingCheckAbsenceForm(
agenda=self.agenda,
initial={'check_type': booking.user_check_type if booking.user_was_present is False else ''},
initial={'check_type': booking.user_check_type_id},
)
booking.presence_form = BookingCheckPresenceForm(
agenda=self.agenda,
initial={'check_type': booking.user_check_type if booking.user_was_present is True else ''},
initial={'check_type': booking.user_check_type_id},
)
booking.kind = 'booking'
results.append(booking)
@ -3138,13 +3139,20 @@ class BookingCheckMixin:
primary_booking__isnull=True,
)
def get_check_type(self):
form = self.get_form()
check_type = None
if form.is_valid() and form.cleaned_data['check_type']:
check_type = CheckType.objects.get(pk=form.cleaned_data['check_type'])
return check_type
def response(self, request, booking):
if request.is_ajax():
booking.absence_form = BookingCheckAbsenceForm(
agenda=self.agenda, initial={'check_type': booking.user_check_type}
agenda=self.agenda, initial={'check_type': booking.user_check_type_id}
)
booking.presence_form = BookingCheckPresenceForm(
agenda=self.agenda, initial={'check_type': booking.user_check_type}
agenda=self.agenda, initial={'check_type': booking.user_check_type_id}
)
return render(
request,
@ -3169,11 +3177,7 @@ class BookingPresenceView(ViewableAgendaMixin, BookingCheckMixin, FormView):
def post(self, request, *args, **kwargs):
booking = self.get_booking(**kwargs)
form = self.get_form()
check_type = None
if form.is_valid():
check_type = form.cleaned_data['check_type']
booking.mark_user_presence(check_type=check_type)
booking.mark_user_presence(check_type=self.get_check_type())
return self.response(request, booking)
@ -3190,11 +3194,7 @@ class BookingAbsenceView(ViewableAgendaMixin, BookingCheckMixin, FormView):
def post(self, request, *args, **kwargs):
booking = self.get_booking(**kwargs)
form = self.get_form()
check_type = None
if form.is_valid():
check_type = form.cleaned_data['check_type']
booking.mark_user_absence(check_type=check_type)
booking.mark_user_absence(check_type=self.get_check_type())
return self.response(request, booking)

View File

@ -9,6 +9,8 @@ from chrono.agendas.models import (
Agenda,
Booking,
Category,
CheckType,
CheckTypeGroup,
Desk,
Event,
EventsType,
@ -1183,6 +1185,9 @@ def test_datetimes_multiple_agendas_shared_custody_holiday_rules(app):
def test_datetimes_multiple_agendas_with_status(app):
group = CheckTypeGroup.objects.create(label='Foo bar')
check_type_absence = CheckType.objects.create(label='Foo reason', group=group, kind='absence')
check_type_presence = CheckType.objects.create(label='Foo reason', group=group, kind='presence')
agenda = Agenda.objects.create(label='agenda', kind='events')
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
event_booked = Event.objects.create(
@ -1222,7 +1227,7 @@ def test_datetimes_multiple_agendas_with_status(app):
event=event_absence_with_reason,
user_external_id='xxx',
user_was_present=False,
user_check_type='foobar',
user_check_type=check_type_absence,
)
event_presence = Event.objects.create(
slug='event-presence',
@ -1231,6 +1236,18 @@ def test_datetimes_multiple_agendas_with_status(app):
agenda=agenda,
)
Booking.objects.create(event=event_presence, user_external_id='xxx', user_was_present=True)
event_presence_with_reason = Event.objects.create(
slug='event-presence_with_reason',
start_datetime=now() - datetime.timedelta(days=9),
places=5,
agenda=agenda,
)
Booking.objects.create(
event=event_presence_with_reason,
user_external_id='xxx',
user_was_present=True,
user_check_type=check_type_presence,
)
event_booked_future = Event.objects.create(
slug='event-booked-future',
start_datetime=now() + datetime.timedelta(days=1),
@ -1256,6 +1273,7 @@ def test_datetimes_multiple_agendas_with_status(app):
'agenda@event-absence',
'agenda@event-absence_with_reason',
'agenda@event-presence',
'agenda@event-presence_with_reason',
'agenda@event-booked-future',
'agenda@event-free-future',
]
@ -1278,6 +1296,7 @@ def test_datetimes_multiple_agendas_with_status(app):
'agenda@event-absence',
'agenda@event-absence_with_reason',
'agenda@event-presence',
'agenda@event-presence_with_reason',
'agenda@event-booked-future',
'agenda@event-free-future',
]
@ -1289,6 +1308,7 @@ def test_datetimes_multiple_agendas_with_status(app):
'absence',
'booked',
'booked',
'booked',
'free',
]
@ -1309,6 +1329,7 @@ def test_datetimes_multiple_agendas_with_status(app):
'agenda@event-absence',
'agenda@event-absence_with_reason',
'agenda@event-presence',
'agenda@event-presence_with_reason',
'agenda@event-booked-future',
'agenda@event-free-future',
]
@ -1321,6 +1342,7 @@ def test_datetimes_multiple_agendas_with_status(app):
'free',
'free',
'free',
'free',
]
# check errors

View File

@ -302,47 +302,87 @@ def test_bookings_api_filter_user_was_present(app, user):
def test_bookings_api_filter_user_absence_reason(app, user):
group = CheckTypeGroup.objects.create(label='Foo')
check_type_absence = CheckType.objects.create(group=group, label='Foo bar', kind='absence')
check_type_presence = CheckType.objects.create(group=group, label='Foo bar', kind='presence')
agenda = Agenda.objects.create(label='Foo bar')
event = Event.objects.create(
agenda=agenda, start_datetime=make_aware(datetime.datetime(2017, 5, 22, 0, 0)), places=10
)
Booking.objects.create(event=event, user_external_id='42', user_was_present=False)
booking2 = Booking.objects.create(
event=event, user_external_id='42', user_was_present=False, user_check_type='foo-bar'
event=event, user_external_id='42', user_was_present=False, user_check_type=check_type_absence
)
Booking.objects.create(
event=event, user_external_id='42', user_was_present=False, user_check_type=check_type_presence
)
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_absence_reason': 'foo'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == []
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_absence_reason': 'foo-bar'})
resp = app.get(
'/api/bookings/', params={'user_external_id': '42', 'user_absence_reason': check_type_absence.slug}
)
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == [booking2.pk]
resp = app.get(
'/api/bookings/', params={'user_external_id': '42', 'user_absence_reason': check_type_absence.label}
)
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == [booking2.pk]
resp = app.get(
'/api/bookings/', params={'user_external_id': '42', 'user_absence_reason': check_type_presence.slug}
)
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == []
Booking.objects.update(user_was_present=True)
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_absence_reason': 'foo-bar'})
resp = app.get(
'/api/bookings/', params={'user_external_id': '42', 'user_absence_reason': check_type_absence.label}
)
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == []
def test_bookings_api_filter_user_presence_reason(app, user):
group = CheckTypeGroup.objects.create(label='Foo')
check_type_absence = CheckType.objects.create(group=group, label='Foo bar', kind='absence')
check_type_presence = CheckType.objects.create(group=group, label='Foo bar', kind='presence')
agenda = Agenda.objects.create(label='Foo bar')
event = Event.objects.create(
agenda=agenda, start_datetime=make_aware(datetime.datetime(2017, 5, 22, 0, 0)), places=10
)
Booking.objects.create(event=event, user_external_id='42', user_was_present=True)
booking2 = Booking.objects.create(
event=event, user_external_id='42', user_was_present=True, user_check_type='foo-bar'
event=event, user_external_id='42', user_was_present=True, user_check_type=check_type_presence
)
Booking.objects.create(
event=event, user_external_id='42', user_was_present=True, user_check_type=check_type_absence
)
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_presence_reason': 'foo'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == []
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_presence_reason': 'foo-bar'})
resp = app.get(
'/api/bookings/', params={'user_external_id': '42', 'user_presence_reason': check_type_presence.slug}
)
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == [booking2.pk]
resp = app.get(
'/api/bookings/', params={'user_external_id': '42', 'user_presence_reason': check_type_presence.label}
)
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == [booking2.pk]
resp = app.get(
'/api/bookings/', params={'user_external_id': '42', 'user_presence_reason': check_type_absence.slug}
)
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == []
Booking.objects.update(user_was_present=False)
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_presence_reason': 'foo-bar'})
resp = app.get(
'/api/bookings/', params={'user_external_id': '42', 'user_presence_reason': check_type_presence.label}
)
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == []
@ -415,16 +455,20 @@ def test_bookings_api_filter_event(app, user):
@pytest.mark.parametrize('flag', [True, False, None])
def test_booking_api_present(app, user, flag):
group = CheckTypeGroup.objects.create(label='Foo')
check_type = CheckType.objects.create(
group=group, label='Foo bar', kind='presence' if flag else 'absence'
)
agenda = Agenda.objects.create(label='Foo bar', kind='events')
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
booking = Booking.objects.create(event=event, user_was_present=flag, user_check_type='foobar')
booking = Booking.objects.create(event=event, user_was_present=flag, user_check_type=check_type)
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.get('/api/booking/%s/' % booking.pk)
assert resp.json['booking_id'] == booking.pk
assert resp.json['user_was_present'] == flag
assert resp.json['user_absence_reason'] == ('foobar' if flag is False else '')
assert resp.json['user_presence_reason'] == ('foobar' if flag is True else '')
assert resp.json['user_absence_reason'] == ('foo-bar' if flag is False else '')
assert resp.json['user_presence_reason'] == ('foo-bar' if flag is True else '')
@pytest.mark.parametrize('flag', [True, False])
@ -594,15 +638,15 @@ def test_booking_patch_api_absence_reason(app, user):
# it works with label
app.patch_json('/api/booking/%s/' % booking.pk, params={'user_absence_reason': 'Foo bar'})
booking.refresh_from_db()
assert booking.user_check_type == 'Foo bar'
assert booking.user_check_type == check_type_absence
# reset
app.patch_json('/api/booking/%s/' % booking.pk, params={'user_absence_reason': ''})
booking.refresh_from_db()
assert booking.user_check_type == ''
assert booking.user_check_type is None
app.patch_json('/api/booking/%s/' % booking.pk, params={'user_absence_reason': None})
booking.refresh_from_db()
assert booking.user_check_type == ''
assert booking.user_check_type is None
# make secondary bookings
Booking.objects.create(event=event, primary_booking=booking, user_was_present=False)
@ -613,14 +657,14 @@ def test_booking_patch_api_absence_reason(app, user):
# it works also with slug
app.patch_json('/api/booking/%s/' % booking.pk, params={'user_absence_reason': check_type_absence.slug})
booking.refresh_from_db()
assert booking.user_check_type == 'Foo bar'
assert booking.user_check_type == check_type_absence
# all secondary bookings are updated
assert list(booking.secondary_booking_set.values_list('user_check_type', flat=True)) == [
'Foo bar',
'Foo bar',
check_type_absence.pk,
check_type_absence.pk,
]
other_booking.refresh_from_db()
assert other_booking.user_check_type == '' # not changed
assert other_booking.user_check_type is None # not changed
# user_was_present is True, can not set user_absence_reason
Booking.objects.update(user_was_present=True)
@ -638,7 +682,7 @@ def test_booking_patch_api_absence_reason(app, user):
assert resp.json['err'] == 0
booking.refresh_from_db()
assert booking.user_was_present is False
assert booking.user_check_type == 'Foo bar'
assert booking.user_check_type == check_type_absence
# mark the event as checked
event.checked = True
@ -702,15 +746,15 @@ def test_booking_patch_api_presence_reason(app, user):
# it works with label
app.patch_json('/api/booking/%s/' % booking.pk, params={'user_presence_reason': 'Foo bar'})
booking.refresh_from_db()
assert booking.user_check_type == 'Foo bar'
assert booking.user_check_type == check_type_presence
# reset
app.patch_json('/api/booking/%s/' % booking.pk, params={'user_presence_reason': ''})
booking.refresh_from_db()
assert booking.user_check_type == ''
assert booking.user_check_type is None
app.patch_json('/api/booking/%s/' % booking.pk, params={'user_presence_reason': None})
booking.refresh_from_db()
assert booking.user_check_type == ''
assert booking.user_check_type is None
# make secondary bookings
Booking.objects.create(event=event, primary_booking=booking, user_was_present=True)
@ -721,14 +765,14 @@ def test_booking_patch_api_presence_reason(app, user):
# it works also with slug
app.patch_json('/api/booking/%s/' % booking.pk, params={'user_presence_reason': check_type_presence.slug})
booking.refresh_from_db()
assert booking.user_check_type == 'Foo bar'
assert booking.user_check_type == check_type_presence
# all secondary bookings are updated
assert list(booking.secondary_booking_set.values_list('user_check_type', flat=True)) == [
'Foo bar',
'Foo bar',
check_type_presence.pk,
check_type_presence.pk,
]
other_booking.refresh_from_db()
assert other_booking.user_check_type == '' # not changed
assert other_booking.user_check_type is None # not changed
# user_was_present is False, can not set user_presence_reason
Booking.objects.update(user_was_present=False)
@ -746,7 +790,7 @@ def test_booking_patch_api_presence_reason(app, user):
assert resp.json['err'] == 0
booking.refresh_from_db()
assert booking.user_was_present is True
assert booking.user_check_type == 'Foo bar'
assert booking.user_check_type == check_type_presence
# mark the event as checked
event.checked = True

View File

@ -1672,7 +1672,7 @@ def test_event_check_filters(app, admin_user):
user_last_name='foo-none bar-val2 reason-foo',
extra_data={'bar': 'val2'},
user_was_present=False,
user_check_type=check_type_absence.label,
user_check_type=check_type_absence,
)
Booking.objects.create(
event=event,
@ -1681,7 +1681,7 @@ def test_event_check_filters(app, admin_user):
user_last_name='foo-none bar-val2 reason-bar',
extra_data={'bar': 'val2'},
user_was_present=True,
user_check_type=check_type_presence.label,
user_check_type=check_type_presence,
)
Booking.objects.create(
event=event,
@ -1690,7 +1690,7 @@ def test_event_check_filters(app, admin_user):
user_last_name='foo-none bar-val2 cancelled-absence',
extra_data={'bar': 'val2'},
user_was_present=False,
user_check_type=check_type_absence.label,
user_check_type=check_type_absence,
cancellation_datetime=now(),
)
Booking.objects.create(
@ -1700,7 +1700,7 @@ def test_event_check_filters(app, admin_user):
user_last_name='foo-none bar-val2 cancelled-presence',
extra_data={'bar': 'val2'},
user_was_present=True,
user_check_type=check_type_presence.label,
user_check_type=check_type_presence,
cancellation_datetime=now(),
)
@ -1782,9 +1782,11 @@ def test_event_check_filters(app, admin_user):
assert 'Subscription foo-val1 bar-val2' in resp
assert 'Subscription foo-none bar-val2' in resp
resp = app.get(
'/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk), params={'extra-data-foo': 'val1'}
)
with CaptureQueriesContext(connection) as ctx:
resp = app.get(
'/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk), params={'extra-data-foo': 'val1'}
)
assert len(ctx.captured_queries) == 13
assert 'User none' not in resp
assert 'User empty' not in resp
assert 'User foo-val1 bar-none presence' in resp
@ -1957,7 +1959,7 @@ def test_event_check_filters(app, admin_user):
resp = app.get(
'/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk),
params={'booking-status': 'absence-Foo reason'},
params={'booking-status': 'absence-%s' % check_type_absence.pk},
)
assert 'User none' not in resp
assert 'User empty' not in resp
@ -1977,7 +1979,7 @@ def test_event_check_filters(app, admin_user):
resp = app.get(
'/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk),
params={'booking-status': 'presence-Bar reason'},
params={'booking-status': 'presence-%s' % check_type_presence.pk},
)
assert 'User none' not in resp
assert 'User empty' not in resp
@ -2068,10 +2070,10 @@ def test_event_check_booking(app, admin_user):
assert resp.pyquery.find('td.booking-actions button[disabled]')[0].text == 'Presence'
booking.refresh_from_db()
assert booking.user_was_present is True
assert booking.user_check_type == ''
assert booking.user_check_type is None
secondary_booking.refresh_from_db()
assert secondary_booking.user_was_present is True
assert secondary_booking.user_check_type == ''
assert secondary_booking.user_check_type is None
event.refresh_from_db()
assert event.checked is False
@ -2088,10 +2090,10 @@ def test_event_check_booking(app, admin_user):
assert resp.pyquery.find('td.booking-actions button[disabled]')[0].text == 'Absence'
booking.refresh_from_db()
assert booking.user_was_present is False
assert booking.user_check_type == ''
assert booking.user_check_type is None
secondary_booking.refresh_from_db()
assert secondary_booking.user_was_present is False
assert secondary_booking.user_check_type == ''
assert secondary_booking.user_check_type is None
event.refresh_from_db()
assert event.checked is True
@ -2101,7 +2103,7 @@ def test_event_check_booking(app, admin_user):
assert len(resp.pyquery.find('td.booking-actions form.absence select')) == 0
assert len(resp.pyquery.find('td.booking-actions form.presence select')) == 0
CheckType.objects.create(label='Foo reason', group=group, kind='absence')
check_type_absence = CheckType.objects.create(label='Foo reason', group=group, kind='absence')
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
assert len(resp.pyquery.find('td.booking-actions form.absence select')) == 1
assert len(resp.pyquery.find('td.booking-actions form.presence select')) == 0
@ -2109,15 +2111,15 @@ def test_event_check_booking(app, admin_user):
# set as absent with check_type
resp = app.post(
'/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk),
params={'csrfmiddlewaretoken': token, 'check_type': 'Foo reason'},
params={'csrfmiddlewaretoken': token, 'check_type': check_type_absence.pk},
).follow()
assert 'Foo reason' in resp
booking.refresh_from_db()
assert booking.user_was_present is False
assert booking.user_check_type == 'Foo reason'
assert booking.user_check_type == check_type_absence
secondary_booking.refresh_from_db()
assert secondary_booking.user_was_present is False
assert secondary_booking.user_check_type == 'Foo reason'
assert secondary_booking.user_check_type == check_type_absence
# set as present without check_type
resp = app.post(
@ -2129,10 +2131,10 @@ def test_event_check_booking(app, admin_user):
assert resp.pyquery.find('td.booking-actions button[disabled]')[0].text == 'Presence'
booking.refresh_from_db()
assert booking.user_was_present is True
assert booking.user_check_type == ''
assert booking.user_check_type is None
secondary_booking.refresh_from_db()
assert secondary_booking.user_was_present is True
assert secondary_booking.user_check_type == ''
assert secondary_booking.user_check_type is None
event.refresh_from_db()
assert event.checked is True
@ -2142,7 +2144,7 @@ def test_event_check_booking(app, admin_user):
assert len(resp.pyquery.find('td.booking-actions form.absence select')) == 1
assert len(resp.pyquery.find('td.booking-actions form.presence select')) == 0
CheckType.objects.create(label='Bar reason', group=group, kind='presence')
check_type_presence = CheckType.objects.create(label='Bar reason', group=group, kind='presence')
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
assert len(resp.pyquery.find('td.booking-actions form.absence select')) == 1
assert len(resp.pyquery.find('td.booking-actions form.presence select')) == 1
@ -2150,15 +2152,15 @@ def test_event_check_booking(app, admin_user):
# set as present with check_type
resp = app.post(
'/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk),
params={'csrfmiddlewaretoken': token, 'check_type': 'Bar reason'},
params={'csrfmiddlewaretoken': token, 'check_type': check_type_presence.pk},
).follow()
assert 'Bar reason' in resp
booking.refresh_from_db()
assert booking.user_was_present is True
assert booking.user_check_type == 'Bar reason'
assert booking.user_check_type == check_type_presence
secondary_booking.refresh_from_db()
assert secondary_booking.user_was_present is True
assert secondary_booking.user_check_type == 'Bar reason'
assert secondary_booking.user_check_type == check_type_presence
# mark the event as checked
event.checked = True
@ -2197,7 +2199,8 @@ def test_event_check_booking(app, admin_user):
def test_event_check_booking_ajax(app, admin_user):
group = CheckTypeGroup.objects.create(label='Foo bar')
CheckType.objects.create(label='Foo reason', group=group)
check_type_absence = CheckType.objects.create(label='Foo reason', group=group)
check_type_presence = CheckType.objects.create(label='Bar reason', group=group, kind='presence')
agenda = Agenda.objects.create(label='Events', kind='events', check_type_group=group)
event = Event.objects.create(
label='xyz',
@ -2215,30 +2218,32 @@ def test_event_check_booking_ajax(app, admin_user):
# set as present
resp = app.post(
'/manage/agendas/%s/bookings/%s/presence' % (agenda.pk, booking.pk),
params={'csrfmiddlewaretoken': token},
params={'csrfmiddlewaretoken': token, 'check_type': check_type_presence.pk},
extra_environ={'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest'},
)
assert '<tr>' not in resp # because this is a fragment
assert resp.pyquery.find('td.booking-status')[0].text.strip() == 'Present'
assert resp.pyquery.find('td.booking-status')[0].text.strip() == 'Present\n \n (Bar reason)'
assert len(resp.pyquery.find('td.booking-actions button[disabled]')) == 1
assert resp.pyquery.find('td.booking-actions button[disabled]')[0].text == 'Presence'
assert '<option value="%s" selected>Bar reason</option>' % check_type_presence.pk in resp
# set as absent
resp = app.post(
'/manage/agendas/%s/bookings/%s/absence' % (agenda.pk, booking.pk),
params={'csrfmiddlewaretoken': token, 'check_type': 'Foo reason'},
params={'csrfmiddlewaretoken': token, 'check_type': check_type_absence.pk},
extra_environ={'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest'},
)
assert '<tr>' not in resp # because this is a fragment
assert resp.pyquery.find('td.booking-status')[0].text.strip() == 'Absent\n \n (Foo reason)'
assert len(resp.pyquery.find('td.booking-actions button[disabled]')) == 1
assert resp.pyquery.find('td.booking-actions button[disabled]')[0].text.startswith('Absence')
assert '<option value="Foo reason" selected>Foo reason</option>' in resp
assert '<option value="%s" selected>Foo reason</option>' % check_type_absence.pk in resp
def test_event_check_all_bookings(app, admin_user):
group = CheckTypeGroup.objects.create(label='Foo bar')
CheckType.objects.create(label='Foo reason', group=group)
CheckType.objects.create(label='Bar reason', group=group, kind='presence')
check_type_absence = CheckType.objects.create(label='Foo reason', group=group)
check_type_presence = CheckType.objects.create(label='Bar reason', group=group, kind='presence')
agenda = Agenda.objects.create(label='Events', kind='events', check_type_group=group)
event = Event.objects.create(
label='xyz',
@ -2262,7 +2267,7 @@ def test_event_check_all_bookings(app, admin_user):
)
booking1.refresh_from_db()
assert booking1.user_was_present is False
assert booking1.user_check_type == ''
assert booking1.user_check_type is None
event.refresh_from_db()
assert event.checked is False
@ -2288,13 +2293,13 @@ def test_event_check_all_bookings(app, admin_user):
)
booking1.refresh_from_db()
assert booking1.user_was_present is False
assert booking1.user_check_type == ''
assert booking1.user_check_type is None
booking2.refresh_from_db()
assert booking2.user_was_present is True
assert booking2.user_check_type == ''
assert booking2.user_check_type is None
secondary_booking.refresh_from_db()
assert secondary_booking.user_was_present is True
assert secondary_booking.user_check_type == ''
assert secondary_booking.user_check_type is None
event.refresh_from_db()
assert event.checked is True
@ -2304,37 +2309,37 @@ def test_event_check_all_bookings(app, admin_user):
assert 'Mark all bookings without status' in resp
app.post(
'/manage/agendas/%s/events/%s/absence' % (agenda.pk, event.pk),
params={'csrfmiddlewaretoken': token, 'check_type': 'Foo reason'},
params={'csrfmiddlewaretoken': token, 'check_type': check_type_absence.pk},
)
booking1.refresh_from_db()
assert booking1.user_was_present is False
assert booking1.user_check_type == ''
assert booking1.user_check_type is None
booking2.refresh_from_db()
assert booking2.user_was_present is True
assert booking2.user_check_type == ''
assert booking2.user_check_type is None
booking3.refresh_from_db()
assert booking3.user_was_present is False
assert booking3.user_check_type == 'Foo reason'
assert booking3.user_check_type == check_type_absence
booking4 = Booking.objects.create(event=event, user_first_name='User', user_last_name='52')
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
assert 'Mark all bookings without status' in resp
app.post(
'/manage/agendas/%s/events/%s/presence' % (agenda.pk, event.pk),
params={'csrfmiddlewaretoken': token, 'check_type': 'Bar reason'},
params={'csrfmiddlewaretoken': token, 'check_type': check_type_presence.pk},
)
booking1.refresh_from_db()
assert booking1.user_was_present is False
assert booking1.user_check_type == ''
assert booking1.user_check_type is None
booking2.refresh_from_db()
assert booking2.user_was_present is True
assert booking2.user_check_type == ''
assert booking2.user_check_type is None
booking3.refresh_from_db()
assert booking3.user_was_present is False
assert booking3.user_check_type == 'Foo reason'
assert booking3.user_check_type == check_type_absence
booking4.refresh_from_db()
assert booking4.user_was_present is True
assert booking4.user_check_type == 'Bar reason'
assert booking4.user_check_type == check_type_presence
# now disable check update
agenda.disable_check_update = True
@ -2344,7 +2349,7 @@ def test_event_check_all_bookings(app, admin_user):
assert 'Mark all bookings without status' not in resp
app.post(
'/manage/agendas/%s/events/%s/absence' % (agenda.pk, event.pk),
params={'csrfmiddlewaretoken': token, 'check_type': 'Foo reason'},
params={'csrfmiddlewaretoken': token, 'check_type': check_type_absence.pk},
status=404,
)
resp = app.post(
@ -2354,7 +2359,7 @@ def test_event_check_all_bookings(app, admin_user):
)
app.post(
'/manage/agendas/%s/events/%s/presence' % (agenda.pk, event.pk),
params={'csrfmiddlewaretoken': token, 'check_type': 'Bar reason'},
params={'csrfmiddlewaretoken': token, 'check_type': check_type_presence.pk},
status=404,
)
resp = app.post(