api: add a suspend action on Booking (#40018)

This commit is contained in:
Lauréline Guérin 2020-02-21 16:15:12 +01:00
parent 22ee564730
commit 8d327c0dfe
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
4 changed files with 80 additions and 0 deletions

View File

@ -475,6 +475,12 @@ class Booking(models.Model):
self.secondary_booking_set.update(in_waiting_list=False)
self.save()
def suspend(self):
self.in_waiting_list = True
with transaction.atomic():
self.secondary_booking_set.update(in_waiting_list=True)
self.save()
def get_ics(self, request=None):
ics = vobject.iCalendar()
ics.add('prodid').value = '-//Entr\'ouvert//NON SGML Publik'

View File

@ -48,5 +48,6 @@ urlpatterns = [
url(r'^booking/(?P<booking_pk>\w+)/$', views.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'),
url(r'^booking/(?P<booking_pk>\w+)/ics/$', views.booking_ics, name='api-booking-ics'),
]

View File

@ -658,6 +658,10 @@ class Fillslots(APIView):
response['api']['accept_url'] = request.build_absolute_uri(
reverse('api-accept-booking', kwargs={'booking_pk': primary_booking.id})
)
else:
response['api']['suspend_url'] = request.build_absolute_uri(
reverse('api-suspend-booking', kwargs={'booking_pk': primary_booking.pk})
)
if agenda.kind == 'meetings':
response['end_datetime'] = format_response_datetime(events[-1].end_datetime)
response['duration'] = (events[-1].end_datetime - events[-1].start_datetime).seconds // 60
@ -776,6 +780,40 @@ class AcceptBooking(APIView):
accept_booking = AcceptBooking.as_view()
class SuspendBooking(APIView):
'''
Suspend a accepted booking.
It will return error codes if the booking was cancelled before (code 1) and
if the bookingis already in waiting list (code 2).
'''
permission_classes = (permissions.IsAuthenticated,)
def post(self, request, booking_pk=None, format=None):
booking = get_object_or_404(Booking, pk=booking_pk)
if booking.cancellation_datetime:
response = {
'err': 1,
'err_class': 'booking is cancelled',
'err_desc': _('booking is cancelled'),
}
return Response(response)
if booking.in_waiting_list:
response = {
'err': 2,
'err_class': 'booking is already in waiting list',
'err_desc': _('booking is already in waiting list'),
}
return Response(response)
booking.suspend()
response = {'err': 0, 'booking_id': booking.pk}
return Response(response)
suspend_booking = SuspendBooking.as_view()
class SlotStatus(APIView):
permission_classes = (permissions.IsAuthenticated,)

View File

@ -410,8 +410,10 @@ def test_booking_api(app, some_data, user):
Booking.objects.get(id=resp.json['booking_id'])
assert resp.json['datetime'] == localtime(event.start_datetime).strftime('%Y-%m-%d %H:%M:%S')
assert 'accept_url' not 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']['suspend_url']).netloc
assert urlparse.urlparse(resp.json['api']['cancel_url']).netloc
assert urlparse.urlparse(resp.json['api']['ics_url']).netloc
assert Booking.objects.count() == 1
@ -606,7 +608,9 @@ def test_booking_api_fillslots(app, some_data, user):
Booking.objects.get(id=primary_booking_id)
assert resp.json['datetime'] == localtime(event.start_datetime).strftime('%Y-%m-%d %H:%M:%S')
assert 'accept_url' not in resp.json['api']
assert 'suspend_url' in resp.json['api']
assert 'cancel_url' in resp.json['api']
assert urlparse.urlparse(resp.json['api']['suspend_url']).netloc
assert urlparse.urlparse(resp.json['api']['cancel_url']).netloc
assert Booking.objects.count() == 3
# these 3 bookings are related, the first is the primary one
@ -1201,6 +1205,7 @@ def test_waiting_list_booking(app, some_data, user):
assert resp.json['err'] == 0
assert resp.json['in_waiting_list'] is True
assert 'accept_url' in resp.json['api']
assert 'suspend_url' not in resp.json['api']
assert 'cancel_url' in resp.json['api']
assert 'ics_url' in resp.json['api']
assert urlparse.urlparse(resp.json['api']['accept_url']).netloc
@ -1263,6 +1268,36 @@ def test_accept_booking(app, some_data, user):
assert Booking.objects.filter(in_waiting_list=False).count() == 0
def test_suspend_booking(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]
event.waiting_list_places = 5
event.save()
# create a booking not on the waiting list
booking = Booking.objects.create(event=event, in_waiting_list=False)
assert booking.in_waiting_list is False
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.post('/api/booking/%s/suspend/' % booking.pk)
booking.refresh_from_db()
assert booking.in_waiting_list is True
# suspend a booking that doesn't exist
resp = app.post('/api/booking/0/suspend/', status=404)
# suspend a booking that is in the waiting list
resp = app.post('/api/booking/%s/suspend/' % booking.pk, status=200)
assert resp.json['err'] == 2
# suspend a booking that was cancelled before
booking.in_waiting_list = False
booking.cancel()
resp = app.post('/api/booking/%s/suspend/' % booking.pk, status=200)
assert resp.json['err'] == 1
assert booking.in_waiting_list is False
def test_multiple_booking_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]