From b2d3660d85d04730cd411d0eeeeecb152035226b Mon Sep 17 00:00:00 2001 From: Valentin Deniaud Date: Wed, 1 Dec 2021 14:20:20 +0100 Subject: [PATCH 3/4] api: filter by subscriptions in recurring events list (#58446) --- chrono/api/serializers.py | 1 + chrono/api/views.py | 15 +++++--- tests/api/test_datetimes.py | 68 +++++++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 5 deletions(-) diff --git a/chrono/api/serializers.py b/chrono/api/serializers.py index d22337cf..bfaaeec7 100644 --- a/chrono/api/serializers.py +++ b/chrono/api/serializers.py @@ -205,6 +205,7 @@ class AgendaOrSubscribedSlugsMixin(metaclass=serializers.SerializerMetaclass): subscribed = CommaSeparatedStringField( required=False, child=serializers.SlugField(max_length=160, allow_blank=False) ) + user_external_id = serializers.CharField(required=False, max_length=250, allow_blank=False) def validate(self, attrs): super().validate(attrs) diff --git a/chrono/api/views.py b/chrono/api/views.py index 8bfcbec5..87f9dacb 100644 --- a/chrono/api/views.py +++ b/chrono/api/views.py @@ -1060,10 +1060,12 @@ class RecurringEventsList(APIView): if not settings.ENABLE_RECURRING_EVENT_BOOKING: raise Http404() - agenda_slugs = get_agendas_from_request(request) - agendas = get_objects_from_slugs(agenda_slugs, qs=Agenda.objects.filter(kind='events')) - agendas = Agenda.prefetch_recurring_events(agendas) + serializer = serializers.AgendaOrSubscribedSlugsSerializer(data=request.query_params) + if not serializer.is_valid(): + raise APIErrorBadRequest(N_('invalid payload'), errors=serializer.errors) + data = serializer.validated_data + agendas = Agenda.prefetch_recurring_events(data['agendas']) events = [] for agenda in agendas: for event in agenda.get_open_recurring_events(): @@ -1072,8 +1074,11 @@ class RecurringEventsList(APIView): event.day = day events.append(event) - agenda_querystring_indexes = {agenda_slug: i for i, agenda_slug in enumerate(agenda_slugs)} - events.sort(key=lambda event: (event.day, agenda_querystring_indexes[event.agenda.slug])) + if 'agendas' in request.query_params: + agenda_querystring_indexes = { + agenda_slug: i for i, agenda_slug in enumerate(data['agenda_slugs']) + } + events.sort(key=lambda event: (event.day, agenda_querystring_indexes[event.agenda.slug])) return Response( { diff --git a/tests/api/test_datetimes.py b/tests/api/test_datetimes.py index 824897d2..27d91b81 100644 --- a/tests/api/test_datetimes.py +++ b/tests/api/test_datetimes.py @@ -1461,6 +1461,74 @@ def test_recurring_events_api_list_multiple_agendas_queries(app): assert len(ctx.captured_queries) == 3 +@pytest.mark.freeze_time('2021-09-06 12:00') +def test_recurring_events_api_list_subscribed(app, user): + category = Category.objects.create(label='Category A') + first_agenda = Agenda.objects.create(label='First agenda', kind='events', category=category) + category = Category.objects.create(label='Category B') + second_agenda = Agenda.objects.create(label='Second agenda', kind='events', category=category) + Event.objects.create( + slug='event', + start_datetime=now(), + recurrence_days=[0, 1, 3, 4], # Monday, Tuesday, Thursday, Friday + places=2, + waiting_list_places=1, + agenda=first_agenda, + recurrence_end_date=now() + datetime.timedelta(days=364), + ) + Event.objects.create( + slug='sunday-event', + start_datetime=now(), + recurrence_days=[6], + places=2, + waiting_list_places=1, + agenda=second_agenda, + recurrence_end_date=now() + datetime.timedelta(days=364), + ) + + Subscription.objects.create( + agenda=first_agenda, + user_external_id='xxx', + date_start=now(), + date_end=now() + datetime.timedelta(days=30), + ) + resp = app.get('/api/agendas/recurring-events/?user_external_id=xxx&subscribed=all') + assert len(resp.json['data']) == 4 + assert all(event['id'].startswith('first-agenda') for event in resp.json['data']) + + resp = app.get('/api/agendas/recurring-events/?user_external_id=xxx&subscribed=category-a') + assert len(resp.json['data']) == 4 + assert all(event['id'].startswith('first-agenda') for event in resp.json['data']) + + resp = app.get('/api/agendas/recurring-events/?user_external_id=xxx&subscribed=category-b') + assert len(resp.json['data']) == 0 + + Subscription.objects.create( + agenda=second_agenda, + user_external_id='xxx', + date_start=now(), + date_end=now() + datetime.timedelta(days=30), + ) + resp = app.get('/api/agendas/recurring-events/?user_external_id=xxx&subscribed=all') + assert len(resp.json['data']) == 5 + + resp = app.get('/api/agendas/recurring-events/?user_external_id=xxx&subscribed=category-b') + assert len(resp.json['data']) == 1 + + # other user + resp = app.get('/api/agendas/recurring-events/?user_external_id=yyy&subscribed=all') + assert len(resp.json['data']) == 0 + + Subscription.objects.create( + agenda=second_agenda, + user_external_id='yyy', + date_start=now(), + date_end=now() + datetime.timedelta(days=30), + ) + resp = app.get('/api/agendas/recurring-events/?user_external_id=yyy&subscribed=all') + assert len(resp.json['data']) == 1 + + @pytest.mark.freeze_time('2021-05-06 14:00') def test_datetimes_multiple_agendas(app): first_agenda = Agenda.objects.create( -- 2.30.2