diff --git a/arkindex/documents/api/elements.py b/arkindex/documents/api/elements.py index b93ab14ab7889df95e9c71a82adf7ba99c8ef7a8..ea5dd24839551682922bc8197905e12a3fb91643 100644 --- a/arkindex/documents/api/elements.py +++ b/arkindex/documents/api/elements.py @@ -873,8 +873,20 @@ class ElementChildren(ElementsListBase): get=extend_schema(description="Retrieve a single element's information and metadata"), patch=extend_schema(description='Rename an element'), put=extend_schema(description="Edit an element's attributes. Requires a write access on the corpus."), - delete=extend_schema(description='Delete an element. Requires either an admin access on the corpus, ' - 'or a write access and to be the creator of this element.'), + delete=extend_schema( + description='Delete an element. Requires either an admin access on the corpus, ' + 'or a write access and to be the creator of this element.', + parameters=[ + OpenApiParameter( + 'delete_children', + description='Delete all child elements of this element recursively. ' + 'By default, this only removes this element as a parent of the child elements, ' + 'without deleting any child element.', + type=bool, + required=False, + ), + ], + ), ) class ElementRetrieve(ACLMixin, RetrieveUpdateDestroyAPIView): serializer_class = ElementSerializer @@ -923,8 +935,12 @@ class ElementRetrieve(ACLMixin, RetrieveUpdateDestroyAPIView): def delete(self, request, *args, **kwargs): self.check_object_permissions(self.request, self.get_object()) + queryset = Element.objects.filter(id=self.kwargs['pk']) - element_trash(queryset, user_id=self.request.user.id) + delete_children = self.request.query_params.get('delete_children', 'false').lower() not in ('false', '0') + + element_trash(queryset, user_id=self.request.user.id, delete_children=delete_children) + return Response(status=status.HTTP_204_NO_CONTENT) diff --git a/arkindex/documents/tests/test_destroy_elements.py b/arkindex/documents/tests/test_destroy_elements.py index 34be212608692331e46a39e1837409e9b22f822d..06823b9c1a15c40dbb14a988243796a7731f33b8 100644 --- a/arkindex/documents/tests/test_destroy_elements.py +++ b/arkindex/documents/tests/test_destroy_elements.py @@ -58,11 +58,41 @@ class TestDestroyElements(FixtureAPITestCase): self.assertEqual(len(args), 0) self.assertCountEqual(list(kwargs.pop('queryset')), list(self.corpus.elements.filter(id=castle_story.id))) self.assertDictEqual(kwargs, { - 'delete_children': True, + 'delete_children': False, 'user_id': self.user.id, 'description': 'Element deletion', }) + @patch('arkindex.project.triggers.documents_tasks.element_trash.delay') + def test_element_destroy_delete_children(self, delay_mock): + self.client.force_login(self.user) + castle_story = self.corpus.elements.create( + type=self.volume_type, + name='Castle story' + ) + self.assertTrue(self.corpus.elements.filter(id=castle_story.id).exists()) + + for delete_children in [True, False]: + with self.subTest(delete_children=delete_children): + delay_mock.reset_mock() + + with self.assertNumQueries(7): + response = self.client.delete( + reverse('api:element-retrieve', kwargs={'pk': str(castle_story.id)}) + + f'?delete_children={delete_children}', + ) + self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) + + self.assertEqual(delay_mock.call_count, 1) + args, kwargs = delay_mock.call_args + self.assertEqual(len(args), 0) + self.assertCountEqual(list(kwargs.pop('queryset')), list(self.corpus.elements.filter(id=castle_story.id))) + self.assertDictEqual(kwargs, { + 'delete_children': delete_children, + 'user_id': self.user.id, + 'description': 'Element deletion', + }) + @patch('arkindex.project.triggers.documents_tasks.element_trash.delay') def test_element_destroy_creator(self, delay_mock): """ @@ -84,7 +114,7 @@ class TestDestroyElements(FixtureAPITestCase): self.assertEqual(len(args), 0) self.assertCountEqual(list(kwargs.pop('queryset')), list(self.private_corpus.elements.filter(id=castle_story.id))) self.assertDictEqual(kwargs, { - 'delete_children': True, + 'delete_children': False, 'user_id': self.user.id, 'description': 'Element deletion', }) @@ -123,7 +153,7 @@ class TestDestroyElements(FixtureAPITestCase): self.assertEqual(len(args), 0) self.assertCountEqual(list(kwargs.pop('queryset')), list(self.corpus.elements.filter(id=self.vol.id))) self.assertDictEqual(kwargs, { - 'delete_children': True, + 'delete_children': False, 'user_id': self.user.id, 'description': 'Element deletion', })