Merge pull request #3111 from FinnStutzenstein/Issue3103

Improving creation of ballots (fixes #3103)
This commit is contained in:
Norman Jäckel 2017-03-24 14:46:25 +01:00 committed by GitHub
commit 85d13179da
5 changed files with 19 additions and 9 deletions

View File

@ -331,7 +331,7 @@ class SpeakerManager(models.Manager):
""" """
Manager for Speaker model. Provides a customized add method. Manager for Speaker model. Provides a customized add method.
""" """
def add(self, user, item): def add(self, user, item, skip_autoupdate=False):
""" """
Customized manager method to prevent anonymous users to be on the Customized manager method to prevent anonymous users to be on the
list of speakers and that someone is twice on one list (off coming list of speakers and that someone is twice on one list (off coming
@ -345,7 +345,9 @@ class SpeakerManager(models.Manager):
_('An anonymous user can not be on lists of speakers.')) _('An anonymous user can not be on lists of speakers.'))
weight = (self.filter(item=item).aggregate( weight = (self.filter(item=item).aggregate(
models.Max('weight'))['weight__max'] or 0) models.Max('weight'))['weight__max'] or 0)
return self.create(item=item, user=user, weight=weight + 1) speaker = self.model(item=item, user=user, weight=weight + 1)
speaker.save(force_insert=True, skip_autoupdate=skip_autoupdate)
return speaker
class Speaker(RESTModelMixin, models.Model): class Speaker(RESTModelMixin, models.Model):

View File

@ -135,9 +135,13 @@ class ItemViewSet(ListModelMixin, RetrieveModelMixin, UpdateModelMixin, GenericV
except (ValueError, Speaker.DoesNotExist): except (ValueError, Speaker.DoesNotExist):
pass pass
else: else:
speaker.delete() speaker.delete(skip_autoupdate=True)
deleted_speaker_name = speaker deleted_speaker_name = speaker
deleted_speaker_count += 1 deleted_speaker_count += 1
# send autoupdate if speakers are deleted
if deleted_speaker_count > 0:
inform_changed_data(item)
if deleted_speaker_count > 1: if deleted_speaker_count > 1:
message = str(deleted_speaker_count) + ' ' + _('speakers have been removed from the list of speakers.') message = str(deleted_speaker_count) + ' ' + _('speakers have been removed from the list of speakers.')
elif deleted_speaker_count == 1: elif deleted_speaker_count == 1:

View File

@ -277,17 +277,19 @@ class Assignment(RESTModelMixin, models.Model):
options.append({ options.append({
'candidate': related_user.user, 'candidate': related_user.user,
'weight': related_user.weight}) 'weight': related_user.weight})
poll.set_options(options) poll.set_options(options, skip_autoupdate=True)
inform_changed_data(self)
# Add all candidates to list of speakers of related agenda item # Add all candidates to list of speakers of related agenda item
# TODO: Try to do this in a bulk create # TODO: Try to do this in a bulk create
for candidate in self.candidates: for candidate in self.candidates:
try: try:
Speaker.objects.add(candidate, self.agenda_item) Speaker.objects.add(candidate, self.agenda_item, skip_autoupdate=True)
except OpenSlidesError: except OpenSlidesError:
# The Speaker is already on the list. Do nothing. # The Speaker is already on the list. Do nothing.
# TODO: Find a smart way not to catch the error concerning AnonymousUser. # TODO: Find a smart way not to catch the error concerning AnonymousUser.
pass pass
inform_changed_data(self.agenda_item)
return poll return poll

View File

@ -122,7 +122,7 @@ class BasePoll(models.Model):
return True return True
return False return False
def set_options(self, options_data=[]): def set_options(self, options_data=[], skip_autoupdate=False):
""" """
Adds new option objects to the poll. Adds new option objects to the poll.
@ -131,7 +131,7 @@ class BasePoll(models.Model):
for option_data in options_data: for option_data in options_data:
option = self.get_option_class()(**option_data) option = self.get_option_class()(**option_data)
option.poll = self option.poll = self
option.save() option.save(skip_autoupdate=skip_autoupdate)
def get_options(self): def get_options(self):
""" """

View File

@ -52,9 +52,10 @@ class ItemViewSetManageSpeaker(TestCase):
mock_queryset = mock_speaker.objects.filter.return_value.exclude.return_value mock_queryset = mock_speaker.objects.filter.return_value.exclude.return_value
mock_queryset.get.return_value.delete.assert_called_with() mock_queryset.get.return_value.delete.assert_called_with()
@patch('openslides.agenda.views.inform_changed_data')
@patch('openslides.agenda.views.has_perm') @patch('openslides.agenda.views.has_perm')
@patch('openslides.agenda.views.Speaker') @patch('openslides.agenda.views.Speaker')
def test_remove_someone_else(self, mock_speaker, mock_has_perm): def test_remove_someone_else(self, mock_speaker, mock_has_perm, mock_inform_changed_data):
self.request.method = 'DELETE' self.request.method = 'DELETE'
self.request.user = 1 self.request.user = 1
self.request.data = {'speaker': '1'} self.request.data = {'speaker': '1'}
@ -63,7 +64,8 @@ class ItemViewSetManageSpeaker(TestCase):
self.view_instance.manage_speaker(self.request) self.view_instance.manage_speaker(self.request)
mock_speaker.objects.get.assert_called_with(pk=1) mock_speaker.objects.get.assert_called_with(pk=1)
mock_speaker.objects.get.return_value.delete.assert_called_with() mock_speaker.objects.get.return_value.delete.assert_called_with(skip_autoupdate=True)
mock_inform_changed_data.assert_called_with(self.mock_item)
class ItemViewSetSpeak(TestCase): class ItemViewSetSpeak(TestCase):