Merge pull request #736 from ostcar/motion-form-workflow

Change the Workflow of a motion in CreateView.
This commit is contained in:
Oskar Hahn 2013-06-15 15:54:10 -07:00
commit 746a8b371a
4 changed files with 67 additions and 35 deletions

View File

@ -140,17 +140,17 @@ class MotionIdentifierMixin(forms.ModelForm):
fields = ('identifier',) fields = ('identifier',)
class MotionSetWorkflowMixin(forms.ModelForm): class MotionWorkflowMixin(forms.ModelForm):
""" """
Mixin to let the user change the workflow of the motion. When he does Mixin to let the user change the workflow of the motion.
so, the motion's state is reset.
""" """
set_workflow = LocalizedModelChoiceField( workflow = LocalizedModelChoiceField(
queryset=Workflow.objects.all(), queryset=Workflow.objects.all(),
required=False, empty_label=None,
label=ugettext_lazy('Workflow'), 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): class MotionImportForm(CssClassMixin, forms.Form):

View File

@ -133,7 +133,7 @@ class Motion(SlideMixin, models.Model):
# Solves the problem, that there can only be one motion with an empty # Solves the problem, that there can only be one motion with an empty
# string as identifier. # string as identifier.
if self.identifier is '': if not self.identifier and isinstance(self.identifier, basestring):
self.identifier = None self.identifier = None
super(Motion, self).save(*args, **kwargs) super(Motion, self).save(*args, **kwargs)
@ -432,7 +432,7 @@ class Motion(SlideMixin, models.Model):
""" """
Set the state of the motion. 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: if type(state) is int:
state = State.objects.get(pk=state) state = State.objects.get(pk=state)
@ -445,10 +445,15 @@ class Motion(SlideMixin, models.Model):
""" """
Set the state to the default state. 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 If the motion is new and workflow is None, it chooses the default
workflow from config. 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 new_state = workflow.first_state
elif self.state: elif self.state:
new_state = self.state.workflow.first_state new_state = self.state.workflow.first_state

View File

@ -39,7 +39,7 @@ from .models import (Motion, MotionSubmitter, MotionSupporter, MotionPoll,
MotionVersion, State, WorkflowError, Category) MotionVersion, State, WorkflowError, Category)
from .forms import (BaseMotionForm, MotionSubmitterMixin, MotionSupporterMixin, from .forms import (BaseMotionForm, MotionSubmitterMixin, MotionSupporterMixin,
MotionDisableVersioningMixin, MotionCategoryMixin, MotionDisableVersioningMixin, MotionCategoryMixin,
MotionIdentifierMixin, MotionSetWorkflowMixin, MotionImportForm) MotionIdentifierMixin, MotionWorkflowMixin, MotionImportForm)
from .pdf import motions_to_pdf, motion_to_pdf, motion_poll_to_pdf from .pdf import motions_to_pdf, motion_to_pdf, motion_poll_to_pdf
from .csv_import import import_motions from .csv_import import import_motions
@ -98,19 +98,10 @@ class MotionEditMixin(object):
Saves the CreateForm or UpdateForm into a motion object. Saves the CreateForm or UpdateForm into a motion object.
""" """
self.object = form.save(commit=False) self.object = form.save(commit=False)
self.manipulate_object(form)
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()
for attr in ['title', 'text', 'reason']: for attr in ['title', 'text', 'reason']:
setattr(version, attr, form.cleaned_data[attr]) setattr(self.version, attr, form.cleaned_data[attr])
try: try:
self.object.category = form.cleaned_data['category'] self.object.category = form.cleaned_data['category']
@ -122,11 +113,7 @@ class MotionEditMixin(object):
except KeyError: except KeyError:
pass pass
workflow = form.cleaned_data.get('set_workflow', None) self.object.save(use_version=self.version)
if workflow:
self.object.reset_state(workflow)
self.object.save(use_version=version)
# Save the submitter an the supporter so the motion. # Save the submitter an the supporter so the motion.
# TODO: Only delete and save neccessary submitters and supporters # TODO: Only delete and save neccessary submitters and supporters
@ -163,11 +150,12 @@ class MotionEditMixin(object):
form_classes.append(MotionCategoryMixin) form_classes.append(MotionCategoryMixin)
if config['motion_min_supporters'] > 0: if config['motion_min_supporters'] > 0:
form_classes.append(MotionSupporterMixin) form_classes.append(MotionSupporterMixin)
form_classes.append(MotionWorkflowMixin)
if self.object: if self.object:
if config['motion_allow_disable_versioning'] and self.object.state.versioning: if config['motion_allow_disable_versioning'] and self.object.state.versioning:
form_classes.append(MotionDisableVersioningMixin) form_classes.append(MotionDisableVersioningMixin)
if self.request.user.has_perm('motion.can_manage_motion'):
form_classes.append(MotionSetWorkflowMixin)
return type('MotionForm', tuple(form_classes), {}) return type('MotionForm', tuple(form_classes), {})
@ -195,10 +183,23 @@ class MotionCreateView(MotionEditMixin, CreateView):
""" """
response = super(MotionCreateView, self).form_valid(form) response = super(MotionCreateView, self).form_valid(form)
self.object.write_log([ugettext_noop('Motion created')], self.request.user) 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) self.object.add_submitter(self.request.user)
return response 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() 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) self.object.write_log([ugettext_noop('All supporters removed')], self.request.user)
return response 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() motion_edit = MotionUpdateView.as_view()

