api: allow passing minimum places count in /datetimes/ (#51172)

This commit is contained in:
Valentin Deniaud 2021-02-17 17:30:06 +01:00
parent 9954337197
commit 929f70d2ac
2 changed files with 48 additions and 7 deletions

View File

@ -344,7 +344,7 @@ def get_event_places(event):
return places
def get_event_detail(request, event, agenda=None):
def get_event_detail(request, event, agenda=None, min_places=1):
agenda = agenda or event.agenda
if event.label and event.primary_event is not None:
event.label = '%s (%s)' % (
@ -359,7 +359,9 @@ def get_event_detail(request, event, agenda=None):
'description': event.description,
'pricing': event.pricing,
'url': event.url,
'disabled': bool(event.full),
'disabled': bool(
event.remaining_places < min_places and event.remaining_waiting_list_places < min_places
),
'api': {
'bookings_url': request.build_absolute_uri(
reverse(
@ -384,16 +386,16 @@ def get_event_detail(request, event, agenda=None):
}
def get_events_meta_detail(request, events, agenda=None):
def get_events_meta_detail(request, events, agenda=None, min_places=1):
bookable_datetimes_number_total = 0
bookable_datetimes_number_available = 0
first_bookable_slot = None
for event in events:
bookable_datetimes_number_total += 1
if not bool(event.full):
if bool(event.remaining_places >= min_places or event.remaining_waiting_list_places >= min_places):
bookable_datetimes_number_available += 1
if not first_bookable_slot:
first_bookable_slot = get_event_detail(request, event, agenda=agenda)
first_bookable_slot = get_event_detail(request, event, agenda=agenda, min_places=min_places)
return {
'no_bookable_datetimes': bool(bookable_datetimes_number_available == 0),
'bookable_datetimes_number_total': bookable_datetimes_number_total,
@ -531,6 +533,15 @@ class Datetimes(APIView):
if agenda.kind != 'events':
raise Http404('agenda found, but it was not an events agenda')
try:
min_places = int(request.GET.get('min_places', 1))
except ValueError:
raise APIError(
_('min_places must be a number'),
err_class='min_places must be a number',
http_status=status.HTTP_400_BAD_REQUEST,
)
date_start, date_end = request.GET.get('date_start'), request.GET.get('date_end')
if date_start:
try:
@ -556,8 +567,8 @@ class Datetimes(APIView):
entries = agenda.get_open_events(annotate_queryset=True, min_start=date_start, max_start=date_end)
response = {
'data': [get_event_detail(request, x, agenda=agenda) for x in entries],
'meta': get_events_meta_detail(request, entries, agenda=agenda),
'data': [get_event_detail(request, x, agenda=agenda, min_places=min_places) for x in entries],
'meta': get_events_meta_detail(request, entries, agenda=agenda, min_places=min_places),
}
return Response(response)

View File

@ -491,6 +491,27 @@ def test_datetime_api_urls(app):
)
def test_datetime_api_min_places(app):
agenda = Agenda.objects.create(label='Foo bar', kind='events')
event = Event.objects.create(start_datetime=now() + datetime.timedelta(days=7), places=5, agenda=agenda)
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
assert not resp.json['data'][0]['disabled']
resp = app.get('/api/agenda/%s/datetimes/?min_places=5' % agenda.slug)
assert not resp.json['data'][0]['disabled']
Booking.objects.create(event=event)
resp = app.get('/api/agenda/%s/datetimes/?min_places=5' % agenda.slug)
assert resp.json['data'][0]['disabled']
resp = app.get('/api/agenda/%s/datetimes/?min_places=wrong' % agenda.slug, status=400)
assert resp.json['err'] == 1
resp = app.get('/api/agenda/%s/datetimes/?min_places=' % agenda.slug, status=400)
assert resp.json['err'] == 1
def test_datetimes_api_meetings_agenda(app, meetings_agenda):
meeting_type = MeetingType.objects.get(agenda=meetings_agenda)
api_url = '/api/agenda/%s/meetings/%s/datetimes/' % (meeting_type.agenda.slug, meeting_type.slug)
@ -5151,6 +5172,15 @@ def test_datetimes_api_meta(app, freezer):
'first_bookable_slot': resp.json['data'][0],
}
resp = app.get(api_url + '?min_places=11')
assert len(resp.json['data']) == 3
assert resp.json['meta'] == {
'no_bookable_datetimes': False,
'bookable_datetimes_number_total': 3,
'bookable_datetimes_number_available': 2,
'first_bookable_slot': resp.json['data'][1],
}
simulate_booking(events[0], 10)
resp = app.get(api_url)
assert len(resp.json['data']) == 3