api: make recurring events list endpoint work with multiple agendas (#57957)
This commit is contained in:
parent
84f5dbc4c8
commit
bb781f8c83
|
@ -21,6 +21,7 @@ from . import views
|
|||
urlpatterns = [
|
||||
url(r'^agenda/$', views.agendas),
|
||||
url(r'^agendas/datetimes/$', views.agendas_datetimes, name='api-agendas-datetimes'),
|
||||
url(r'^agendas/recurring-events/$', views.recurring_events_list, name='api-agenda-recurring-events'),
|
||||
url(
|
||||
r'^agendas/events/fillslots/$',
|
||||
views.agendas_events_fillslots,
|
||||
|
@ -39,11 +40,6 @@ urlpatterns = [
|
|||
views.events_fillslots,
|
||||
name='api-agenda-events-fillslots',
|
||||
),
|
||||
url(
|
||||
r'^agenda/(?P<agenda_identifier>[\w-]+)/recurring-events/$',
|
||||
views.recurring_events_list,
|
||||
name='api-agenda-recurring-events',
|
||||
),
|
||||
url(
|
||||
r'^agenda/(?P<agenda_identifier>[\w-]+)/recurring-events/fillslots/$',
|
||||
views.recurring_fillslots,
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import collections
|
||||
import copy
|
||||
import datetime
|
||||
import itertools
|
||||
import uuid
|
||||
|
@ -1073,28 +1074,38 @@ class RecurringEventsList(APIView):
|
|||
if not settings.ENABLE_RECURRING_EVENT_BOOKING:
|
||||
raise Http404()
|
||||
|
||||
agenda = get_object_or_404(Agenda, slug=agenda_identifier, kind='events')
|
||||
entries = agenda.get_open_recurring_events()
|
||||
agenda_slugs = get_agendas_from_request(request)
|
||||
agendas = get_objects_from_slugs(agenda_slugs, qs=Agenda.objects.filter(kind='events'))
|
||||
|
||||
events = []
|
||||
for event in entries:
|
||||
for day in event.recurrence_days:
|
||||
slug = '%s:%s' % (event.slug, day)
|
||||
events.append(
|
||||
for agenda in agendas:
|
||||
for event in agenda.get_open_recurring_events():
|
||||
for day in event.recurrence_days:
|
||||
event = copy.copy(event)
|
||||
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]))
|
||||
|
||||
return Response(
|
||||
{
|
||||
'data': [
|
||||
{
|
||||
'id': slug,
|
||||
'text': get_event_text(event, agenda, day),
|
||||
'id': '%s@%s:%s' % (event.agenda.slug, event.slug, event.day),
|
||||
'text': get_event_text(event, event.agenda, event.day),
|
||||
'label': event.label or '',
|
||||
'day': WEEKDAYS[day].capitalize(),
|
||||
'day': WEEKDAYS[event.day].capitalize(),
|
||||
'date': format_response_date(event.start_datetime),
|
||||
'datetime': format_response_datetime(event.start_datetime),
|
||||
'description': event.description,
|
||||
'pricing': event.pricing,
|
||||
'url': event.url,
|
||||
}
|
||||
)
|
||||
|
||||
return Response({'data': events})
|
||||
for event in events
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
recurring_events_list = RecurringEventsList.as_view()
|
||||
|
|
|
@ -1337,6 +1337,7 @@ def test_past_datetimes_recurring_event(app, user):
|
|||
def test_recurring_events_api_list(app, freezer):
|
||||
freezer.move_to('2021-09-06 12:00')
|
||||
agenda = Agenda.objects.create(label='Foo bar', kind='events')
|
||||
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
||||
Event.objects.create(label='Normal event', start_datetime=now(), places=5, agenda=agenda)
|
||||
event = Event.objects.create(
|
||||
label='Example Event',
|
||||
|
@ -1346,10 +1347,10 @@ def test_recurring_events_api_list(app, freezer):
|
|||
agenda=agenda,
|
||||
)
|
||||
|
||||
resp = app.get('/api/agenda/xxx/recurring-events/', status=404)
|
||||
resp = app.get('/api/agendas/recurring-events/', status=400)
|
||||
|
||||
# recurring events without recurrence_end_date are not bookable
|
||||
resp = app.get('/api/agenda/%s/recurring-events/' % agenda.slug)
|
||||
resp = app.get('/api/agendas/recurring-events/?agendas=%s' % agenda.slug)
|
||||
assert len(resp.json['data']) == 0
|
||||
|
||||
event.recurrence_end_date = now() + datetime.timedelta(days=30)
|
||||
|
@ -1364,35 +1365,98 @@ def test_recurring_events_api_list(app, freezer):
|
|||
recurrence_end_date=now() + datetime.timedelta(days=45),
|
||||
)
|
||||
|
||||
resp = app.get('/api/agenda/%s/recurring-events/' % agenda.slug)
|
||||
resp = app.get('/api/agendas/recurring-events/?agendas=%s' % agenda.slug)
|
||||
assert len(resp.json['data']) == 4
|
||||
assert resp.json['data'][0]['id'] == 'example-event:0'
|
||||
assert resp.json['data'][0]['id'] == 'foo-bar@example-event:0'
|
||||
assert resp.json['data'][0]['text'] == 'Monday: Example Event'
|
||||
assert resp.json['data'][0]['label'] == 'Example Event'
|
||||
assert resp.json['data'][0]['day'] == 'Monday'
|
||||
assert resp.json['data'][1]['id'] == 'example-event:3'
|
||||
assert resp.json['data'][1]['text'] == 'Thursday: Example Event'
|
||||
assert resp.json['data'][1]['label'] == 'Example Event'
|
||||
assert resp.json['data'][1]['day'] == 'Thursday'
|
||||
assert resp.json['data'][2]['id'] == 'example-event:4'
|
||||
assert resp.json['data'][2]['text'] == 'Friday: Example Event'
|
||||
assert resp.json['data'][1]['id'] == 'foo-bar@other:1'
|
||||
assert resp.json['data'][1]['text'] == 'Tuesday: Other'
|
||||
assert resp.json['data'][1]['label'] == 'Other'
|
||||
assert resp.json['data'][1]['day'] == 'Tuesday'
|
||||
assert resp.json['data'][2]['id'] == 'foo-bar@example-event:3'
|
||||
assert resp.json['data'][2]['text'] == 'Thursday: Example Event'
|
||||
assert resp.json['data'][2]['label'] == 'Example Event'
|
||||
assert resp.json['data'][2]['day'] == 'Friday'
|
||||
assert resp.json['data'][3]['id'] == 'other:1'
|
||||
assert resp.json['data'][3]['text'] == 'Tuesday: Other'
|
||||
assert resp.json['data'][3]['label'] == 'Other'
|
||||
assert resp.json['data'][3]['day'] == 'Tuesday'
|
||||
assert resp.json['data'][2]['day'] == 'Thursday'
|
||||
assert resp.json['data'][3]['id'] == 'foo-bar@example-event:4'
|
||||
assert resp.json['data'][3]['text'] == 'Friday: Example Event'
|
||||
assert resp.json['data'][3]['label'] == 'Example Event'
|
||||
assert resp.json['data'][3]['day'] == 'Friday'
|
||||
|
||||
event.publication_datetime = now() + datetime.timedelta(days=2)
|
||||
event.save()
|
||||
resp = app.get('/api/agenda/%s/recurring-events/' % agenda.slug)
|
||||
resp = app.get('/api/agendas/recurring-events/?agendas=%s' % agenda.slug)
|
||||
assert len(resp.json['data']) == 1
|
||||
|
||||
freezer.move_to(event.recurrence_end_date)
|
||||
resp = app.get('/api/agenda/%s/recurring-events/' % agenda.slug)
|
||||
resp = app.get('/api/agendas/recurring-events/?agendas=%s' % agenda.slug)
|
||||
assert len(resp.json['data']) == 1
|
||||
|
||||
|
||||
@pytest.mark.freeze_time('2021-09-06 12:00')
|
||||
def test_recurring_events_api_list_multiple_agendas(app):
|
||||
agenda = Agenda.objects.create(label='First Agenda', kind='events')
|
||||
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
||||
start, end = now(), now() + datetime.timedelta(days=30)
|
||||
Event.objects.create(
|
||||
label='A',
|
||||
start_datetime=start,
|
||||
places=2,
|
||||
recurrence_end_date=end,
|
||||
recurrence_days=[0, 2, 5],
|
||||
agenda=agenda,
|
||||
)
|
||||
Event.objects.create(
|
||||
label='B', start_datetime=start, places=2, recurrence_end_date=end, recurrence_days=[1], agenda=agenda
|
||||
)
|
||||
agenda2 = Agenda.objects.create(label='Second Agenda', kind='events')
|
||||
Desk.objects.create(agenda=agenda2, slug='_exceptions_holder')
|
||||
Event.objects.create(
|
||||
label='C',
|
||||
start_datetime=start,
|
||||
places=2,
|
||||
recurrence_end_date=end,
|
||||
recurrence_days=[2, 3],
|
||||
agenda=agenda2,
|
||||
)
|
||||
|
||||
resp = app.get('/api/agendas/recurring-events/?agendas=first-agenda,second-agenda')
|
||||
event_ids = [x['id'] for x in resp.json['data']]
|
||||
assert event_ids == [
|
||||
'first-agenda@a:0',
|
||||
'first-agenda@b:1',
|
||||
'first-agenda@a:2',
|
||||
'second-agenda@c:2',
|
||||
'second-agenda@c:3',
|
||||
'first-agenda@a:5',
|
||||
]
|
||||
assert event_ids.index('first-agenda@a:2') < event_ids.index('second-agenda@c:2')
|
||||
|
||||
# sorting depends on querystring order
|
||||
resp = app.get('/api/agendas/recurring-events/?agendas=second-agenda,first-agenda')
|
||||
event_ids = [x['id'] for x in resp.json['data']]
|
||||
assert event_ids.index('first-agenda@a:2') > event_ids.index('second-agenda@c:2')
|
||||
|
||||
resp = app.get('/api/agendas/recurring-events/?agendas=second-agenda')
|
||||
assert [x['id'] for x in resp.json['data']] == ['second-agenda@c:2', 'second-agenda@c:3']
|
||||
|
||||
|
||||
@pytest.mark.freeze_time('2021-09-06 12:00')
|
||||
def test_recurring_events_api_list_multiple_agendas_queries(app):
|
||||
for i in range(20):
|
||||
agenda = Agenda.objects.create(slug=f'{i}', kind='events')
|
||||
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
|
||||
)
|
||||
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) == 23
|
||||
|
||||
|
||||
@pytest.mark.freeze_time('2021-05-06 14:00')
|
||||
def test_datetimes_multiple_agendas(app):
|
||||
first_agenda = Agenda.objects.create(
|
||||
|
|
Loading…
Reference in New Issue