api: fix get_open_events & get_past_events with subscribed (#62046)

This commit is contained in:
Lauréline Guérin 2022-02-22 14:06:13 +01:00
parent c97a43feb6
commit 56300815e7
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
4 changed files with 212 additions and 9 deletions

View File

@ -665,6 +665,7 @@ class Agenda(models.Model):
user_external_id=None,
bypass_delays=False,
show_out_of_minimal_delay=False,
show_only_subscribed=False,
):
assert self.kind == 'events'
@ -708,13 +709,23 @@ class Agenda(models.Model):
entries = Event.annotate_queryset_for_user(entries, user_external_id)
if max_start:
min_start = max(min_start or localtime(now()), localtime(now()))
entries = self.add_event_recurrences(
entries,
max(min_start or localtime(now()), localtime(now())),
min_start,
max_start,
include_full=include_full,
prefetched_queryset=prefetched_queryset,
)
if show_only_subscribed:
filtered_entries = []
for e in entries:
e_start_date = localtime(e.start_datetime).date()
for s in self.prefetched_subscriptions:
if s.date_start <= e_start_date < s.date_end:
filtered_entries.append(e)
break
entries = filtered_entries
return entries
@ -724,6 +735,7 @@ class Agenda(models.Model):
min_start=None,
max_start=None,
user_external_id=None,
show_only_subscribed=False,
):
assert self.kind == 'events'
@ -755,6 +767,15 @@ class Agenda(models.Model):
min(max_start or localtime(now()), localtime(now())),
prefetched_queryset=prefetched_queryset,
)
if show_only_subscribed:
filtered_entries = []
for e in entries:
e_start_date = localtime(e.start_datetime).date()
for s in self.prefetched_subscriptions:
if s.date_start <= e_start_date < s.date_end:
filtered_entries.append(e)
break
entries = filtered_entries
return entries
@ -946,6 +967,13 @@ class Agenda(models.Model):
agenda__subscriptions__date_start__lte=F('start_datetime'),
agenda__subscriptions__date_end__gt=F('start_datetime'),
)
qs = qs.prefetch_related(
Prefetch(
'subscriptions',
queryset=Subscription.objects.filter(user_external_id=user_external_id),
to_attr='prefetched_subscriptions',
)
)
exceptions_desk = Desk.objects.filter(slug='_exceptions_holder').prefetch_related(
'unavailability_calendars'

View File

@ -907,6 +907,7 @@ class MultipleAgendasDatetimes(APIView):
entries.extend(
agenda.get_past_events(
prefetched_queryset=True,
show_only_subscribed=bool('subscribed' in payload),
min_start=payload.get('date_start'),
max_start=payload.get('date_end'),
)
@ -914,10 +915,11 @@ class MultipleAgendasDatetimes(APIView):
entries.extend(
agenda.get_open_events(
prefetched_queryset=True,
min_start=payload.get('date_start'),
max_start=payload.get('date_end'),
bypass_delays=payload.get('bypass_delays'),
show_out_of_minimal_delay=show_past_events,
show_only_subscribed=bool('subscribed' in payload),
min_start=payload.get('date_start'),
max_start=payload.get('date_end'),
)
)

View File

@ -2002,7 +2002,7 @@ def test_datetimes_multiple_agendas_queries(app):
params={'subscribed': 'all', 'user_external_id': 'xxx', 'show_past_events': True},
)
assert len(resp.json['data']) == 30
assert len(ctx.captured_queries) == 7
assert len(ctx.captured_queries) == 8
with CaptureQueriesContext(connection) as ctx:
resp = app.get(
@ -2010,7 +2010,7 @@ def test_datetimes_multiple_agendas_queries(app):
params={'subscribed': 'category-a', 'user_external_id': 'xxx', 'show_past_events': True},
)
assert len(resp.json['data']) == 30
assert len(ctx.captured_queries) == 7
assert len(ctx.captured_queries) == 8
@pytest.mark.freeze_time('2021-05-06 14:00')
@ -2067,11 +2067,41 @@ def test_datetimes_multiple_agendas_subscribed(app):
resp = app.get('/api/agendas/datetimes/', params={'subscribed': 'all', 'user_external_id': 'xxx'})
assert len(resp.json['data']) == 0
subscription.date_start = now() + datetime.timedelta(days=10)
subscription.date_end = now() + datetime.timedelta(days=21) # second event on subscription's last day
subscription.save()
resp = app.get('/api/agendas/datetimes/', params={'subscribed': 'all', 'user_external_id': 'xxx'})
assert len(resp.json['data']) == 1
assert resp.json['data'][0]['id'] == 'first-agenda@event-2'
resp = app.get(
'/api/agendas/datetimes/',
params={
'subscribed': 'all',
'user_external_id': 'xxx',
# date_start before subscription's period, and includes the first event
'date_start': now().strftime('%Y-%m-%d'),
},
)
assert len(resp.json['data']) == 1
assert resp.json['data'][0]['id'] == 'first-agenda@event-2'
subscription.date_start = now()
subscription.date_end = now() + datetime.timedelta(days=6) # first event on subscription's last day
subscription.save()
resp = app.get('/api/agendas/datetimes/', params={'subscribed': 'all', 'user_external_id': 'xxx'})
assert len(resp.json['data']) == 1
assert resp.json['data'][0]['id'] == 'first-agenda@event'
resp = app.get(
'/api/agendas/datetimes/',
params={
'subscribed': 'all',
'user_external_id': 'xxx',
# date_end after subscription's period, and includes the second event
'date_end': (now() + datetime.timedelta(days=30)).strftime('%Y-%m-%d'),
},
)
assert len(resp.json['data']) == 1
assert resp.json['data'][0]['id'] == 'first-agenda@event'
# no subscription to second agenda
resp = app.get('/api/agendas/datetimes/', params={'subscribed': 'category-a', 'user_external_id': 'xxx'})
@ -2129,3 +2159,98 @@ def test_datetimes_multiple_agendas_subscribed(app):
status=400,
)
assert 'mutually exclusive' in resp.json['errors']['non_field_errors'][0]
@pytest.mark.freeze_time('2021-05-06 14:00')
def test_datetimes_multiple_agendas_recurring_subscribed_dates(app):
agenda = Agenda.objects.create(label='Agenda', kind='events', minimal_booking_delay=0)
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
event = Event.objects.create(
slug='recurring',
start_datetime=now() + datetime.timedelta(days=-15, hours=1),
recurrence_days=[localtime().weekday()],
recurrence_end_date=now() + datetime.timedelta(days=15),
places=5,
agenda=agenda,
)
resp = app.get('/api/agendas/datetimes/', params={'subscribed': 'all', 'user_external_id': 'xxx'})
assert len(resp.json['data']) == 0
subscription = Subscription.objects.create(
agenda=agenda,
user_external_id='xxx',
date_start=datetime.date(2021, 4, 29),
date_end=datetime.date(2021, 5, 14),
)
resp = app.get('/api/agendas/datetimes/', params={'subscribed': 'all', 'user_external_id': 'xxx'})
assert len(resp.json['data']) == 2
assert resp.json['data'][0]['id'] == 'agenda@recurring:2021-05-06-1700'
assert resp.json['data'][1]['id'] == 'agenda@recurring:2021-05-13-1700'
resp = app.get(
'/api/agendas/datetimes/',
params={
'subscribed': 'all',
'user_external_id': 'xxx',
'show_past_events': True,
'date_start': subscription.date_start.strftime('%Y-%m-%d'),
},
)
resp = app.get(
'/api/agendas/datetimes/',
params={'subscribed': 'all', 'user_external_id': 'xxx', 'show_past_events': True},
)
assert len(resp.json['data']) == 2 # no start_date
assert resp.json['data'][0]['id'] == 'agenda@recurring:2021-05-06-1700'
assert resp.json['data'][1]['id'] == 'agenda@recurring:2021-05-13-1700'
resp = app.get(
'/api/agendas/datetimes/',
params={
'subscribed': 'all',
'user_external_id': 'xxx',
'show_past_events': True,
'date_start': subscription.date_start.strftime('%Y-%m-%d'),
},
)
assert len(resp.json['data']) == 3
assert resp.json['data'][0]['id'] == 'agenda@recurring:2021-04-29-1700'
assert resp.json['data'][1]['id'] == 'agenda@recurring:2021-05-06-1700'
assert resp.json['data'][2]['id'] == 'agenda@recurring:2021-05-13-1700'
# date_start before subscription's period,
# date_end after subscription's period
resp = app.get(
'/api/agendas/datetimes/',
params={
'subscribed': 'all',
'user_external_id': 'xxx',
'show_past_events': True,
'date_start': event.start_datetime.strftime('%Y-%m-%d'),
'date_end': (now() + datetime.timedelta(days=15)).strftime('%Y-%m-%d'),
},
)
assert len(resp.json['data']) == 3
assert resp.json['data'][0]['id'] == 'agenda@recurring:2021-04-29-1700'
assert resp.json['data'][1]['id'] == 'agenda@recurring:2021-05-06-1700'
assert resp.json['data'][2]['id'] == 'agenda@recurring:2021-05-13-1700'
# test subscription's limits
subscription.date_start = datetime.date(2021, 4, 29)
subscription.date_end = datetime.date(2021, 5, 13)
subscription.save()
resp = app.get(
'/api/agendas/datetimes/',
params={
'subscribed': 'all',
'user_external_id': 'xxx',
'show_past_events': True,
'date_start': event.start_datetime.strftime('%Y-%m-%d'),
'date_end': (now() + datetime.timedelta(days=15)).strftime('%Y-%m-%d'),
},
)
assert len(resp.json['data']) == 2
assert resp.json['data'][0]['id'] == 'agenda@recurring:2021-04-29-1700'
assert resp.json['data'][1]['id'] == 'agenda@recurring:2021-05-06-1700'

