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',)
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):

View File

@ -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

View File

@ -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()

View File

@ -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)