api: show_past_events for agendas/datetimes endpoint (#56615)
This commit is contained in:
parent
23dd874fdc
commit
f07d2bb8b2
|
@ -654,6 +654,8 @@ class Agenda(models.Model):
|
|||
|
||||
if prefetched_queryset:
|
||||
entries = self.prefetched_events
|
||||
# we may have past events
|
||||
entries = [e for e in entries if e.start_datetime >= localtime(now())]
|
||||
else:
|
||||
# recurring events are never opened
|
||||
entries = self.event_set.filter(recurrence_days__isnull=True)
|
||||
|
@ -702,23 +704,29 @@ class Agenda(models.Model):
|
|||
|
||||
def get_past_events(
|
||||
self,
|
||||
prefetched_queryset=False,
|
||||
min_start=None,
|
||||
max_start=None,
|
||||
user_external_id=None,
|
||||
):
|
||||
assert self.kind == 'events'
|
||||
|
||||
# recurring events are never opened
|
||||
entries = self.event_set.filter(recurrence_days__isnull=True)
|
||||
# exclude canceled events except for event recurrences
|
||||
entries = entries.filter(Q(cancelled=False) | Q(primary_event__isnull=False))
|
||||
# we want only past events
|
||||
entries = entries.filter(start_datetime__lt=localtime(now()))
|
||||
if prefetched_queryset:
|
||||
entries = self.prefetched_events
|
||||
# we may have future events
|
||||
entries = [e for e in entries if e.start_datetime < localtime(now())]
|
||||
else:
|
||||
# no recurring events
|
||||
entries = self.event_set.filter(recurrence_days__isnull=True)
|
||||
# exclude canceled events except for event recurrences
|
||||
entries = entries.filter(Q(cancelled=False) | Q(primary_event__isnull=False))
|
||||
# we want only past events
|
||||
entries = entries.filter(start_datetime__lt=localtime(now()))
|
||||
|
||||
if min_start:
|
||||
if min_start and not prefetched_queryset:
|
||||
entries = entries.filter(start_datetime__gte=min_start)
|
||||
|
||||
if max_start:
|
||||
if max_start and not prefetched_queryset:
|
||||
entries = entries.filter(start_datetime__lt=max_start)
|
||||
|
||||
if user_external_id:
|
||||
|
@ -729,6 +737,7 @@ class Agenda(models.Model):
|
|||
entries,
|
||||
min_start,
|
||||
min(max_start or localtime(now()), localtime(now())),
|
||||
prefetched_queryset=prefetched_queryset,
|
||||
)
|
||||
|
||||
return entries
|
||||
|
@ -870,16 +879,23 @@ class Agenda(models.Model):
|
|||
]
|
||||
|
||||
@staticmethod
|
||||
def prefetch_events_and_exceptions(qs, user_external_id=None):
|
||||
def prefetch_events_and_exceptions(
|
||||
qs, user_external_id=None, show_past_events=False, min_start=None, max_start=None
|
||||
):
|
||||
event_queryset = Event.objects.filter(
|
||||
Q(publication_date__isnull=True) | Q(publication_date__lte=localtime(now()).date()),
|
||||
recurrence_days__isnull=True,
|
||||
cancelled=False,
|
||||
start_datetime__gte=localtime(now()),
|
||||
).order_by()
|
||||
|
||||
if user_external_id:
|
||||
event_queryset = Event.annotate_queryset_for_user(event_queryset, user_external_id)
|
||||
if not show_past_events:
|
||||
event_queryset = event_queryset.filter(start_datetime__gte=localtime(now()))
|
||||
if min_start:
|
||||
event_queryset = event_queryset.filter(start_datetime__gte=min_start)
|
||||
if max_start:
|
||||
event_queryset = event_queryset.filter(start_datetime__lt=max_start)
|
||||
|
||||
recurring_event_queryset = Event.objects.filter(
|
||||
Q(publication_date__isnull=True) | Q(publication_date__lte=localtime(now()).date()),
|
||||
|
|
|
@ -133,6 +133,7 @@ class MultipleAgendasDatetimesSerializer(DatetimesSerializer):
|
|||
agendas = CommaSeparatedStringField(
|
||||
required=True, child=serializers.SlugField(max_length=160, allow_blank=False)
|
||||
)
|
||||
show_past_events = serializers.BooleanField(default=False)
|
||||
|
||||
|
||||
class EventSerializer(serializers.ModelSerializer):
|
||||
|
|
|
@ -842,27 +842,31 @@ class MultipleAgendasDatetimes(APIView):
|
|||
)
|
||||
payload = serializer.validated_data
|
||||
|
||||
if 'events' in payload:
|
||||
raise APIError(
|
||||
_('events parameter is not supported'),
|
||||
err_class='events parameter is not supported',
|
||||
http_status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
agenda_slugs = payload['agendas']
|
||||
agendas = get_objects_from_slugs(agenda_slugs, qs=Agenda.objects.filter(kind='events'))
|
||||
|
||||
user_external_id = payload.get('user_external_id') or payload.get('exclude_user_external_id')
|
||||
disable_booked = bool(payload.get('exclude_user_external_id'))
|
||||
agendas = Agenda.prefetch_events_and_exceptions(agendas, user_external_id=user_external_id)
|
||||
show_past_events = bool(payload.get('show_past_events'))
|
||||
agendas = Agenda.prefetch_events_and_exceptions(
|
||||
agendas,
|
||||
user_external_id=user_external_id,
|
||||
show_past_events=show_past_events,
|
||||
min_start=payload.get('date_start'),
|
||||
max_start=payload.get('date_end'),
|
||||
)
|
||||
|
||||
entries = []
|
||||
for agenda in agendas:
|
||||
if show_past_events:
|
||||
entries.extend(
|
||||
agenda.get_past_events(
|
||||
prefetched_queryset=True,
|
||||
)
|
||||
)
|
||||
entries.extend(
|
||||
agenda.get_open_events(
|
||||
prefetched_queryset=True,
|
||||
min_start=payload.get('date_start'),
|
||||
max_start=payload.get('date_end'),
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
@ -1462,8 +1462,53 @@ def test_datetimes_multiple_agendas(app):
|
|||
resp = app.get('/api/agendas/datetimes/', params={'agendas': 'first-agenda,xxx,yyy'}, status=400)
|
||||
assert resp.json['err_desc'] == 'invalid slugs: xxx, yyy'
|
||||
|
||||
# no support for past events
|
||||
resp = app.get('/api/agendas/datetimes/', params={'agendas': agenda_slugs, 'events': 'past'}, status=400)
|
||||
# it's possible to show past events
|
||||
resp = app.get('/api/agendas/datetimes/', params={'agendas': agenda_slugs, 'show_past_events': True})
|
||||
assert len(resp.json['data']) == 2
|
||||
assert resp.json['data'][0]['id'] == 'first-agenda@event'
|
||||
assert resp.json['data'][1]['id'] == 'second-agenda@event'
|
||||
|
||||
Event.objects.create(
|
||||
slug='event-in-past',
|
||||
start_datetime=now() - datetime.timedelta(days=5),
|
||||
places=5,
|
||||
agenda=first_agenda,
|
||||
)
|
||||
Event.objects.create( # not visible in datetimes api
|
||||
slug='recurring-in-past',
|
||||
start_datetime=now() - datetime.timedelta(days=5),
|
||||
recurrence_days=[localtime().weekday()],
|
||||
recurrence_end_date=now() - datetime.timedelta(days=5),
|
||||
places=5,
|
||||
agenda=first_agenda,
|
||||
)
|
||||
|
||||
resp = app.get('/api/agendas/datetimes/', params={'agendas': agenda_slugs, 'show_past_events': True})
|
||||
assert len(resp.json['data']) == 3
|
||||
assert resp.json['data'][0]['id'] == 'first-agenda@event-in-past'
|
||||
assert resp.json['data'][0]['disabled'] is True
|
||||
assert resp.json['data'][1]['id'] == 'first-agenda@event'
|
||||
assert resp.json['data'][1]['disabled'] is False
|
||||
assert resp.json['data'][2]['id'] == 'second-agenda@event'
|
||||
assert resp.json['data'][2]['disabled'] is False
|
||||
|
||||
date_start = localtime() - datetime.timedelta(days=4)
|
||||
resp = app.get(
|
||||
'/api/agendas/datetimes/',
|
||||
params={'agendas': agenda_slugs, 'date_start': date_start, 'show_past_events': True},
|
||||
)
|
||||
assert len(resp.json['data']) == 2
|
||||
assert resp.json['data'][0]['id'] == 'first-agenda@event'
|
||||
assert resp.json['data'][1]['id'] == 'second-agenda@event'
|
||||
|
||||
date_end = localtime() + datetime.timedelta(days=5, hours=1)
|
||||
resp = app.get(
|
||||
'/api/agendas/datetimes/',
|
||||
params={'agendas': agenda_slugs, 'date_end': date_end, 'show_past_events': True},
|
||||
)
|
||||
assert len(resp.json['data']) == 2
|
||||
assert resp.json['data'][0]['id'] == 'first-agenda@event-in-past'
|
||||
assert resp.json['data'][1]['id'] == 'first-agenda@event'
|
||||
|
||||
|
||||
@pytest.mark.freeze_time('2021-05-06 14:00')
|
||||
|
@ -1474,9 +1519,11 @@ def test_datetimes_multiple_agendas_sort(app):
|
|||
second_agenda = Agenda.objects.create(label='Second agenda', kind='events')
|
||||
Desk.objects.create(agenda=second_agenda, slug='_exceptions_holder')
|
||||
Event.objects.create(label='09-05', start_datetime=now().replace(day=9), places=5, agenda=second_agenda)
|
||||
Event.objects.create(label='04-05', start_datetime=now().replace(day=4), places=5, agenda=second_agenda)
|
||||
third_agenda = Agenda.objects.create(label='Third agenda', kind='events')
|
||||
Desk.objects.create(agenda=third_agenda, slug='_exceptions_holder')
|
||||
Event.objects.create(label='09-05', start_datetime=now().replace(day=9), places=5, agenda=third_agenda)
|
||||
Event.objects.create(label='04-05', start_datetime=now().replace(day=4), places=5, agenda=third_agenda)
|
||||
|
||||
# check events are ordered by start_datetime and then by agenda order in querystring
|
||||
agenda_slugs = ','.join((first_agenda.slug, third_agenda.slug, second_agenda.slug))
|
||||
|
@ -1486,16 +1533,28 @@ def test_datetimes_multiple_agendas_sort(app):
|
|||
assert resp.json['data'][1]['id'] == 'second-agenda@09-05'
|
||||
assert resp.json['data'][2]['id'] == 'first-agenda@10-05'
|
||||
|
||||
resp = app.get('/api/agendas/datetimes/', params={'agendas': agenda_slugs, 'show_past_events': True})
|
||||
assert len(resp.json['data']) == 5
|
||||
assert resp.json['data'][0]['id'] == 'third-agenda@04-05'
|
||||
assert resp.json['data'][1]['id'] == 'second-agenda@04-05'
|
||||
assert resp.json['data'][2]['id'] == 'third-agenda@09-05'
|
||||
assert resp.json['data'][3]['id'] == 'second-agenda@09-05'
|
||||
assert resp.json['data'][4]['id'] == 'first-agenda@10-05'
|
||||
|
||||
|
||||
@pytest.mark.freeze_time('2021-05-06 14:00')
|
||||
def test_datetimes_multiple_agendas_queries(app):
|
||||
for i in range(10):
|
||||
agenda = Agenda.objects.create(label=str(i), kind='events')
|
||||
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
||||
Event.objects.create(start_datetime=now() - datetime.timedelta(days=5), places=5, agenda=agenda)
|
||||
Event.objects.create(start_datetime=now() + datetime.timedelta(days=5), places=5, agenda=agenda)
|
||||
Event.objects.create(start_datetime=now() + datetime.timedelta(days=5), places=5, agenda=agenda)
|
||||
|
||||
with CaptureQueriesContext(connection) as ctx:
|
||||
resp = app.get('/api/agendas/datetimes/', params={'agendas': ','.join(str(i) for i in range(10))})
|
||||
assert len(resp.json['data']) == 20
|
||||
resp = app.get(
|
||||
'/api/agendas/datetimes/',
|
||||
params={'agendas': ','.join(str(i) for i in range(10)), 'show_past_events': True},
|
||||
)
|
||||
assert len(resp.json['data']) == 30
|
||||
assert len(ctx.captured_queries) == 7
|
||||
|
|
Loading…
Reference in New Issue