api: filter by subscriptions in recurring events list (#58446)
This commit is contained in:
parent
2e7d87ffe7
commit
270daa2202
|
@ -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)
|
||||
|
|
|
@ -1084,10 +1084,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']).select_related('category')
|
||||
events = []
|
||||
for agenda in agendas:
|
||||
for event in agenda.get_open_recurring_events():
|
||||
|
@ -1096,8 +1098,24 @@ 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], event.slug)
|
||||
)
|
||||
elif 'subscribed' in request.query_params:
|
||||
category_querystring_indexes = {category: i for i, category in enumerate(data['subscribed'])}
|
||||
sort_by_category = bool(data['subscribed'] != ['all'])
|
||||
events.sort(
|
||||
key=lambda event: (
|
||||
event.day,
|
||||
category_querystring_indexes[event.agenda.category.slug] if sort_by_category else None,
|
||||
event.agenda.slug,
|
||||
event.slug,
|
||||
)
|
||||
)
|
||||
|
||||
return Response(
|
||||
{
|
||||
|
|
|
@ -1448,18 +1448,122 @@ def test_recurring_events_api_list_multiple_agendas(app):
|
|||
|
||||
@pytest.mark.freeze_time('2021-09-06 12:00')
|
||||
def test_recurring_events_api_list_multiple_agendas_queries(app):
|
||||
category = Category.objects.create(label='Category A')
|
||||
for i in range(20):
|
||||
agenda = Agenda.objects.create(slug=f'{i}', kind='events')
|
||||
agenda = Agenda.objects.create(slug=f'{i}', kind='events', category=category)
|
||||
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
||||
start, end = now(), now() + datetime.timedelta(days=30)
|
||||
Event.objects.create(
|
||||
start_datetime=start, places=2, recurrence_end_date=end, recurrence_days=[1, 2], agenda=agenda
|
||||
)
|
||||
Subscription.objects.create(
|
||||
agenda=agenda,
|
||||
user_external_id='xxx',
|
||||
date_start=now(),
|
||||
date_end=now() + datetime.timedelta(days=60),
|
||||
)
|
||||
with CaptureQueriesContext(connection) as ctx:
|
||||
resp = app.get('/api/agendas/recurring-events/?agendas=%s' % ','.join(str(i) for i in range(20)))
|
||||
assert len(resp.json['data']) == 40
|
||||
assert len(ctx.captured_queries) == 3
|
||||
|
||||
with CaptureQueriesContext(connection) as ctx:
|
||||
resp = app.get('/api/agendas/recurring-events/?subscribed=category-a&user_external_id=xxx')
|
||||
assert len(resp.json['data']) == 40
|
||||
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, 6], # Monday, Tuesday, Thursday, Friday
|
||||
places=2,
|
||||
agenda=first_agenda,
|
||||
recurrence_end_date=now() + datetime.timedelta(days=364),
|
||||
)
|
||||
Event.objects.create(
|
||||
slug='sunday-event',
|
||||
start_datetime=now(),
|
||||
recurrence_days=[5],
|
||||
places=2,
|
||||
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
|
||||
|
||||
# events are sorted by day
|
||||
assert [x['id'] for x in resp.json['data']] == [
|
||||
'first-agenda@event:0',
|
||||
'first-agenda@event:1',
|
||||
'first-agenda@event:3',
|
||||
'second-agenda@sunday-event:5',
|
||||
'first-agenda@event:6',
|
||||
]
|
||||
|
||||
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
|
||||
|
||||
# sorting depends on querystring order
|
||||
Event.objects.create(
|
||||
slug='event',
|
||||
start_datetime=now(),
|
||||
recurrence_days=[0],
|
||||
places=2,
|
||||
agenda=second_agenda,
|
||||
recurrence_end_date=now() + datetime.timedelta(days=364),
|
||||
)
|
||||
resp = app.get('/api/agendas/recurring-events/?subscribed=category-a,category-b&user_external_id=xxx')
|
||||
event_ids = [x['id'] for x in resp.json['data']]
|
||||
assert event_ids.index('first-agenda@event:0') < event_ids.index('second-agenda@event:0')
|
||||
|
||||
resp = app.get('/api/agendas/recurring-events/?subscribed=category-b,category-a&user_external_id=xxx')
|
||||
event_ids = [x['id'] for x in resp.json['data']]
|
||||
assert event_ids.index('first-agenda@event:0') > event_ids.index('second-agenda@event:0')
|
||||
|
||||
|
||||
@pytest.mark.freeze_time('2021-05-06 14:00')
|
||||
def test_datetimes_multiple_agendas(app):
|
||||
|
|
Loading…
Reference in New Issue