api: cancel a booking when making a new one (#33489)
This commit is contained in:
parent
aeea3b78d6
commit
ab9ff7adf1
|
@ -18,6 +18,7 @@ from collections import defaultdict
|
|||
import datetime
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.db import transaction
|
||||
from django.http import Http404, HttpResponse
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils.dateparse import parse_date
|
||||
|
@ -315,6 +316,7 @@ class SlotSerializer(serializers.Serializer):
|
|||
user_display_label = serializers.CharField(max_length=250, allow_blank=True)
|
||||
backoffice_url = serializers.URLField(allow_blank=True)
|
||||
count = serializers.IntegerField(min_value=1)
|
||||
cancel_booking_id = serializers.IntegerField()
|
||||
|
||||
|
||||
class SlotsSerializer(SlotSerializer):
|
||||
|
@ -381,6 +383,23 @@ class Fillslots(APIView):
|
|||
'reason': 'count cannot be less than or equal to zero'
|
||||
}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
to_cancel_booking = None
|
||||
if 'cancel_booking_id' in payload:
|
||||
cancel_error = None
|
||||
try:
|
||||
to_cancel_booking = Booking.objects.get(pk=payload.get('cancel_booking_id'))
|
||||
if to_cancel_booking.cancellation_datetime:
|
||||
cancel_error = 'cancel booking: booking already cancelled'
|
||||
else:
|
||||
to_cancel_places_count = to_cancel_booking.secondary_booking_set.count() + 1
|
||||
if places_count != to_cancel_places_count:
|
||||
cancel_error = 'cancel booking: count is different'
|
||||
except Booking.DoesNotExist:
|
||||
cancel_error = 'cancel booking: booking does no exist'
|
||||
|
||||
if cancel_error:
|
||||
return Response({'err': 1, 'reason': cancel_error})
|
||||
|
||||
extra_data = {}
|
||||
for k, v in request.data.items():
|
||||
if k not in serializer.validated_data:
|
||||
|
@ -447,22 +466,27 @@ class Fillslots(APIView):
|
|||
if (event.booked_places + places_count) > event.places:
|
||||
return Response({'err': 1, 'reason': 'sold out'})
|
||||
|
||||
# now we have a list of events, book them.
|
||||
primary_booking = None
|
||||
for event in events:
|
||||
for i in range(places_count):
|
||||
new_booking = Booking(event_id=event.id,
|
||||
in_waiting_list=in_waiting_list,
|
||||
label=payload.get('label', ''),
|
||||
user_name=payload.get('user_name', ''),
|
||||
backoffice_url=payload.get('backoffice_url', ''),
|
||||
user_display_label=payload.get('user_display_label', ''),
|
||||
extra_data=extra_data)
|
||||
if primary_booking is not None:
|
||||
new_booking.primary_booking = primary_booking
|
||||
new_booking.save()
|
||||
if primary_booking is None:
|
||||
primary_booking = new_booking
|
||||
with transaction.atomic():
|
||||
if to_cancel_booking:
|
||||
cancelled_booking_id = to_cancel_booking.pk
|
||||
to_cancel_booking.cancel()
|
||||
|
||||
# now we have a list of events, book them.
|
||||
primary_booking = None
|
||||
for event in events:
|
||||
for i in range(places_count):
|
||||
new_booking = Booking(event_id=event.id,
|
||||
in_waiting_list=in_waiting_list,
|
||||
label=payload.get('label', ''),
|
||||
user_name=payload.get('user_name', ''),
|
||||
backoffice_url=payload.get('backoffice_url', ''),
|
||||
user_display_label=payload.get('user_display_label', ''),
|
||||
extra_data=extra_data)
|
||||
if primary_booking is not None:
|
||||
new_booking.primary_booking = primary_booking
|
||||
new_booking.save()
|
||||
if primary_booking is None:
|
||||
primary_booking = new_booking
|
||||
|
||||
response = {
|
||||
'err': 0,
|
||||
|
@ -486,6 +510,8 @@ class Fillslots(APIView):
|
|||
response['desk'] = {
|
||||
'label': available_desk.label,
|
||||
'slug': available_desk.slug}
|
||||
if to_cancel_booking:
|
||||
response['cancelled_booking_id'] = cancelled_booking_id
|
||||
|
||||
return Response(response)
|
||||
|
||||
|
|
|
@ -721,6 +721,75 @@ def test_booking_api_with_data(app, some_data, user):
|
|||
assert Booking.objects.count() == 1
|
||||
assert Booking.objects.all()[0].extra_data == {'hello': 'world'}
|
||||
|
||||
|
||||
def test_booking_api_with_cancel_booking(app, some_data, user):
|
||||
agenda_id = Agenda.objects.filter(label=u'Foo bar')[0].id
|
||||
event_0, event_1, event_2, event_3 = Event.objects.filter(agenda_id=agenda_id)[0:4]
|
||||
|
||||
app.authorization = ('Basic', ('john.doe', 'password'))
|
||||
app.post_json('/api/agenda/%s/fillslot/%s/' % (agenda_id, event_0.id))
|
||||
assert Booking.objects.count() == 1
|
||||
first_booking = Booking.objects.first()
|
||||
|
||||
# Book a new event and cancel previous booking
|
||||
resp = app.post_json(
|
||||
'/api/agenda/%s/fillslot/%s/' % (agenda_id, event_1.id),
|
||||
params={'cancel_booking_id': first_booking.pk}
|
||||
)
|
||||
assert resp.json['err'] == 0
|
||||
assert resp.json['cancelled_booking_id'] == first_booking.pk
|
||||
assert Booking.objects.count() == 2
|
||||
first_booking = Booking.objects.get(pk=first_booking.pk)
|
||||
assert first_booking.cancellation_datetime
|
||||
|
||||
# Cancelling an already cancelled booking returns an error
|
||||
resp = app.post_json(
|
||||
'/api/agenda/%s/fillslot/%s/' % (agenda_id, event_1.id),
|
||||
params={'cancel_booking_id': first_booking.pk}
|
||||
)
|
||||
assert resp.json['err'] == 1
|
||||
assert resp.json['reason'] == 'cancel booking: booking already cancelled'
|
||||
assert Booking.objects.count() == 2
|
||||
|
||||
# Cancelling a non existent booking returns an error
|
||||
resp = app.post_json(
|
||||
'/api/agenda/%s/fillslot/%s/' % (agenda_id, event_1.id),
|
||||
params={'cancel_booking_id': '-1'}
|
||||
)
|
||||
assert resp.json['err'] == 1
|
||||
assert resp.json['reason'] == 'cancel booking: booking does no exist'
|
||||
assert Booking.objects.count() == 2
|
||||
|
||||
# Cancelling booking with different count than new booking
|
||||
resp = app.post_json(
|
||||
'/api/agenda/%s/fillslot/%s/' % (agenda_id, event_2.id),
|
||||
params={'count': 2}
|
||||
)
|
||||
assert resp.json['err'] == 0
|
||||
assert Booking.objects.count() == 4
|
||||
booking_id = resp.json['booking_id']
|
||||
|
||||
resp = app.post_json(
|
||||
'/api/agenda/%s/fillslot/%s/' % (agenda_id, event_3.id),
|
||||
params={'cancel_booking_id': booking_id, 'count': 1}
|
||||
)
|
||||
assert resp.json['err'] == 1
|
||||
assert resp.json['reason'] == 'cancel booking: count is different'
|
||||
assert Booking.objects.count() == 4
|
||||
|
||||
# cancel_booking_id must be an integer
|
||||
app.post_json(
|
||||
'/api/agenda/%s/fillslot/%s/' % (agenda_id, event_0.id),
|
||||
params={'cancel_booking_id': 'no an integer'},
|
||||
status=400)
|
||||
|
||||
# cancel_booking_id can't be empty if specified
|
||||
app.post_json(
|
||||
'/api/agenda/%s/fillslot/%s/' % (agenda_id, event_0.id),
|
||||
params={'cancel_booking_id': ''},
|
||||
status=400)
|
||||
|
||||
|
||||
def test_booking_cancellation_api(app, some_data, user):
|
||||
agenda_id = Agenda.objects.filter(label=u'Foo bar')[0].id
|
||||
event = Event.objects.filter(agenda_id=agenda_id)[0]
|
||||
|
|
Loading…
Reference in New Issue