api: list bookings of somebody (#51187)

This commit is contained in:
Lauréline Guérin 2021-02-18 15:56:44 +01:00
parent 929f70d2ac
commit d23eafcfc6
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
5 changed files with 269 additions and 10 deletions

View File

@ -55,6 +55,7 @@ urlpatterns = [
views.meeting_datetimes,
name='api-agenda-meeting-datetimes',
),
url(r'^bookings/$', views.bookings, name='api-bookings'),
url(r'^booking/(?P<booking_pk>\w+)/$', views.booking, name='api-booking'),
url(r'^booking/(?P<booking_pk>\w+)/cancel/$', views.cancel_booking, name='api-cancel-booking'),
url(r'^booking/(?P<booking_pk>\w+)/accept/$', views.accept_booking, name='api-accept-booking'),

View File

@ -19,7 +19,6 @@ import datetime
import itertools
import uuid
from django.db import transaction
from django.db.models import Prefetch, Q
from django.http import Http404, HttpResponse
@ -32,8 +31,10 @@ from django.utils.timezone import now, make_aware, localtime
from django.utils.translation import gettext_noop
from django.utils.translation import ugettext_lazy as _
from django_filters import rest_framework as filters
from rest_framework import permissions, serializers, status
from rest_framework.exceptions import ValidationError
from rest_framework.generics import ListAPIView
from rest_framework.views import APIView
from chrono.api.utils import Response, APIError
@ -1242,7 +1243,8 @@ class BookingSerializer(serializers.ModelSerializer):
class Meta:
model = Booking
fields = ['user_was_present', 'user_absence_reason', 'extra_data']
fields = ['id', 'in_waiting_list', 'user_was_present', 'user_absence_reason', 'extra_data']
read_only_fields = ['id', 'in_waiting_list']
def validate_user_absence_reason(self, value):
if value is None:
@ -1250,6 +1252,66 @@ class BookingSerializer(serializers.ModelSerializer):
return value
class BookingFilter(filters.FilterSet):
agenda = filters.CharFilter(field_name='event__agenda__slug', lookup_expr='exact')
category = filters.CharFilter(field_name='event__agenda__category__slug', lookup_expr='exact')
date_start = filters.DateFilter(field_name='event__start_datetime', lookup_expr='gte')
date_end = filters.DateFilter(field_name='event__start_datetime', method='filter_date_end')
def filter_date_end(self, queryset, name, value):
# we want to include all events starting during the targeted day
lookup = '__'.join([name, 'lt'])
return queryset.filter(**{lookup: value + datetime.timedelta(days=1)})
class Meta:
model = Booking
fields = [
'user_external_id',
'agenda',
'category',
'date_start',
'date_end',
'user_was_present',
'user_absence_reason',
]
class BookingsAPI(ListAPIView):
filter_backends = (filters.DjangoFilterBackend,)
serializer_class = BookingSerializer
filterset_class = BookingFilter
def get(self, request, *args, **kwargs):
if not request.GET.get('user_external_id'):
response = {
'err': 1,
'err_class': 'missing param user_external_id',
'err_desc': _('missing param user_external_id'),
}
return Response(response)
try:
response = super().get(request, *args, **kwargs)
except ValidationError as e:
return Response(
{
'err': 1,
'err_class': 'invalid payload',
'err_desc': _('invalid payload'),
'errors': e.detail,
},
status=status.HTTP_400_BAD_REQUEST,
)
return Response({'err': 0, 'data': response.data})
def get_queryset(self):
return Booking.objects.all().order_by('pk')
bookings = BookingsAPI.as_view()
class BookingAPI(APIView):
permission_classes = (permissions.IsAuthenticated,)
serializer_class = BookingSerializer
@ -1280,13 +1342,14 @@ class BookingAPI(APIView):
if response:
return response
response = {
'err': 0,
'booking_id': self.booking.pk,
'in_waiting_list': self.booking.in_waiting_list,
'user_was_present': self.booking.user_was_present,
'user_absence_reason': self.booking.user_absence_reason,
}
serializer = self.serializer_class(self.booking)
response = serializer.data
response.update(
{
'err': 0,
'booking_id': self.booking.pk,
}
)
return Response(response)
def patch(self, request, *args, **kwargs):

View File

@ -56,6 +56,7 @@ INSTALLED_APPS = (
'chrono.api',
'chrono.manager',
'rest_framework',
'django_filters',
)
MIDDLEWARE = (

View File

@ -164,6 +164,7 @@ setup(
'django>=1.11, <2.3',
'gadjo',
'djangorestframework>=3.4',
'django-filter',
'django-jsonfield >= 0.9.3',
'vobject',
'python-dateutil',

View File

@ -1963,6 +1963,199 @@ def test_booking_api_with_cancel_booking(app, some_data, user):
assert Booking.objects.count() == 6
def test_bookings_api(app, user):
events_agenda = Agenda.objects.create(kind='events')
events_event = Event.objects.create(agenda=events_agenda, start_datetime=now(), places=10)
events_booking1 = Booking.objects.create(event=events_event, user_external_id='enfant-1234')
events_booking2 = Booking.objects.create(event=events_event, user_external_id='enfant-1234')
Booking.objects.create(event=events_event, user_external_id='foobar')
Booking.objects.create(event=events_event)
meetings_agenda = Agenda.objects.create(kind='meetings')
meetings_event = Event.objects.create(agenda=meetings_agenda, start_datetime=now(), places=1)
meetings_booking1 = Booking.objects.create(event=meetings_event, user_external_id='enfant-1234')
Booking.objects.create(event=meetings_event, user_external_id='baz')
Booking.objects.create(event=meetings_event, user_external_id='baz')
Booking.objects.create(event=meetings_event)
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.get('/api/bookings/')
assert resp.json['err'] == 1
assert resp.json['err_class'] == 'missing param user_external_id'
assert resp.json['err_desc'] == 'missing param user_external_id'
resp = app.get('/api/bookings/', params={'user_external_id': ''})
assert resp.json['err'] == 1
assert resp.json['err_class'] == 'missing param user_external_id'
assert resp.json['err_desc'] == 'missing param user_external_id'
resp = app.get('/api/bookings/', params={'user_external_id': 'enfant-1234'})
assert resp.json['err'] == 0
assert resp.json['data'] == [
{
'id': events_booking1.pk,
'in_waiting_list': False,
'user_was_present': None,
'user_absence_reason': '',
'extra_data': None,
},
{
'id': events_booking2.pk,
'in_waiting_list': False,
'user_was_present': None,
'user_absence_reason': '',
'extra_data': None,
},
{
'id': meetings_booking1.pk,
'in_waiting_list': False,
'user_was_present': None,
'user_absence_reason': '',
'extra_data': None,
},
]
def test_bookings_api_filter_agenda(app, user):
bookings = []
for label in ['foobar', 'foobaz']:
agenda = Agenda.objects.create(label='foobar')
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
bookings.append(Booking.objects.create(event=event, user_external_id='42'))
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'agenda': 'foo'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == []
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'agenda': 'foobar'})
assert [b['id'] for b in resp.json['data']] == [bookings[0].pk]
def test_bookings_api_filter_category(app, user):
bookings = []
for label in ['foobar', 'foobaz']:
category = Category.objects.create(label=label)
agenda = Agenda.objects.create(category=category)
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
bookings.append(Booking.objects.create(event=event, user_external_id='42'))
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'category': 'foo'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == []
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'category': 'foobar'})
assert [b['id'] for b in resp.json['data']] == [bookings[0].pk]
def test_bookings_api_filter_date_start(app, user):
agenda = Agenda.objects.create()
event = Event.objects.create(
agenda=agenda, start_datetime=make_aware(datetime.datetime(2017, 5, 22, 0, 0)), places=10
)
booking = Booking.objects.create(event=event, user_external_id='42')
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_start': 'foo'}, status=400)
assert resp.json['err'] == 1
assert resp.json['err_class'] == "invalid payload"
assert resp.json['err_desc'] == "invalid payload"
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_start': '2017-05-21'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == [booking.pk]
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_start': '2017-05-22'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == [booking.pk]
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_start': '2017-05-23'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == []
event.start_datetime = make_aware(datetime.datetime(2017, 5, 22, 23, 59))
event.save()
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_start': '2017-05-21'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == [booking.pk]
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_start': '2017-05-22'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == [booking.pk]
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_start': '2017-05-23'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == []
def test_bookings_api_filter_date_end(app, user):
agenda = Agenda.objects.create()
event = Event.objects.create(
agenda=agenda, start_datetime=make_aware(datetime.datetime(2017, 5, 22, 0, 0)), places=10
)
booking = Booking.objects.create(event=event, user_external_id='42')
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_end': 'foo'}, status=400)
assert resp.json['err'] == 1
assert resp.json['err_class'] == "invalid payload"
assert resp.json['err_desc'] == "invalid payload"
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_end': '2017-05-21'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == []
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_end': '2017-05-22'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == [booking.pk]
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_end': '2017-05-23'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == [booking.pk]
event.start_datetime = make_aware(datetime.datetime(2017, 5, 22, 23, 59))
event.save()
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_end': '2017-05-21'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == []
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_end': '2017-05-22'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == [booking.pk]
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_end': '2017-05-23'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == [booking.pk]
def test_bookings_api_filter_user_was_present(app, user):
agenda = Agenda.objects.create()
event = Event.objects.create(
agenda=agenda, start_datetime=make_aware(datetime.datetime(2017, 5, 22, 0, 0)), places=10
)
Booking.objects.create(event=event, user_external_id='42')
booking2 = Booking.objects.create(event=event, user_external_id='42', user_was_present=True)
booking3 = Booking.objects.create(event=event, user_external_id='42', user_was_present=False)
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_was_present': True})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == [booking2.pk]
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_was_present': False})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == [booking3.pk]
def test_bookings_api_filter_user_absence_reason(app, user):
agenda = Agenda.objects.create()
event = Event.objects.create(
agenda=agenda, start_datetime=make_aware(datetime.datetime(2017, 5, 22, 0, 0)), places=10
)
Booking.objects.create(event=event, user_external_id='42')
booking2 = Booking.objects.create(event=event, user_external_id='42', user_absence_reason='foo-bar')
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_absence_reason': 'foo'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == []
resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_absence_reason': 'foo-bar'})
assert resp.json['err'] == 0
assert [b['id'] for b in resp.json['data']] == [booking2.pk]
@pytest.mark.parametrize('flag', [True, False, None])
def test_booking_api_present(app, user, flag):
agenda = Agenda.objects.create(kind='events')