The Leave workflow application
(not up to date)
Follow instructions in the INSTALL.TXT file included in the goflow distribution. You can then play with the leave demo application (available online too). You will find here some details of the leave application implementation.
defining the workflow process
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 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.
So, the process is the following: http://goflow.alwaysdata.net/leavedemo/media/img/leaveactivities.png
below, the process translated as django entities, with a python syntax (it is not a real code, it's just more readable by humans):
Process(title='leave', begin='Begin', end='End') Activity(title='Begin', application='checkstatus', pushApplication='route_to_secretary', splitMode='xor', roles=('secretary',)) Activity(title='Approval', application='approvalform', pushApplication='route_to_supervisor', splitMode='xor', roles=('secretary',)) Activity(title='Refinement', application='refine', pushApplication='route_to_customer', joinMode='xor', splitMode='xor') Activity(title='UpdateHR', application='hrform', pushApplication='route_to_secretary', roles=('supervisor',)) Activity(title='End', application='finalinfo', pushApplication='route_to_customer', joinMode='xor', roles=('secretary',), autoFinish=False) Transition(name='send_to_approval', input = 'Begin', output='Approval', condition="instance.condition=='OK: Forward to supervisor'") Transition(name='send_to_refinement', input = 'Begin', output='Refinement', condition="instance.condition=='Denied: Back to requester'") Transition(name='request_approved', input = 'Approval', output='UpdateHR', condition="instance.condition=='OK: Forward to secretary'") Transition(name='not_approved', input = 'Approval', output='Refinement', condition="instance.condition=='Denied: Back to requester'") Transition(name='tell_employee', input = 'UpdateHR', output='End') Transition(name='cancel_request', input = 'Refinement', output='End', condition="instance.condition=='Withdraw request'") Transition(name='re_request', input = 'Refinement', output='Begin', condition="instance.condition=='Re-request'")
this diagram is a graphviz dot representation. It has written by hand, but soon, it should be generated.
Some definitions:
A transition is a path from an Activity to another one.
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.
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)
settings file
(a little obsolete since rev 14)
standard settings
First, tell Django you want to use the workflow engine:
INSTALLED_APPS = ( .... 'leavedemo.leave', # the leave application 'goflow.workflow', # goflow workflow engine )
If you use send_mail application, you should define these:
DEFAULT_FROM_EMAIL = email sender EMAIL_HOST = smtp server
specific settings
WF_APPS_PREFIX = 'leavedemo'
This is the url prefix for workflow application definition; for example, in the workflow definition the application app1 is mapped on the url /leavedemo/app1
WF_PUSH_APPS_PREFIX = 'leavedemo.leave.pushapplications'
this is the module containing the push applications functions; for example, the push application pushapp1 is a function defined as following in the leavedemo/leave/pushapplications.py module:
def pushapp1(workitem): ... return aUser
If you use send_mail application, you should define these:
EMAIL_SUBJECT_PREFIX = '[Goflow notification]'
urls.py file
Starting a workflow instance
the start_application is a handler that display a form used to create an instance of the workflow process:
usage:
(r'^leave/start/(app)/(model)/$', 'goflow.workflow.applications.start_application'),
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".
other usage:
(r'^leave/request/$', 'goflow.workflow.applications.start_application', {'process_name':'leave', 'form_class':RequestForm, 'template':'start_leave.html'}),
New: see workflow urls below: an instance can be started with just a model (see also leave demo)
Simple info application
the only parameter is a template; this application just shows an inf panel to a user.
(r'^leave/finalinfo/$', 'goflow.workflow.applications.simple_application', {'template':'finalinfo.html'}),
Form application
this application displays a form to the user: by clicking on a submit button, the activity is terminated with
the instance condition set to the submit button value (label displayed)
(r'^leave/checkstatus/$', 'goflow.workflow.applications.application_form', {'form_class':ApprovalForm, 'template':'checkstatus.html', 'submit_name':'approval'}),
Custom applications
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).
workflow urls
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:
(r'^leave/', include('goflow.workflow.urls')),
So the workflow engine provides handlers and default templates below:
(r'^mywork/$', 'goflow.workflow.views.mywork', {'template':'mywork.html'}), (r'^otherswork/$', 'goflow.workflow.views.otherswork', {'template':'otherswork.html'}), (r'^otherswork/instancehistory/$', 'goflow.workflow.views.instancehistory', {'template':'instancehistory.html'}), (r'^myrequests/$', 'goflow.workflow.views.myrequests', {'template':'myrequests.html'}), (r'^myrequests/instancehistory/$', 'goflow.workflow.views.instancehistory', {'template':'instancehistory.html'}), (r'^mywork/activate/$', 'goflow.workflow.views.activate', {'template':'activate.html'}), (r'^mywork/complete/$', 'goflow.workflow.views.complete', {'template':'complete.html'}), (r'^start/(?P<app_label>.*)/(?P<model_name>.*)/$', 'goflow.workflow.applications.start_application'), (r'^cron/$','django.contrib.workflow.views.cron'),
- mywork: displays the tasks list of the current user
- ....
- start: start a new instance given a model
- cron: cron simulation task for timeout management
next soon
Application templates
You can (may) redefine the templates associated with standard workflow views.
For each application, a specific template has to be built. The context available has following variales:
- form: form (newforms framework)
- instance: instance object
- ob: object (application-defined) linked to instance
- instance_props: properties of instance
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.