View File

@ -85,7 +85,7 @@ class TestMotionCreateView(MotionViewTestCase):
response = self.admin_client.post(self.url, {'title': 'new motion', response = self.admin_client.post(self.url, {'title': 'new motion',
'text': 'motion text', 'text': 'motion text',
'reason': 'motion reason', 'reason': 'motion reason',
'submitter': self.admin.person_id}) 'workflow': 1})
self.assertEqual(response.status_code, 302) self.assertEqual(response.status_code, 302)
self.assertTrue(Motion.objects.filter(versions__title='new motion').exists()) 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', response = self.admin_client.post(self.url, {'title': 'new motion_title',
'text': 'motion text', 'text': 'motion text',
'reason': 'motion reason', 'reason': 'motion reason',
'submitter': self.admin.person_id}) 'submitter': self.admin.person_id,
'workflow': 1})
self.assertRedirects(response, '/motion/1/') self.assertRedirects(response, '/motion/1/')
motion = Motion.objects.get(pk=1) motion = Motion.objects.get(pk=1)
self.assertEqual(motion.title, 'new motion_title') self.assertEqual(motion.title, 'new motion_title')
@ -172,7 +173,8 @@ class TestMotionUpdateView(MotionViewTestCase):
def test_versioning(self): def test_versioning(self):
self.assertFalse(self.motion1.state.versioning) 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.state = versioning_state
self.motion1.save() self.motion1.save()
motion = Motion.objects.get(pk=self.motion1.pk) 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', response = self.admin_client.post(self.url, {'title': 'another new motion_title',
'text': 'another motion text', 'text': 'another motion text',
'reason': 'another motion reason', 'reason': 'another motion reason',
'workflow': workflow.pk,
'submitter': self.admin.person_id}) 'submitter': self.admin.person_id})
self.assertRedirects(response, '/motion/1/') self.assertRedirects(response, '/motion/1/')
motion = Motion.objects.get(pk=self.motion1.pk) motion = Motion.objects.get(pk=self.motion1.pk)
@ -189,7 +192,8 @@ class TestMotionUpdateView(MotionViewTestCase):
def test_disable_versioning(self): def test_disable_versioning(self):
self.assertFalse(self.motion1.state.versioning) 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.state = versioning_state
self.motion1.save() self.motion1.save()
motion = Motion.objects.get(pk=self.motion1.pk) motion = Motion.objects.get(pk=self.motion1.pk)
@ -201,6 +205,7 @@ class TestMotionUpdateView(MotionViewTestCase):
'text': 'another motion text', 'text': 'another motion text',
'reason': 'another motion reason', 'reason': 'another motion reason',
'submitter': self.admin.person_id, 'submitter': self.admin.person_id,
'workflow': workflow.pk,
'disable_versioning': 'true'}) 'disable_versioning': 'true'})
self.assertRedirects(response, '/motion/1/') self.assertRedirects(response, '/motion/1/')
motion = Motion.objects.get(pk=self.motion1.pk) motion = Motion.objects.get(pk=self.motion1.pk)
@ -208,7 +213,8 @@ class TestMotionUpdateView(MotionViewTestCase):
def test_no_versioning_without_new_data(self): def test_no_versioning_without_new_data(self):
self.assertFalse(self.motion1.state.versioning) 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.state = versioning_state
self.motion1.title = 'Chah4kaaKasiVuishi5x' self.motion1.title = 'Chah4kaaKasiVuishi5x'
self.motion1.text = 'eedieFoothae2iethuo3' self.motion1.text = 'eedieFoothae2iethuo3'
@ -221,6 +227,7 @@ class TestMotionUpdateView(MotionViewTestCase):
response = self.admin_client.post(self.url, {'title': 'Chah4kaaKasiVuishi5x', response = self.admin_client.post(self.url, {'title': 'Chah4kaaKasiVuishi5x',
'text': 'eedieFoothae2iethuo3', 'text': 'eedieFoothae2iethuo3',
'reason': 'ier2laiy1veeGoo0mau2', 'reason': 'ier2laiy1veeGoo0mau2',
'workflow': workflow.pk,
'submitter': self.admin.person_id}) 'submitter': self.admin.person_id})
self.assertRedirects(response, '/motion/1/') self.assertRedirects(response, '/motion/1/')
motion = Motion.objects.get(pk=self.motion1.pk) motion = Motion.objects.get(pk=self.motion1.pk)
@ -235,7 +242,7 @@ class TestMotionUpdateView(MotionViewTestCase):
response = self.admin_client.post(self.url, {'title': 'oori4KiaghaeSeuzaim2', response = self.admin_client.post(self.url, {'title': 'oori4KiaghaeSeuzaim2',
'text': 'eequei1Tee1aegeNgee0', 'text': 'eequei1Tee1aegeNgee0',
'submitter': self.admin.person_id, 'submitter': self.admin.person_id,
'set_workflow': 2}) 'workflow': 2})
self.assertRedirects(response, '/motion/1/') self.assertRedirects(response, '/motion/1/')
self.assertEqual(Motion.objects.get(pk=self.motion1.pk).state.workflow.pk, 2) self.assertEqual(Motion.objects.get(pk=self.motion1.pk).state.workflow.pk, 2)