Merge pull request #651 from normanjaeckel/Workflow_Adjustablility_2

Workflow adjustablility (new feature)
This commit is contained in:
Oskar Hahn 2013-05-16 04:35:58 -07:00
commit 9a881eceeb
6 changed files with 47 additions and 10 deletions

View File

@ -17,7 +17,7 @@ from openslides.config.api import config
from openslides.utils.forms import CssClassMixin
from openslides.utils.forms import CleanHtmlFormMixin
from openslides.utils.person import PersonFormField, MultiplePersonFormField
from .models import Motion, Category
from .models import Motion, Category, Workflow
class BaseMotionForm(CleanHtmlFormMixin, CssClassMixin, forms.ModelForm):
@ -137,6 +137,19 @@ class MotionIdentifierMixin(forms.ModelForm):
fields = ('identifier',)
class MotionSetWorkflowMixin(forms.ModelForm):
"""
Mixin to let the user change the workflow of the motion. When he does
so, the motion's state is reset.
"""
set_workflow = forms.ModelChoiceField(
queryset=Workflow.objects.all(),
required=False,
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.'))
class MotionImportForm(CssClassMixin, forms.Form):
"""
Form for motion import via csv file.

View File

@ -421,13 +421,16 @@ class Motion(SlideMixin, models.Model):
self.set_identifier()
self.state = state
def reset_state(self):
def reset_state(self, workflow=None):
"""
Set the state to the default state.
If the motion is new, it chooses the default workflow from config.
If the motion is new and workflow is None, it chooses the default
workflow from config.
"""
if self.state:
if workflow:
new_state = workflow.first_state
elif self.state:
new_state = self.state.workflow.first_state
else:
new_state = (Workflow.objects.get(pk=config['motion_workflow']).first_state or

View File

@ -187,10 +187,11 @@ def create_builtin_workflows(sender, **kwargs):
versioning=True)
state_2_9 = State.objects.create(name=ugettext_noop('needs review'),
workflow=workflow_2,
action_word=ugettext_noop('Needs review'),
versioning=True)
state_2_10 = State.objects.create(name=ugettext_noop('rejected (not authorized)'),
workflow=workflow_2,
action_word=ugettext_noop('reject (not authorized)'),
action_word=ugettext_noop('Reject (not authorized)'),
versioning=True)
state_2_1.next_states.add(state_2_2, state_2_5, state_2_10)
state_2_2.next_states.add(state_2_3, state_2_4, state_2_5, state_2_6, state_2_7, state_2_8, state_2_9)

View File

@ -57,7 +57,7 @@
<div class="row-fluid">
<div class="span8">
{# TODO: show only for complex workflow #}
{# TODO: show only for workflow with versioning #}
{% if motion.version.version_number < motion.last_version.version_number %}
<span class="label label-warning">
<i class="icon-warning-sign icon-white"></i> {% trans "This is not the newest version." %}
@ -289,7 +289,7 @@
<h4>{% trans "Manage motion" %}</h4>
<div class="btn-group btn-group-vertical">
{% for state in motion.state.next_states.all %}
<a href="{% url 'motion_set_state' motion.pk state.pk %}" class="btn btn-small">{% trans state.name %}</a>
<a href="{% url 'motion_set_state' motion.pk state.pk %}" class="btn btn-small">{% trans state.get_action_word %}</a>
{% endfor %}
</div>
<p></p>

View File

@ -38,7 +38,7 @@ from .models import (Motion, MotionSubmitter, MotionSupporter, MotionPoll,
MotionVersion, State, WorkflowError, Category)
from .forms import (BaseMotionForm, MotionSubmitterMixin, MotionSupporterMixin,
MotionDisableVersioningMixin, MotionCategoryMixin,
MotionIdentifierMixin, MotionImportForm)
MotionIdentifierMixin, MotionSetWorkflowMixin, MotionImportForm)
from .pdf import motions_to_pdf, motion_to_pdf, motion_poll_to_pdf
from .csv_import import import_motions
@ -91,8 +91,9 @@ class MotionMixin(object):
def manipulate_object(self, form):
"""
Save the version data into the motion object before it is saved in
the Database.
Saves the version data into the motion object before it is saved in
the Database. Does also set category, identifier and new workflow
if given.
"""
super(MotionMixin, self).manipulate_object(form)
for attr in ['title', 'text', 'reason']:
@ -120,6 +121,10 @@ class MotionMixin(object):
except KeyError:
pass
workflow = form.cleaned_data.get('set_workflow', None)
if workflow:
self.object.reset_state(workflow)
def post_save(self, form):
"""
Save the submitter an the supporter so the motion.
@ -161,6 +166,8 @@ class MotionMixin(object):
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), {})

View File

@ -219,6 +219,19 @@ class TestMotionUpdateView(MotionViewTestCase):
motion = Motion.objects.get(pk=self.motion1.pk)
self.assertEqual(motion.versions.count(), 1)
def test_set_another_workflow(self):
self.assertEqual(self.motion1.state.workflow.pk, 1)
response = self.admin_client.post(self.url, {'title': 'oori4KiaghaeSeuzaim2',
'text': 'eequei1Tee1aegeNgee0',
'submitter': self.admin})
self.assertEqual(Motion.objects.get(pk=self.motion1.pk).state.workflow.pk, 1)
response = self.admin_client.post(self.url, {'title': 'oori4KiaghaeSeuzaim2',
'text': 'eequei1Tee1aegeNgee0',
'submitter': self.admin,
'set_workflow': 2})
self.assertRedirects(response, '/motion/1/')
self.assertEqual(Motion.objects.get(pk=self.motion1.pk).state.workflow.pk, 2)
class TestMotionDeleteView(MotionViewTestCase):
def test_get(self):