Projet

Général

Profil

0001-api-list-bookings-of-somebody-51187.patch

Lauréline Guérin, 18 février 2021 15:57

Télécharger (15,4 ko)

Voir les différences:

Subject: [PATCH] api: list bookings of somebody (#51187)

 chrono/api/urls.py  |   1 +
 chrono/api/views.py |  83 ++++++++++++++++---
 chrono/settings.py  |   1 +
 setup.py            |   1 +
 tests/test_api.py   | 190 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 266 insertions(+), 10 deletions(-)
chrono/api/urls.py
55 55
        views.meeting_datetimes,
56 56
        name='api-agenda-meeting-datetimes',
57 57
    ),
58
    url(r'^bookings/$', views.bookings, name='api-bookings'),
58 59
    url(r'^booking/(?P<booking_pk>\w+)/$', views.booking, name='api-booking'),
59 60
    url(r'^booking/(?P<booking_pk>\w+)/cancel/$', views.cancel_booking, name='api-cancel-booking'),
60 61
    url(r'^booking/(?P<booking_pk>\w+)/accept/$', views.accept_booking, name='api-accept-booking'),
chrono/api/views.py
19 19
import itertools
20 20
import uuid
21 21

  
22

  
23 22
from django.db import transaction
24 23
from django.db.models import Prefetch, Q
25 24
from django.http import Http404, HttpResponse
......
32 31
from django.utils.translation import gettext_noop
33 32
from django.utils.translation import ugettext_lazy as _
34 33

  
34
from django_filters import rest_framework as filters
35 35
from rest_framework import permissions, serializers, status
36

  
36
from rest_framework.exceptions import ValidationError
37
from rest_framework.generics import ListAPIView
37 38
from rest_framework.views import APIView
38 39

  
39 40
from chrono.api.utils import Response
......
1243 1244

  
1244 1245
    class Meta:
1245 1246
        model = Booking
1246
        fields = ['user_was_present', 'user_absence_reason']
1247
        fields = ['id', 'in_waiting_list', 'user_was_present', 'user_absence_reason']
1248
        read_only_fields = ['id', 'in_waiting_list']
1247 1249

  
1248 1250
    def validate_user_absence_reason(self, value):
1249 1251
        if value is None:
......
1251 1253
        return value
1252 1254

  
1253 1255

  
1256
class BookingFilter(filters.FilterSet):
1257
    agenda = filters.CharFilter(field_name='event__agenda__slug', lookup_expr='exact')
1258
    category = filters.CharFilter(field_name='event__agenda__category__slug', lookup_expr='exact')
1259
    date_start = filters.DateFilter(field_name='event__start_datetime', lookup_expr='gte')
1260
    date_end = filters.DateFilter(field_name='event__start_datetime', method='filter_date_end')
1261

  
1262
    def filter_date_end(self, queryset, name, value):
1263
        # we want to include all events starting during the targeted day
1264
        lookup = '__'.join([name, 'lt'])
1265
        return queryset.filter(**{lookup: value + datetime.timedelta(days=1)})
1266

  
1267
    class Meta:
1268
        model = Booking
1269
        fields = [
1270
            'user_external_id',
1271
            'agenda',
1272
            'category',
1273
            'date_start',
1274
            'date_end',
1275
            'user_was_present',
1276
            'user_absence_reason',
1277
        ]
1278

  
1279

  
1280
class BookingsAPI(ListAPIView):
1281
    filter_backends = (filters.DjangoFilterBackend,)
1282
    serializer_class = BookingSerializer
1283
    filterset_class = BookingFilter
1284

  
1285
    def get(self, request, *args, **kwargs):
1286
        if not request.GET.get('user_external_id'):
1287
            response = {
1288
                'err': 1,
1289
                'err_class': 'missing param user_external_id',
1290
                'err_desc': _('missing param user_external_id'),
1291
            }
1292
            return Response(response)
1293

  
1294
        try:
1295
            response = super().get(request, *args, **kwargs)
1296
        except ValidationError as e:
