api: get event status and fillslot with event pk or slug (#15726)

This commit is contained in:
Lauréline Guérin 2019-11-06 17:00:12 +01:00
parent 0f4040f9a5
commit 90dfb10afa
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
3 changed files with 43 additions and 18 deletions

View File

@ -23,11 +23,11 @@ urlpatterns = [
url(r'agenda/(?P<agenda_identifier>[\w-]+)/$', views.agenda_detail),
url(r'agenda/(?P<agenda_identifier>[\w-]+)/datetimes/$', views.datetimes, name='api-agenda-datetimes'),
url(r'agenda/(?P<agenda_identifier>[\w-]+)/fillslot/(?P<event_pk>[\w:-]+)/$',
url(r'agenda/(?P<agenda_identifier>[\w-]+)/fillslot/(?P<event_identifier>[\w:-]+)/$',
views.fillslot, name='api-fillslot'),
url(r'agenda/(?P<agenda_identifier>[\w-]+)/fillslots/$',
views.fillslots, name='api-agenda-fillslots'),
url(r'agenda/(?P<agenda_identifier>[\w-]+)/status/(?P<event_pk>\d+)/$', views.slot_status,
url(r'agenda/(?P<agenda_identifier>[\w-]+)/status/(?P<event_identifier>[\w-]+)/$', views.slot_status,
name='api-event-status'),
url(r'agenda/meetings/(?P<meeting_identifier>[\w-]+)/datetimes/$',

View File

@ -185,6 +185,7 @@ class Datetimes(APIView):
datetime.datetime.combine(parse_date(request.GET['date_end']), datetime.time(0, 0))))
response = {'data': [{'id': x.id,
'slug': x.slug,
'text': force_text(x),
'datetime': format_response_datetime(x.start_datetime),
'description': x.description,
@ -194,13 +195,13 @@ class Datetimes(APIView):
reverse('api-fillslot',
kwargs={
'agenda_identifier': agenda.slug,
'event_pk': x.id,
'event_identifier': x.slug,
})),
'status_url': request.build_absolute_uri(
reverse('api-event-status',
kwargs={
'agenda_identifier': agenda.slug,
'event_pk': x.id,
'event_identifier': x.slug,
}))
},
} for x in entries]}
@ -240,12 +241,12 @@ class MeetingDatetimes(APIView):
# create fillslot API URL as a template, to avoid expensive calls
# to request.build_absolute_uri()
fake_event_pk = '__event_id__'
fake_event_identifier = '__event_identifier__'
fillslot_url = request.build_absolute_uri(
reverse('api-fillslot',
kwargs={
'agenda_identifier': agenda.slug,
'event_pk': fake_event_pk,
'event_identifier': fake_event_identifier,
}))
response = {'data': [{'id': x.id,
@ -253,7 +254,7 @@ class MeetingDatetimes(APIView):
'text': force_text(x),
'disabled': bool(x.full),
'api': {
'fillslot_url': fillslot_url.replace(fake_event_pk, str(x.id)),
'fillslot_url': fillslot_url.replace(fake_event_identifier, str(x.id)),
},
} for x in slots]}
return Response(response)
@ -333,7 +334,7 @@ class Fillslots(APIView):
permission_classes = (permissions.IsAuthenticated,)
serializer_class = SlotsSerializer
def post(self, request, agenda_identifier=None, event_pk=None, format=None):
def post(self, request, agenda_identifier=None, event_identifier=None, format=None):
return self.fillslot(request=request, agenda_identifier=agenda_identifier,
format=format)
@ -467,7 +468,10 @@ class Fillslots(APIView):
full=False, places=1,
desk=available_desk))
else:
events = Event.objects.filter(id__in=slots).order_by('start_datetime')
try:
events = Event.objects.filter(id__in=[int(s) for s in slots]).order_by('start_datetime')
except ValueError:
events = Event.objects.filter(slug__in=slots).order_by('start_datetime')
# search free places. Switch to waiting list if necessary.
in_waiting_list = False
@ -538,10 +542,10 @@ fillslots = Fillslots.as_view()
class Fillslot(Fillslots):
serializer_class = SlotSerializer
def post(self, request, agenda_identifier=None, event_pk=None, format=None):
def post(self, request, agenda_identifier=None, event_identifier=None, format=None):
return self.fillslot(request=request,
agenda_identifier=agenda_identifier,
slots=[event_pk], # fill a "list on one slot"
slots=[event_identifier], # fill a "list on one slot"
format=format)
fillslot = Fillslot.as_view()
@ -610,8 +614,18 @@ accept_booking = AcceptBooking.as_view()
class SlotStatus(APIView):
permission_classes = (permissions.IsAuthenticated,)
def get(self, request, agenda_identifier=None, event_pk=None, format=None):
event = get_object_or_404(Event, id=event_pk)
def get_object(self, event_identifier):
try:
return Event.objects.get(slug=event_identifier)
except Event.DoesNotExist:
try:
# legacy access by event id
return Event.objects.get(pk=int(event_identifier))
except (ValueError, Event.DoesNotExist):
raise Http404()
def get(self, request, agenda_identifier=None, event_identifier=None, format=None):
event = self.get_object(event_identifier)
response = {
'err': 0,
'places': {
@ -626,6 +640,7 @@ class SlotStatus(APIView):
response['places']['waiting_list_available'] = (event.waiting_list_places - event.waiting_list)
return Response(response)
slot_status = SlotStatus.as_view()

View File

@ -225,7 +225,7 @@ def test_datetime_api_status_url(app, some_data):
agenda = Agenda.objects.get(label=u'Foo bar2')
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
for datum in resp.json['data']:
assert urlparse.urlparse(datum['api']['status_url']).path == '/api/agenda/%s/status/%s/' % (agenda.slug, datum['id'])
assert urlparse.urlparse(datum['api']['status_url']).path == '/api/agenda/%s/status/%s/' % (agenda.slug, datum['slug'])
def test_datetimes_api_meetings_agenda(app, meetings_agenda):
meeting_type = MeetingType.objects.get(agenda=meetings_agenda)
@ -333,7 +333,7 @@ def test_booking_api(app, some_data, user):
for agenda_key in (agenda.slug, agenda.id): # acces datetimes via agenda slug or id (legacy)
resp_datetimes = app.get('/api/agenda/%s/datetimes/' % agenda_key)
event_fillslot_url = [x for x in resp_datetimes.json['data'] if x['id'] == event.id][0]['api']['fillslot_url']
assert urlparse.urlparse(event_fillslot_url).path == '/api/agenda/%s/fillslot/%s/' % (agenda.slug, event.id)
assert urlparse.urlparse(event_fillslot_url).path == '/api/agenda/%s/fillslot/%s/' % (agenda.slug, event.slug)
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda.slug, event.id))
@ -346,7 +346,8 @@ def test_booking_api(app, some_data, user):
assert urlparse.urlparse(resp.json['api']['ics_url']).netloc
assert Booking.objects.count() == 1
resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id))
# access by slug
resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda.id, event.slug))
assert Booking.objects.count() == 2
assert Booking.objects.filter(event__agenda=agenda).count() == 2
@ -467,6 +468,7 @@ def test_booking_ics(app, some_data, meetings_agenda, user):
def test_booking_api_fillslots(app, some_data, user):
agenda = Agenda.objects.filter(label=u'Foo bar')[0]
events_ids = [x.id for x in Event.objects.filter(agenda=agenda) if x.in_bookable_period()]
events_slugs = [x.slug for x in Event.objects.filter(agenda=agenda) if x.in_bookable_period()]
assert len(events_ids) == 3
event = [x for x in Event.objects.filter(agenda=agenda) if x.in_bookable_period()][0] # first event
@ -495,7 +497,8 @@ def test_booking_api_fillslots(app, some_data, user):
assert bookings[1].primary_booking.id == bookings[0].id == primary_booking_id
assert bookings[2].primary_booking.id == bookings[0].id == primary_booking_id
resp = app.post('/api/agenda/%s/fillslots/' % agenda.slug, params={'slots': events_ids})
# access by slug
resp = app.post('/api/agenda/%s/fillslots/' % agenda.slug, params={'slots': events_slugs})
primary_booking_id_2 = resp.json['booking_id']
assert Booking.objects.count() == 6
assert Booking.objects.filter(event__agenda=agenda).count() == 6
@ -915,6 +918,12 @@ def test_status(app, some_data, user):
assert resp.json['places']['waiting_list_available'] == 4
assert resp.json['places']['waiting_list_reserved'] == 1
# access by slug
resp = app.get('/api/agenda/%s/status/%s/' % (agenda_id, event.slug))
# not found event
resp = app.get('/api/agenda/%s/status/%s/' % (agenda_id, 'unknown'), status=404)
def test_waiting_list_datetimes(app, some_data, user):
agenda_id = Agenda.objects.filter(label=u'Foo bar')[0].id
event = Event.objects.filter(agenda_id=agenda_id).exclude(start_datetime__lt=now())[0]
@ -1343,7 +1352,8 @@ def test_agenda_meeting_api_multiple_desk(app, meetings_agenda, user):
booking_url = event_data['api']['fillslot_url']
with CaptureQueriesContext(connection) as ctx:
app.post(booking_url)
assert len(ctx.captured_queries) == queries_count_fillslot1
# 2 + idx: because of slug unicity
assert len(ctx.captured_queries) == queries_count_fillslot1 + 2 + idx
with CaptureQueriesContext(connection) as ctx:
app.get('/api/agenda/meetings/%s/datetimes/' % meeting_type.id)