Skip to content

Tasks in parallel

A state can create tasks of its own, e.g. two approvals at the same time. Automatic transitions move on when the tasks are done.

use Anvil\Workflow\Task;
use Anvil\Workflow\TaskCondition;
State::make('in_review')->label('In review')->tasks([
Task::make('manager')->label('Approval of the manager')
->by(Actor::resolver('line-manager'))
->outcomes(['approved' => 'Approve', 'rejected' => 'Reject'])
->fourEyes('creator'),
Task::make('owner')->label('Approval of the data owner')
->by(Actor::field('budget_owner_id'))
->outcomes(['approved' => 'Approve', 'rejected' => 'Reject'])
->form([TextInput::make('cost_center')->required()->maxLength(20)], outcomes: ['approved'])
->commentRequired('rejected')
->fourEyes('creator')
->due(3),
Task::make('legal')->label('Legal check')
->description('Only needed for contracts with new suppliers.')
->by(Actor::role('Legal'))
->required(false),
]),
// transitions
Transition::make('accept')->from('in_review')->to('approved')->automatic(TaskCondition::all('approved')),
Transition::make('decline')->from('in_review')->to('rejected')->automatic(TaskCondition::any('rejected')),
Method Meaning Default
Task::make('key') key: lower case letters, digits and -, unique within the state
label(), description() title (followed by the record) and text in the inbox key
by(Actor ...) candidates; slots work as for transitions
outcomes([...]) buttons of the task, value => label ([a-z][a-z0-9_]*) one outcome done
form([...], outcomes: [...]) fields asked when completing (list, closure or building block key); stored with the task. With outcomes only those outcomes validate and store them none
commentRequired('rejected') these outcomes need a comment
required(false) not needed for TaskCondition::all() required
fourEyes(...) names of earlier transitions or creator; those people are not candidates
due(days) due after this many working days; the candidates are reminded once when it has passed due with its state

Candidates are resolved when the task is created; four eyes excludes people before they ever see the task. A released tenant configuration resolves the candidates of open tasks again.

Condition Met when
TaskCondition::all('approved') all required tasks of the state are done with the outcome
TaskCondition::all('approved', 'manager', 'owner') the named tasks are done with the outcome
TaskCondition::all() all required tasks are done, with any outcome
TaskCondition::any('rejected') one task (or one of the named ones) is done with the outcome

After every completed task the first automatic transition whose condition is met runs as the system; the comment of the task (or “task: outcome”) becomes its reason. An automatic transition has no form; with actors of its own it can also be run by hand. Leaving the state cancels the open tasks of the state.

Candidates complete tasks in the inbox with an outcome, the fields and a comment. The detail page of the record lists its tasks with outcome and who completed them.