Tasks¶
User Tasks¶
Creating a User Task¶
When you click on a user task in the BPMN modeler, the Properties Panel includes a form tab. Use this tab to build your questions.
The following example shows how a form might be set up in Camumda.
Manual Tasks¶
Running The Model¶
If you have set up our example repository, this model can be run with the following command:
./camunda-bpmn-runner.py -p order_product -d bpmn/tutorial/product_prices.dmn -b bpmn/camunda/task_types.bpmn
Example Application Code¶
Handling the User Task¶
dct = {}
for field in task.task_spec.form.fields:
if isinstance(field, EnumFormField):
option_map = dict([ (opt.name, opt.id) for opt in field.options ])
options = "(" + ', '.join(option_map) + ")"
prompt = f"{field.label} {options} "
option = input(prompt)
while option not in option_map:
print(f'Invalid selection!')
option = input(prompt)
response = option_map[option]
else:
response = input(f"{field.label} ")
if field.type == "long":
response = int(response)
update_data(dct, field.id, response)
DeepMerge.merge(task.data, dct)
The list of form fields for a task is stored in task.task_spec.form_fields
.
For Enumerated fields, we want to get the possible options and present them to the
user. The variable names of the fields were stored in field.id
, but since
we set labels for each of the fields, we’d like to display those instead, and map
the user’s selection back to the variable name.
For other fields, we’ll just store whatever the user enters, although in the case
where the data type was specified to be a long
, we’ll convert it to a
number.
Finally, we need to explicitly store the user-provided response in a variable
with the expected name with update_data(dct, field.id, response)
and merge
the newly collected data into our task data with DeepMerge.merge(task.data, dct)
.
Our update_data
function handles “dot notation” in field names, which creates
nested dictionaries based on the path components.
def update_data(dct, name, value):
path = name.split('.')
current = dct
for component in path[:-1]:
if component not in current:
current[component] = {}
current = current[component]
current[path[-1]] = value