doc/book/en/B0020-define-workflows.en.txt
changeset 1206 6db7addc2869
parent 858 e6ae125d5903
child 1220 9f80ecdb057a
equal deleted inserted replaced
1205:79d33f7db590 1206:6db7addc2869
     3 .. _Workflow:
     3 .. _Workflow:
     4 
     4 
     5 Workflow definition
     5 Workflow definition
     6 ===================
     6 ===================
     7 
     7 
       
     8 [TODO :  All this is too obscure and often not very understandable...]
       
     9 
     8 General
    10 General
     9 -------
    11 -------
    10 
    12 
    11 A workflow can be defined in a `CubicWeb` application thanks to the system 
    13 [XXX define what a "Workflow" is: states, transitions, transition graph ]
    12 entities ``State`` and ``Transition``. Those are defined within all 
       
    13 `CubicWeb` application and can be set-up through the main administrator interface.
       
    14 
       
    15 Once your schema is defined, you can start creating the set of states and
       
    16 the required transitions for your applications entities.
       
    17 
       
    18 You first need to define the states and then the transitions between those
       
    19 to complete your workflow.
       
    20 
       
    21 A ``State`` defines the status of an entity. While creating a new state, 
       
    22 you will be first given the option to select the entity type the state
       
    23 can be applied to. By choosing ``Apply``, a new section will be displayed
       
    24 in the editing screen to enable you to add relation to the state you are
       
    25 creating.
       
    26 
       
    27 A ``Transition`` is also based on an entity type it can be applied to.
       
    28 By choosing ``Apply``, a new section will be displayed in the editing 
       
    29 screen to enable you to add relation to the transition you are
       
    30 creating.
       
    31 
       
    32 At the transition level you will also define the group of user which can
       
    33 aplly this transition to an object.
       
    34 
       
    35 
    14 
    36 Example of a simple workflow
    15 Example of a simple workflow
    37 ----------------------------
    16 ----------------------------
    38 
    17 
    39 Please see the tutorial to view and example of a simple workflow.
    18 Please see the tutorial to view an example of a simple workflow.
    40 
    19 
    41 
    20 
    42 [Create a simple workflow for BlogDemo, to have a moderator approve new blog 
    21 [Create a simple workflow for BlogDemo, to have a moderator approve new blog 
    43 entry to be published. This implies, specify a dedicated group of blog
    22 entry to be published. This implies specifying a dedicated group of blog
    44 moderator as well as hide the view of a blog entry to the user until
    23 moderator as well as hiding the view of a blog entry to the user until
    45 it reaches the state published]
    24 it reaches the state published]
    46 
    25 
    47 Set-up a workflow
    26 Set-up a workflow
    48 -----------------
    27 -----------------
    49 
    28 
    50 We want to create a workflow to control the quality of the BlogEntry 
    29 We want to create a workflow to control the quality of the BlogEntry 
    51 submitted on your application. When a BlogEntry is created by a user
    30 submitted on your application. When a BlogEntry is created by a user
    52 its state should be `submitted`. To be visible to all, it needs to
    31 its state should be `submitted`. To be visible to all, it has to
    53 be in the state `published`. To move from `submitted` to `published`
    32 be in the state `published`. To move it from `submitted` to `published`,
    54 we need a transition that we can name `approve_blogentry`.
    33 we need a transition that we can call `approve_blogentry`.
    55 
    34 
    56 We do not want every user to be allowed to change the state of a 
    35 A BlogEntry state should not be modifiable by every user.
    57 BlogEntry. We need to define a group of user, `moderators`, and 
    36 So we have to define a group of users, `moderators`, and 
    58 this group will have appropriate permissions to approve BlogEntry
    37 this group will have appropriate permissions to publish a BlogEntry.
    59 to be published and visible to all.
       
    60 
    38 
    61 There are two ways to create a workflow, form the user interface,
    39 There are two ways to create a workflow: from the user interface,
    62 and also by defining it in ``migration/postcreate.py``. 
    40 or by defining it in ``migration/postcreate.py``. 
    63 This script is executed each time a new ``cubicweb-ctl db-init`` is done. 
    41 This script is executed each time a new ``cubicweb-ctl db-init`` is done. 
    64 If you create the states and transitions through the user interface
    42 We strongly recommand to create the workflow in ``migration/postcreate.py``
    65 this means that next time you will need to initialize the database
    43 and we will now show you how. Read `Under the hood`_ to understand why.
    66 you will have to re-create all the entities. 
       
    67 We strongly recommand you create the workflow in ``migration\postcreate.py``
       
    68 and we will now show you how.
       
    69 The user interface would only be a reference for you to view the states 
       
    70 and transitions but is not the appropriate interface to define your
       
    71 application workflow.
       
    72 
    44 
    73 Update the schema
    45 Update the schema
    74 ~~~~~~~~~~~~~~~~~
    46 ~~~~~~~~~~~~~~~~~
    75 To enable a BlogEntry to have a State, we have to define a relation
    47 If we want a State for our BlogEntry, we have to define a relation
    76 ``in_state`` in the schema of BlogEntry. Please do as follows, add
    48 ``in_state`` in the schema of BlogEntry. So we add
    77 the line ``in_state (...)``::
    49 the line ``in_state (...)``::
    78 
    50 
    79   class BlogEntry(EntityType):
    51   class BlogEntry(EntityType):
    80       title = String(maxsize=100, required=True)
    52       title = String(maxsize=100, required=True)
    81       publish_date = Date(default='TODAY')
    53       publish_date = Date(default='TODAY')
    84       text = String(fulltextindexed=True)
    56       text = String(fulltextindexed=True)
    85       category = String(vocabulary=('important','business'))
    57       category = String(vocabulary=('important','business'))
    86       entry_of = SubjectRelation('Blog', cardinality='?*')
    58       entry_of = SubjectRelation('Blog', cardinality='?*')
    87       in_state = SubjectRelation('State', cardinality='1*')
    59       in_state = SubjectRelation('State', cardinality='1*')
    88 
    60 
    89 As you updated the schema, you will have re-execute ``cubicweb-ctl db-init``
    61 As you updated the schema, you have to re-execute ``cubicweb-ctl db-init``
    90 to initialize the database and migrate your existing entities.
    62 to initialize the database and migrate your existing entities.
       
    63 
    91 [WRITE ABOUT MIGRATION]
    64 [WRITE ABOUT MIGRATION]
    92 
    65 
    93 Create states, transitions and group permissions
    66 Create states, transitions and group permissions
    94 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    67 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    95 
    68 
    96 At the time the ``postcreate.py`` script is executed, several methods
    69 The ``postcreate.py`` script is executed in a special environment, adding
    97 can be used. They are all defined in the ``class ServerMigrationHelper``.
    70 several `CubicWeb` primitives that can be used.
    98 We will only discuss the method we use to create a wrokflow here.
    71 They are all defined in the ``class ServerMigrationHelper``.
       
    72 We will only discuss the methods we use to create a workflow in this example.
    99 
    73 
   100 To define our workflow for BlogDemo, please add the following lines
    74 To define our workflow for BlogDemo, please add the following lines
   101 to ``migration/postcreate.py``::
    75 to ``migration/postcreate.py``::
   102   
    76   
   103   _ = unicode
    77   _ = unicode
   104 
    78 
   105   moderators      = add_entity('EGroup', name=u"moderators")
    79   moderators = add_entity('EGroup', name=u"moderators")
       
    80 
       
    81 This adds the `moderators` user group.
       
    82 
       
    83 ::
   106 
    84 
   107   submitted = add_state(_('submitted'), 'BlogEntry', initial=True)
    85   submitted = add_state(_('submitted'), 'BlogEntry', initial=True)
   108   published = add_state(_('published'), 'BlogEntry')
    86   published = add_state(_('published'), 'BlogEntry')
   109 
    87 
       
    88 ``add_state`` expects as first argument the name of the state you want
       
    89 to create, then the entity type on which the state can be applied,
       
    90 and an optional argument to say if it is supposed to be the initial state
       
    91 of the entity type.
       
    92 
       
    93 ::
       
    94 
   110   add_transition(_('approve_blogentry'), 'BlogEntry', (submitted,), published, ('moderators', 'managers'),)
    95   add_transition(_('approve_blogentry'), 'BlogEntry', (submitted,), published, ('moderators', 'managers'),)
       
    96 
       
    97 
       
    98 ``add_transition`` expects 
       
    99 
       
   100   * as the first argument the name of the
       
   101     transition, then the entity type on which the transition can be applied,
       
   102   * then the list of states on which the transition can be trigged,
       
   103   * the target state of the transition, 
       
   104   * and the permissions
       
   105     (e.g. a list of user groups who can apply the transition; the user
       
   106     has to belong to at least one of the listed group to perform the action).
       
   107 
       
   108 ::
   111 
   109 
   112   checkpoint()
   110   checkpoint()
   113 
   111 
   114 .. note::
   112 .. note::
   115   Do not forget to add the `_()` in front of all states and transitions names while creating
   113   Do not forget to add the `_()` in front of all states and transitions names while creating
   116   a workflow so that they will be identified by the i18n catalog scripts.
   114   a workflow so that they will be identified by the i18n catalog scripts.
   117 
   115 
   118 ``add_entity`` is used here to define the new group of users that we
   116 In addition to the user group condition, we could have added a RQL condition. 
   119 need to define the transitions, `moderators`.
   117 In this case, the user can only perform the action if 
   120 If this group required by the transition is not defined before the
   118 the two conditions are satisfied. 
   121 transition is created, it will not create the relation `transition 
       
   122 require the group moderator`.
       
   123 
       
   124 ``add_state`` expects as the first argument the name of the state you are
       
   125 willing to create, then the entity type on which the state can be applied, 
       
   126 and an optionnal argument to set if the state is the initial state
       
   127 of the entity type or not.
       
   128 
       
   129 ``add_transition`` expects as the first argument the name of the 
       
   130 transition, then the entity type on which we can apply the transition,
       
   131 then the list of possible initial states from which the transition
       
   132 can be applied, the target state of the transition, and the permissions
       
   133 (e.g. list of the groups of users who can apply the transition, the user
       
   134 needs to belong to at least one of the listed group).
       
   135 
       
   136 
       
   137 We could have also added a RQL condition in addition to a group to 
       
   138 which the user should belong to. 
       
   139 
       
   140 If we use both RQL condition and group, the two must be satisfied 
       
   141 for the user to be allowed to apply the transition.
       
   142 
   119 
   143 If we use a RQL condition on a transition, we can use the following 
   120 If we use a RQL condition on a transition, we can use the following 
   144 variables:
   121 variables:
   145 
   122 
   146 * `%(eid)s`, object's eid
   123 * `%(eid)s`, object's eid
   148 * `%(seid)s`, the object's current state eid
   125 * `%(seid)s`, the object's current state eid
   149 
   126 
   150 
   127 
   151 .. image:: images/lax-book.03-transitions-view.en.png
   128 .. image:: images/lax-book.03-transitions-view.en.png
   152 
   129 
   153 You can now notice that in the actions box of a BlogEntry, the state
   130 You can notice that in the action box of a BlogEntry, the state
   154 is now listed as well as the possible transitions from this state
   131 is now listed as well as the possible transitions defined by the workflow.
   155 defined by the workflow. This transition, as defined in the workflow,
   132 The transitions will only be displayed for users having the right permissions.
   156 will only being displayed for the users belonging to the group
   133 In our example, the transition `approve_blogentry` will only be displayed 
   157 moderators of managers.
   134 for the users belonging to the group `moderators` or `managers`.
       
   135 
       
   136 
       
   137 Under the hood
       
   138 ~~~~~~~~~~~~~~
       
   139 
       
   140 A workflow is a collection of entities of type ``State`` and of type ``Transition``
       
   141 which are standard `CubicWeb` entity types.
       
   142 For instance, the following lines::
       
   143 
       
   144   submitted = add_state(_('submitted'), 'BlogEntry', initial=True)
       
   145   published = add_state(_('published'), 'BlogEntry')
       
   146 
       
   147 will create two entities of type ``State``, one with name 'submitted', and the other
       
   148 with name 'published'. Whereas::
       
   149 
       
   150   add_transition(_('approve_blogentry'), 'BlogEntry', (submitted,), published, ('moderators', 'managers'),)
       
   151  
       
   152 will create an entity of type ``Transition`` with name 'approve_blogentry' which will
       
   153 be linked to the ``State`` entities created before.
       
   154 As a consequence, we could use the administration interface to do these operations.
       
   155 But it is not recommanded because it will be uselessly complicated
       
   156 and will be only local to your instance.
       
   157 
       
   158 
       
   159 Indeed, if you create the states and transitions through the user interface,
       
   160 next time you initialize the database
       
   161 you will have to re-create all the entities. 
       
   162 The user interface should only be a reference for you to view the states 
       
   163 and transitions, but is not the appropriate interface to define your
       
   164 application workflow.
       
   165 
       
   166