Document Approval
This example demonstrates a document approval workflow with submission, review, revisions, and multi-level approvals.
Complete Flow
flow
machine: @document
scenario: submission
given:
@author is logged in
document is created with title "Q4 Report"
on> :submit from @author
document moves to #pending_review
notify available reviewers
expect:
= document is in #pending_review
on :claim from @reviewer
document moves to #in_review
$reviewer: string becomes @reviewer.id
expect:
= document is in #in_review
expect:
= document is ready for review
scenario: review
given:
document is in #in_review
@reviewer has claimed document
on> :approve from @reviewer
? document meets standards
document moves to #approved
$approvals: number increases by 1
? $approvals equals $required_approvals
document moves to #published
emit :published to @author
expect:
= $approvals increased
on> :request_changes from @reviewer
document moves to #revision
emit :changes_requested to @author
with:
| comments | $review_comments |
expect:
= document is in #revision
on> :resubmit from @author
document moves to #pending_review
$version: number increases by 1
notify @reviewer
expect:
= document is in #pending_review
= $version increased
expect:
= document workflow completedMulti-Level Approval
For documents requiring multiple approvers:
flow
machine: @document
scenario: multi-level approval
given:
document is created
$required_approvals: number is 3
$approvals: number is 0
on> :submit from @author
document moves to #pending_review
emit :review_request to @reviewers
on :approve from @reviewer
? document is in #pending_review
? not already_approved_by($reviewer)
$approvals increases by 1
$approved_by adds @reviewer.id
? $approvals >= $required_approvals
document moves to #fully_approved
emit :document_approved to @author
expect:
= $approvals increased
on :reject from @reviewer
document moves to #rejected
$rejection_reason becomes $reason
emit :document_rejected to @author
with:
| reviewer | @reviewer.id |
| reason | $rejection_reason |
expect:
= approval process completedApproval with Hierarchy
Documents that need different levels of approval:
flow
machine: @document
scenario: hierarchical approval
given:
document is created with type "contract"
$contract_value: number is 50000
on> :submit from @author
document moves to #awaiting_manager
on> :approve from @manager
? $contract_value < 10000
document moves to #approved
emit :approved to @author
? $contract_value >= 10000
? $contract_value < 100000
document moves to #awaiting_director
emit :review_request to @director
? $contract_value >= 100000
document moves to #awaiting_vp
emit :review_request to @vp
on> :approve from @director
? document is in #awaiting_director
? $contract_value < 100000
document moves to #approved
emit :approved to @author
? $contract_value >= 100000
document moves to #awaiting_vp
emit :review_request to @vp
on> :approve from @vp
? document is in #awaiting_vp
document moves to #approved
emit :approved to @author
on> :reject from @manager
document moves to #rejected
on> :reject from @director
document moves to #rejected
on> :reject from @vp
document moves to #rejected
expect:
= document has been processedState Diagram
@document
┌─────────────────────────────────────────────────────────────────────┐
│ │
│ ┌─────────┐ :submit ┌────────────────┐ │
│ │ #draft │──────────────>│ #pending_review│ │
│ └─────────┘ └───────┬────────┘ │
│ ▲ │ │
│ │ :claim │
│ │ │ │
│ │ ▼ │
│ │ ┌─────────────┐ │
│ │ │ #in_review │ │
│ │ └──────┬──────┘ │
│ │ │ │
│ │ ┌──────────────┼──────────────┐ │
│ │ │ │ │ │
│ │ :approve :request_changes :reject │
│ │ │ │ │ │
│ │ ▼ ▼ ▼ │
│ │ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │ │ #approved │ │ #revision │ │ #rejected │ │
│ │ └─────┬─────┘ └─────┬─────┘ └───────────┘ │
│ │ │ │ │
│ │ │ :resubmit │
│ │ │ │ │
│ │ │ └─────────────────────────────┐ │
│ │ │ │ │
│ │ │ [all approvals] │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌─────────────┐ │ │
│ │ │ #published │ │ │
│ │ └─────────────┘ │ │
│ │ │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘Lane Diagram
┌───────────┬────────────┬────────────┐
│ @author │ @reviewer │ @system │
├───────────┼────────────┼────────────┤
│ │ │ │
│ :submit │ │ │
│ ──────────┼──> │ │
│ │ │ │
│ │ notified │ │
│ │ │ │
│ │ :claim │ │
│ │ ──────────>│ │
│ │ │ │
│ │ reviews │ │
│ │ │ │
│ │ :request_ │ │
│ │ changes │ │
│ <─────────┼────────────│ │
│ │ │ │
│ revises │ │ │
│ │ │ │
│ :resubmit │ │ │
│ ──────────┼──> │ │
│ │ │ │
│ │ :approve │ │
│ │ ──────────>│ │
│ │ │ │
│ :published│ │ │
│ <─────────┼────────────┼────────────│
│ │ │ │
└───────────┴────────────┴────────────┘Testing Scenarios
Simple Approval
flow
scenario: document approved on first review
given:
@author is logged in
document is created
on> :submit from @author
document moves to #pending_review
on :claim from @reviewer
document moves to #in_review
on> :approve from @reviewer
$approvals becomes 1
document moves to #published
expect:
= document is in #published
= @author received :publishedRevision Cycle
flow
scenario: document requires revision
given:
@author is logged in
document is created
$version: number is 1
on> :submit from @author
document moves to #pending_review
on :claim from @reviewer
document moves to #in_review
on> :request_changes from @reviewer
document moves to #revision
on> :resubmit from @author
$version becomes 2
document moves to #pending_review
on> :approve from @reviewer
document moves to #published
expect:
= document is in #published
= $version equals 2Multi-Approver Flow
flow
scenario: three approvals required
given:
$required_approvals: number is 3
$approvals: number is 0
on> :submit from @author
document moves to #pending_review
on> :approve from @reviewer_1
$approvals becomes 1
on> :approve from @reviewer_2
$approvals becomes 2
on> :approve from @reviewer_3
$approvals becomes 3
document moves to #fully_approved
expect:
= document is in #fully_approved
= $approvals equals 3Rejection
flow
scenario: document rejected
given:
@author is logged in
document is created
on> :submit from @author
document moves to #pending_review
on :claim from @reviewer
document moves to #in_review
on> :reject from @reviewer
$rejection_reason becomes "Does not meet standards"
document moves to #rejected
expect:
= document is in #rejected
= @author received :document_rejected