ssossossosso
Documentation Home »The Oro Book »Workflows
2.3 version

Workflows

Overview

In a business application, a workflow is a sequence of steps or rules applied to a process from its initiation to completion. In OroCRM, workflows organize and direct users’ work, making them follow particular steps in a pre-defined order, or preventing them from performing actions that either contradict or conflict with the logical steps of a process.

A workflow step is a state of an entity record. It is represented by an instance of the WorkflowStep class.

The process of moving an entity from one step to another is called a transition.

Simple workflows can be created via the user interface. For more information on how to do it, see Workflow Management.

This guide provides you with the basic assistance on how to create workflows by adding information into the configuration files. For more detailed information about the workflow configuration, see Workflow Guide on GitHub.

Configure a Workflow

To configure a custom workflow, create the workflows.yml file with the configuration and save it into the /Resources/config/oro directory of your bundle.

For each entity, you can configure as many workflows as required.

Note

Pay attention to the business logic. When you create workflows that can be mutually exclusive, make sure that there is no possibility that they may be activated simultaneously.

Translations

To correctly display the user interface text concerning workflow process (button labels, page names, etc.), you need to specify translations for it.

Create translation files as:

<YourBundle>/Resources/translations/workflows.{lang_code}.yml,

where {lang_code} is a two-letter language code, e.g. workflows.en.yml.

You need to create such file for each language that you will use.

Tip

To simplify creation of the translation file, you can first create a workflow configuration, and then dump all related translation keys to the workflows.{lang_code}.yml. For example, if you create workflow ‘my_workflow’:

app/console oro:workflow:translations:dump my_workflow –locale=en > <YourBundle>/Resources/translations/workflows.en.yml

For more information, see Workflow Translation Wizard on GitHub.

Add a Workflow

In the workflows.yml, use the workflows key to specify that you are going to add workflows.

1
# src/Acme/DemoBundle/Resources/config/oro/workflows.yml

The value of the workflows key is the array of workflows.

To define a new workflow, add its name to the array.

1
2
3
4
# src/Acme/DemoBundle/Resources/config/oro/workflows.yml

workflows:
    phone_call:   # This is the workflow name.

For each workflow key, the corresponding value is the array of the workflow settings. The basic settings include the definitions of:

  • An entity that the workflow is applicable to.
  • The initial step that is attained upon initializing the workflow.

In the following example, you can find the configuration of the Phone Call workflow. This workflow defines the process of making a call to a customer:

1
2
3
4
5
6
7
8
9
# src/Acme/DemoBundle/Resources/config/oro/workflows.yml

workflows:
    phone_call:
        entity: Acme\Bundle\DemoBundle\Entity\PhoneCall    # This is the entity that the workflow is applicable to.
        start_step: start_call                             # This is the initial step that is attained upon initializing of the workflow.
        defaults:
            active: true
        priority: 10

Translations

Define the the user-interface workflow name:

Translation Key Description
oro.workflows.{workflow_name}.label The workflow name.
1
2
3
4
5
6
    # src/Acme/DemoBundle/Resources/translations/workflows.en.yml

    oro:
        workflow:
            phone_call:
                label: 'Phone Call'                      # The workflow name as it appears on the user interface.

Define Workflow Steps

Next, define the workflow steps—that is, which states the record can attain through the workflow:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
    # src/Acme/DemoBundle/Resources/config/oro/workflows.yml

    workflows:
    phone_call:
        entity: Acme\Bundle\DemoBundle\Entity\PhoneCall
            start_step: start_call                 # The initial state of the record is represented by the start_call step.
        defaults:
            active: true
        priority: 10
        steps:
                start_call:                         # The workflow step.
                    allowed_transitions:            # The list of transitions that can be made from this step.
                    - connected
                    - not_answered
                start_conversation:                 # The workflow step.
                    allowed_transitions:            # The list of transitions that can be made from this step.
                    - end_conversation
                end_call:                           # The workflow step.
                is_final: true

In this example, the record can have three states:
  • start_call
  • start_conversation
  • end_call

Note that the start_call step is specified as the start step: start_step: start_call. The end_call step is marked as final (is_final: true) which means that the workflow terminates when this step is reached.

The allowed_transitions key in the values of a step defines which transitions can be made from the step.

Note

