129 lines
4.5 KiB
ReStructuredText
129 lines
4.5 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/master/bpmn/lanes.bpmn>`_ workflow
|
|
- `top_level <https://github.com/sartography/spiff-example-cli/bpmn/top_level.bpmn>`_ workflow
|
|
- `call_activity <https://github.com/sartography/spiff-example-cli/blob/master/bpmn/call_activity.bpmn>`_ workflow
|
|
- `product_prices <https://github.com/sartography/spiff-example-cli/blob/master/bpmn/product_prices.dmn>`_ DMN table
|
|
- `shipping_costs <https://github.com/sartography/spiff-example-cli/blob/master/bpmn/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 a 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/lanes.png
|
|
:scale: 30%
|
|
:align: center
|
|
|
|
Workflow with lanes
|
|
|
|
To run this workflow
|
|
|
|
.. code-block:: console
|
|
|
|
./run.py -p order_product \
|
|
-d bpmn/product_prices.dmn bpmn/shipping_costs.dmn \
|
|
-b bpmn/lanes.bpmn
|
|
|
|
For a simple code example of displaying a tasks lane, see `Handling Lanes`_
|
|
|
|
Subprocesses
|
|
^^^^^^^^^^^^
|
|
|
|
In general, subprocesses are a way of grouping work into smaller units. This, in
|
|
theory, will help us to re-use sections of business logic, but it will also allow
|
|
us to treat groups of work as a unit.
|
|
|
|
Subprocesses come in two different flavors. In this workflow we see an Expanded
|
|
Subprocess. Unfortunately, we can't collapse an expanded subprocess within BPMN.js,
|
|
so expanded subprocesses are mainly useful for conceptualizing a group of tasks as
|
|
a unit.
|
|
|
|
It also possible to refer to external subprocesses via a Call Activity Task. This
|
|
allows us to 'call' a separate workflow in a different file by referencing the ID of
|
|
the called workflow, 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/dmn_table_updated.png
|
|
:scale: 30%
|
|
: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 around selecting and
|
|
customizing products and refer to that in our main workflow.
|
|
|
|
.. figure:: figures/call_activity.png
|
|
:scale: 30%
|
|
:align: center
|
|
|
|
Subworkflow for product selection
|
|
|
|
When configuring the subworkflow, we need to make sure the 'CallActivity Type' of the
|
|
parent workflow is 'BPMN' and the 'Called Element' matches the ID we assigned in the
|
|
subworkflow.
|
|
|
|
.. figure:: figures/top_level.png
|
|
:scale: 30%
|
|
:align: center
|
|
|
|
Parent workflow
|
|
|
|
Running the Model
|
|
^^^^^^^^^^^^^^^^^
|
|
|
|
.. code-block:: console
|
|
|
|
./run.py -p order_product \
|
|
-d bpmn/product_prices.dmn bpmn/shipping_costs.dmn \
|
|
-b bpmn/top_level.bpmn bpmn/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
|
|
|
|
if hasattr(task.task_spec, 'lane') and task.task_spec.lane is not None:
|
|
lane = f'[{task.task_spec.lane}]'
|
|
else:
|
|
lane = ''
|
|
|
|
The tasks lane can be obtained from :code:`task.task_spec.lane`. Not all tasks
|
|
will have a :code:`lane` attribute, so we need to check to make sure it exists
|
|
before attempting to access it (this is true for many task attributes).
|
|
|
|
See the Filtering Tasks Section of :doc:`advanced` more information
|
|
about working with lanes in Spiff.
|