View File

@ -3222,9 +3222,10 @@ def test_recurring_events_api_fillslots_subscribed(app, user):
resp = app.post_json(fillslots_url % 'category-a', params=params)
assert resp.json['booking_count'] == 9
assert Booking.objects.count() == 9
assert Booking.objects.filter(event__primary_event=event).count() == 9
assert Booking.objects.order_by('event__start_datetime').filter(event__primary_event=event).count() == 9
assert (
Booking.objects.first().event.start_datetime.strftime('%d/%m') == '20/09'
Booking.objects.order_by('event__start_datetime').first().event.start_datetime.strftime('%d/%m')
== '20/09'
) # first subscription's day
assert Booking.objects.last().event.start_datetime.strftime('%d/%m') == '18/10' # last subscription's day
subscription.date_end = now() + datetime.timedelta(days=46) # Friday 22/10
@ -3234,13 +3235,60 @@ def test_recurring_events_api_fillslots_subscribed(app, user):
assert Booking.objects.count() == 10
assert Booking.objects.filter(event__primary_event=event).count() == 10
assert (
Booking.objects.first().event.start_datetime.strftime('%d/%m') == '20/09'
Booking.objects.order_by('event__start_datetime').first().event.start_datetime.strftime('%d/%m')
== '20/09'
) # first subscription's day
assert Booking.objects.last().event.start_datetime.strftime('%d/%m') == '21/10' # last subscription's day
assert (
Booking.objects.order_by('event__start_datetime').last().event.start_datetime.strftime('%d/%m')
== '21/10'
) # last subscription's day
# wrong category
resp = app.post_json(fillslots_url % 'category-b', params=params, status=400)
# book Monday and Thursday of first event, in subscription range, but with date_start and date_end params
resp = app.post_json(
fillslots_url % 'category-a' + '&date_start=2021-09-21&date_end=2021-10-21', params=params
)
assert resp.json['booking_count'] == 0
assert resp.json['cancelled_booking_count'] == 2
assert Booking.objects.filter(cancellation_datetime__isnull=True).count() == 8
assert (
Booking.objects.filter(cancellation_datetime__isnull=True)
.order_by('event__start_datetime')
.first()
.event.start_datetime.strftime('%d/%m')
== '23/09'
) # first subscription's day
assert (
Booking.objects.filter(cancellation_datetime__isnull=True)
.order_by('event__start_datetime')
.last()
.event.start_datetime.strftime('%d/%m')
== '18/10'
)
resp = app.post_json(
fillslots_url % 'category-a' + '&date_start=2021-09-01&date_end=2021-10-31', params=params
)
assert resp.json['booking_count'] == 2
assert resp.json['cancelled_booking_count'] == 0
assert Booking.objects.filter(cancellation_datetime__isnull=True).count() == 10
assert (
Booking.objects.filter(cancellation_datetime__isnull=True)
.order_by('event__start_datetime')
.first()
.event.start_datetime.strftime('%d/%m')
== '20/09'
) # first subscription's day
assert (
Booking.objects.filter(cancellation_datetime__isnull=True)
.order_by('event__start_datetime')
.last()
.event.start_datetime.strftime('%d/%m')
== '21/10'
)
# not subscribed category
params['slots'] = 'second-agenda@sunday-event:6'
resp = app.post_json(fillslots_url % 'category-b', params=params, status=400)