| | 1 | == The Leave workflow application == |
| | 2 | (not up to date) |
| | 3 | |
| | 4 | Follow instructions in the [https://opensvn.csie.org/goflow/trunk/INSTALL.TXT INSTALL.TXT] file included in the [https://opensvn.csie.org/goflow/trunk/goflow goflow distribution]. |
| | 5 | You can then play with the leave demo application (available [wiki:GoFlow:demo online] too). |
| | 6 | |
| | 7 | You will find here some details of the leave application implementation. |
| | 8 | |
| | 9 | === defining the workflow process === |
| | 10 | First, let's take a look at the process definition; the process is stored in the database, by using entities like Process, Activities, Transitions, Application (see workflow/models.py, and the [http://goflow.alwaysdata.net/images/workflow.png goflow data model] generated by modelviz/graphviz). In the leavedemo project, the process is dumped with the django dumpdata utility, and provided as a fixture. Typically, when you want to define a process, you will use the admin web console. |
| | 11 | |
| | 12 | So, the process is the following: |
| | 13 | http://goflow.alwaysdata.net/leavedemo/media/img/leaveactivities.png |
| | 14 | |
| | 15 | below, the process translated as django entities, with a python syntax (it is not a real code, it's just more readable by humans): |
| | 16 | {{{ |
| | 17 | Process(title='leave', begin='Begin', end='End') |
| | 18 | |
| | 19 | Activity(title='Begin', application='checkstatus', |
| | 20 | pushApplication='route_to_secretary', |
| | 21 | splitMode='xor', roles=('secretary',)) |
| | 22 | |
| | 23 | Activity(title='Approval', application='approvalform', |
| | 24 | pushApplication='route_to_supervisor', |
| | 25 | splitMode='xor', roles=('secretary',)) |
| | 26 | |
| | 27 | Activity(title='Refinement', application='refine', |
| | 28 | pushApplication='route_to_customer', |
| | 29 | joinMode='xor', splitMode='xor') |
| | 30 | |
| | 31 | Activity(title='UpdateHR', application='hrform', |
| | 32 | pushApplication='route_to_secretary', |
| | 33 | roles=('supervisor',)) |
| | 34 | |
| | 35 | Activity(title='End', application='finalinfo', |
| | 36 | pushApplication='route_to_customer', |
| | 37 | joinMode='xor', roles=('secretary',), |
| | 38 | autoFinish=False) |
| | 39 | |
| | 40 | Transition(name='send_to_approval', |
| | 41 | input = 'Begin', output='Approval', |
| | 42 | condition="instance.condition=='OK: Forward to supervisor'") |
| | 43 | |
| | 44 | Transition(name='send_to_refinement', |
| | 45 | input = 'Begin', output='Refinement', |
| | 46 | condition="instance.condition=='Denied: Back to requester'") |
| | 47 | |
| | 48 | Transition(name='request_approved', |
| | 49 | input = 'Approval', output='UpdateHR', |
| | 50 | condition="instance.condition=='OK: Forward to secretary'") |
| | 51 | |
| | 52 | Transition(name='not_approved', |
| | 53 | input = 'Approval', output='Refinement', |
| | 54 | condition="instance.condition=='Denied: Back to requester'") |
| | 55 | |
| | 56 | Transition(name='tell_employee', |
| | 57 | input = 'UpdateHR', output='End') |
| | 58 | |
| | 59 | Transition(name='cancel_request', |
| | 60 | input = 'Refinement', output='End', |
| | 61 | condition="instance.condition=='Withdraw request'") |
| | 62 | |
| | 63 | Transition(name='re_request', |
| | 64 | input = 'Refinement', output='Begin', |
| | 65 | condition="instance.condition=='Re-request'") |
| | 66 | }}} |
| | 67 | this [http://goflow.alwaysdata.net/images/leave.png diagram] is a graphviz dot representation. It has |
| | 68 | written by hand, but soon, it should be generated. |
| | 69 | |
| | 70 | '''Some definitions:''' |
| | 71 | [[BR]]A ''transition'' is a path from an ''Activity'' to another one. |
| | 72 | [[BR]]An ''Activity'' is a task that a person (or an automatic process) with a specific role must achieve: it is linked to an ''Application'' which is typically an URL declared in the ''urls.py'' file. |
| | 73 | [[BR]]A ''push application'' is a handler that return a user, given the context of process instance (in fact the parameter of the handler is a ''workitem'', we will see this later) |
| | 74 | |
| | 75 | === settings file === |
| | 76 | ''(a little obsolete since rev 14)'' |
| | 77 | ==== standard settings ==== |
| | 78 | First, tell Django you want to use the workflow engine: |
| | 79 | {{{ |
| | 80 | INSTALLED_APPS = ( |
| | 81 | .... |
| | 82 | 'leavedemo.leave', # the leave application |
| | 83 | 'goflow.workflow', # goflow workflow engine |
| | 84 | ) |
| | 85 | }}} |
| | 86 | |
| | 87 | If you use ''send_mail'' application, you should define these: |
| | 88 | {{{ |
| | 89 | DEFAULT_FROM_EMAIL = email sender |
| | 90 | EMAIL_HOST = smtp server |
| | 91 | }}} |
| | 92 | ==== specific settings ==== |
| | 93 | |
| | 94 | {{{ |
| | 95 | WF_APPS_PREFIX = 'leavedemo' |
| | 96 | }}} |
| | 97 | This is the url prefix for workflow application definition; |
| | 98 | for example, in the workflow definition the application ''app1'' is |
| | 99 | mapped on the url ''/leavedemo/app1'' |
| | 100 | |
| | 101 | {{{ |
| | 102 | WF_PUSH_APPS_PREFIX = 'leavedemo.leave.pushapplications' |
| | 103 | }}} |
| | 104 | this is the module containing the push applications functions; |
| | 105 | for example, the push application ''pushapp1'' is a function defined as |
| | 106 | following in the ''leavedemo/leave/pushapplications.py'' module: |
| | 107 | {{{ |
| | 108 | def pushapp1(workitem): |
| | 109 | ... |
| | 110 | return aUser |
| | 111 | }}} |
| | 112 | |
| | 113 | If you use ''send_mail'' application, you should define these: |
| | 114 | {{{ |
| | 115 | EMAIL_SUBJECT_PREFIX = '[Goflow notification]' |
| | 116 | }}} |
| | 117 | |
| | 118 | === urls.py file === |
| | 119 | |
| | 120 | ==== Starting a workflow instance ==== |
| | 121 | |
| | 122 | the ''start_application'' is a handler that display a form used to create an instance of the workflow process: |
| | 123 | |
| | 124 | usage: |
| | 125 | {{{ |
| | 126 | (r'^leave/start/(app)/(model)/$', 'goflow.workflow.applications.start_application'), |
| | 127 | }}} |
| | 128 | This above is the simplest way to start: the default process has the same name as app, and the default template used is "start_[model].html". |
| | 129 | |
| | 130 | other usage: |
| | 131 | {{{ |
| | 132 | (r'^leave/request/$', |
| | 133 | 'goflow.workflow.applications.start_application', |
| | 134 | {'process_name':'leave', 'form_class':RequestForm, 'template':'start_leave.html'}), |
| | 135 | }}} |
| | 136 | |
| | 137 | ''New:'' |
| | 138 | see ''workflow urls'' below: an instance can be started with just a model (see also leave demo) |
| | 139 | |
| | 140 | ==== Simple info application ==== |
| | 141 | the only parameter is a template; this application just shows an inf panel to a user. |
| | 142 | {{{ |
| | 143 | (r'^leave/finalinfo/$', 'goflow.workflow.applications.simple_application', {'template':'finalinfo.html'}), |
| | 144 | }}} |
| | 145 | |
| | 146 | |
| | 147 | ==== Form application ==== |
| | 148 | this application displays a form to the user: by clicking on a submit button, the activity is terminated with |
| | 149 | the instance condition set to the submit button value (label displayed) |
| | 150 | {{{ |
| | 151 | (r'^leave/checkstatus/$', 'goflow.workflow.applications.application_form', {'form_class':ApprovalForm, |
| | 152 | 'template':'checkstatus.html', |
| | 153 | 'submit_name':'approval'}), |
| | 154 | }}} |
| | 155 | |
| | 156 | ==== Custom applications ==== |
| | 157 | for more advanced usages, you may write your own applications: for this, take a look at the application form code (see above) and copy-paste the code in your project (in an applications.py file) and customize it; one advantage is that the urls.py file can be quite simpler (less parameters on the application url line). |
| | 158 | |
| | 159 | |
| | 160 | === workflow urls === |
| | 161 | Some urls are workflow standard tasks, managed by the engine itself; like CRUD urls managed by admin, the workflow standard tasks are available with the following line in the ''urls.py'' file: |
| | 162 | {{{ |
| | 163 | (r'^leave/', include('goflow.workflow.urls')), |
| | 164 | }}} |
| | 165 | |
| | 166 | So the workflow engine provides handlers and default templates below: |
| | 167 | {{{ |
| | 168 | (r'^mywork/$', 'goflow.workflow.views.mywork', {'template':'mywork.html'}), |
| | 169 | (r'^otherswork/$', 'goflow.workflow.views.otherswork', {'template':'otherswork.html'}), |
| | 170 | (r'^otherswork/instancehistory/$', 'goflow.workflow.views.instancehistory', {'template':'instancehistory.html'}), |
| | 171 | (r'^myrequests/$', 'goflow.workflow.views.myrequests', {'template':'myrequests.html'}), |
| | 172 | (r'^myrequests/instancehistory/$', 'goflow.workflow.views.instancehistory', {'template':'instancehistory.html'}), |
| | 173 | (r'^mywork/activate/$', 'goflow.workflow.views.activate', {'template':'activate.html'}), |
| | 174 | (r'^mywork/complete/$', 'goflow.workflow.views.complete', {'template':'complete.html'}), |
| | 175 | (r'^start/(?P<app_label>.*)/(?P<model_name>.*)/$', 'goflow.workflow.applications.start_application'), |
| | 176 | (r'^cron/$','django.contrib.workflow.views.cron'), |
| | 177 | }}} |
| | 178 | |
| | 179 | * ''mywork'': displays the tasks list of the current user |
| | 180 | * .... |
| | 181 | * ''start'': start a new instance given a model |
| | 182 | * ''cron'': cron simulation task for timeout management |
| | 183 | |
| | 184 | ''next soon'' |
| | 185 | |
| | 186 | === Application templates === |
| | 187 | You can (may) redefine the templates associated with standard workflow views. |
| | 188 | |
| | 189 | For each application, a specific template has to be built. The context available has following variales: |
| | 190 | * ''form'': form (newforms framework) |
| | 191 | * ''instance'': instance object |
| | 192 | * ''ob'': object (application-defined) linked to instance |
| | 193 | * ''instance_props'': properties of instance |
| | 194 | |
| | 195 | The application developper should insert submit input fields when he inserts forms; the ''application_form'' handler then will update ''instance.condition'' with the value of the submit button pressed. |