Workflow
The original
workflow
notes are in the app documentation: https://gitlab.com/kb/workflow/blob/master/docs/source/index.rst
User Manual
Start Event (startEvent
)
Note
13/01/2022, We are adding a user to the process on creation
(process_identity_add_participant
), so perhaps we won’t need the
userPk
in future?
For details, see commit 8361c1103cf09021a795c648cc867ee2549736a6
We need to search for workflow processes started by a user (#5553):
The Flowable
startedBy
filter looks for the owner of the workflow, but we don’t set an owner.As a workaround, we set the
user_pk
in the start event when we create a workflow.
The started_by
filter searches for the userPk
variable in the
_historic_process
and _process_instances
methods (workflow/activiti.py
)
All workflows require a userPk
in the startEvent
e.g:
<startEvent id="startEvent1" flowable:formFieldValidation="true">
<extensionElements>
<flowable:formProperty id="userPk" type="long" required="true"></flowable:formProperty>
</extensionElements>
</startEvent>
Note
If the start event doesn’t include the userPk
, then we throw an
ActivitiError
exception.
Form Fields
Check Box
To create a series of tick boxes, the type
must be boolean
:
<activiti:formProperty id="monday" name="Monday" type="boolean" expression="True"></activiti:formProperty>
<activiti:formProperty id="tuesday" name="Tuesday" type="boolean" expression="True"></activiti:formProperty>
<activiti:formProperty id="wednesday" name="Wednesday" type="boolean" expression="True"></activiti:formProperty>
Form Headings
To create a form heading, add a formProperty
with _heading
appended to
the id
e.g:
<activiti:formProperty id="invoice_heading" name="Invoice Heading" type="string" required="true" writable="false">
The name
will display as the heading.
You can add help text in Settings, Mapping, Mapping, <field name>
,
Help Text.
Note:
writable
must befalse
The property must not have a
value
(not sure where this comes from)If the
name
is empty, you must add help text.
Group
Get the (first) group ID for a task (not sure if you can have more than one):
activiti = Activiti()
group_id = activiti.task_group_id(task_id)
To get the actual group:
def group(group_pk):
try:
return Group.objects.get(pk=group_pk)
except Group.DoesNotExist:
return None
Tip
For more information, see Get all identity links for a task
HTTP Task
Add the apiUrl
to the start event.
The requestUrl
will use this variable as follows:
${apiUrl}/refresh-variables/${execution.getProcessInstanceId()}/
See this ticket for an example API and a test workflow: https://www.kbsoftware.co.uk/crm/ticket/4974/
Tip
If you are running Flowable inside Kubernetes, then make sure your
apiUrl
is accessible from there.
Tip
This is a very useful forum post to help with variables in the HTTP task: How should I use PUT/POST in Http task when I am limited to only strings
Mapping
Imported User, import-user
If your workflow includes a user ID in the start event, then select
import-user
to have the full name and email address automatically generated when the workflow is started.The
work
API also regenerates the variables when a task is completed (source code inwork.api._variables_to_save
).
Options
|
Attach a simple PDF document with a table containing the form variables. To get it working, add a form variable with an id of |
|
Copy attachments to Alfresco:
|
|
Will add a Delete Workflow button to the task. This is useful when the workflow is in development as the process can be deleted quickly and easily. |
Permissions
Process
The Workflow
model has two security related fields:
security_history
(can view workflow history for any user)security_history_my
(can view workflow history where they have been involved)
Tip
The code below is for checking the permissions for a single process.
To get a list of workflows where the user has permission, the
WorkflowManager
has security_history
and
security_history_my
methods which can be used.
Start by checking the security_history
. If the user doesn’t have
security_history
permission, check security_history_my
:
def user_has_security_history_for_process(user, process):
"""Does the user have permission to view the history for this process?"""
result = False
workflow = get_workflow(process.process_key)
if workflow.has_security_history(user):
result = True
else:
# permission to view workflows where they have been involved
if workflow.has_security_history_my(user):
# has the user been involved with this process?
activiti = Activiti()
identity_list = activiti.process_identity_list(process.process_id)
if user.pk in set([x.user for x in identity_list]):
result = True
return result
Note
Code from work/service.py
.
Here is an example configuration:
Created two Global Groups where needed i.e. adding the word Delete and then configuring the mapping as shown below.
Hopefully a sensible way to approach this.
Prerequisite
Every task must have the following form variable:
|
The text in the |
Script Task
From JSON process variables - any gotchas?, to save data in json
format:
<scriptTask id="sid-780D1BD8-9E03-4802-8EC3-C944F5B00A67" scriptFormat="javascript" flowable:autoStoreVariables="false">
<script>
<![CDATA[var ObjectMapper = com.fasterxml.jackson.databind.ObjectMapper;
var data = {};
data.name = "Andrea";
var httpTaskData = JSON.stringify(data);
var json = new ObjectMapper().readTree(httpTaskData);
execution.setVariable("httpTaskData", json);]]>
</script>
</scriptTask>
Tip
Make sure the scriptFormat
is set to javascript
.
Management Commands
6699-mapping-export
To export the mapping for a workflow:
django-admin 6699-mapping-export myTempWorkflow
Tip
The management command will create an export file e.g.
myTempWorkflow-mapping-export.json
To import the mapping for the workflow:
django-admin 6699-mapping-import ~/temp/myTempWorkflow-mapping-export.json
create_pending_workflows
Will use ScheduledWorkflowUser.objects.pending_with_options
to check the
database for pending workflows
(created since the first minute of the day) and start them in Activiti.
It takes an optional argument - the name of the process definition e.g:
django-admin.py create_pending_workflows timeOff
history-process
Call the history_process
API and output some information to a CSV file:
# source ('workflow')
workflow/management/commands/history-process.py
# e.g.
django-admin history-process periodicReview finished 2021-03-12 2021-03-14 document_code
django-admin history-process periodicReview started 2021-03-12 2021-03-14 document_code
Tip
Use started
for workflows started within the two dates.
Use finished
for workflows finishing within the two dates.
Tip
The document_code
in the example above is a variable name to add
to the CSV file.
rest_task
, rest_process
and rest-variable
Tip
Source code for these management commands is in
workflow/management/commands/
Display task data (and find the process ID) e.g:
django-admin rest-task fe485d7c-ce6b-11eb-b755-000d3a7f022c
Display process data e.g:
django-admin rest-process ba224c9a-7db3-11eb-ad2b-000d3a7f022c
# to display the data for one of the variables
django-admin rest-process ba224c9a-7db3-11eb-ad2b-000d3a7f022c documentTitle
Display (and update) a variable e.g:
django-admin rest-variable ba224c9a-7db3-11eb-ad2b-000d3a7f022c documentTitle
# to update the variable
django-admin rest-variable ba224c9a-7db3-11eb-ad2b-000d3a7f022c documentTitle "Management Systems"
Note
rest-variable
can only update string
variables at present.
Feel free to update and improve!
Find all workflows for a process key and list a variable:
# source ('workflow')
workflow/management/commands/workflow-variable-to-csv.py
# e.g.
django-admin workflow-variable-to-csv timeOff document_code
# Sample output
process status created value
af3cece6-afb9 Current 10/01/2024 13:10 DOC-1991
9d3bb3e3-afb9 Current 10/01/2024 13:10 DOC-1992
a4176087-afb9 Current 10/01/2024 13:10 DOC-1993
Settings
Activiti
A standard install will have Flowable running on localhost
. To configure
this, add the following settings:
# 'settings/base.py'
ACTIVITI_HOST = 'localhost'
ACTIVITI_PORT = 8080
# 'settings/local.py'
ACTIVITI_PATH = 'activiti-rest'
# 'settings/production.py'
ACTIVITI_PATH = 'activiti-rest-{}'.format(DOMAIN.replace('.', '-').replace('-', '_'))
If Flowable is running on a different server, you can configure the settings differently e.g:
# 'settings/base.py'
ACTIVITI_PORT = 8080
# 'settings/local.py'
ACTIVITI_HOST = 'localhost'
ACTIVITI_PATH = 'activiti-rest'
# 'settings/production.py'
ACTIVITI_HOST = get_env_variable("ACTIVITI_HOST")
ACTIVITI_PATH = 'activiti-rest-{}'.format(DOMAIN.replace('.', '-').replace('-', '_'))
workflow
app
The URL for an API should be added to WORKFLOW_API_URL
.
We also have a WORKFLOW_PLUGIN
system which can be used to add extra
variables to a workflow e.g:
WORKFLOW_API_URL = get_env_variable("WORKFLOW_API_URL")
WORKFLOW_PLUGIN = ("example_workflow.models.WorkflowContact",)
Add the WORKFLOW_API_URL
to the pillar
file for your project.
Warning
Do not append a /
to the end of the WORKFLOW_API_URL
e.g.
http://127.0.0.1:3042/api/0.1
Settings (Dashboard)
History
Settings, Workflow, Tasks has a new History menu option which allows you to filter by workflow type e.g.
Task History
Settings, Workflow, Tasks and clicking on a process, gives you access to Task History:
Task
Delete by ID
from workflow.activiti import Activiti
activiti = Activiti()
# replace `17077`` with your task ID
task = activiti.task_status(17077)
task.process_key
activiti.process_delete(task.process_id)
Owner
To see if a user owns a task, we need to check:
Are they an
assignee
on the task (task.assignee == user.pk
)?Are they a member of the group…