api: allow empty slots parameter in multiple event booking (#56000)
This commit is contained in:
parent
96b10d052b
commit
89ccbc922a
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
Loading…
Reference in New Issue