doc/book/en/B0020-define-workflows.en.txt
author Julien Jehannet <julien.jehannet@logilab.fr>
Thu, 19 Feb 2009 20:19:05 +0100
changeset 858 e6ae125d5903
parent 306 1ed1da008e50
child 1206 6db7addc2869
permissions -rw-r--r--
reorganize debian packages (Closes: #1168) - Merge cubicweb-core into cubicweb-common - Fix lintian errors - Install bash_completion file correctly - Clean debian/rules

.. -*- coding: utf-8 -*-

.. _Workflow:

Workflow definition
===================

General
-------

A workflow can be defined in a `CubicWeb` application thanks to the system 
entities ``State`` and ``Transition``. Those are defined within all 
`CubicWeb` application and can be set-up through the main administrator interface.

Once your schema is defined, you can start creating the set of states and
the required transitions for your applications entities.

You first need to define the states and then the transitions between those
to complete your workflow.

A ``State`` defines the status of an entity. While creating a new state, 
you will be first given the option to select the entity type the state
can be applied to. By choosing ``Apply``, a new section will be displayed
in the editing screen to enable you to add relation to the state you are
creating.

A ``Transition`` is also based on an entity type it can be applied to.
By choosing ``Apply``, a new section will be displayed in the editing 
screen to enable you to add relation to the transition you are
creating.

At the transition level you will also define the group of user which can
aplly this transition to an object.


Example of a simple workflow
----------------------------

Please see the tutorial to view and example of a simple workflow.


[Create a simple workflow for BlogDemo, to have a moderator approve new blog 
entry to be published. This implies, specify a dedicated group of blog
moderator as well as hide the view of a blog entry to the user until
it reaches the state published]

Set-up a workflow
-----------------

We want to create a workflow to control the quality of the BlogEntry 
submitted on your application. When a BlogEntry is created by a user
its state should be `submitted`. To be visible to all, it needs to
be in the state `published`. To move from `submitted` to `published`
we need a transition that we can name `approve_blogentry`.

We do not want every user to be allowed to change the state of a 
BlogEntry. We need to define a group of user, `moderators`, and 
this group will have appropriate permissions to approve BlogEntry
to be published and visible to all.

There are two ways to create a workflow, form the user interface,
and also by defining it in ``migration/postcreate.py``. 
This script is executed each time a new ``cubicweb-ctl db-init`` is done. 
If you create the states and transitions through the user interface
this means that next time you will need to initialize the database
you will have to re-create all the entities. 
We strongly recommand you create the workflow in ``migration\postcreate.py``
and we will now show you how.
The user interface would only be a reference for you to view the states 
and transitions but is not the appropriate interface to define your
application workflow.

Update the schema
~~~~~~~~~~~~~~~~~
To enable a BlogEntry to have a State, we have to define a relation
``in_state`` in the schema of BlogEntry. Please do as follows, add
the line ``in_state (...)``::

  class BlogEntry(EntityType):
      title = String(maxsize=100, required=True)
      publish_date = Date(default='TODAY')
      text_format = String(meta=True, internationalizable=True, maxsize=50,
                           default='text/rest', constraints=[format_constraint])
      text = String(fulltextindexed=True)
      category = String(vocabulary=('important','business'))
      entry_of = SubjectRelation('Blog', cardinality='?*')
      in_state = SubjectRelation('State', cardinality='1*')

As you updated the schema, you will have re-execute ``cubicweb-ctl db-init``
to initialize the database and migrate your existing entities.
[WRITE ABOUT MIGRATION]

Create states, transitions and group permissions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

At the time the ``postcreate.py`` script is executed, several methods
can be used. They are all defined in the ``class ServerMigrationHelper``.
We will only discuss the method we use to create a wrokflow here.

To define our workflow for BlogDemo, please add the following lines
to ``migration/postcreate.py``::
  
  _ = unicode

  moderators      = add_entity('EGroup', name=u"moderators")

  submitted = add_state(_('submitted'), 'BlogEntry', initial=True)
  published = add_state(_('published'), 'BlogEntry')

  add_transition(_('approve_blogentry'), 'BlogEntry', (submitted,), published, ('moderators', 'managers'),)

  checkpoint()

.. note::
  Do not forget to add the `_()` in front of all states and transitions names while creating
  a workflow so that they will be identified by the i18n catalog scripts.

``add_entity`` is used here to define the new group of users that we
need to define the transitions, `moderators`.
If this group required by the transition is not defined before the
transition is created, it will not create the relation `transition 
require the group moderator`.

``add_state`` expects as the first argument the name of the state you are
willing to create, then the entity type on which the state can be applied, 
and an optionnal argument to set if the state is the initial state
of the entity type or not.

``add_transition`` expects as the first argument the name of the 
transition, then the entity type on which we can apply the transition,
then the list of possible initial states from which the transition
can be applied, the target state of the transition, and the permissions
(e.g. list of the groups of users who can apply the transition, the user
needs to belong to at least one of the listed group).


We could have also added a RQL condition in addition to a group to 
which the user should belong to. 

If we use both RQL condition and group, the two must be satisfied 
for the user to be allowed to apply the transition.

If we use a RQL condition on a transition, we can use the following 
variables:

* `%(eid)s`, object's eid
* `%(ueid)s`, user executing the query eid
* `%(seid)s`, the object's current state eid


.. image:: images/lax-book.03-transitions-view.en.png

You can now notice that in the actions box of a BlogEntry, the state
is now listed as well as the possible transitions from this state
defined by the workflow. This transition, as defined in the workflow,
will only being displayed for the users belonging to the group
moderators of managers.