Removed transitions and move to a Node based workflow element
This commit is contained in:
@@ -4,11 +4,14 @@ from django.db import models
|
||||
from django.contrib.contenttypes import generic
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import ugettext
|
||||
|
||||
from permissions.models import StoredPermission
|
||||
|
||||
from .literals import OPERAND_CHOICES, OPERAND_AND
|
||||
#from .literals import NODE_TYPE_TASK, NODE_TYPE_START, NODE_TYPE_END
|
||||
|
||||
#NODE_TYPE_CHOICES
|
||||
|
||||
class Ability(models.Model):
|
||||
label = models.CharField(max_length=128, unique=True, verbose_name = _(u'label'))
|
||||
@@ -24,44 +27,149 @@ class Ability(models.Model):
|
||||
|
||||
class Workflow(models.Model):
|
||||
label = models.CharField(max_length=128, unique=True, verbose_name = _(u'label'))
|
||||
initial_node = models.ForeignKey('WorkflowNode', related_name='workflow_initial_node', blank=True, null=True, verbose_name=_(u'initial node'))
|
||||
initial_state = models.ForeignKey('WorkflowState', related_name='workflow_initial_state', blank=True, null=True, verbose_name=_(u'initial state'))
|
||||
description = models.TextField(blank=True, verbose_name=_(u'description'))
|
||||
|
||||
def __unicode__(self):
|
||||
return self.label
|
||||
|
||||
@property
|
||||
def workflow_nodes(self):
|
||||
return self.workflownode_set
|
||||
|
||||
def get_nodes(self):
|
||||
return [workflow_node.node for workflow_node in self.workflownode_set.all()]
|
||||
|
||||
def add_node(self, node):
|
||||
workflow_node = WorkflowNode(
|
||||
workflow=self,
|
||||
node=node)
|
||||
workflow_node.save()
|
||||
return workflow_node
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
is_new = not self.pk
|
||||
result = super(Workflow, self).save(*args, **kwargs)
|
||||
|
||||
if is_new:
|
||||
# Instanciate a new start node
|
||||
start_node = Start()
|
||||
start_node.save()
|
||||
|
||||
# Set the start node a
|
||||
workflow_node = self.add_node(node=start_node)
|
||||
|
||||
self.initial_node = workflow_node
|
||||
self.save()
|
||||
|
||||
return result
|
||||
|
||||
class Meta:
|
||||
verbose_name = _(u'workflow')
|
||||
verbose_name_plural = _(u'workflows')
|
||||
|
||||
|
||||
class State(models.Model):
|
||||
|
||||
|
||||
class Node(models.Model):
|
||||
"""
|
||||
Must provide:
|
||||
possible_next_nodes()
|
||||
Arguments: None
|
||||
Returns:
|
||||
List of possible nodes after this one executes
|
||||
|
||||
choices()
|
||||
Arguments: workflow
|
||||
Returns:
|
||||
{
|
||||
'next_node': workflow.nodes.all()
|
||||
}
|
||||
|
||||
execute()
|
||||
Arguments: workflow_instance
|
||||
Returns: next_node
|
||||
"""
|
||||
|
||||
label = models.CharField(max_length=128, verbose_name=_(u'label'))
|
||||
description = models.TextField(blank=True, verbose_name=_(u'description'))
|
||||
|
||||
def __unicode__(self):
|
||||
#return '%s (%s)' % (self.name, self.workflow.name)
|
||||
return self.label
|
||||
|
||||
class Meta:
|
||||
verbose_name = _(u'state')
|
||||
verbose_name_plural = _(u'states')
|
||||
abstract = True
|
||||
|
||||
|
||||
class Start(Node):
|
||||
"""
|
||||
The node with which all workflows start
|
||||
"""
|
||||
content_type = models.ForeignKey(ContentType, null=True)
|
||||
object_id = models.PositiveIntegerField(null=True)
|
||||
next_node = generic.GenericForeignKey(ct_field='content_type', fk_field='object_id')
|
||||
|
||||
def __unicode__(self):
|
||||
return ugettext(u'Start')
|
||||
|
||||
def possible_next_nodes(self):
|
||||
return self.next_node
|
||||
|
||||
def choices(self, workflow):
|
||||
return {
|
||||
'next_node': workflow.nodes.all()
|
||||
}
|
||||
|
||||
def execute(self, workflow_instance):
|
||||
return self.next_node
|
||||
|
||||
class Meta(Node.Meta):
|
||||
verbose_name = _(u'start')
|
||||
verbose_name_plural = _(u'starts')
|
||||
|
||||
|
||||
class Transition(models.Model):
|
||||
class End(Node):
|
||||
class Meta(Node.Meta):
|
||||
verbose_name = _(u'start')
|
||||
verbose_name_plural = _(u'starts')
|
||||
|
||||
|
||||
'''
|
||||
class Sequence(Node):
|
||||
"""
|
||||
A node that is enabled after the completion of a preceding node in the same workflow
|
||||
"""
|
||||
content_type = models.ForeignKey(ContentType)
|
||||
object_id = models.PositiveIntegerField()
|
||||
next_node = generic.GenericForeignKey(ct_field='content_type', fk_field='object_id')
|
||||
#node_type = NODE_TYPE_TASK
|
||||
|
||||
def execute(self):
|
||||
return self.next_node
|
||||
|
||||
class Meta(Node.Meta):
|
||||
verbose_name = _(u'task')
|
||||
verbose_name_plural = _(u'tasks')
|
||||
'''
|
||||
|
||||
class State(models.Model):
|
||||
label = models.CharField(max_length=128, verbose_name=_(u'label'))
|
||||
description = models.TextField(blank=True, verbose_name=_(u'description'))
|
||||
|
||||
def __unicode__(self):
|
||||
#return '%s (%s)' % (self.name, self.workflow.name)
|
||||
return self.label
|
||||
|
||||
class Meta:
|
||||
verbose_name = _(u'transition')
|
||||
verbose_name_plural = _(u'transitions')
|
||||
|
||||
|
||||
verbose_name = _(u'state')
|
||||
verbose_name_plural = _(u'states')
|
||||
ordering = ('label',)
|
||||
|
||||
|
||||
class WorkflowState(models.Model):
|
||||
"""
|
||||
List of possible states the object of this worflow could be in
|
||||
"""
|
||||
workflow = models.ForeignKey(Workflow, verbose_name=_(u'workflow'))
|
||||
state = models.ForeignKey(State, verbose_name=_(u'state'))
|
||||
description = models.TextField(blank=True, verbose_name=_(u'description'))
|
||||
@@ -69,17 +177,33 @@ class WorkflowState(models.Model):
|
||||
def __unicode__(self):
|
||||
return unicode(self.state)
|
||||
|
||||
@property
|
||||
def transitions(self):
|
||||
return self.workflowstatetransition_set
|
||||
|
||||
class Meta:
|
||||
#unique_together = ('workflow', 'state')
|
||||
unique_together = ('workflow', 'state')
|
||||
verbose_name = _(u'workflow state')
|
||||
verbose_name_plural = _(u'workflows states')
|
||||
|
||||
# TODO: Reduntant - remove
|
||||
class WorkflowNode(models.Model):
|
||||
workflow = models.ForeignKey(Workflow, verbose_name=_(u'workflow'))
|
||||
content_type = models.ForeignKey(ContentType)#, limit_choices_to={'model__in': ('model1', 'model2')})#, related_name='workflow_state_ability_object')#, blank=True, null=True)
|
||||
object_id = models.PositiveIntegerField()#blank=True, null=True)
|
||||
node = generic.GenericForeignKey(ct_field='content_type', fk_field='object_id')
|
||||
description = models.TextField(blank=True, verbose_name=_(u'description'))
|
||||
|
||||
def __unicode__(self):
|
||||
return unicode(self.node)
|
||||
|
||||
class WorkflowStateAbilityGrant(models.Model):
|
||||
#def save(self, *args, **kwargs):
|
||||
# if not issubclass(
|
||||
# return super(WorkflowNode, self).save(*args, **kwargs)
|
||||
|
||||
class Meta:
|
||||
#unique_together = ('workflow', 'state')
|
||||
verbose_name = _(u'workflow node')
|
||||
verbose_name_plural = _(u'workflows nodes')
|
||||
|
||||
"""
|
||||
class WorkflowTaskAbilityGrant(models.Model):
|
||||
workflow_state = models.ForeignKey(WorkflowState, related_name='workflow_state_ability', verbose_name=_(u'workflow state'))
|
||||
content_type = models.ForeignKey(ContentType, related_name='workflow_state_ability_object')#, blank=True, null=True)
|
||||
object_id = models.PositiveIntegerField()#blank=True, null=True)
|
||||
@@ -133,16 +257,69 @@ class WorkflowStateTransitionAbility(models.Model):
|
||||
verbose_name = _(u'transition')
|
||||
verbose_name_plural = _(u'transitions')
|
||||
|
||||
|
||||
"""
|
||||
class WorkflowInstance(models.Model):
|
||||
workflow = models.ForeignKey(Workflow, verbose_name = _(u'workflow'))
|
||||
workflow = models.ForeignKey(Workflow, verbose_name=_(u'workflow'))
|
||||
content_type = models.ForeignKey(ContentType, verbose_name=_(u'Content type'), related_name='workflow_instance_object')#, blank=True, null=True)
|
||||
object_id = models.PositiveIntegerField()#blank=True, null=True)
|
||||
content_object = generic.GenericForeignKey(ct_field='content_type', fk_field='object_id')
|
||||
workflow_state = models.ForeignKey(WorkflowState, related_name='workflow_instance_state', verbose_name=_(u'state'))
|
||||
|
||||
def __unicode__(self):
|
||||
return unicode(self.content_object)
|
||||
|
||||
@property
|
||||
def active_nodes(self):
|
||||
return self.workflowinstanceactivenode_set
|
||||
|
||||
def set_active_state(self, state):
|
||||
active_state = self.get_active_state()
|
||||
if active_state:
|
||||
active_state.delete()
|
||||
|
||||
# Trigger an exception if the state argument if not allowed for this workflow
|
||||
state = WorkflowState.objects.get(workflow=self.workflow, state=state).state
|
||||
|
||||
self.workflowinstanceactivestate_set.create(
|
||||
workflow_instance = self,
|
||||
state = state
|
||||
)
|
||||
|
||||
def get_active_state(self):
|
||||
try:
|
||||
return self.workflowinstanceactivestate_set.get().state
|
||||
except WorkflowInstanceActiveState.DoesNotExist:
|
||||
return None
|
||||
|
||||
active_state = property(get_active_state, set_active_state)
|
||||
|
||||
class Meta:
|
||||
unique_together = ('content_type', 'object_id', 'workflow')
|
||||
verbose_name = _(u'workflow instance')
|
||||
verbose_name_plural = _(u'workflow instances')
|
||||
|
||||
# unique_together = ('content_type', 'object_id', 'workflow')
|
||||
|
||||
|
||||
class WorkflowInstanceActiveNode(models.Model):
|
||||
workflow_instance = models.ForeignKey(WorkflowInstance, verbose_name=_(u'workflow instance'))
|
||||
workflow_node = models.ForeignKey(WorkflowNode, verbose_name=_(u'workflow node'))
|
||||
|
||||
class Meta:
|
||||
verbose_name = _(u'workflow instance active node')
|
||||
verbose_name_plural = _(u'workflow instances active nodes')
|
||||
|
||||
|
||||
class WorkflowInstanceActiveState(models.Model):
|
||||
"""
|
||||
This class holds the active state for the workflow instance
|
||||
"""
|
||||
workflow_instance = models.ForeignKey(WorkflowInstance, verbose_name=_(u'workflow instance'))
|
||||
state = models.ForeignKey(State, null=True, verbose_name=_(u'state'))
|
||||
|
||||
class Meta:
|
||||
unique_together = ('workflow_instance', 'state')
|
||||
verbose_name = _(u'workflow instance active state')
|
||||
verbose_name_plural = _(u'workflow instances active states')
|
||||
|
||||
|
||||
# TODO: WorkflowInstanceActiveNodeHistory
|
||||
# TODO: WorkflowInstanceActiveStateHistory
|
||||
|
||||
Reference in New Issue
Block a user