From 2d0cb4f1b2868495a690dcdc7160d21cc5826fd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= Date: Thu, 9 Jun 2022 16:35:13 +0200 Subject: [PATCH] api: use check_types from lingo (#66015) --- chrono/api/serializers.py | 22 +- .../datetimes/test_events_multiple_agendas.py | 9 +- tests/api/test_booking.py | 200 ++++++------------ 3 files changed, 74 insertions(+), 157 deletions(-) diff --git a/chrono/api/serializers.py b/chrono/api/serializers.py index 223538fc..ac36d99a 100644 --- a/chrono/api/serializers.py +++ b/chrono/api/serializers.py @@ -13,7 +13,6 @@ from chrono.agendas.models import ( Booking, BookingColor, Category, - CheckType, Event, EventsType, Person, @@ -23,6 +22,7 @@ from chrono.agendas.models import ( Subscription, TimePeriodExceptionGroup, ) +from chrono.utils.lingo import get_agenda_check_types def get_objects_from_slugs(slugs, qs): @@ -240,19 +240,13 @@ class BookingSerializer(serializers.ModelSerializer): 'presence': _('unknown presence reason'), } - if not self.instance.event.agenda.check_type_group: - raise serializers.ValidationError(error_messages[kind]) - - check_types_qs = self.instance.event.agenda.check_type_group.check_types.filter( - kind=kind, disabled=False - ) - try: - return check_types_qs.get(slug=value) - except CheckType.DoesNotExist: - try: - return check_types_qs.get(label=value) - except (CheckType.DoesNotExist, CheckType.MultipleObjectsReturned): - raise serializers.ValidationError(error_messages[kind]) + check_types = get_agenda_check_types(self.instance.event.agenda) + for check_type in check_types: + if check_type.kind != kind: + continue + if value in [check_type.slug, check_type.label]: + return check_type + raise serializers.ValidationError(error_messages[kind]) def validate_user_absence_reason(self, value): return self._validate_check_type('absence', value) diff --git a/tests/api/datetimes/test_events_multiple_agendas.py b/tests/api/datetimes/test_events_multiple_agendas.py index fc2312bf..050dd934 100644 --- a/tests/api/datetimes/test_events_multiple_agendas.py +++ b/tests/api/datetimes/test_events_multiple_agendas.py @@ -9,8 +9,6 @@ from chrono.agendas.models import ( Agenda, Booking, Category, - CheckType, - CheckTypeGroup, Desk, Event, EventsType, @@ -1207,9 +1205,6 @@ 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( @@ -1249,7 +1244,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_slug=check_type_absence.slug, + user_check_type_slug='foo-reason', ) event_presence = Event.objects.create( slug='event-presence', @@ -1268,7 +1263,7 @@ def test_datetimes_multiple_agendas_with_status(app): event=event_presence_with_reason, user_external_id='xxx', user_was_present=True, - user_check_type_slug=check_type_presence.slug, + user_check_type_slug='foo-reason', ) event_booked_future = Event.objects.create( slug='event-booked-future', diff --git a/tests/api/test_booking.py b/tests/api/test_booking.py index e77781fd..65c33e0b 100644 --- a/tests/api/test_booking.py +++ b/tests/api/test_booking.py @@ -6,17 +6,8 @@ from django.db import connection from django.test.utils import CaptureQueriesContext from django.utils.timezone import localtime, make_aware, now -from chrono.agendas.models import ( - Agenda, - Booking, - BookingColor, - Category, - CheckType, - CheckTypeGroup, - Desk, - Event, - MeetingType, -) +from chrono.agendas.models import Agenda, Booking, BookingColor, Category, Desk, Event, MeetingType +from chrono.utils.lingo import CheckType pytestmark = pytest.mark.django_db @@ -324,9 +315,6 @@ 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 @@ -336,48 +324,37 @@ def test_bookings_api_filter_user_absence_reason(app, user): event=event, user_external_id='42', user_was_present=False, - user_check_type_slug=check_type_absence.slug, - user_check_type_label=check_type_absence.label, + user_check_type_slug='foo-bar', + user_check_type_label='Foo bar', ) Booking.objects.create( event=event, user_external_id='42', user_was_present=True, - user_check_type_slug=check_type_presence.slug, - user_check_type_label=check_type_presence.label, + user_check_type_slug='foo-bar-2', + user_check_type_label='Foo bar 2', ) 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': check_type_absence.slug} - ) + resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_absence_reason': 'foo-bar'}) 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} - ) + resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_absence_reason': 'Foo bar'}) 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} - ) + resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_absence_reason': 'foo-bar-2'}) 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': check_type_absence.label} - ) + resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_absence_reason': 'Foo bar 2'}) 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 @@ -387,40 +364,32 @@ def test_bookings_api_filter_user_presence_reason(app, user): event=event, user_external_id='42', user_was_present=True, - user_check_type_slug=check_type_presence.slug, - user_check_type_label=check_type_presence.label, + user_check_type_slug='foo-bar', + user_check_type_label='Foo bar', ) Booking.objects.create( event=event, user_external_id='42', user_was_present=False, - user_check_type_slug=check_type_absence.slug, - user_check_type_label=check_type_absence.label, + user_check_type_slug='foo-bar-2', + user_check_type_label='Foo bar 2', ) 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': check_type_presence.slug} - ) + resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_presence_reason': 'foo-bar'}) 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} - ) + resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_presence_reason': 'Foo bar'}) 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} - ) + resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_presence_reason': 'foo-bar-2'}) 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': check_type_presence.label} - ) + resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_presence_reason': 'Foo bar 2'}) assert resp.json['err'] == 0 assert [b['id'] for b in resp.json['data']] == [] @@ -493,13 +462,9 @@ 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_slug=check_type.slug) + booking = Booking.objects.create(event=event, user_was_present=flag, user_check_type_slug='foo-bar') app.authorization = ('Basic', ('john.doe', 'password')) resp = app.get('/api/booking/%s/' % booking.pk) @@ -634,7 +599,9 @@ def test_booking_patch_api_present(app, user, flag): assert resp.json['err'] == 0 -def test_booking_patch_api_absence_reason(app, user): +@mock.patch('chrono.api.serializers.get_agenda_check_types') +def test_booking_patch_api_absence_reason(check_types, app, user): + check_types.return_value = [] agenda = Agenda.objects.create(kind='events') event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10) booking = Booking.objects.create(event=event, user_was_present=False) @@ -648,44 +615,27 @@ def test_booking_patch_api_absence_reason(app, user): assert resp.json['err'] == 4 assert resp.json['err_desc'] == 'invalid payload' - 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 baz', kind='presence') - check_type_absence_disabled = CheckType.objects.create( - label='disabled', group=group, kind='absence', disabled=True - ) - resp = app.patch_json( '/api/booking/%s/' % booking.pk, params={'user_absence_reason': 'foobar'}, status=400 ) assert resp.json['err'] == 4 assert resp.json['err_desc'] == 'invalid payload' - # wrong kind - resp = app.patch_json( - '/api/booking/%s/' % booking.pk, params={'user_absence_reason': 'Foo baz'}, status=400 - ) - assert resp.json['err'] == 4 - assert resp.json['err_desc'] == 'invalid payload' - resp = app.patch_json( - '/api/booking/%s/' % booking.pk, params={'user_absence_reason': check_type_presence.slug}, status=400 - ) - assert resp.json['err'] == 4 - assert resp.json['err_desc'] == 'invalid payload' - # set check_type - agenda.check_type_group = group - agenda.save() + check_types.return_value = [ + CheckType(slug='foo-bar', label='Foo bar', kind='absence'), + CheckType(slug='foo-baz', label='Foo baz', kind='presence'), + ] # 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_slug == check_type_absence.slug - assert booking.user_check_type_label == check_type_absence.label + assert booking.user_check_type_slug == 'foo-bar' + assert booking.user_check_type_label == 'Foo bar' - # disabled + # unknown resp = app.patch_json( '/api/booking/%s/' % booking.pk, - params={'user_absence_reason': check_type_absence_disabled.slug}, + params={'user_presence_reason': 'unknown'}, status=400, ) assert resp.json['err'] == 4 @@ -708,14 +658,14 @@ def test_booking_patch_api_absence_reason(app, user): other_booking = Booking.objects.create(event=event) # it works also with slug - app.patch_json('/api/booking/%s/' % booking.pk, params={'user_absence_reason': check_type_absence.slug}) + app.patch_json('/api/booking/%s/' % booking.pk, params={'user_absence_reason': 'foo-bar'}) booking.refresh_from_db() - assert booking.user_check_type_slug == check_type_absence.slug - assert booking.user_check_type_label == check_type_absence.label + assert booking.user_check_type_slug == 'foo-bar' + assert booking.user_check_type_label == 'Foo bar' # all secondary bookings are updated assert list(booking.secondary_booking_set.values_list('user_check_type_slug', flat=True)) == [ - check_type_absence.slug, - check_type_absence.slug, + 'foo-bar', + 'foo-bar', ] other_booking.refresh_from_db() assert other_booking.user_check_type_slug is None # not changed @@ -724,7 +674,7 @@ def test_booking_patch_api_absence_reason(app, user): # user_was_present is True, can not set user_absence_reason Booking.objects.update(user_was_present=True) resp = app.patch_json( - '/api/booking/%s/' % booking.pk, params={'user_absence_reason': check_type_absence.slug}, status=400 + '/api/booking/%s/' % booking.pk, params={'user_absence_reason': 'foo-bar'}, status=400 ) assert resp.json['err'] == 6 assert resp.json['err_desc'] == 'user is marked as present, can not set absence reason' @@ -732,27 +682,25 @@ def test_booking_patch_api_absence_reason(app, user): # but it's ok if user_was_present is set to False resp = app.patch_json( '/api/booking/%s/' % booking.pk, - params={'user_absence_reason': check_type_absence.slug, 'user_was_present': False}, + params={'user_absence_reason': 'foo-bar', 'user_was_present': False}, ) assert resp.json['err'] == 0 booking.refresh_from_db() assert booking.user_was_present is False - assert booking.user_check_type_slug == check_type_absence.slug - assert booking.user_check_type_label == check_type_absence.label + assert booking.user_check_type_slug == 'foo-bar' + assert booking.user_check_type_label == 'Foo bar' # mark the event as checked event.checked = True event.save() - resp = app.patch_json( - '/api/booking/%s/' % booking.pk, params={'user_absence_reason': check_type_absence.slug} - ) + resp = app.patch_json('/api/booking/%s/' % booking.pk, params={'user_absence_reason': 'foo-bar'}) assert resp.json['err'] == 0 # now disable check update agenda.disable_check_update = True agenda.save() resp = app.patch_json( - '/api/booking/%s/' % booking.pk, params={'user_absence_reason': check_type_absence.slug}, status=400 + '/api/booking/%s/' % booking.pk, params={'user_absence_reason': 'foo-bar'}, status=400 ) assert resp.json['err'] == 5 assert resp.json['err_desc'] == 'event is marked as checked' @@ -760,7 +708,9 @@ def test_booking_patch_api_absence_reason(app, user): assert resp.json['err'] == 0 -def test_booking_patch_api_presence_reason(app, user): +@mock.patch('chrono.api.serializers.get_agenda_check_types') +def test_booking_patch_api_presence_reason(check_types, app, user): + check_types.return_value = [] agenda = Agenda.objects.create(kind='events') event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10) booking = Booking.objects.create(event=event, user_was_present=True) @@ -774,44 +724,27 @@ def test_booking_patch_api_presence_reason(app, user): assert resp.json['err'] == 4 assert resp.json['err_desc'] == 'invalid payload' - group = CheckTypeGroup.objects.create(label='Foo') - check_type_presence = CheckType.objects.create(group=group, label='Foo bar', kind='presence') - check_type_absence = CheckType.objects.create(group=group, label='Foo baz', kind='absence') - check_type_presence_disabled = CheckType.objects.create( - label='disabled', group=group, kind='presence', disabled=True - ) - resp = app.patch_json( '/api/booking/%s/' % booking.pk, params={'user_presence_reason': 'foobar'}, status=400 ) assert resp.json['err'] == 4 assert resp.json['err_desc'] == 'invalid payload' - # wrong kind - resp = app.patch_json( - '/api/booking/%s/' % booking.pk, params={'user_presence_reason': 'Foo baz'}, status=400 - ) - assert resp.json['err'] == 4 - assert resp.json['err_desc'] == 'invalid payload' - resp = app.patch_json( - '/api/booking/%s/' % booking.pk, params={'user_presence_reason': check_type_absence.slug}, status=400 - ) - assert resp.json['err'] == 4 - assert resp.json['err_desc'] == 'invalid payload' - # set check_type - agenda.check_type_group = group - agenda.save() + check_types.return_value = [ + CheckType(slug='foo-bar', label='Foo bar', kind='presence'), + CheckType(slug='foo-baz', label='Foo baz', kind='absence'), + ] # 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_slug == check_type_presence.slug - assert booking.user_check_type_label == check_type_presence.label + assert booking.user_check_type_slug == 'foo-bar' + assert booking.user_check_type_label == 'Foo bar' - # disabled + # unknown resp = app.patch_json( '/api/booking/%s/' % booking.pk, - params={'user_presence_reason': check_type_presence_disabled.slug}, + params={'user_presence_reason': 'unknown'}, status=400, ) assert resp.json['err'] == 4 @@ -834,14 +767,14 @@ def test_booking_patch_api_presence_reason(app, user): other_booking = Booking.objects.create(event=event) # it works also with slug - app.patch_json('/api/booking/%s/' % booking.pk, params={'user_presence_reason': check_type_presence.slug}) + app.patch_json('/api/booking/%s/' % booking.pk, params={'user_presence_reason': 'foo-bar'}) booking.refresh_from_db() - assert booking.user_check_type_slug == check_type_presence.slug - assert booking.user_check_type_label == check_type_presence.label + assert booking.user_check_type_slug == 'foo-bar' + assert booking.user_check_type_label == 'Foo bar' # all secondary bookings are updated assert list(booking.secondary_booking_set.values_list('user_check_type_slug', flat=True)) == [ - check_type_presence.slug, - check_type_presence.slug, + 'foo-bar', + 'foo-bar', ] other_booking.refresh_from_db() assert other_booking.user_check_type_slug is None # not changed @@ -850,7 +783,7 @@ def test_booking_patch_api_presence_reason(app, user): # user_was_present is False, can not set user_presence_reason Booking.objects.update(user_was_present=False) resp = app.patch_json( - '/api/booking/%s/' % booking.pk, params={'user_presence_reason': check_type_presence.slug}, status=400 + '/api/booking/%s/' % booking.pk, params={'user_presence_reason': 'foo-bar'}, status=400 ) assert resp.json['err'] == 6 assert resp.json['err_desc'] == 'user is marked as absent, can not set presence reason' @@ -858,27 +791,25 @@ def test_booking_patch_api_presence_reason(app, user): # but it's ok if user_was_present is set to True resp = app.patch_json( '/api/booking/%s/' % booking.pk, - params={'user_presence_reason': check_type_presence.slug, 'user_was_present': True}, + params={'user_presence_reason': 'foo-bar', 'user_was_present': True}, ) assert resp.json['err'] == 0 booking.refresh_from_db() assert booking.user_was_present is True - assert booking.user_check_type_slug == check_type_presence.slug - assert booking.user_check_type_label == check_type_presence.label + assert booking.user_check_type_slug == 'foo-bar' + assert booking.user_check_type_label == 'Foo bar' # mark the event as checked event.checked = True event.save() - resp = app.patch_json( - '/api/booking/%s/' % booking.pk, params={'user_presence_reason': check_type_presence.slug} - ) + resp = app.patch_json('/api/booking/%s/' % booking.pk, params={'user_presence_reason': 'foo-bar'}) assert resp.json['err'] == 0 # now disable check update agenda.disable_check_update = True agenda.save() resp = app.patch_json( - '/api/booking/%s/' % booking.pk, params={'user_presence_reason': check_type_presence.slug}, status=400 + '/api/booking/%s/' % booking.pk, params={'user_presence_reason': 'foo-bar'}, status=400 ) assert resp.json['err'] == 5 assert resp.json['err_desc'] == 'event is marked as checked' @@ -887,10 +818,7 @@ def test_booking_patch_api_presence_reason(app, user): def test_booking_patch_api_both_reasons(app, user): - group = CheckTypeGroup.objects.create(label='Foo') - CheckType.objects.create(group=group, label='Foo bar', kind='presence') - CheckType.objects.create(group=group, label='Foo baz', kind='absence') - agenda = Agenda.objects.create(kind='events', check_type_group=group) + agenda = Agenda.objects.create(kind='events') event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10) booking = Booking.objects.create(event=event)