Merge pull request #736 from ostcar/motion-form-workflow
Change the Workflow of a motion in CreateView.
This commit is contained in:
commit
746a8b371a
@ -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):
|
||||||
|
@ -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
|
||||||
|
@ -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()
|
||||||
|
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user