api: add an endpoint to patch an event (#57305)
This commit is contained in:
parent
9a2272396b
commit
030a355ebf
|
@ -49,6 +49,11 @@ urlpatterns = [
|
|||
views.recurring_fillslots,
|
||||
name='api-recurring-fillslots',
|
||||
),
|
||||
url(
|
||||
r'^agenda/(?P<agenda_identifier>[\w-]+)/event/(?P<event_identifier>[\w:-]+)/$',
|
||||
views.events,
|
||||
name='api-event',
|
||||
),
|
||||
url(
|
||||
r'^agenda/(?P<agenda_identifier>[\w-]+)/status/(?P<event_identifier>[\w:-]+)/$',
|
||||
views.event_status,
|
||||
|
|
|
@ -2203,6 +2203,80 @@ class ResizeBooking(APIView):
|
|||
resize_booking = ResizeBooking.as_view()
|
||||
|
||||
|
||||
class Events(APIView):
|
||||
permission_classes = (permissions.IsAuthenticated,)
|
||||
serializer_class = serializers.EventSerializer
|
||||
|
||||
def get_object(self, agenda_identifier, event_identifier):
|
||||
agenda = get_object_or_404(Agenda, slug=agenda_identifier, kind='events')
|
||||
if ':' in event_identifier:
|
||||
return get_event_recurrence(agenda, event_identifier)
|
||||
try:
|
||||
return agenda.event_set.get(slug=event_identifier)
|
||||
except Event.DoesNotExist:
|
||||
raise Http404()
|
||||
|
||||
def patch(self, request, agenda_identifier=None, event_identifier=None, format=None):
|
||||
event = self.get_object(agenda_identifier, event_identifier)
|
||||
serializer = self.serializer_class(event, data=request.data, partial=True)
|
||||
if not serializer.is_valid():
|
||||
raise APIError(
|
||||
_('invalid payload'),
|
||||
err_class='invalid payload',
|
||||
errors=serializer.errors,
|
||||
http_status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
payload = serializer.validated_data
|
||||
changed_data = []
|
||||
for field in serializer.fields.keys():
|
||||
if field in payload and payload[field] != getattr(event, field):
|
||||
changed_data.append(field)
|
||||
|
||||
if event.primary_event:
|
||||
for field in changed_data:
|
||||
if field in (
|
||||
'recurrence_end_date',
|
||||
'publication_date',
|
||||
'recurrence_days',
|
||||
'recurrence_week_interval',
|
||||
):
|
||||
raise APIError(
|
||||
_('%s cannot be modified on an event recurrence') % field,
|
||||
err_class='%s cannot be modified on an event recurrence' % field,
|
||||
http_status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
protected_fields = ['start_datetime', 'recurrence_days', 'recurrence_week_interval']
|
||||
if event.recurrence_days and event.has_recurrences_booked():
|
||||
for field in changed_data:
|
||||
if field in protected_fields:
|
||||
raise APIError(
|
||||
_('%s cannot be modified because some recurrences have bookings attached to them.')
|
||||
% field,
|
||||
err_class='%s cannot be modified because some recurrences have bookings attached to them.'
|
||||
% field,
|
||||
http_status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
if 'recurrence_end_date' in changed_data and event.has_recurrences_booked(
|
||||
after=payload['recurrence_end_date']
|
||||
):
|
||||
raise APIError(
|
||||
_('recurrence_end_date cannot be modified because bookings exist after this date.'),
|
||||
err_class='recurrence_end_date cannot be modified because bookings exist after this date.',
|
||||
http_status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
with event.update_recurrences(
|
||||
changed_data, payload, protected_fields, protected_fields + ['recurrence_end_date']
|
||||
):
|
||||
event = serializer.save()
|
||||
return Response({'err': 0, 'data': get_event_detail(request, event)})
|
||||
|
||||
|
||||
events = Events.as_view()
|
||||
|
||||
|
||||
class EventStatus(APIView):
|
||||
permission_classes = (permissions.IsAuthenticated,)
|
||||
|
||||
|
|
|
@ -331,3 +331,183 @@ def test_add_event(app, user):
|
|||
'2021-12-16',
|
||||
'2021-12-18',
|
||||
]
|
||||
|
||||
|
||||
def test_update_event(app, user):
|
||||
api_url = '/api/agenda/%s/event/%s/' % ('nop', 'nop')
|
||||
|
||||
# no authentication
|
||||
resp = app.patch(api_url, status=401)
|
||||
assert resp.json['detail'] == 'Authentication credentials were not provided.'
|
||||
|
||||
# wrong password
|
||||
app.authorization = ('Basic', ('john.doe', 'wrong'))
|
||||
resp = app.patch(api_url, status=401)
|
||||
assert resp.json['detail'] == 'Invalid username/password.'
|
||||
|
||||
app.authorization = ('Basic', ('john.doe', 'password'))
|
||||
|
||||
# missing agenda
|
||||
resp = app.patch(api_url, status=404)
|
||||
assert resp.json['detail'] == 'Not found.'
|
||||
|
||||
meeting_agenda = Agenda.objects.create(label='Foo bar Meeting', kind='meetings')
|
||||
|
||||
# using meeting agenda
|
||||
api_url = '/api/agenda/%s/event/%s/' % (meeting_agenda.slug, 'nop')
|
||||
resp = app.patch(api_url, status=404)
|
||||
assert resp.json['detail'] == 'Not found.'
|
||||
|
||||
agenda = Agenda.objects.create(label='Foo bar')
|
||||
|
||||
# missing event
|
||||
api_url = '/api/agenda/%s/event/%s/' % (agenda.slug, 'nop')
|
||||
resp = app.patch(api_url, status=404)
|
||||
assert resp.json['detail'] == 'Not found.'
|
||||
|
||||
# missing recurring event
|
||||
api_url = '/api/agenda/%s/event/%s/' % (agenda.slug, 'nop:2021-11-15-1538')
|
||||
resp = app.patch(api_url, status=400)
|
||||
assert resp.json['err']
|
||||
assert resp.json['err_desc'] == 'unknown recurring event slug: nop'
|
||||
|
||||
event = Event.objects.create(agenda=agenda, start_datetime=now(), places=10, waiting_list_places=5)
|
||||
api_url = '/api/agenda/%s/event/%s/' % (agenda.slug, event.slug)
|
||||
|
||||
# update with errors in datetime parts
|
||||
params = {
|
||||
'start_datetime': '2021-11-15 minuit',
|
||||
'recurrence_days': '7, 8',
|
||||
}
|
||||
resp = app.patch(api_url, params=params, status=400)
|
||||
assert resp.json['err']
|
||||
assert resp.json['err_desc'] == 'invalid payload'
|
||||
assert 'Datetime has wrong format' in resp.json['errors']['start_datetime'][0]
|
||||
assert resp.json['errors']['recurrence_days']['0'][0] == 'Ensure this value is less than or equal to 6.'
|
||||
|
||||
# update with almost all optional managed fields
|
||||
params = {
|
||||
'start_datetime': '2021-11-15 15:38',
|
||||
'duration': 42,
|
||||
'publication_date': '2021-09-20',
|
||||
'places': 8,
|
||||
'waiting_list_places': 3,
|
||||
'label': 'FOO camp',
|
||||
'description': 'An event',
|
||||
'pricing': 'free',
|
||||
'url': 'http://example.org/foo/bar/?',
|
||||
}
|
||||
resp = app.patch(api_url, params=params)
|
||||
assert not resp.json['err']
|
||||
event = Event.objects.filter(agenda=agenda).get(slug=event.slug)
|
||||
assert event.duration == 42
|
||||
assert event.places == 8
|
||||
assert event.waiting_list_places == 3
|
||||
assert event.label == 'FOO camp'
|
||||
assert event.description == 'An event'
|
||||
assert event.pricing == 'free'
|
||||
assert event.url == 'http://example.org/foo/bar/?'
|
||||
|
||||
# update event as a recurring event
|
||||
params = {
|
||||
'recurrence_days': '0,3,5',
|
||||
'recurrence_week_interval': 2,
|
||||
'recurrence_end_date': '2021-12-27',
|
||||
}
|
||||
resp = app.patch(api_url, params=params)
|
||||
assert not resp.json['err']
|
||||
event = Event.objects.filter(agenda=agenda).get(slug=event.slug)
|
||||
assert event.recurrences.count() == 9
|
||||
assert [x.places for x in event.recurrences.all()] == [8] * 9
|
||||
|
||||
recurrence_slug = event.recurrences.first().slug
|
||||
assert recurrence_slug == 'foo-bar-event--2021-11-15-1538'
|
||||
recurrence_url = '/api/agenda/%s/event/%s/' % (agenda.slug, 'foo-bar-event:2021-11-15-1538')
|
||||
|
||||
# update unprotected fields of one of the event recurrencies
|
||||
params = {
|
||||
'start_datetime': '2021-11-14 14:00',
|
||||
'duration': 43,
|
||||
'places': 9,
|
||||
'waiting_list_places': 4,
|
||||
'label': 'BAR camp',
|
||||
'description': 'An occurence of an event recurrence',
|
||||
'pricing': '5€',
|
||||
'url': 'http://example.org/bar/bar/',
|
||||
}
|
||||
resp = app.patch(recurrence_url, params=params)
|
||||
assert not resp.json['err']
|
||||
recurrence = Event.objects.filter(agenda=agenda).get(slug=recurrence_slug)
|
||||
assert recurrence.duration == 43
|
||||
assert recurrence.places == 9
|
||||
assert recurrence.waiting_list_places == 4
|
||||
assert recurrence.label == 'BAR camp'
|
||||
assert recurrence.description == 'An occurence of an event recurrence'
|
||||
assert recurrence.pricing == '5€'
|
||||
assert recurrence.url == 'http://example.org/bar/bar/'
|
||||
|
||||
# try to update protected fields of one of the event recurrencies
|
||||
params = {
|
||||
'publication_date': '2021-11-15',
|
||||
}
|
||||
resp = app.patch(recurrence_url, params=params, status=400)
|
||||
assert resp.json['err']
|
||||
assert 'cannot be modified' in resp.json['err_desc']
|
||||
|
||||
# update protected fields of one of the event recurrencies providing same value
|
||||
assert 'cannot be modified' in resp.json['err_desc']
|
||||
params = {
|
||||
'recurrence_week_interval': 1,
|
||||
}
|
||||
resp = app.patch(recurrence_url, params=params)
|
||||
assert not resp.json['err']
|
||||
|
||||
booking = Booking.objects.create(event=event.recurrences.all()[2])
|
||||
|
||||
# update unprotected fields
|
||||
params = {
|
||||
'places': 7,
|
||||
}
|
||||
resp = app.patch(api_url, params=params)
|
||||
assert not resp.json['err']
|
||||
event = Event.objects.filter(agenda=agenda).get(slug=event.slug)
|
||||
assert [x.places for x in event.recurrences.all()] == [7] * 9
|
||||
|
||||
# try to update recurring event protected fields
|
||||
params = {
|
||||
'recurrence_days': '1,2',
|
||||
}
|
||||
resp = app.patch(api_url, params=params, status=400)
|
||||
assert resp.json['err']
|
||||
assert 'cannot be modified' in resp.json['err_desc']
|
||||
|
||||
assert booking.event.start_datetime.date() == datetime.date(2021, 11, 20)
|
||||
|
||||
# try to reduce recurrence end date before booked event
|
||||
params = {
|
||||
'recurrence_end_date': '2021-11-20',
|
||||
}
|
||||
resp = app.patch(api_url, params=params, status=400)
|
||||
assert resp.json['err']
|
||||
assert 'bookings exist after this date.' in resp.json['err_desc']
|
||||
|
||||
# reduce recurrence end date after booked event
|
||||
params = {
|
||||
'recurrence_end_date': '2021-11-21',
|
||||
}
|
||||
resp = app.patch(api_url, params=params)
|
||||
assert not resp.json['err']
|
||||
event = Event.objects.filter(agenda=agenda).get(slug=event.slug)
|
||||
assert event.recurrences.count() == 3
|
||||
|
||||
booking.cancel()
|
||||
|
||||
# update no more protected fields
|
||||
params = {
|
||||
'recurrence_days': '1,2,3,4,5',
|
||||
'recurrence_week_interval': 1,
|
||||
}
|
||||
resp = app.patch(api_url, params=params)
|
||||
assert not resp.json['err']
|
||||
event = Event.objects.filter(agenda=agenda).get(slug=event.slug)
|
||||
assert event.recurrences.count() == 5
|
||||
|
|
Loading…
Reference in New Issue