diff --git a/CHANGELOG b/CHANGELOG index c51d10445..ba6ef1179 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -15,6 +15,7 @@ Agenda: - Removed mptt. Assignments: - Renamed app from assignment to assignments. +- Removed possibility to block candidates. - Massive refactoring and cleanup of the app. Motions: - Renamed app from motion to motions. diff --git a/openslides/assignments/migrations/0005_auto_20160109_1624.py b/openslides/assignments/migrations/0005_auto_20160109_1624.py new file mode 100644 index 000000000..a86b98afe --- /dev/null +++ b/openslides/assignments/migrations/0005_auto_20160109_1624.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('assignments', '0004_auto_20160109_1329'), + ] + + operations = [ + migrations.RemoveField( + model_name='assignmentrelateduser', + name='status', + ), + migrations.AddField( + model_name='assignmentrelateduser', + name='elected', + field=models.BooleanField(default=False), + ), + ] diff --git a/openslides/assignments/models.py b/openslides/assignments/models.py index 719f01edb..3b3d0c242 100644 --- a/openslides/assignments/models.py +++ b/openslides/assignments/models.py @@ -24,15 +24,6 @@ class AssignmentRelatedUser(RESTModelMixin, models.Model): """ Many to Many table between an assignment and user. """ - STATUS_CANDIDATE = 1 - STATUS_ELECTED = 2 - STATUS_BLOCKED = 3 - STATUSES = ( - (STATUS_CANDIDATE, ugettext_lazy('candidate')), - (STATUS_ELECTED, ugettext_lazy('elected')), - (STATUS_BLOCKED, ugettext_lazy('blocked')), - ) - assignment = models.ForeignKey( 'Assignment', on_delete=models.CASCADE, @@ -40,9 +31,7 @@ class AssignmentRelatedUser(RESTModelMixin, models.Model): user = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE) - status = models.IntegerField( - choices=STATUSES, - default=STATUS_CANDIDATE) + elected = models.BooleanField(default=False) class Meta: default_permissions = () @@ -106,9 +95,9 @@ class Assignment(RESTModelMixin, models.Model): settings.AUTH_USER_MODEL, through='AssignmentRelatedUser') """ - Users that are candidates, elected or blocked as candidate. + Users that are candidates or elected. - See AssignmentRelatedUser for more infos. + See AssignmentRelatedUser for more information. """ tags = models.ManyToManyField(Tag, blank=True) @@ -145,7 +134,7 @@ class Assignment(RESTModelMixin, models.Model): Queryset that represents the candidates for the assignment. """ return self.related_users.filter( - assignmentrelateduser__status=AssignmentRelatedUser.STATUS_CANDIDATE) + assignmentrelateduser__elected=False) @property def elected(self): @@ -153,15 +142,7 @@ class Assignment(RESTModelMixin, models.Model): Queryset that represents all elected users for the assignment. """ return self.related_users.filter( - assignmentrelateduser__status=AssignmentRelatedUser.STATUS_ELECTED) - - @property - def blocked(self): - """ - Queryset that represents all blocked users for the assignment. - """ - return self.related_users.filter( - assignmentrelateduser__status=AssignmentRelatedUser.STATUS_BLOCKED) + assignmentrelateduser__elected=True) def is_candidate(self, user): """ @@ -179,21 +160,13 @@ class Assignment(RESTModelMixin, models.Model): """ return self.elected.filter(pk=user.pk).exists() - def is_blocked(self, user): - """ - Returns True if the user is blocked for candidature. - - Costs one database query. - """ - return self.blocked.filter(pk=user.pk).exists() - def set_candidate(self, user): """ Adds the user as candidate. """ related_user, __ = self.assignment_related_users.update_or_create( user=user, - defaults={'status': AssignmentRelatedUser.STATUS_CANDIDATE}) + defaults={'elected': False}) def set_elected(self, user): """ @@ -201,15 +174,7 @@ class Assignment(RESTModelMixin, models.Model): """ related_user, __ = self.assignment_related_users.update_or_create( user=user, - defaults={'status': AssignmentRelatedUser.STATUS_ELECTED}) - - def set_blocked(self, user): - """ - Block user from this assignment, so he can not get an candidate. - """ - related_user, __ = self.assignment_related_users.update_or_create( - user=user, - defaults={'status': AssignmentRelatedUser.STATUS_BLOCKED}) + defaults={'elected': True}) def delete_related_user(self, user): """ diff --git a/openslides/assignments/serializers.py b/openslides/assignments/serializers.py index 9a6766e9c..f14968be3 100644 --- a/openslides/assignments/serializers.py +++ b/openslides/assignments/serializers.py @@ -29,7 +29,7 @@ class AssignmentRelatedUserSerializer(ModelSerializer): fields = ( 'id', 'user', - 'status', + 'elected', 'assignment') # js-data needs the assignment-id in the nested object to define relations. diff --git a/openslides/assignments/views.py b/openslides/assignments/views.py index f0c45c325..fac971a3c 100644 --- a/openslides/assignments/views.py +++ b/openslides/assignments/views.py @@ -107,7 +107,7 @@ class AssignmentViewSet(ModelViewSet): return _('You were nominated successfully.') def withdraw_self(self, request, assignment): - # Withdraw candidature and set self blocked. + # Withdraw candidature. if assignment.phase == assignment.PHASE_FINISHED: raise ValidationError({'detail': _('You can not withdraw your candidature to this election because it is finished.')}) if assignment.phase == assignment.PHASE_VOTING and not request.user.has_perm('assignments.can_manage'): @@ -115,16 +115,14 @@ class AssignmentViewSet(ModelViewSet): self.permission_denied(request) if not assignment.is_candidate(request.user): raise ValidationError({'detail': _('You are not a candidate of this election.')}) - assignment.set_blocked(request.user) - return _( - 'You have withdrawn your candidature successfully. ' - 'You can not be nominated by other participants anymore.') + assignment.delete_related_user(request.user) + return _('You have withdrawn your candidature successfully.') def get_user_from_request_data(self, request): """ Helper method to get a specific user from request data (not the request.user) so that the views self.candidature_other or - self.mark_elected can play with him. + self.mark_elected can play with it. """ if not isinstance(request.data, dict): detail = _('Invalid data. Expected dictionary, got %s.') % type(request.data) @@ -165,8 +163,6 @@ class AssignmentViewSet(ModelViewSet): # To nominate another user during voting you have to be a manager. self.permission_denied(request) if not request.user.has_perm('assignments.can_manage'): - if assignment.is_blocked(user): - raise ValidationError({'detail': _('User %s does not want to be a candidate. Only a manager can do this.') % user}) if assignment.is_elected(user): raise ValidationError({'detail': _('User %s is already elected.') % user}) if assignment.is_candidate(user): @@ -181,10 +177,10 @@ class AssignmentViewSet(ModelViewSet): if assignment.phase == assignment.PHASE_FINISHED: detail = _('You can not delete someones candidature to this election because it is finished.') raise ValidationError({'detail': detail}) - if not assignment.is_candidate(user) and not assignment.is_blocked(user): + if not assignment.is_candidate(user): raise ValidationError({'detail': _('User %s has no status in this election.') % user}) assignment.delete_related_user(user) - return _('Candidate %s was withdrawn/unblocked successfully.') % user + return _('Candidate %s was withdrawn successfully.') % user @detail_route(methods=['post', 'delete']) def mark_elected(self, request, pk=None): diff --git a/tests/integration/assignments/test_viewset.py b/tests/integration/assignments/test_viewset.py index 06892faee..75027d1f0 100644 --- a/tests/integration/assignments/test_viewset.py +++ b/tests/integration/assignments/test_viewset.py @@ -65,7 +65,6 @@ class CanidatureSelf(TestCase): self.assertEqual(response.status_code, 200) self.assertFalse(Assignment.objects.get(pk=self.assignment.pk).candidates.filter(username='admin').exists()) - self.assertTrue(Assignment.objects.get(pk=self.assignment.pk).blocked.filter(username='admin').exists()) def test_withdraw_self_twice(self): response = self.client.delete(reverse('assignment-candidature-self', args=[self.assignment.pk])) @@ -90,7 +89,6 @@ class CanidatureSelf(TestCase): self.assertEqual(response.status_code, 200) self.assertFalse(Assignment.objects.get(pk=self.assignment.pk).candidates.exists()) - self.assertTrue(Assignment.objects.get(pk=self.assignment.pk).blocked.filter(username='admin').exists()) def test_withdraw_self_during_voting_non_admin(self): self.assignment.set_candidate(get_user_model().objects.get(username='admin'))