From 2ac57e72bd6ee3ab5eed1dc5ab5f228d36e4814a Mon Sep 17 00:00:00 2001 From: Valentin Deniaud Date: Thu, 9 Dec 2021 16:44:41 +0100 Subject: [PATCH] api: add agenda deletion (#59127) --- chrono/api/urls.py | 2 +- chrono/api/views.py | 23 ++++++++++++++++------- tests/api/test_all.py | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 8 deletions(-) diff --git a/chrono/api/urls.py b/chrono/api/urls.py index 424c5f7c..73f3280c 100644 --- a/chrono/api/urls.py +++ b/chrono/api/urls.py @@ -28,7 +28,7 @@ urlpatterns = [ views.agendas_events_fillslots, name='api-agendas-events-fillslots', ), - url(r'^agenda/(?P[\w-]+)/$', views.agenda_detail), + url(r'^agenda/(?P[\w-]+)/$', views.agenda), url(r'^agenda/(?P[\w-]+)/datetimes/$', views.datetimes, name='api-agenda-datetimes'), url( r'^agenda/(?P[\w-]+)/fillslot/(?P[\w:-]+)/$', diff --git a/chrono/api/views.py b/chrono/api/views.py index 65d29b46..845164c8 100644 --- a/chrono/api/views.py +++ b/chrono/api/views.py @@ -757,19 +757,28 @@ class Agendas(APIView): agendas = Agendas.as_view() -class AgendaDetail(APIView): - """ - Retrieve an agenda instance. - """ - - permission_classes = () +class AgendaAPI(APIView): + permission_classes = (permissions.IsAuthenticatedOrReadOnly,) def get(self, request, agenda_identifier): agenda = get_object_or_404(Agenda, slug=agenda_identifier) return Response({'data': get_agenda_detail(request, agenda, check_events=True)}) + def delete(self, request, agenda_identifier): + agenda = get_object_or_404(Agenda, slug=agenda_identifier) + + has_bookings = Booking.objects.filter( + event__agenda=agenda, event__start_datetime__gt=now(), cancellation_datetime__isnull=True + ).exists() + + if has_bookings: + raise APIError(_('This cannot be removed as there are bookings for a future date.')) + + agenda.delete() + return Response({'err': 0}) + -agenda_detail = AgendaDetail.as_view() +agenda = AgendaAPI.as_view() class Datetimes(APIView): diff --git a/tests/api/test_all.py b/tests/api/test_all.py index 34861590..d493ca4e 100644 --- a/tests/api/test_all.py +++ b/tests/api/test_all.py @@ -10,6 +10,7 @@ from chrono.agendas.models import ( AbsenceReason, AbsenceReasonGroup, Agenda, + Booking, Category, Desk, Event, @@ -525,6 +526,37 @@ def test_virtual_agenda_detail(app, virtual_meetings_agenda): } +def test_agenda_api_delete(app, user): + agenda = Agenda.objects.create(label='Foo bar', kind='events') + + # unauthenticated + resp = app.delete('/api/agenda/%s/' % agenda.slug, status=401) + assert Agenda.objects.count() == 1 + + app.authorization = ('Basic', ('john.doe', 'password')) + resp = app.delete('/api/agenda/%s/' % agenda.slug) + assert resp.json['err'] == 0 + assert not Agenda.objects.exists() + + +def test_agenda_api_delete_busy(app, user): + agenda = Agenda.objects.create(label='Foo bar', kind='events') + Desk.objects.create(agenda=agenda, slug='_exceptions_holder') + event = Event.objects.create(start_datetime=now() + datetime.timedelta(days=10), places=10, agenda=agenda) + booking = Booking.objects.create(event=event) + + app.authorization = ('Basic', ('john.doe', 'password')) + resp = app.delete('/api/agenda/%s/' % agenda.slug) + assert resp.json['err'] == 1 + assert 'This cannot be removed' in resp.json['err_desc'] + + booking.cancellation_datetime = now() + booking.save() + resp = app.delete('/api/agenda/%s/' % agenda.slug) + assert resp.json['err'] == 0 + assert not Agenda.objects.exists() + + def test_virtual_agendas_meetingtypes_api(app): virt_agenda = Agenda.objects.create(label='Virtual agenda', kind='virtual') -- 2.30.2