Workflow with multiple approvals required
We needed to set-up a document so that it had to be approved (reviewed) by a certain number of people before it was published. The following instructions are a combination of instructions from http://plone.org/documentation/howto/HowToWorkflowPerms and the generous help of Riccardo Lemmi, Dieter Maurer and others on the mailing lists.
Setting up a custom workflow
As this workflow is only required for this specific document it was necessary to create a custom workflow rather than edit the standard Plone workflow.
- In the ZMI, under Plone/portal workflow click on the contents tab
- Copy and paste the default Plone_workflow then rename the copy with a relevant name
- Click on the new workflow to edit it
Making the pending document invisible
Whilst the document is awaiting approval we don't want it to be available to anonymous users or members. As I wasn't sure where the view permission for the pending and visible states is acquired from, I wanted to manually set this within the workflow.
- Click on the States tab for your custom workflow
- Click on the pending state, then the permissions tab
- Remove the tick from Acquire permission settings for Access contents information and View and then make sure there are no ticks in the corresponding Anonymous and Authenticated columns
- Save the changes
- Do the same for the Visible state
Adding variables
These are used to track how many approvals the document has received and which reviewers made those approvals.
- Return to your new workflow root and click on the Variables tab
- At the bottom of the page add a variable called
approvals - Click on your new approvals variable
- Change Variable update mode to:
update only when the new state specifies a new value
- Change the Default Value to 0 (zero)
- Save your changes
- Now add a variable called
reviewer_name - Change Variable update mode to:
update only when the new state specifies a new value
- In Default Expression add:
python:[]
So the variable is stored in a list.
- Save changes
Adding a new transition
After being submitted the document needs to be stored in a new transition state before being published.
- Click on the Transitions tab
- At the bottom of the page add a transition called
approve - Click on your new approve transition
- Add the Title - Reviewer approves content
- In Guard -
- add Permission:
Review portal content (for any reviewer) or Role: name_of_reviewerRole (to specifiy a specific reviewer type)
- add Permission:
To ensure only reviewers or a specific role can approve the document.
- in the Expression box add:
python:request.AUTHENTICATED_USER.getUserName() not in state_change.status.get('reviewer_name','')
*This checks against the reviewer_name list to ensure this reviewer hasn't already approved the document.*
- In Display in actions box add -
- Name: Approve
- URL::
%(content_url)s/content_approve_form
- Save changes then click on the Variables tab
- From the variables drop-down box choose approvals
- In the Expression box add:
python:int(state_change.status.get('approvals',0))+1
Increases the approvals variable by 1.
- Click Add
- From the variables drop-down box choose reviewer_name
- In the Expression box add:
python: state_change.status.get('reviewer_name') + [user.getUserName()]
Adds the approving reviewer's name to the reviewer_name list so they can't approve a second time.
- Click Add
Changing the Publish transition
Since publishing should now happen automatically once all the necessary approvals have been received we need to make a quick change to the publish transition.
- Go back to Transitions and click on publish to edit it
- Change the Trigger type to Automatic
- In Guard, in the Expression box add:
python:int(state_change.status.get('approvals',0))>=4
So the document will be published when the approvals variable reaches 4.
- Save changes
Changing the Retract transition
(You'll want to follow exactly the same process as this for the reject transition.)
- On the Transitions choose retract to edit it
- Click on the variables tab
- Add the following expression to the approvals variable:
python:int(state_change.status.get('approvals',0))==0
Sets approvals back to 0.
- add the following expression to the reviewer_name variable:
python:[]
Empties the reviewer_name list.
Nb - This step is important! If approvals isn't set back from 4 to 0 the document will instantly be re-published. It also empties the list of reviewers, otherwise those already in the list wouldn't be able to approve the document in future.
Changing the state
Now the approve transition is set up it needs to be made part of the workflow...
- Go back to your custom workflows
front pageand click on the States tab - Click on the pending state and add a tick next to the transition Approve
- Save changes
Applying the workflow to a document
Now everything is set up you'll need to register this workflow with the document it needs to be applied to.
- Go back to the portal workflow page with the list of documents and their workflows
- Next to the document that you want to add your custom workflow to, change the name to that of the new workflow
- Click change
- Click the update security settings to apply the new workflow to all relevant documents
Known issues
The main issue I'm aware of with this is that, once approved, the document is still isted in the reviewer's list of documents to be reviewed. David Chestnut has sent me a possible solution to this which I'll add here once I've tested it... though he's welcome to add it himself ;)
If you have any suggestions for improvements to this document don't hesitate to add comments or even to dive in and amend it yourself!

Author: