From 9853f2c433622a76fed18c68cdda14f62c1b4700 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Fri, 14 Jun 2013 09:56:16 +0200 Subject: [PATCH] Change the Workflow of a motion in CreateView. The Manager can choose the workflow in the createview. The default value is the workflow from the config. In the UpdateView the workflow in which the motion is, is choosen by default. The workflow will only be reset, if it is changed. --- openslides/motion/forms.py | 12 ++++---- openslides/motion/models.py | 11 +++++-- openslides/motion/views.py | 60 ++++++++++++++++++++++++------------- tests/motion/test_views.py | 19 ++++++++---- 4 files changed, 67 insertions(+), 35 deletions(-) diff --git a/openslides/motion/forms.py b/openslides/motion/forms.py index 2a177e7a8..f738fa75c 100644 --- a/openslides/motion/forms.py +++ b/openslides/motion/forms.py @@ -140,17 +140,17 @@ class MotionIdentifierMixin(forms.ModelForm): fields = ('identifier',) -class MotionSetWorkflowMixin(forms.ModelForm): +class MotionWorkflowMixin(forms.ModelForm): """ - Mixin to let the user change the workflow of the motion. When he does - so, the motion's state is reset. + Mixin to let the user change the workflow of the motion. """ - set_workflow = LocalizedModelChoiceField( + workflow = LocalizedModelChoiceField( queryset=Workflow.objects.all(), - required=False, + empty_label=None, label=ugettext_lazy('Workflow'), - help_text=ugettext_lazy('Set a specific workflow to switch to it. If you do so, the state of the motion will be reset.')) + help_text=ugettext_lazy('Set a specific workflow to switch to it. ' + 'If you do so, the state of the motion will be reset.')) class MotionImportForm(CssClassMixin, forms.Form): diff --git a/openslides/motion/models.py b/openslides/motion/models.py index 3dd2683aa..8c819b99f 100644 --- a/openslides/motion/models.py +++ b/openslides/motion/models.py @@ -133,7 +133,7 @@ class Motion(SlideMixin, models.Model): # Solves the problem, that there can only be one motion with an empty # string as identifier. - if self.identifier is '': + if not self.identifier and isinstance(self.identifier, basestring): self.identifier = None super(Motion, self).save(*args, **kwargs) @@ -432,7 +432,7 @@ class Motion(SlideMixin, models.Model): """ Set the state of the motion. - State can be the id of a state object or a state object. + 'state' can be the id of a state object or a state object. """ if type(state) is int: state = State.objects.get(pk=state) @@ -445,10 +445,15 @@ class Motion(SlideMixin, models.Model): """ Set the state to the default state. + 'workflow' can be a workflow, an id of a workflow or None. + If the motion is new and workflow is None, it chooses the default workflow from config. """ - if workflow: + if type(workflow) is int: + workflow = Workflow.objects.get(pk=workflow) + + if workflow is not None: new_state = workflow.first_state elif self.state: new_state = self.state.workflow.first_state diff --git a/openslides/motion/views.py b/openslides/motion/views.py index 544f58d15..7d68dd1ae 100644 --- a/openslides/motion/views.py +++ b/openslides/motion/views.py @@ -39,7 +39,7 @@ from .models import (Motion, MotionSubmitter, MotionSupporter, MotionPoll, MotionVersion, State, WorkflowError, Category) from .forms import (BaseMotionForm, MotionSubmitterMixin, MotionSupporterMixin, MotionDisableVersioningMixin, MotionCategoryMixin, - MotionIdentifierMixin, MotionSetWorkflowMixin, MotionImportForm) + MotionIdentifierMixin, MotionWorkflowMixin, MotionImportForm) from .pdf import motions_to_pdf, motion_to_pdf, motion_poll_to_pdf from .csv_import import import_motions @@ -98,19 +98,10 @@ class MotionEditMixin(object): Saves the CreateForm or UpdateForm into a motion object. """ self.object = form.save(commit=False) - - if type(self) == MotionUpdateView: - # Decide if a new version is saved to the database - if (self.object.state.versioning and - not form.cleaned_data.get('disable_versioning', False)): - version = self.object.get_new_version() - else: - version = self.object.get_last_version() - else: - version = self.object.get_new_version() + self.manipulate_object(form) for attr in ['title', 'text', 'reason']: - setattr(version, attr, form.cleaned_data[attr]) + setattr(self.version, attr, form.cleaned_data[attr]) try: self.object.category = form.cleaned_data['category'] @@ -122,11 +113,7 @@ class MotionEditMixin(object): except KeyError: pass - workflow = form.cleaned_data.get('set_workflow', None) - if workflow: - self.object.reset_state(workflow) - - self.object.save(use_version=version) + self.object.save(use_version=self.version) # Save the submitter an the supporter so the motion. # TODO: Only delete and save neccessary submitters and supporters @@ -163,11 +150,12 @@ class MotionEditMixin(object): form_classes.append(MotionCategoryMixin) if config['motion_min_supporters'] > 0: form_classes.append(MotionSupporterMixin) + form_classes.append(MotionWorkflowMixin) + if self.object: if config['motion_allow_disable_versioning'] and self.object.state.versioning: form_classes.append(MotionDisableVersioningMixin) - if self.request.user.has_perm('motion.can_manage_motion'): - form_classes.append(MotionSetWorkflowMixin) + return type('MotionForm', tuple(form_classes), {}) @@ -195,10 +183,23 @@ class MotionCreateView(MotionEditMixin, CreateView): """ response = super(MotionCreateView, self).form_valid(form) self.object.write_log([ugettext_noop('Motion created')], self.request.user) - if not 'submitter' in form.cleaned_data: + if (not 'submitter' in form.cleaned_data or + not form.cleaned_data['submitter']): self.object.add_submitter(self.request.user) return response + def get_initial(self): + initial = super(MotionCreateView, self).get_initial() + if self.request.user.has_perm('motion.can_manage_motion'): + initial['workflow'] = config['motion_workflow'] + return initial + + def manipulate_object(self, form): + self.version = self.object.get_new_version() + + workflow = form.cleaned_data.get('workflow', config['motion_workflow']) + self.object.reset_state(workflow) + motion_create = MotionCreateView.as_view() @@ -226,6 +227,25 @@ class MotionUpdateView(MotionEditMixin, UpdateView): self.object.write_log([ugettext_noop('All supporters removed')], self.request.user) return response + def get_initial(self): + initial = super(MotionUpdateView, self).get_initial() + if self.request.user.has_perm('motion.can_manage_motion'): + initial['workflow'] = self.object.state.workflow + return initial + + def manipulate_object(self, form): + workflow = form.cleaned_data.get('workflow', None) + if (workflow is not None and + workflow != self.object.state.workflow): + self.object.reset_state(workflow) + + # Decide if a new version is saved to the database + if (self.object.state.versioning and + not form.cleaned_data.get('disable_versioning', False)): + self.version = self.object.get_new_version() + else: + self.version = self.object.get_last_version() + motion_edit = MotionUpdateView.as_view() diff --git a/tests/motion/test_views.py b/tests/motion/test_views.py index 6cda947c9..fe01ccbd2 100644 --- a/tests/motion/test_views.py +++ b/tests/motion/test_views.py @@ -85,7 +85,7 @@ class TestMotionCreateView(MotionViewTestCase): response = self.admin_client.post(self.url, {'title': 'new motion', 'text': 'motion text', 'reason': 'motion reason', - 'submitter': self.admin.person_id}) + 'workflow': 1}) self.assertEqual(response.status_code, 302) self.assertTrue(Motion.objects.filter(versions__title='new motion').exists()) @@ -151,7 +151,8 @@ class TestMotionUpdateView(MotionViewTestCase): response = self.admin_client.post(self.url, {'title': 'new motion_title', 'text': 'motion text', 'reason': 'motion reason', - 'submitter': self.admin.person_id}) + 'submitter': self.admin.person_id, + 'workflow': 1}) self.assertRedirects(response, '/motion/1/') motion = Motion.objects.get(pk=1) self.assertEqual(motion.title, 'new motion_title') @@ -172,7 +173,8 @@ class TestMotionUpdateView(MotionViewTestCase): def test_versioning(self): self.assertFalse(self.motion1.state.versioning) - versioning_state = State.objects.create(name='automatic_versioning', workflow=self.motion1.state.workflow, versioning=True) + workflow = self.motion1.state.workflow + versioning_state = State.objects.create(name='automatic_versioning', workflow=workflow, versioning=True) self.motion1.state = versioning_state self.motion1.save() motion = Motion.objects.get(pk=self.motion1.pk) @@ -182,6 +184,7 @@ class TestMotionUpdateView(MotionViewTestCase): response = self.admin_client.post(self.url, {'title': 'another new motion_title', 'text': 'another motion text', 'reason': 'another motion reason', + 'workflow': workflow.pk, 'submitter': self.admin.person_id}) self.assertRedirects(response, '/motion/1/') motion = Motion.objects.get(pk=self.motion1.pk) @@ -189,7 +192,8 @@ class TestMotionUpdateView(MotionViewTestCase): def test_disable_versioning(self): self.assertFalse(self.motion1.state.versioning) - versioning_state = State.objects.create(name='automatic_versioning', workflow=self.motion1.state.workflow, versioning=True) + workflow = self.motion1.state.workflow + versioning_state = State.objects.create(name='automatic_versioning', workflow=workflow, versioning=True) self.motion1.state = versioning_state self.motion1.save() motion = Motion.objects.get(pk=self.motion1.pk) @@ -201,6 +205,7 @@ class TestMotionUpdateView(MotionViewTestCase): 'text': 'another motion text', 'reason': 'another motion reason', 'submitter': self.admin.person_id, + 'workflow': workflow.pk, 'disable_versioning': 'true'}) self.assertRedirects(response, '/motion/1/') motion = Motion.objects.get(pk=self.motion1.pk) @@ -208,7 +213,8 @@ class TestMotionUpdateView(MotionViewTestCase): def test_no_versioning_without_new_data(self): self.assertFalse(self.motion1.state.versioning) - versioning_state = State.objects.create(name='automatic_versioning', workflow=self.motion1.state.workflow, versioning=True) + workflow = self.motion1.state.workflow + versioning_state = State.objects.create(name='automatic_versioning', workflow=workflow, versioning=True) self.motion1.state = versioning_state self.motion1.title = 'Chah4kaaKasiVuishi5x' self.motion1.text = 'eedieFoothae2iethuo3' @@ -221,6 +227,7 @@ class TestMotionUpdateView(MotionViewTestCase): response = self.admin_client.post(self.url, {'title': 'Chah4kaaKasiVuishi5x', 'text': 'eedieFoothae2iethuo3', 'reason': 'ier2laiy1veeGoo0mau2', + 'workflow': workflow.pk, 'submitter': self.admin.person_id}) self.assertRedirects(response, '/motion/1/') motion = Motion.objects.get(pk=self.motion1.pk) @@ -235,7 +242,7 @@ class TestMotionUpdateView(MotionViewTestCase): response = self.admin_client.post(self.url, {'title': 'oori4KiaghaeSeuzaim2', 'text': 'eequei1Tee1aegeNgee0', 'submitter': self.admin.person_id, - 'set_workflow': 2}) + 'workflow': 2}) self.assertRedirects(response, '/motion/1/') self.assertEqual(Motion.objects.get(pk=self.motion1.pk).state.workflow.pk, 2)