1297
            return Response(
1298
                {
1299
                    'err': 1,
1300
                    'err_class': 'invalid payload',
1301
                    'err_desc': _('invalid payload'),
1302
                    'errors': e.detail,
1303
                },
1304
                status=status.HTTP_400_BAD_REQUEST,
1305
            )
1306

  
1307
        return Response({'err': 0, 'data': response.data})
1308

  
1309
    def get_queryset(self):
1310
        return Booking.objects.all().order_by('pk')
1311

  
1312

  
1313
bookings = BookingsAPI.as_view()
1314

  
1315

  
1254 1316
class BookingAPI(APIView):
1255 1317
    permission_classes = (permissions.IsAuthenticated,)
1256 1318
    serializer_class = BookingSerializer
......
1281 1343
        if response:
1282 1344
            return response
1283 1345

  
1284
        response = {
1285
            'err': 0,
1286
            'booking_id': self.booking.pk,
1287
            'in_waiting_list': self.booking.in_waiting_list,
1288
            'user_was_present': self.booking.user_was_present,
1289
            'user_absence_reason': self.booking.user_absence_reason,
1290
        }
1346
        serializer = self.serializer_class(self.booking)
1347
        response = serializer.data
1348
        response.update(
1349
            {
1350
                'err': 0,
1351
                'booking_id': self.booking.pk,
1352
            }
1353
        )
1291 1354
        return Response(response)
1292 1355

  
1293 1356
    def patch(self, request, *args, **kwargs):
chrono/settings.py
56 56
    'chrono.api',
57 57
    'chrono.manager',
58 58
    'rest_framework',
59
    'django_filters',
