api: mark user as present or not (#38678)

This commit is contained in:
Lauréline Guérin 2020-11-30 09:51:48 +01:00
parent 96d1618186
commit d0bc3146d6
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
5 changed files with 210 additions and 4 deletions

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('agendas', '0070_auto_20201202_1834'),
]
operations = [
migrations.AddField(
model_name='booking',
name='user_was_present',
field=models.NullBooleanField(),
),
]

View File

@ -1098,6 +1098,8 @@ class Booking(models.Model):
user_name = models.CharField(max_length=250, blank=True)
user_email = models.EmailField(blank=True)
user_phone_number = models.CharField(max_length=16, blank=True)
user_was_present = models.NullBooleanField()
form_url = models.URLField(blank=True)
backoffice_url = models.URLField(blank=True)
cancel_callback_url = models.URLField(blank=True)

View File

@ -55,7 +55,7 @@ urlpatterns = [
views.meeting_datetimes,
name='api-agenda-meeting-datetimes',
),
url(r'^booking/(?P<booking_pk>\w+)/$', views.booking),
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'),
url(r'^booking/(?P<booking_pk>\w+)/suspend/$', views.suspend_booking, name='api-suspend-booking'),

View File

@ -1093,6 +1093,9 @@ class Fillslots(APIView):
'slug': primary_booking.event.agenda.slug,
},
'api': {
'booking_url': request.build_absolute_uri(
reverse('api-booking', kwargs={'booking_pk': primary_booking.id})
),
'cancel_url': request.build_absolute_uri(
reverse('api-cancel-booking', kwargs={'booking_pk': primary_booking.id})
),
@ -1162,16 +1165,81 @@ class Fillslot(Fillslots):
fillslot = Fillslot.as_view()
class BookingSerializer(serializers.ModelSerializer):
class Meta:
model = Booking
fields = ['user_was_present']
class BookingAPI(APIView):
permission_classes = (permissions.IsAuthenticated,)
serializer_class = BookingSerializer
def initial(self, request, *args, **kwargs):
super(BookingAPI, self).initial(request, *args, **kwargs)
self.booking = Booking.objects.get(id=kwargs.get('booking_pk'), cancellation_datetime__isnull=True)
super().initial(request, *args, **kwargs)
self.booking = get_object_or_404(Booking, pk=kwargs.get('booking_pk'))
def check_booking(self, check_waiting_list=False):
if self.booking.cancellation_datetime:
return Response(
{'err': 1, 'err_class': 'booking is cancelled', 'err_desc': _('booking is cancelled')}
)
if self.booking.primary_booking is not None:
return Response({'err': 2, 'err_class': 'secondary booking', 'err_desc': _('secondary booking')})
if check_waiting_list and self.booking.in_waiting_list:
response = {
'err': 3,
'err_class': 'booking is in waiting list',
'err_desc': _('booking is in waiting list'),
}
return Response(response)
def get(self, request, *args, **kwargs):
response = self.check_booking()
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,
}
return Response(response)
def patch(self, request, *args, **kwargs):
response = self.check_booking(check_waiting_list=True)
if response:
return response
serializer = self.serializer_class(self.booking, data=request.data, partial=True)
if not serializer.is_valid():
return Response(
{
'err': 4,
'err_class': 'invalid payload',
'err_desc': _('invalid payload'),
'errors': serializer.errors,
},
status=status.HTTP_400_BAD_REQUEST,
)
serializer.save()
self.booking.secondary_booking_set.update(user_was_present=self.booking.user_was_present)
response = {'err': 0, 'booking_id': self.booking.pk}
return Response(response)
def delete(self, request, *args, **kwargs):
response = self.check_booking()
if response:
return response
self.booking.cancel()
response = {'err': 0, 'booking_id': self.booking.id}
response = {'err': 0, 'booking_id': self.booking.pk}
return Response(response)

View File