The is_final flag added to the end_call step does not mean that you cannot specify transitions after it—you can specify as many as you require. This flag is used internally for additional data manipulation (for example, to report records on which a workflow has run to its final step).

Translations

Define how the workflow step name will appear on the user interface:

Translation Key | Description
oro.workflow.{workflow_name}.step.{step_name}.label | The workflow step name.
1
2
3
4
5
6
7
8
9
    # src/Acme/DemoBundle/Resources/translations/workflows.en.yml

    oro:
        workflow:
            phone_call:
                step:
                    start_call.label: 'Start Phone Call'
                    start_conversation.label: 'Call Phone Conversation'
                    end_call.label: 'End Phone Call'

Configure Transitions

To configure transitions, define the following:

  • Which transitions are available (place transition name keys under the transitions key).
  • To which steps they bring an entity record (the step_to key under the transition name key).
  • Which conditions must be satisfied for the transition to be available and what actions must be taken before and after the transition.
  • Which automatic triggers apply if any.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
    # src/Acme/DemoBundle/Resources/config/oro/workflows.yml

    workflows:
        phone_call:
            # ...
            transitions:
                connected:                                                # The workflow transition.
                    step_to: start_conversation                           # The step the transition brings an entity record.
                    transition_definition: connected_definition           # The transition definition that defines conditions which enable the transition, and pre/post actions.
                not_answered:
                    step_to: end_call
                    transition_definition: not_answered_definition
                end_conversation:
                    step_to: end_call
                    transition_definition: end_conversation_definition
                    triggers:                                             # The triggers that activate the transition.
                        -
                            cron: '* * * * *'
                            filter: "e.someStatus = 'OPEN'"

Translations

Define how the workflow transition name will appear on the user interface and the warning message:

Field Description
oro.workflow.{workflow_name}.transition.{transition_name}.label The transition name.
oro.workflow.{workflow_name}.transition.{transition_name}.warning_message A notification message text shown before the transition is executed.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
    # src/Acme/DemoBundle/Resources/translations/workflows.en.yml

    oro:
        workflow:
            phone_call:
                transition:
                    connected:
                                label: 'Connected'
                            warning_message: 'Connection performed!'
                not_answered
                            label: 'Not Answered'
                end_conversation
                            label: 'End Conversation'

Specify Modifiable Attributes

You can enable a user to modify attributes of the record during transitions. To do this, list attributes that can be modified during any of the workflow’s transitions under the attributes key:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
        # src/Acme/DemoBundle/Resources/config/oro/workflows.yml

        workflows:
    phone_call:
        # ...
        attributes:
                phone_call:                             # The workflow attribute.
                type: entity
                options:
                    class: Acme\Bundle\DemoWorkflowBundle\Entity\PhoneCall
                call_timeout:                           # The workflow attribute.
                type: integer
                call_successful:                        # The workflow attribute.
                type: boolean
            conversation_successful:
                type: boolean
            conversation_comment:
                type: string
            conversation_result:
                type: string
            conversation:
                type: entity
                options:
                    class: Acme\Bundle\DemoWorkflowBundle\Entity\PhoneConversation

Tip

By default, the attribute data is stored inside the WorkflowItem entity. Consequently, this data can only be accessed in the scope of the specific workflow for an entity.

To automatically store and retrieve attributes data by a property path (i.e. such attributes can be considered as links to an entity’s values), use the property_path option instead:

1
2
3
4
5
6
workflows:
    phone_call:
        # ...
        attributes:
            timeout:
                property_path: entity.call_timeout

The entity part of the property path refers to the underlying entity. You can change the name using the entity_attribute option.

Translations

For attributes, you need to add labels into two places: first, to the list of all attribute labels, second, to the list of labels for attributes of each transition that has them.

oro.workflow.{workflow_name}.attribute.{attribute_name}.label A default label text for the attribute.
oro.workflow.{workflow_name}.transition.{transition_name}.attribute.{attribute_name}.label A label text for attribute of the corresponding particular transition.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
    # src/Acme/DemoBundle/Resources/translations/workflows.en.yml

    oro:
        workflow:
        phone_call:
            attribute:
                    phone_call
                                label: 'Phone Call'
                call_timeout
                            label: 'Call Timeout'
                call_successful
                    label: 'Call Successful'
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
    # src/Acme/DemoBundle/Resources/translations/workflows.en.yml

    oro:
        workflow:
            phone_call:
                transition:
                    connected:
                        ...
                        attribute:
                            opportunity:
                                label: 'Call Successful'