59 60
)
60 61

  
61 62
MIDDLEWARE = (
setup.py
164 164
        'django>=1.11, <2.3',
165 165
        'gadjo',
166 166
        'djangorestframework>=3.4',
167
        'django-filter',
167 168
        'django-jsonfield >= 0.9.3',
168 169
        'vobject',
169 170
        'python-dateutil',
tests/test_api.py
1935 1935
    assert Booking.objects.count() == 6
1936 1936

  
1937 1937

  
1938
def test_bookings_api(app, user):
1939
    events_agenda = Agenda.objects.create(kind='events')
1940
    events_event = Event.objects.create(agenda=events_agenda, start_datetime=now(), places=10)
1941
    events_booking1 = Booking.objects.create(event=events_event, user_external_id='enfant-1234')
1942
    events_booking2 = Booking.objects.create(event=events_event, user_external_id='enfant-1234')
1943
    Booking.objects.create(event=events_event, user_external_id='foobar')
1944
    Booking.objects.create(event=events_event)
1945

  
1946
    meetings_agenda = Agenda.objects.create(kind='meetings')
1947
    meetings_event = Event.objects.create(agenda=meetings_agenda, start_datetime=now(), places=1)
1948
    meetings_booking1 = Booking.objects.create(event=meetings_event, user_external_id='enfant-1234')
1949
    Booking.objects.create(event=meetings_event, user_external_id='baz')
1950
    Booking.objects.create(event=meetings_event, user_external_id='baz')
1951
    Booking.objects.create(event=meetings_event)
1952

  
1953
    app.authorization = ('Basic', ('john.doe', 'password'))
1954
    resp = app.get('/api/bookings/')
1955
    assert resp.json['err'] == 1
1956
    assert resp.json['err_class'] == 'missing param user_external_id'
1957
    assert resp.json['err_desc'] == 'missing param user_external_id'
1958

  
1959
    resp = app.get('/api/bookings/', params={'user_external_id': ''})
1960
    assert resp.json['err'] == 1
1961
    assert resp.json['err_class'] == 'missing param user_external_id'
1962
    assert resp.json['err_desc'] == 'missing param user_external_id'
1963

  
1964
    resp = app.get('/api/bookings/', params={'user_external_id': 'enfant-1234'})
1965
    assert resp.json['err'] == 0
1966
    assert resp.json['data'] == [
1967
        {
1968
            'id': events_booking1.pk,
1969
            'in_waiting_list': False,
1970
            'user_was_present': None,
1971
            'user_absence_reason': '',
1972
        },
1973
        {
1974
            'id': events_booking2.pk,
1975
            'in_waiting_list': False,
1976
            'user_was_present': None,
1977
            'user_absence_reason': '',
1978
        },
1979
        {
1980
            'id': meetings_booking1.pk,
1981
            'in_waiting_list': False,
1982
            'user_was_present': None,
1983
            'user_absence_reason': '',
1984
        },
1985
    ]
1986

  
1987

  
1988
def test_bookings_api_filter_agenda(app, user):
1989
    bookings = []
1990
    for label in ['foobar', 'foobaz']:
1991
        agenda = Agenda.objects.create(label='foobar')
1992
        event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
1993
        bookings.append(Booking.objects.create(event=event, user_external_id='42'))
1994

  
1995
    app.authorization = ('Basic', ('john.doe', 'password'))
1996
    resp = app.get('/api/bookings/', params={'user_external_id': '42', 'agenda': 'foo'})
1997
    assert resp.json['err'] == 0
1998
    assert [b['id'] for b in resp.json['data']] == []
1999

  
2000
    resp = app.get('/api/bookings/', params={'user_external_id': '42', 'agenda': 'foobar'})
2001
    assert [b['id'] for b in resp.json['data']] == [bookings[0].pk]
2002

  
2003

  
2004
def test_bookings_api_filter_category(app, user):
2005
    bookings = []
2006
    for label in ['foobar', 'foobaz']:
2007
        category = Category.objects.create(label=label)
2008
        agenda = Agenda.objects.create(category=category)
2009
        event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
2010
        bookings.append(Booking.objects.create(event=event, user_external_id='42'))
2011

  
2012
    app.authorization = ('Basic', ('john.doe', 'password'))
2013
    resp = app.get('/api/bookings/', params={'user_external_id': '42', 'category': 'foo'})
2014
    assert resp.json['err'] == 0
2015
    assert [b['id'] for b in resp.json['data']] == []
2016

  
2017
    resp = app.get('/api/bookings/', params={'user_external_id': '42', 'category': 'foobar'})
2018
    assert [b['id'] for b in resp.json['data']] == [bookings[0].pk]
2019

  
2020

  
2021
def test_bookings_api_filter_date_start(app, user):
2022
    agenda = Agenda.objects.create()
2023
    event = Event.objects.create(
2024
        agenda=agenda, start_datetime=make_aware(datetime.datetime(2017, 5, 22, 0, 0)), places=10
2025
    )
2026
    booking = Booking.objects.create(event=event, user_external_id='42')
2027

  
2028
    app.authorization = ('Basic', ('john.doe', 'password'))
2029
    resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_start': 'foo'}, status=400)
2030
    assert resp.json['err'] == 1
2031
    assert resp.json['err_class'] == "invalid payload"
2032
    assert resp.json['err_desc'] == "invalid payload"
2033

  
2034
    resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_start': '2017-05-21'})
2035
    assert resp.json['err'] == 0
2036
    assert [b['id'] for b in resp.json['data']] == [booking.pk]
2037
    resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_start': '2017-05-22'})
2038
    assert resp.json['err'] == 0
2039
    assert [b['id'] for b in resp.json['data']] == [booking.pk]
2040
    resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_start': '2017-05-23'})
2041
    assert resp.json['err'] == 0
2042
    assert [b['id'] for b in resp.json['data']] == []
2043

  
2044
    event.start_datetime = make_aware(datetime.datetime(2017, 5, 22, 23, 59))
2045
    event.save()
2046
    resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_start': '2017-05-21'})
2047
    assert resp.json['err'] == 0
2048
    assert [b['id'] for b in resp.json['data']] == [booking.pk]
2049
    resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_start': '2017-05-22'})
2050
    assert resp.json['err'] == 0
2051
    assert [b['id'] for b in resp.json['data']] == [booking.pk]
2052
    resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_start': '2017-05-23'})
2053
    assert resp.json['err'] == 0
2054
    assert [b['id'] for b in resp.json['data']] == []
2055

  
2056

  
2057
def test_bookings_api_filter_date_end(app, user):
2058
    agenda = Agenda.objects.create()
2059
    event = Event.objects.create(
2060
        agenda=agenda, start_datetime=make_aware(datetime.datetime(2017, 5, 22, 0, 0)), places=10
2061
    )
2062
    booking = Booking.objects.create(event=event, user_external_id='42')
2063

  
2064
    app.authorization = ('Basic', ('john.doe', 'password'))
2065
    resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_end': 'foo'}, status=400)
2066
    assert resp.json['err'] == 1
2067
    assert resp.json['err_class'] == "invalid payload"
2068
    assert resp.json['err_desc'] == "invalid payload"
2069

  
2070
    resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_end': '2017-05-21'})
2071
    assert resp.json['err'] == 0
2072
    assert [b['id'] for b in resp.json['data']] == []
2073
    resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_end': '2017-05-22'})
2074
    assert resp.json['err'] == 0
2075
    assert [b['id'] for b in resp.json['data']] == [booking.pk]
2076
    resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_end': '2017-05-23'})
2077
    assert resp.json['err'] == 0
2078
    assert [b['id'] for b in resp.json['data']] == [booking.pk]
2079

  
2080
    event.start_datetime = make_aware(datetime.datetime(2017, 5, 22, 23, 59))
2081
    event.save()
2082
    resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_end': '2017-05-21'})
2083
    assert resp.json['err'] == 0
2084
    assert [b['id'] for b in resp.json['data']] == []
2085
    resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_end': '2017-05-22'})
2086
    assert resp.json['err'] == 0
2087
    assert [b['id'] for b in resp.json['data']] == [booking.pk]
2088
    resp = app.get('/api/bookings/', params={'user_external_id': '42', 'date_end': '2017-05-23'})
2089
    assert resp.json['err'] == 0
2090
    assert [b['id'] for b in resp.json['data']] == [booking.pk]
2091

  
2092

  
2093
def test_bookings_api_filter_user_was_present(app, user):
2094
    agenda = Agenda.objects.create()
2095
    event = Event.objects.create(
2096
        agenda=agenda, start_datetime=make_aware(datetime.datetime(2017, 5, 22, 0, 0)), places=10
2097
    )
2098
    Booking.objects.create(event=event, user_external_id='42')
2099
    booking2 = Booking.objects.create(event=event, user_external_id='42', user_was_present=True)
2100
    booking3 = Booking.objects.create(event=event, user_external_id='42', user_was_present=False)
2101

  
2102
    app.authorization = ('Basic', ('john.doe', 'password'))
2103
    resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_was_present': True})
2104
    assert resp.json['err'] == 0
2105
    assert [b['id'] for b in resp.json['data']] == [booking2.pk]
2106
    resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_was_present': False})
2107
    assert resp.json['err'] == 0
2108
    assert [b['id'] for b in resp.json['data']] == [booking3.pk]
2109

  
2110

  
2111
def test_bookings_api_filter_user_absence_reason(app, user):
2112
    agenda = Agenda.objects.create()
2113
    event = Event.objects.create(
2114
        agenda=agenda, start_datetime=make_aware(datetime.datetime(2017, 5, 22, 0, 0)), places=10
2115
    )
2116
    Booking.objects.create(event=event, user_external_id='42')
2117
    booking2 = Booking.objects.create(event=event, user_external_id='42', user_absence_reason='foo-bar')
2118

  
2119
    app.authorization = ('Basic', ('john.doe', 'password'))
2120
    resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_absence_reason': 'foo'})
2121
    assert resp.json['err'] == 0
2122
    assert [b['id'] for b in resp.json['data']] == []
2123
    resp = app.get('/api/bookings/', params={'user_external_id': '42', 'user_absence_reason': 'foo-bar'})
2124
    assert resp.json['err'] == 0
2125
    assert [b['id'] for b in resp.json['data']] == [booking2.pk]
2126

  
2127

  
1938 2128
@pytest.mark.parametrize('flag', [True, False, None])
1939 2129
def test_booking_api_present(app, user, flag):
1940 2130
    agenda = Agenda.objects.create(kind='events')
1941
-