Author: | Dave Kuhlman |
---|---|
Address: | dkuhlman@rexx.com http://www.rexx.com/~dkuhlman |
Revision: | 1.0a |
Date: | July 19, 2005 |
Copyright: | Copyright (c) 2005 Dave Kuhlman. All Rights Reserved. This software is subject to the provisions of the Zope Public License, Version 2.1 (ZPL): http://www.zope.org/Resources/License/ |
Abstract
This document describes a procedure for implementing a business process as a CPS workflow. It is based on the CPSWorkflowHowTo.
This document attempts to give guidance toward the implementation of business processes as CPS workflows. The general procedure suggested here is to copy and then modify CPSWorkflowHowTo to implement your workflow.
Licensing -- A reminder -- This document suggests that you proceed by beginning with and then modifying CPSWorkflowHowTo. If you do so, you should preserve and honor the license for that product.
Our business process implementation model assumes that instances of a single document type are managed by CPS workflow.
The instructions given below uses an order execution workflow as an example of how to turn the CPSWorkflowHowTo into a workflow that manages a business process. For our examples, we use the following name mappings:
Follow these steps.
Use the original distribution of CPSWorkflowHowTo. It is available at: http://www.cps-project.org/sections/documentation/developers/cpsworkflow. (Look for "Sample product".) Expand it in Products directory of your Zope instance. Then rename the resulting sub-directory.
This should result in a subdirectory under Products that is named for your business process, for example "OrderExecutionWF".
Rename the following file:
Here are some modifications you will want to make:
Extensions/install.py:
workflows/__init__.py
workflows/order_execution_workflow.py:
This module defines the workflow. See below for more notes on defining the workflow
documents/__init__.py
documents/order_document.py:
There are also comments in some files that you will want to modify.
Here are other files that you will want to check and possibly modify:
Note the license at the top of some of these files. You should preserve and honor the terms of this license.
Roles are defined in:
Suggestion: You may want to install the ZMIntrospection product and use it to inspect existing workflow objects. See section Help from ZMIntrospection for more on this.
Stacks are defined and used in function getOrderExecutionWorkflowStates in module workflows.orderexec_workflow.py.
You can learn more about the definition of stacks by looking in the following places:
A stack is defined with a dictionary. The following keys and values are applicable in the dictionary that defines a stack:
stackdef_type -- is the stack definition type. Possible values are:
stack_type -- stack type (cf. above for the different available types. Possible values are:
var_id -- workflow variable id used to store this new variable.
'managed_role_exprs' -- A dictionary whose keys are role names and whose values are tales expressions that specify "the managed roles, e.g. roles that the stack definition can cope with. Roles have an associated tales expression evaluated within the stack definition context, defining the policy for the given role." (from the CPSWorkflowHowTo document) Here is an example:
{ # SectionReviewer: top of the stack, and at current level 'SectionReviewer': "python:stack.getAllLevels() and " \ "level == stack.getAllLevels()[-1] and " \ "level == stack.getCurrentLevel()", # SectionIntermediateReviewer: not top of the stack or not at current level 'SectionIntermediateReviewer': "python:stack.getAllLevels() and " \ "level < stack.getAllLevels()[-1] or " \ "level != stack.getCurrentLevel()", },
'empty_stack_manage_guard' -- This is the guard and management policy that is applied when the stack is empty. Specify Who can manage the stack when the stack is empty. Here is an example:
{ 'guard_roles': '; '.join(edit_roles), },
Note: You can also define new stack definitions, new stacks, and new stack elements. The CPSWorkflowHowTo describes this. And, there are examples:
States are defined in function getOrderExecutionWorkflowStates in module workflows.orderexec_workflow.py.
You can learn more about the definition of states by looking in the following places:
You can learn most of what you need to know by reading the existing function. In addition, here are a few notes about defining states:
Here are the keys and values for a single state dictionary:
title -- The title: a string.
description -- The description: a string.
transitions -- A tuple or list of transitions, for example:
'transitions': ('accept', 'reject', ),
state_behaviors -- The behaviors for the state. Possible values are:
Note that for each behavior type, there is another key that enables you to specify the variables to which the behavior is applied. See below.
stackdefs -- A dictionary containing stack definitions. The keys are the workflow variable ID of each variable. The values are the definition of the variable. See below for the definition of a workflow stack.
push_on_workflow_variable -- List of variables applicable for behavior STATE_BEHAVIOR_PUSH_DELEGATEES.
pop_on_workflow_variable -- List of variables applicable for behavior STATE_BEHAVIOR_POP_DELEGATEES.
workflow_up_on_workflow_variable -- List of variables applicable for behavior STATE_BEHAVIOR_WORKFLOW_UP.
workflow_down_on_workflow_variable -- List of variables applicable for behavior STATE_BEHAVIOR_WORKFLOW_DOWN.
workflow_reset_on_workflow_variable -- List of variables applicable for behavior STATE_BEHAVIOR_WORKFLOW_RESET.
Transitions are defined in function getOrderExecutionWorkflowTransitions in module order_execution_workflow.py.
You can learn more about the definition of states by looking in the following places:
You can learn most of what you need to know by reading the existing function in CPSWorkflowHowTo. In addition, here are a few notes about defining transitions:
Here are the keys and values for a single transition dictionary:
'title' -- 'Reviewer rejects publishing',
'description' --
'new_state_id' -- '',
'trigger_type' -- One of:
'transition_behavior' -- A tuple containing one or more of transition flags. These correspond to the flags shown in the properties view of a transition in the ZMI. This tuple can contain the following flags:
clone_allowed_transitions -- ???
checkout_allowed_initial_transitions --
checkin_allowed_transitions --
push_on_workflow_variable -- A list/tuple of variables (strings).
pop_on_workflow_variable -- A list/tuple of variables (strings).
workflow_up_on_workflow_variable -- A list/tuple of variables (strings).
workflow_down_on_workflow_variable -- A list/tuple of variables (strings).
workflow_reset_on_workflow_variable -- A list/tuple of variables (strings).
'actbox_name' -- Name of the action in the action box.
'actbox_category' -- Usually 'workflow',
'actbox_url' -- The URL of the form file. Examples are:
'actbox_url': '%(content_url)s/content_move_up_delegatees_form?current_var_id=Reviewers', '%(content_url)s/content_reject_form',
'script_name' -- Script (before).
'after_script_name' -- Script (after).
'props' -- A dictionary. The keys are:
'guard_roles' -- The list of roles that are allowed to cause this transition. The value might look something like this:
edit_roles = 'Manager; SectionManager; SectionReviewer; '
'guard_expr' -- A procedure which must return a true value in order for the transition to be performed. Here is an example:
"python:user.has_role(('Manager', 'SectionManager', 'SectionReviewer'), here) or " \ "user.has_role(('SectionIntermediateReviewer',), here) and " \ "here.portal_workflow.canManageStack(here, 'Reviewers')"
It may be helpful to "introspect" the states, transitions, etc. in existing workflows. To do so, install the ZMIntrospection product. I did this by doing the following from the command line from within the Products directory of my Zope instance:
svn co http://svn.nuxeo.org/pub/ZMIntrospection/trunk ZMIntrospection
Then restarting Zope. Now, in the ZMI, click on a state or transition within a workflow and then click on the "Introspection" tab.
For example, when I look at the the pending state in the cps_validation_wf from the CPSWorkflowHowTo (/cps1/portal_workflow/cps_validation_wf/states/pending), then click on the "Introspection" tab, I see the following:
{'Reviewers': <HierarchicalStackDefinition at 0xb3b392ac>, '__ac_local_roles__': {'dave': ['Owner']}, '_objects': ({'id': 'Reviewers', 'meta_type': 'Hierarchical Stack Definition'},), 'description': '', 'id': 'pending', 'permission_roles': { 'Modify portal content': ('Manager', 'SectionManager', 'SectionReviewer', 'SectionIntermediateReviewer'), 'View': ('Manager', 'SectionManager', 'SectionReviewer', 'SectionIntermediateReviewer') }, 'pop_on_workflow_variable': ('Reviewers',), 'push_on_workflow_variable': ('Reviewers',), 'state_behaviors': (101, 102, 104, 103), 'title': 'Waiting for reviewer', 'transitions': ('accept', 'reject', 'manage_delegatees', 'move_up_delegatees', 'move_down_delegatees'), 'workflow_down_on_workflow_variable': ('Reviewers',), 'workflow_up_on_workflow_variable': ('Reviewers',) }
(I've done a bit of reformatting for readability of the above.)
Here are a few notes:
The definition of state_behaviors above shows numbers, for example, 101, 102, etc. In your source code, you should be using the defined constants, for example, STATE_BEHAVIOR_PUSH_DELEGATEES, STATE_BEHAVIOR_POP_DELEGATEES, which you can import as follows:
from Products.CPSWorkflow.states import \ STATE_BEHAVIOR_PUSH_DELEGATEES, \ STATE_BEHAVIOR_POP_DELEGATEES, \ STATE_BEHAVIOR_WORKFLOW_UP, \ STATE_BEHAVIOR_WORKFLOW_DOWN
I was not able to introspect the workflow stack Reviewer in the cps_validation_wf from the CPSWorkflowHowTo. I clicked on the "States" tab, then on the state pending, then on the "Workflow Stacks" tab, then on Reviewers, and finally clicked on the "Introspection" tab. But, what I got was the dictionary for the state, not the workflow stack. This is an idiosyncrasy of the ZMI interface, I believe. So, just a warning that you show look at what you see to make sure it's what you want.
Hopefully, you now know enough to be able to define your own workflow. You might want to follow the instructions in the CPSWorkflowHowTo, which uses the ZMI, but create those definitions in Python source code, as described above, instead.
So, how can you go about designing a workflow. Let's assume that your business process is clearly defined and understood. Then, try following these steps: