mirror of
https://github.com/status-im/spiff-arena.git
synced 2025-02-12 01:36:58 +00:00
126 lines
4.7 KiB
ReStructuredText
126 lines
4.7 KiB
ReStructuredText
Organizing More Complex Workflows
|
|
=================================
|
|
|
|
BPMN Model
|
|
----------
|
|
|
|
We'll be using the following files from `spiff-example-cli <https://github.com/sartography/spiff-example-cli>`_.
|
|
|
|
- `lanes <https://github.com/sartography/spiff-example-cli/blob/main/tutorial/bpmn/lanes.bpmn>`_ workflow
|
|
- `top_level <https://github.com/sartography/spiff-example-cli/blob/main/bpmn/tutorial/top_level.bpmn>`_ workflow
|
|
- `call_activity <https://github.com/sartography/spiff-example-cli/blob/main/tutorial/bpmn/call_activity.bpmn>`_ workflow
|
|
- `product_prices <https://github.com/sartography/spiff-example-cli/blob/main/tutorial/bpmn/product_prices.dmn>`_ DMN table
|
|
- `shipping_costs <https://github.com/sartography/spiff-example-cli/blob/main/bpmn/tutorial/shipping_costs.dmn>`_ DMN table
|
|
|
|
Lanes
|
|
^^^^^
|
|
|
|
Lanes are a method in BPMN to distinguish roles for the workflow and who is
|
|
responsible for which actions. In some cases this will be different business
|
|
units, and in some cases this will be different individuals - it really depends
|
|
on the nature of the workflow. Within the BPMN editor, this is done by choosing the
|
|
'Create pool/participant' option from the toolbar on the left hand side.
|
|
|
|
We'll modify our workflow to get the customer's payment information and send it
|
|
to an employee who will charge the customer and fulfill the order.
|
|
|
|
.. figure:: figures/organization/lanes.png
|
|
:scale: 30%
|
|
:align: center
|
|
|
|
Workflow with lanes
|
|
|
|
To run this workflow
|
|
|
|
.. code-block:: console
|
|
|
|
./spiff-bpmn-runner.py -p order_product \
|
|
-d bpmn/tutorial/product_prices.dmn bpmn/tutorial/shipping_costs.dmn \
|
|
-b bpmn/tutorial/lanes.bpmn
|
|
|
|
For a simple code example of displaying a tasks lane, see `Handling Lanes`_
|
|
|
|
Subprocesses
|
|
^^^^^^^^^^^^
|
|
|
|
Subprocesses allow us to conceptualize a group of tasks as a unit by creating a
|
|
mini-workflow inside a task. Subprocess Tasks come in two different flavors: expanded
|
|
or collapsed. The difference between the two types is visual rather than functional.
|
|
|
|
It also possible to refer to external processes via a Call Activity Task. This
|
|
allows us to 'call' a separate Process (which might be stored independently of the
|
|
Process we're implementing) by referencing the ID of the called Process, which can simplify
|
|
business logic and make it re-usable.
|
|
|
|
We'll expand 'Fulfill Order' into sub tasks -- retrieving the product and shipping
|
|
the order -- and create an Expanded Subprocess.
|
|
|
|
We'll also expand our selection of products, adding several new products and the ability
|
|
to customize certain products by size and style in addition to color.
|
|
|
|
.. figure:: figures/organization/dmn_table_updated.png
|
|
:scale: 60%
|
|
:align: center
|
|
|
|
Updated product list
|
|
|
|
.. note::
|
|
|
|
I've added what customizations are available for each product in the 'Annotations'
|
|
column of the DMN table. This is not actually used by Spiff; it simply provides
|
|
the option of documenting the decisions contained in the table.
|
|
|
|
Since adding gateways for navigating the new options will add a certain amount of
|
|
clutter to our diagram, we'll create a separate workflow for selecting and customizing
|
|
products and refer to that in our main workflow.
|
|
|
|
.. figure:: figures/organization/call_activity.png
|
|
:scale: 30%
|
|
:align: center
|
|
|
|
Subworkflow for product selection
|
|
|
|
We need to make sure the 'Called Element' matches the ID we assigned in the called Process.
|
|
|
|
.. figure:: figures/organization/top_level.png
|
|
:scale: 30%
|
|
:align: center
|
|
|
|
Parent workflow
|
|
|
|
|
|
Running the Model
|
|
^^^^^^^^^^^^^^^^^
|
|
|
|
.. code-block:: console
|
|
|
|
./spiff-bpmn-runner.py -p order_product \
|
|
-d bpmn/tutorial/product_prices.dmn bpmn/tutorial/shipping_costs.dmn \
|
|
-b bpmn/tutorial/top_level.bpmn bpmn/tutorial/call_activity.bpmn
|
|
|
|
Example Application Code
|
|
------------------------
|
|
|
|
Handling Lanes
|
|
^^^^^^^^^^^^^^
|
|
|
|
We are not required to handle lanes in our application, but most of the time we'll
|
|
probably want a way of filtering on lanes and selectively displaying tasks. In
|
|
our sample application, we'll simply display which lane a task belongs to.
|
|
|
|
.. code:: python
|
|
|
|
def get_task_description(self, task, include_state=True):
|
|
|
|
task_spec = task.task_spec
|
|
lane = f'{task_spec.lane}' if task_spec.lane is not None else '-'
|
|
name = task_spec.bpmn_name if task_spec.bpmn_name is not None else '-'
|
|
description = task_spec.description if task_spec.description is not None else 'Task'
|
|
state = f'{task.get_state_name()}' if include_state else ''
|
|
return f'[{lane}] {name} ({description}: {task_spec.bpmn_id}) {state}'
|
|
|
|
The tasks lane can be obtained from :code:`task.task_spec.lane`, which will be :code:`None`
|
|
if the task is not part of a lane.
|
|
|
|
See the Filtering Tasks Section of :doc:`advanced` more information about working with lanes in Spiff.
|