|
1 .. -*- coding: utf-8 -*- |
|
2 |
|
3 .. _Workflow: |
|
4 |
|
5 Workflow definition |
|
6 =================== |
|
7 |
|
8 General |
|
9 ------- |
|
10 |
|
11 A workflow can be defined in a `CubicWeb` application thanks to the system |
|
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 |
|
36 Example of a simple workflow |
|
37 ---------------------------- |
|
38 |
|
39 Please see the tutorial to view and example of a simple workflow. |
|
40 |
|
41 |
|
42 [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 |
|
44 moderator as well as hide the view of a blog entry to the user until |
|
45 it reaches the state published] |
|
46 |
|
47 Set-up a workflow |
|
48 ----------------- |
|
49 |
|
50 Before starting, make sure you refresh your mind by reading [link to |
|
51 definition_workflow chapter]. |
|
52 |
|
53 We want to create a workflow to control the quality of the BlogEntry |
|
54 submitted on your application. When a BlogEntry is created by a user |
|
55 its state should be `submitted`. To be visible to all, it needs to |
|
56 be in the state `published`. To move from `submitted` to `published` |
|
57 we need a transition that we can name `approve_blogentry`. |
|
58 |
|
59 We do not want every user to be allowed to change the state of a |
|
60 BlogEntry. We need to define a group of user, `moderators`, and |
|
61 this group will have appropriate permissions to approve BlogEntry |
|
62 to be published and visible to all. |
|
63 |
|
64 There are two ways to create a workflow, form the user interface, |
|
65 and also by defining it in ``migration/postcreate.py``. This script |
|
66 is executed each time a new ``./bin/laxctl db-init`` is done. |
|
67 If you create the states and transitions through the user interface |
|
68 this means that next time you will need to initialize the database |
|
69 you will have to re-create all the entities. |
|
70 We strongly recommand you create the workflow in ``migration\postcreate.py`` |
|
71 and we will now show you how. |
|
72 The user interface would only be a reference for you to view the states |
|
73 and transitions but is not the appropriate interface to define your |
|
74 application workflow. |
|
75 |
|
76 Update the schema |
|
77 ~~~~~~~~~~~~~~~~~ |
|
78 To enable a BlogEntry to have a State, we have to define a relation |
|
79 ``in_state`` in the schema of BlogEntry. Please do as follows, add |
|
80 the line ``in_state (...)``:: |
|
81 |
|
82 class BlogEntry(EntityType): |
|
83 title = String(maxsize=100, required=True) |
|
84 publish_date = Date(default='TODAY') |
|
85 text_format = String(meta=True, internationalizable=True, maxsize=50, |
|
86 default='text/rest', constraints=[format_constraint]) |
|
87 text = String(fulltextindexed=True) |
|
88 category = String(vocabulary=('important','business')) |
|
89 entry_of = SubjectRelation('Blog', cardinality='?*') |
|
90 in_state = SubjectRelation('State', cardinality='1*') |
|
91 |
|
92 As you updated the schema, you will have re-execute ``./bin/laxctl db-init`` |
|
93 to initialize the database and migrate your existing entities. |
|
94 [WRITE ABOUT MIGRATION] |
|
95 |
|
96 Create states, transitions and group permissions |
|
97 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
98 |
|
99 At the time the ``postcreate.py`` script is executed, several methods |
|
100 can be used. They are all defined in the ``class ServerMigrationHelper``. |
|
101 We will only discuss the method we use to create a wrokflow here. |
|
102 |
|
103 To define our workflow for BlogDemo, please add the following lines |
|
104 to ``migration/postcreate.py``:: |
|
105 |
|
106 _ = unicode |
|
107 |
|
108 moderators = add_entity('EGroup', name=u"moderators") |
|
109 |
|
110 submitted = add_state(_('submitted'), 'BlogEntry', initial=True) |
|
111 published = add_state(_('published'), 'BlogEntry') |
|
112 |
|
113 add_transition(_('approve_blogentry'), 'BlogEntry', (submitted,), published, ('moderators', 'managers'),) |
|
114 |
|
115 checkpoint() |
|
116 |
|
117 .. note:: |
|
118 Do not forget to add the `_()` in front of all states and transitions names while creating |
|
119 a workflow so that they will be identified by the i18n catalog scripts. |
|
120 |
|
121 ``add_entity`` is used here to define the new group of users that we |
|
122 need to define the transitions, `moderators`. |
|
123 If this group required by the transition is not defined before the |
|
124 transition is created, it will not create the relation `transition |
|
125 require the group moderator`. |
|
126 |
|
127 ``add_state`` expects as the first argument the name of the state you are |
|
128 willing to create, then the entity type on which the state can be applied, |
|
129 and an optionnal argument to set if the state is the initial state |
|
130 of the entity type or not. |
|
131 |
|
132 ``add_transition`` expects as the first argument the name of the |
|
133 transition, then the entity type on which we can apply the transition, |
|
134 then the list of possible initial states from which the transition |
|
135 can be applied, the target state of the transition, and the permissions |
|
136 (e.g. list of the groups of users who can apply the transition, the user |
|
137 needs to belong to at least one of the listed group). |
|
138 |
|
139 |
|
140 We could have also added a RQL condition in addition to a group to |
|
141 which the user should belong to. |
|
142 |
|
143 If we use both RQL condition and group, the two must be satisfied |
|
144 for the user to be allowed to apply the transition. |
|
145 |
|
146 If we use a RQL condition on a transition, we can use the following |
|
147 variables: |
|
148 |
|
149 * `%(eid)s`, object's eid |
|
150 * `%(ueid)s`, user executing the query eid |
|
151 * `%(seid)s`, the object's current state eid |
|
152 |
|
153 |
|
154 .. image:: images/lax-book.03-transitions-view.en.png |
|
155 |
|
156 You can now notice that in the actions box of a BlogEntry, the state |
|
157 is now listed as well as the possible transitions from this state |
|
158 defined by the workflow. This transition, as defined in the workflow, |
|
159 will only being displayed for the users belonging to the group |
|
160 moderators of managers. |
|
161 |