Built-in Workflows are created by listening to a signal which is sent after syncdb.
This commit is contained in:
parent
73723feb74
commit
514577f7c6
0
openslides/core/__init__.py
Normal file
0
openslides/core/__init__.py
Normal file
16
openslides/core/signals.py
Normal file
16
openslides/core/signals.py
Normal file
@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
openslides.core.signals
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Core Signals.
|
||||
|
||||
:copyright: (c) 2011-2013 by the OpenSlides team, see AUTHORS.
|
||||
:license: GNU GPL, see LICENSE for more details.
|
||||
"""
|
||||
|
||||
from django.dispatch import Signal
|
||||
|
||||
|
||||
post_database_setup = Signal()
|
@ -27,6 +27,7 @@ from django.core.management import execute_from_command_line
|
||||
from openslides import get_version
|
||||
from openslides.utils.tornado_webserver import run_tornado
|
||||
|
||||
|
||||
CONFIG_TEMPLATE = """#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
@ -1,280 +0,0 @@
|
||||
[
|
||||
{
|
||||
"pk":1,
|
||||
"model":"motion.workflow",
|
||||
"fields":{
|
||||
"name":"Simple Workflow",
|
||||
"first_state":1
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk":2,
|
||||
"model":"motion.workflow",
|
||||
"fields":{
|
||||
"name":"Complex Workflow",
|
||||
"first_state":5
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk":1,
|
||||
"model":"motion.state",
|
||||
"fields":{
|
||||
"name":"submitted",
|
||||
"workflow":1,
|
||||
"dont_set_new_version_active":false,
|
||||
"allow_submitter_edit":true,
|
||||
"next_states":[
|
||||
2,
|
||||
3,
|
||||
4
|
||||
],
|
||||
"allow_support":true,
|
||||
"action_word":"",
|
||||
"icon":"",
|
||||
"versioning":false,
|
||||
"allow_create_poll":true
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk":2,
|
||||
"model":"motion.state",
|
||||
"fields":{
|
||||
"name":"accepted",
|
||||
"workflow":1,
|
||||
"dont_set_new_version_active":false,
|
||||
"allow_submitter_edit":false,
|
||||
"next_states":[
|
||||
|
||||
],
|
||||
"allow_support":false,
|
||||
"action_word":"accept",
|
||||
"icon":"",
|
||||
"versioning":false,
|
||||
"allow_create_poll":false
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk":3,
|
||||
"model":"motion.state",
|
||||
"fields":{
|
||||
"name":"rejected",
|
||||
"workflow":1,
|
||||
"dont_set_new_version_active":false,
|
||||
"allow_submitter_edit":false,
|
||||
"next_states":[
|
||||
|
||||
],
|
||||
"allow_support":false,
|
||||
"action_word":"reject",
|
||||
"icon":"",
|
||||
"versioning":false,
|
||||
"allow_create_poll":false
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk":4,
|
||||
"model":"motion.state",
|
||||
"fields":{
|
||||
"name":"not decided",
|
||||
"workflow":1,
|
||||
"dont_set_new_version_active":false,
|
||||
"allow_submitter_edit":false,
|
||||
"next_states":[
|
||||
|
||||
],
|
||||
"allow_support":false,
|
||||
"action_word":"do not decide",
|
||||
"icon":"",
|
||||
"versioning":false,
|
||||
"allow_create_poll":false
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk":5,
|
||||
"model":"motion.state",
|
||||
"fields":{
|
||||
"name":"published",
|
||||
"workflow":2,
|
||||
"dont_set_new_version_active":false,
|
||||
"allow_submitter_edit":true,
|
||||
"next_states":[
|
||||
6,
|
||||
9,
|
||||
14
|
||||
],
|
||||
"allow_support":true,
|
||||
"action_word":"",
|
||||
"icon":"",
|
||||
"versioning":false,
|
||||
"allow_create_poll":false
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk":6,
|
||||
"model":"motion.state",
|
||||
"fields":{
|
||||
"name":"permitted",
|
||||
"workflow":2,
|
||||
"dont_set_new_version_active":true,
|
||||
"allow_submitter_edit":true,
|
||||
"next_states":[
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
10,
|
||||
11,
|
||||
12,
|
||||
13
|
||||
],
|
||||
"allow_support":false,
|
||||
"action_word":"permit",
|
||||
"icon":"",
|
||||
"versioning":true,
|
||||
"allow_create_poll":true
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk":7,
|
||||
"model":"motion.state",
|
||||
"fields":{
|
||||
"name":"accepted",
|
||||
"workflow":2,
|
||||
"dont_set_new_version_active":false,
|
||||
"allow_submitter_edit":false,
|
||||
"next_states":[
|
||||
|
||||
],
|
||||
"allow_support":false,
|
||||
"action_word":"accept",
|
||||
"icon":"",
|
||||
"versioning":true,
|
||||
"allow_create_poll":false
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk":8,
|
||||
"model":"motion.state",
|
||||
"fields":{
|
||||
"name":"rejected",
|
||||
"workflow":2,
|
||||
"dont_set_new_version_active":false,
|
||||
"allow_submitter_edit":false,
|
||||
"next_states":[
|
||||
|
||||
],
|
||||
"allow_support":false,
|
||||
"action_word":"reject",
|
||||
"icon":"",
|
||||
"versioning":true,
|
||||
"allow_create_poll":false
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk":9,
|
||||
"model":"motion.state",
|
||||
"fields":{
|
||||
"name":"withdrawed",
|
||||
"workflow":2,
|
||||
"dont_set_new_version_active":false,
|
||||
"allow_submitter_edit":false,
|
||||
"next_states":[
|
||||
|
||||
],
|
||||
"allow_support":false,
|
||||
"action_word":"withdraw",
|
||||
"icon":"",
|
||||
"versioning":true,
|
||||
"allow_create_poll":false
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk":10,
|
||||
"model":"motion.state",
|
||||
"fields":{
|
||||
"name":"adjourned",
|
||||
"workflow":2,
|
||||
"dont_set_new_version_active":false,
|
||||
"allow_submitter_edit":false,
|
||||
"next_states":[
|
||||
|
||||
],
|
||||
"allow_support":false,
|
||||
"action_word":"adjourn",
|
||||
"icon":"",
|
||||
"versioning":true,
|
||||
"allow_create_poll":false
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk":11,
|
||||
"model":"motion.state",
|
||||
"fields":{
|
||||
"name":"not concerned",
|
||||
"workflow":2,
|
||||
"dont_set_new_version_active":false,
|
||||
"allow_submitter_edit":false,
|
||||
"next_states":[
|
||||
|
||||
],
|
||||
"allow_support":false,
|
||||
"action_word":"",
|
||||
"icon":"",
|
||||
"versioning":true,
|
||||
"allow_create_poll":false
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk":12,
|
||||
"model":"motion.state",
|
||||
"fields":{
|
||||
"name":"commited a bill",
|
||||
"workflow":2,
|
||||
"dont_set_new_version_active":false,
|
||||
"allow_submitter_edit":false,
|
||||
"next_states":[
|
||||
|
||||
],
|
||||
"allow_support":false,
|
||||
"action_word":"commit a bill",
|
||||
"icon":"",
|
||||
"versioning":true,
|
||||
"allow_create_poll":false
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk":13,
|
||||
"model":"motion.state",
|
||||
"fields":{
|
||||
"name":"needs review",
|
||||
"workflow":2,
|
||||
"dont_set_new_version_active":false,
|
||||
"allow_submitter_edit":false,
|
||||
"next_states":[
|
||||
|
||||
],
|
||||
"allow_support":false,
|
||||
"action_word":"",
|
||||
"icon":"",
|
||||
"versioning":true,
|
||||
"allow_create_poll":false
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk":14,
|
||||
"model":"motion.state",
|
||||
"fields":{
|
||||
"name":"rejected (not authorized)",
|
||||
"workflow":2,
|
||||
"dont_set_new_version_active":false,
|
||||
"allow_submitter_edit":false,
|
||||
"next_states":[
|
||||
|
||||
],
|
||||
"allow_support":false,
|
||||
"action_word":"reject (not authorized)",
|
||||
"icon":"",
|
||||
"versioning":true,
|
||||
"allow_create_poll":false
|
||||
}
|
||||
}
|
||||
]
|
@ -349,7 +349,8 @@ class Motion(SlideMixin, models.Model):
|
||||
if self.state:
|
||||
self.state = self.state.workflow.first_state
|
||||
else:
|
||||
self.state = Workflow.objects.get(pk=config['motion_workflow']).first_state
|
||||
self.state = (Workflow.objects.get(pk=config['motion_workflow']).first_state or
|
||||
Workflow.objects.get(pk=config['motion_workflow']).state_set.all()[0])
|
||||
|
||||
def slide(self):
|
||||
"""Return the slide dict."""
|
||||
@ -716,7 +717,7 @@ class Workflow(models.Model):
|
||||
name = models.CharField(max_length=255)
|
||||
"""A string representing the workflow."""
|
||||
|
||||
first_state = models.OneToOneField(State, related_name='+')
|
||||
first_state = models.OneToOneField(State, related_name='+', null=True)
|
||||
"""A one-to-one relation to a state, the starting point for the workflow."""
|
||||
|
||||
def __unicode__(self):
|
||||
@ -733,5 +734,5 @@ class Workflow(models.Model):
|
||||
|
||||
def check_first_state(self):
|
||||
"""Checks whether the first_state itself belongs to the workflow."""
|
||||
if not self.first_state.workflow == self:
|
||||
if self.first_state and not self.first_state.workflow == self:
|
||||
raise WorkflowError('%s can not be first state of %s because it does not belong to it.' % (self.first_state, self))
|
||||
|
@ -11,9 +11,12 @@
|
||||
"""
|
||||
|
||||
from django.dispatch import receiver
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import ugettext as _, ugettext_noop
|
||||
|
||||
from openslides.config.signals import default_config_value
|
||||
from openslides.core.signals import post_database_setup
|
||||
|
||||
from .models import Workflow, State
|
||||
|
||||
|
||||
@receiver(default_config_value, dispatch_uid="motion_default_config")
|
||||
@ -28,3 +31,76 @@ def default_config(sender, key, **kwargs):
|
||||
'motion_pdf_preamble': '',
|
||||
'motion_allow_disable_versioning': False,
|
||||
'motion_workflow': 1}.get(key)
|
||||
|
||||
|
||||
@receiver(post_database_setup, dispatch_uid='motion_create_builtin_workflows')
|
||||
def create_builtin_workflows(sender, **kwargs):
|
||||
"""
|
||||
Creates a simple and a complex workflow.
|
||||
"""
|
||||
workflow_1 = Workflow.objects.create(name=ugettext_noop('Simple Workflow'))
|
||||
state_1_1 = State.objects.create(name=ugettext_noop('submitted'),
|
||||
workflow=workflow_1,
|
||||
allow_create_poll=True,
|
||||
allow_support=True,
|
||||
allow_submitter_edit=True)
|
||||
state_1_2 = State.objects.create(name=ugettext_noop('accepted'),
|
||||
workflow=workflow_1,
|
||||
action_word=ugettext_noop('Accept'))
|
||||
state_1_3 = State.objects.create(name=ugettext_noop('rejected'),
|
||||
workflow=workflow_1,
|
||||
action_word=ugettext_noop('Reject'))
|
||||
state_1_4 = State.objects.create(name=ugettext_noop('not decided'),
|
||||
workflow=workflow_1,
|
||||
action_word=ugettext_noop('Do not decide'))
|
||||
state_1_1.next_states.add(state_1_2, state_1_3, state_1_4)
|
||||
workflow_1.first_state = state_1_1
|
||||
workflow_1.save()
|
||||
|
||||
workflow_2 = Workflow.objects.create(name=ugettext_noop('Complex Workflow'))
|
||||
state_2_1 = State.objects.create(name=ugettext_noop('published'),
|
||||
workflow=workflow_2,
|
||||
allow_support=True,
|
||||
allow_submitter_edit=True)
|
||||
state_2_2 = State.objects.create(name=ugettext_noop('permitted'),
|
||||
workflow=workflow_2,
|
||||
action_word=ugettext_noop('Permit'),
|
||||
allow_create_poll=True,
|
||||
allow_submitter_edit=True,
|
||||
versioning=True,
|
||||
dont_set_new_version_active=True)
|
||||
state_2_3 = State.objects.create(name=ugettext_noop('accepted'),
|
||||
workflow=workflow_2,
|
||||
action_word=ugettext_noop('Accept'),
|
||||
versioning=True)
|
||||
state_2_4 = State.objects.create(name=ugettext_noop('rejected'),
|
||||
workflow=workflow_2,
|
||||
action_word=ugettext_noop('Reject'),
|
||||
versioning=True)
|
||||
state_2_5 = State.objects.create(name=ugettext_noop('withdrawed'),
|
||||
workflow=workflow_2,
|
||||
action_word=ugettext_noop('Withdraw'),
|
||||
versioning=True)
|
||||
state_2_6 = State.objects.create(name=ugettext_noop('adjourned'),
|
||||
workflow=workflow_2,
|
||||
action_word=ugettext_noop('Adjourn'),
|
||||
versioning=True)
|
||||
state_2_7 = State.objects.create(name=ugettext_noop('not concerned'),
|
||||
workflow=workflow_2,
|
||||
action_word=ugettext_noop('Do not concern'),
|
||||
versioning=True)
|
||||
state_2_8 = State.objects.create(name=ugettext_noop('commited a bill'),
|
||||
workflow=workflow_2,
|
||||
action_word=ugettext_noop('Commit a bill'),
|
||||
versioning=True)
|
||||
state_2_9 = State.objects.create(name=ugettext_noop('needs review'),
|
||||
workflow=workflow_2,
|
||||
versioning=True)
|
||||
state_2_10 = State.objects.create(name=ugettext_noop('rejected (not authorized)'),
|
||||
workflow=workflow_2,
|
||||
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)
|
||||
workflow_2.first_state = state_2_1
|
||||
workflow_2.save()
|
||||
|
@ -1,55 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
openslides.motion.workflow
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This file is only for development. It will be moved out of
|
||||
the openslides module before the next release.
|
||||
|
||||
:copyright: (c) 2011-2013 by the OpenSlides team, see AUTHORS.
|
||||
:license: GNU GPL, see LICENSE for more details.
|
||||
"""
|
||||
|
||||
from django.utils.translation import ugettext_noop
|
||||
|
||||
from .models import Workflow, State
|
||||
|
||||
|
||||
def _init_builtin_workflows():
|
||||
"""
|
||||
Saves a simple and a complex workflow into the database.
|
||||
This function is only called manually and lives here only for development.
|
||||
"""
|
||||
workflow_1 = Workflow(name=ugettext_noop('Simple Workflow'), id=1)
|
||||
state_1_1 = State.objects.create(name=ugettext_noop('submitted'), workflow=workflow_1,
|
||||
allow_create_poll=True, allow_support=True, allow_submitter_edit=True)
|
||||
state_1_2 = State.objects.create(name=ugettext_noop('accepted'), workflow=workflow_1, action_word=ugettext_noop('accept'))
|
||||
state_1_3 = State.objects.create(name=ugettext_noop('rejected'), workflow=workflow_1, action_word=ugettext_noop('reject'))
|
||||
state_1_4 = State.objects.create(name=ugettext_noop('not decided'), workflow=workflow_1, action_word=ugettext_noop('do not decide'))
|
||||
state_1_1.next_states.add(state_1_2, state_1_3, state_1_4)
|
||||
state_1_1.save() # Is this neccessary?
|
||||
workflow_1.first_state = state_1_1
|
||||
workflow_1.save()
|
||||
|
||||
workflow_2 = Workflow(name=ugettext_noop('Complex Workflow'), id=2)
|
||||
state_2_1 = State.objects.create(name=ugettext_noop('published'), workflow=workflow_2, allow_support=True, allow_submitter_edit=True)
|
||||
state_2_2 = State.objects.create(name=ugettext_noop('permitted'), workflow=workflow_2, action_word=ugettext_noop('permit'),
|
||||
allow_create_poll=True, allow_submitter_edit=True, versioning=True, dont_set_new_version_active=True)
|
||||
state_2_3 = State.objects.create(name=ugettext_noop('accepted'), workflow=workflow_2, action_word=ugettext_noop('accept'), versioning=True)
|
||||
state_2_4 = State.objects.create(name=ugettext_noop('rejected'), workflow=workflow_2, action_word=ugettext_noop('reject'), versioning=True)
|
||||
state_2_5 = State.objects.create(name=ugettext_noop('withdrawed'), workflow=workflow_2,
|
||||
action_word=ugettext_noop('withdraw'), versioning=True)
|
||||
state_2_6 = State.objects.create(name=ugettext_noop('adjourned'), workflow=workflow_2, action_word=ugettext_noop('adjourn'), versioning=True)
|
||||
state_2_7 = State.objects.create(name=ugettext_noop('not concerned'), workflow=workflow_2, versioning=True)
|
||||
state_2_8 = State.objects.create(name=ugettext_noop('commited a bill'), workflow=workflow_2,
|
||||
action_word=ugettext_noop('commit a bill'), versioning=True)
|
||||
state_2_9 = State.objects.create(name=ugettext_noop('needs review'), workflow=workflow_2, versioning=True)
|
||||
state_2_10 = State.objects.create(name=ugettext_noop('rejected (not authorized)'), workflow=workflow_2,
|
||||
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)
|
||||
state_2_1.save() # Is this neccessary?
|
||||
state_2_2.save() # Is this neccessary?
|
||||
workflow_2.first_state = state_2_1
|
||||
workflow_2.save()
|
25
openslides/utils/management/commands/syncdb.py
Normal file
25
openslides/utils/management/commands/syncdb.py
Normal file
@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
openslides.utils.management.commands.syncdb
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Overrides the Django syncdb command to setup the database.
|
||||
|
||||
:copyright: (c) 2011-2013 by the OpenSlides team, see AUTHORS.
|
||||
:license: GNU GPL, see LICENSE for more details.
|
||||
"""
|
||||
|
||||
from django.core.management.commands.syncdb import Command as _Command
|
||||
|
||||
from openslides.core.signals import post_database_setup
|
||||
|
||||
|
||||
class Command(_Command):
|
||||
"""
|
||||
Setup the database and sends the signal post_database_setup.
|
||||
"""
|
||||
def handle_noargs(self, *args, **kwargs):
|
||||
return_value = super(Command, self).handle_noargs(*args, **kwargs)
|
||||
post_database_setup.send(sender=self)
|
||||
return return_value
|
@ -10,6 +10,7 @@
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
from openslides.core.signals import post_database_setup
|
||||
from openslides.participant.models import User
|
||||
from openslides.config.models import config
|
||||
from openslides.motion.models import Motion, Workflow, State
|
||||
@ -18,6 +19,7 @@ from openslides.motion.exceptions import WorkflowError
|
||||
|
||||
class ModelTest(TestCase):
|
||||
def setUp(self):
|
||||
post_database_setup.send(sender=self)
|
||||
self.motion = Motion.objects.create(title='v1')
|
||||
self.test_user = User.objects.create(username='blub')
|
||||
self.workflow = Workflow.objects.get(pk=1)
|
||||
@ -113,18 +115,18 @@ class ModelTest(TestCase):
|
||||
|
||||
self.motion.state = State.objects.get(pk=6)
|
||||
self.assertEqual(self.motion.state.name, 'permitted')
|
||||
self.assertEqual(self.motion.state.get_action_word(), 'permit')
|
||||
self.assertEqual(self.motion.state.get_action_word(), 'Permit')
|
||||
with self.assertRaises(WorkflowError):
|
||||
self.motion.support(self.test_user)
|
||||
with self.assertRaises(WorkflowError):
|
||||
self.motion.unsupport(self.test_user)
|
||||
|
||||
def test_new_states_or_workflows(self):
|
||||
workflow_1 = Workflow(name='W1', id=1000)
|
||||
workflow_1 = Workflow.objects.create(name='W1')
|
||||
state_1 = State.objects.create(name='S1', workflow=workflow_1)
|
||||
workflow_1.first_state = state_1
|
||||
workflow_1.save()
|
||||
workflow_2 = Workflow(name='W2', id=2000)
|
||||
workflow_2 = Workflow.objects.create(name='W2')
|
||||
state_2 = State.objects.create(name='S2', workflow=workflow_2)
|
||||
workflow_2.first_state = state_2
|
||||
workflow_2.save()
|
||||
|
Loading…
Reference in New Issue
Block a user