| 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. |