@ -909,10 +909,13 @@ def test_booking_api(app, some_data, user):
resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda.slug, event.id))
Booking.objects.get(id=resp.json['booking_id'])
assert resp.json['datetime'] == localtime(event.start_datetime).strftime('%Y-%m-%d %H:%M:%S')
assert 'booking_url' in resp.json['api']
assert 'accept_url' in resp.json['api']
assert 'suspend_url' in resp.json['api']
assert 'cancel_url' in resp.json['api']
assert 'ics_url' in resp.json['api']
assert urlparse.urlparse(resp.json['api']['booking_url']).netloc
assert urlparse.urlparse(resp.json['api']['accept_url']).netloc
assert urlparse.urlparse(resp.json['api']['suspend_url']).netloc
assert urlparse.urlparse(resp.json['api']['cancel_url']).netloc
assert urlparse.urlparse(resp.json['api']['ics_url']).netloc
@ -1117,9 +1120,12 @@ def test_booking_api_fillslots(app, some_data, user):
primary_booking_id = resp.json['booking_id']
Booking.objects.get(id=primary_booking_id)
assert resp.json['datetime'] == localtime(event.start_datetime).strftime('%Y-%m-%d %H:%M:%S')
assert 'booking_url' in resp.json['api']
assert 'accept_url' in resp.json['api']
assert 'suspend_url' in resp.json['api']
assert 'cancel_url' in resp.json['api']
assert urlparse.urlparse(resp.json['api']['booking_url']).netloc
assert urlparse.urlparse(resp.json['api']['accept_url']).netloc
assert urlparse.urlparse(resp.json['api']['suspend_url']).netloc
assert urlparse.urlparse(resp.json['api']['cancel_url']).netloc
assert Booking.objects.count() == 3
@ -1904,6 +1910,117 @@ def test_booking_api_with_cancel_booking(app, some_data, user):
assert Booking.objects.count() == 6
@pytest.mark.parametrize('flag', [True, False, None])
def test_booking_api_present(app, user, flag):
agenda = Agenda.objects.create(kind='events')
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
booking = Booking.objects.create(event=event, user_was_present=flag)
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.get('/api/booking/%s/' % booking.pk)
assert resp.json['booking_id'] == booking.pk
assert resp.json['user_was_present'] == flag
@pytest.mark.parametrize('flag', [True, False])
def test_booking_api_waiting_list(app, user, flag):
agenda = Agenda.objects.create(kind='events')
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
booking = Booking.objects.create(event=event, in_waiting_list=flag)
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.get('/api/booking/%s/' % booking.pk)
assert resp.json['booking_id'] == booking.pk
assert resp.json['in_waiting_list'] == flag
def test_booking_api_error(app, user):
agenda = Agenda.objects.create(kind='events')
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
booking = Booking.objects.create(event=event)
app.authorization = ('Basic', ('john.doe', 'password'))
# unknown
booking.cancel()
for method in ['get', 'delete', 'patch']:
getattr(app, method)('/api/booking/0/', status=404)
# cancelled
booking.cancel()
for method in ['get', 'delete', 'patch']:
resp = getattr(app, method)('/api/booking/%s/' % booking.pk)
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'booking is cancelled'
# not a primary booking
secondary = Booking.objects.create(event=event, primary_booking=booking)
for method in ['get', 'delete', 'patch']:
resp = getattr(app, method)('/api/booking/%s/' % secondary.pk)
assert resp.json['err'] == 2
assert resp.json['err_desc'] == 'secondary booking'
# in waiting list
booking.cancellation_datetime = None
booking.in_waiting_list = True
booking.save()
resp = app.get('/api/booking/%s/' % booking.pk)
assert resp.json['err'] == 0
resp = app.patch('/api/booking/%s/' % booking.pk)
assert resp.json['err'] == 3
assert resp.json['err_desc'] == 'booking is in waiting list'
resp = app.delete('/api/booking/%s/' % booking.pk)
assert resp.json['err'] == 0
def test_booking_patch_api(app, user):
agenda = Agenda.objects.create(kind='events')
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
booking = Booking.objects.create(event=event)
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.patch('/api/booking/%s/' % booking.pk)
assert resp.json['err'] == 0
resp = app.patch('/api/booking/%s/' % booking.pk, params={'user_was_present': 'foobar'}, status=400)
assert resp.json['err'] == 4
assert resp.json['err_desc'] == 'invalid payload'
@pytest.mark.parametrize('flag', [True, False, None])
def test_booking_patch_api_present(app, user, flag):
agenda = Agenda.objects.create(kind='events')
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10)
booking = Booking.objects.create(event=event)
app.authorization = ('Basic', ('john.doe', 'password'))
# set flag
app.patch_json('/api/booking/%s/' % booking.pk, params={'user_was_present': flag})
booking.refresh_from_db()
assert booking.user_was_present == flag
# reset
app.patch_json('/api/booking/%s/' % booking.pk, params={'user_was_present': None})
booking.refresh_from_db()
assert booking.user_was_present is None
# make secondary bookings
Booking.objects.create(event=event, primary_booking=booking)
Booking.objects.create(event=event, primary_booking=booking)
# and other booking
other_booking = Booking.objects.create(event=event)
app.patch_json('/api/booking/%s/' % booking.pk, params={'user_was_present': flag})
booking.refresh_from_db()
assert booking.user_was_present == flag
# all secondary bookings are upadted
assert list(booking.secondary_booking_set.values_list('user_was_present', flat=True)) == [flag, flag]
other_booking.refresh_from_db()
assert other_booking.user_was_present is None # not changed
def test_booking_cancellation_api(app, some_data, user):
agenda = Agenda.objects.filter(label=u'Foo bar')[0]
event = [x for x in Event.objects.filter(agenda=agenda) if x.in_bookable_period()][0]