From 8a8755f22dbf8a5fd7baf562c4f32cd4ccfa3aab Mon Sep 17 00:00:00 2001 From: FinnStutzenstein Date: Fri, 24 Feb 2017 08:37:27 +0100 Subject: [PATCH] Fixing create view for amendments (fixing #3004) --- openslides/motions/static/js/motions/site.js | 8 +++ .../static/templates/motions/motion-list.html | 2 +- openslides/motions/views.py | 22 +++++- tests/integration/motions/test_viewset.py | 69 ++++++++++++++++++- 4 files changed, 96 insertions(+), 5 deletions(-) diff --git a/openslides/motions/static/js/motions/site.js b/openslides/motions/static/js/motions/site.js index e40e8e174..9fa12aca8 100644 --- a/openslides/motions/static/js/motions/site.js +++ b/openslides/motions/static/js/motions/site.js @@ -1428,6 +1428,7 @@ angular.module('OpenSlidesApp.motions.site', [ Workflow.bindAll({}, $scope, 'workflows'); $scope.model = {}; + $scope.alert = {}; // Check whether this is a new amendment. var isAmendment = $scope.$parent.motion && $scope.$parent.motion.id; @@ -1464,6 +1465,13 @@ angular.module('OpenSlidesApp.motions.site', [ $state.go('motions.motion.detail', {id: success.id}); } $scope.closeThisDialog(); + }, + function (error) { + var message = ''; + for (var e in error.data) { + message += e + ': ' + error.data[e] + ' '; + } + $scope.alert = {type: 'danger', msg: message, show: true}; } ); }; diff --git a/openslides/motions/static/templates/motions/motion-list.html b/openslides/motions/static/templates/motions/motion-list.html index 92cb9363e..2b0bb6260 100644 --- a/openslides/motions/static/templates/motions/motion-list.html +++ b/openslides/motions/static/templates/motions/motion-list.html @@ -590,7 +590,7 @@
- + {{ motion.motionBlock.title }}
diff --git a/openslides/motions/views.py b/openslides/motions/views.py index ba95772f2..d8613ff38 100644 --- a/openslides/motions/views.py +++ b/openslides/motions/views.py @@ -85,14 +85,32 @@ class MotionViewSet(ModelViewSet): """ Customized view endpoint to create a new motion. """ + # Check if parent motion exists + parent_motion = None + if 'parent_id' in request.data: + try: + parent_motion = Motion.objects.get(pk=request.data['parent_id']) + except Motion.DoesNotExist: + raise ValidationError({'detail': _('The parent motion does not exist.')}) + # Check permission to send some data. if not has_perm(request.user, 'motions.can_manage'): - whitelist = ( + whitelist = [ 'title', 'text', 'reason', 'comments', # This is checked later. - ) + ] + if parent_motion: # For creating amendments. + whitelist.extend([ + 'parent_id', + 'category_id', # This will be set to the matching + 'motion_block_id', # values from parent_motion. + ]) + request.data['category_id'] = ( + parent_motion.category.id if parent_motion.category else None) + request.data['motion_block_id'] = ( + parent_motion.motion_block.id if parent_motion.motion_block else None) for key in request.data.keys(): if key not in whitelist: # Non-staff users are allowed to send only some data. diff --git a/tests/integration/motions/test_viewset.py b/tests/integration/motions/test_viewset.py index ab3e3014e..5769acdbe 100644 --- a/tests/integration/motions/test_viewset.py +++ b/tests/integration/motions/test_viewset.py @@ -264,8 +264,8 @@ class CreateMotion(TestCase): Test to create a motion by a delegate, non staff user. """ self.admin = get_user_model().objects.get(username='admin') - self.admin.groups.add(3) - self.admin.groups.remove(4) + self.admin.groups.add(2) + self.admin.groups.remove(3) response = self.client.post( reverse('motion-list'), @@ -274,6 +274,71 @@ class CreateMotion(TestCase): self.assertEqual(response.status_code, status.HTTP_201_CREATED) + def test_amendment_motion(self): + """ + Test to create a motion with a parent motion as staff user. + """ + parent_motion = self.create_parent_motion() + response = self.client.post( + reverse('motion-list'), + {'title': 'test_title_doe93Jsjd2sW20dkSl20', + 'text': 'test_text_feS20SksD8D25skmwD25', + 'parent_id': parent_motion.id}) + created_motion = Motion.objects.get(pk=int(response.data['id'])) + + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + self.assertEqual(created_motion.parent, parent_motion) + + def test_amendment_motion_parent_not_exist(self): + """ + Test to create an amendment motion with a non existing parent. + """ + response = self.client.post( + reverse('motion-list'), + {'title': 'test_title_gEjdkW93Wj23KS2s8dSe', + 'text': 'test_text_lfwLIC&AjfsaoijOEusa', + 'parent_id': 100}) + + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertEqual(response.data, {'detail': 'The parent motion does not exist.'}) + + def test_amendment_motion_non_admin(self): + """ + Test to create an amendment motion by a delegate. The parents + category should be also set on the new motion. + """ + parent_motion = self.create_parent_motion() + category = Category.objects.create( + name='test_category_name_Dslk3Fj8s8Ps36S3Kskw', + prefix='TEST_PREFIX_L23skfmlq3kslamslS39') + parent_motion.category = category + parent_motion.save() + + self.admin = get_user_model().objects.get(username='admin') + self.admin.groups.add(2) + self.admin.groups.remove(3) + + response = self.client.post( + reverse('motion-list'), + {'title': 'test_title_fk3a0slalms47KSewnWG', + 'text': 'test_text_al3FMwSCNM31WOmw9ezx', + 'parent_id': parent_motion.id}) + created_motion = Motion.objects.get(pk=int(response.data['id'])) + + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + self.assertEqual(created_motion.parent, parent_motion) + self.assertEqual(created_motion.category, category) + + def create_parent_motion(self): + """ + Returns a new created motion used for testing amendments. + """ + response = self.client.post( + reverse('motion-list'), + {'title': 'test_title_3leoeo2qac7830c92j9s', + 'text': 'test_text_9dm3ks9gDuW20Al38L9w'}) + return Motion.objects.get(pk=int(response.data['id'])) + class RetrieveMotion(TestCase): """