Configure Transition Triggers

A transition trigger is what initiates a transition. Transitions can be automatically initiated on event (by an event trigger) or by a cron job (by a cron trigger).

Important

Please note that a trigger initiates the transition even if the workflow has not been started for the record.

Event Trigger

To set up an event trigger, configure the following options:

  • entity_class—Specify the class of the entity that triggers the transition.

  • event—Specify the type of the event. Enter one of the following values:

    • create
    • update
    • delete
  • field—This option is applicable only for the update event. Enter the name of the field that should be updated to trigger the transition.

  • queued—Whether the trigger must be queued. Specify one of the following values:

    true—Put the trigger into the initiation queue. This is a default value.

    false—Process the trigger immediately.

  • require—The condition that should be matched to activate the trigger. Define the condition using Symfony Expression Language. You can use the following aliases when constructing the expression:

    • entity—The entity that dispatches the event.
    • mainEntity—The underlying entity of the trigger’ workflow.
    • wd—The workflow definition.
    • wi—The workflow item.
  • relation—Property path to mainEntity relative to entity if they are different.

Example
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
workflows:
    phone_call:
        # ...
        transitions:
            connected:
                ...
                triggers:
                    -
                        entity_class: Oro\Bundle\SaleBundle\Entity\Quote    # The entity class: the trigger is activated when you work with the Quote entity records.
                        event: update                                       # The event type: the trigger activates on the update action.
                        field: status                                       # The field that must be updated to activate the trigger.
                        queued: false                                       # Process the trigger immediately.
                        relation: call                                      # The relation to the Workflow entity.
                        require: "entity.status = 'pending'"                # The trigger activation condition.

Cron Trigger

To set up a cron trigger, configure the following options:

  • cron—A cron definition.

  • queued—Whether the trigger must be queued. Specify one of the following values:

    true—Put the trigger into the initiation queue. This is a default value. false—Process the trigger immediately.

  • filter—The condition that should be matched to activate the trigger. Define the condition using Symfony Expression Language. You can use the following aliases when constructing the expression:

    • e—The entity name.
    • wd—The workflow definition.
    • wi—The workflow item.
    • ws—The current workflow step.
Example
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
workflows:
    phone_call:
        # ...
        transitions:
            connected:
                ...
                triggers:
                    -
                        cron: '* * * * *'                                   # The cron definition.
                        filter: "e.someStatus = 'OPEN'"                     # The dql-filter.

Configure Transition Definitions

A transition definition is used by a transition to check conditions and to perform the init action and post actions.

To set up an event trigger, configure the following options:

  • conditions—The condition that should be matched for transition to be initiated.
  • post_actions—The actions that must be performed upon the transition to the next step.
  • init_actions—The actions that may be performed on the workflow item before the conditions are matched and transition is initiated.

Example

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
workflows:
    phone_call:
        # ...
        transition_definitions:

            # Try to establish a call.

            connected_definition:

                # Check that timeout is set.

                conditions:
                    @not_blank: [$call_timeout]

                # Set call_successfull = true

                post_actions:
                    - @assign_value: [$call_successfull, true]
                init_actions:
                    - @increment_value: [$call_attempt]

            # Callee did not answer.

            not_answered_definition:

                # Make sure that caller waited at least 60 seconds:
                # call_timeout not empty and >= 60

                conditions:
                    @and:
                        - @not_blank: [$call_timeout]
                        - @ge: [$call_timeout, 60]

                # Set call_successfull = false

                post_actions:
                    - @assign_value: [$call_successfull, false]

            end_conversation_definition:
                conditions:

                    # Check that required properties are set.

                    @and:
                        - @not_blank: [$conversation_result]
                        - @not_blank: [$conversation_comment]
                        - @not_blank: [$conversation_successful]

                post_actions:

                # Create the PhoneConversation entity and set its properties.
                # Pass data from the workflow to the conversation.

                    - @create_entity:
                        class: Acme\Bundle\DemoWorkflowBundle\Entity\PhoneConversation
                        attribute: $conversation
                        data:
                            result: $conversation_result
                            comment: $conversation_comment
                            successful: $conversation_successful
                            call: $phone_call
Browse maintained versions:
current1.102.02.32.4