NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages
Approvals for Laravel

Workflow presets

Capture a reusable rule, quorum, stage and expiry setup in config('approvals.workflows') so call sites stay short. A preset is flat (one rule) or staged (a stages list):

use RoundlyConsulting\Approvals\Enums\ApprovalRule;

'workflows' => [
    'payout' => [
        'rule' => ApprovalRule::Quorum->value,
        'quorum' => 2,
        'required_approvers' => 3,
        'expiry' => 86400,
    ],
    'release' => [
        'reject_on_stage_rejection' => true,
        'stages' => [
            ['rule' => ApprovalRule::Unanimous->value, 'required_approvers' => 2, 'name' => 'engineering'],
            ['rule' => ApprovalRule::Any->value,       'required_approvers' => 1, 'name' => 'product'],
        ],
    ],
],

Opening a request from a preset

use RoundlyConsulting\Approvals\Facades\Approvals;

// Flat preset: a single approver list.
Approvals::request($budget)->workflow('payout')->open([$a, $b, $c]);

// Staged preset: one approver group per stage, in order.
Approvals::request($release)->workflow('release')->open([[$eng1, $eng2], [$product]]);

// Read a validated preset without opening anything.
Approvals::preset('payout');   // WorkflowPreset

open() returns the opened ApprovalRequest. The request records the preset name in its workflow column, and a preset expiry lapses the request like expiresIn().

Preset keys

KeyScopeNotes
ruleflat, per stageAn ApprovalRule case or its value; defaults to unanimous when not set (absent, null or blank).
quorumflat, per stageOptional integer threshold; blank is not set.
required_approversflat, per stageThe approvals needed — optional on a flat preset (defaults to the list size), a required positive integer on every stage. The approver list must name at least that many.
expirypresetOptional positive seconds — the opened request lapses like expiresIn(); blank is not set (no expiry).
reject_on_stage_rejectionstagedA boolean or a boolean spelling ('false', 0, 'off', … read as false); defaults to true — a blank value is not set, so true too.
stagesstagedNon-empty list of stage shapes: rule, required_approvers, optional quorum and name (a string when set; blank is not set).

Approver lists

  • Flat preset — pass a flat approver list; those are the request’s named approvers. The preset’s required_approvers is the number of approvals needed when set, otherwise one per approver.
  • Staged preset — pass one approver group per stage, in stage order; the number of groups must equal the number of stages. A stage’s required_approvers is the number of approvals it needs, so its group must name at least that many approvers.
  • A list that names fewer approvers than required_approvers throws InvalidApprovalRequestException when the request opens.

Validation

An unknown or malformed preset throws UnknownWorkflowException — a missing name, a preset that is not an array, an empty stages list, a stage without a positive integer required_approvers, a non-integer quorum, required_approvers or expiry, an expiry below 1, a non-string stage name, a reject_on_stage_rejection that is neither a boolean nor a boolean spelling, an unknown rule, or a staged preset opened with the wrong number of approver groups. An optional preset key left blank ('') is not set and takes its default: unanimous for rule, none for quorum, expiry and name, true for reject_on_stage_rejection. A workflows value that is not an array throws InvalidConfigurationException instead.

Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

More ways to support, including crypto

By donating, you agree to our donation terms.

Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.