api: allow empty slots parameter in multiple event booking (#56000)

This commit is contained in:
Valentin Deniaud 2021-08-05 15:39:59 +02:00
parent 96b10d052b
commit 89ccbc922a
2 changed files with 27 additions and 7 deletions

View File

@ -585,7 +585,7 @@ def get_events_from_slots(slots, request, agenda, payload):
_('event is already booked by user'), err_class='event is already booked by user'
)
if not events.exists():
if slots and not events.exists():
raise APIError(
_('unknown event identifiers or slugs'),
err_class='unknown event identifiers or slugs',
@ -1144,7 +1144,7 @@ class SlotSerializer(serializers.Serializer):
class StringOrListField(serializers.ListField):
def to_internal_value(self, data):
if isinstance(data, str):
data = [s.strip() for s in data.split(',')]
data = [s.strip() for s in data.split(',') if s.strip()]
return super().to_internal_value(data)
@ -1163,9 +1163,13 @@ class SlotsSerializer(SlotSerializer):
return attrs
class EventsSlotsSerializer(SlotsSerializer):
class EventsSlotsSerializer(SlotSerializer):
slots = StringOrListField(required=True, child=serializers.CharField(max_length=160))
def validate(self, attrs):
super().validate(attrs)
if not 'slots' in attrs:
raise serializers.ValidationError({'slots': _('This field is required.')})
if not attrs.get('user_external_id'):
raise serializers.ValidationError({'user_external_id': _('This field is required.')})
return attrs
@ -1599,7 +1603,7 @@ class RecurringFillslots(APIView):
for slug, days in slots.items():
event_filter |= Q(agenda=agenda, primary_event__slug=slug, start_datetime__week_day__in=days)
events_to_book = Event.objects.filter(event_filter)
events_to_book = Event.objects.filter(event_filter) if event_filter else Event.objects.none()
events_to_book = events_to_book.filter(start_datetime__gte=start_datetime, cancelled=False)
if end_datetime:
events_to_book = events_to_book.filter(start_datetime__lte=end_datetime)

View File

@ -381,7 +381,7 @@ def test_booking_api_fillslots(app, some_data, user):
resp = app.post_json('/api/agenda/%s/fillslots/' % agenda.id, params={'slots': ''}, status=400)
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'invalid payload'
assert resp.json['errors']['slots']['0'] == ['This field may not be blank.']
assert resp.json['errors']['slots'] == ['This field is required.']
# invalid slots format
resp = app.post_json('/api/agenda/%s/fillslots/' % agenda.id, params={'slots': 'foobar'}, status=400)
assert resp.json['err'] == 1
@ -2184,12 +2184,16 @@ def test_recurring_events_api_fillslots(app, user, freezer):
assert resp.json['booking_count'] == 4
assert Booking.objects.filter(user_external_id='user_id_4').count() == 4
del params['user_external_id']
resp = app.post_json(fillslots_url, params=params, status=400)
resp = app.post_json(fillslots_url, params={'slots': 'event:0'}, status=400)
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'invalid payload'
assert resp.json['errors']['user_external_id'] == ['This field is required.']
resp = app.post_json(fillslots_url, params={'user_external_id': 'a'}, status=400)
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'invalid payload'
assert resp.json['errors']['slots'] == ['This field is required.']
resp = app.post_json(fillslots_url, params={'user_external_id': 'a', 'slots': 'a:a'}, status=400)
assert resp.json['err'] == 1
assert resp.json['err_desc'] == 'invalid slot: a:a'
@ -2291,6 +2295,12 @@ def test_recurring_events_api_fillslots_change_bookings(app, user, freezer):
assert events.filter(booked_places_count=1).count() == 156
assert events.filter(waiting_list_count=1).count() == 52
# passing empty slots cancels all bookings
params['slots'] = ''
resp = app.post_json(fillslots_url, params=params)
assert resp.json['cancelled_booking_count'] == 104
assert Booking.objects.filter(user_external_id='user_id_2').count() == 0
# only recurring events are impacted
normal_event = Event.objects.create(
start_datetime=now() + datetime.timedelta(days=1), places=2, agenda=agenda
@ -2375,6 +2385,12 @@ def test_api_events_fillslots(app, user):
# new event booking went in waiting list despite free slots on main list
assert Booking.objects.filter(in_waiting_list=True, event=event).count() == 2
# passing empty slots cancels all bookings
params['slots'] = ''
resp = app.post_json(fillslots_url, params=params)
assert resp.json['cancelled_booking_count'] == 3
assert Booking.objects.filter(user_external_id='user_id').count() == 0
resp = app.post('/api/agenda/foobar/events/fillslots/', status=404)
resp = app.post('/api/agenda/0/events/fillslots/', status=404)