Skip to content

Product Engineering

Model approvals as state transitions, not a chain of buttons

A practical way to design approval workflows that preserve who requested, reviewed and changed a business record.

By · Published · 6 min read

A purchase request can have buttons labelled Submit, Approve and Reject. That does not yet define what happens when the requester approves their own request, when an approver leaves the company, or when the quantity changes after approval. Those are product rules, and the screen cannot be their only home.

An approval workflow is clearer when the record has named states and permitted transitions. A request may be Draft, Submitted, Approved, Rejected or Cancelled. Each transition records who performed it, when it happened and what conditions were checked.

Write down the transitions before drawing the screen

For each state, list the actions available and the roles that may perform them. Decide whether the requester may edit after submission, whether a rejected request can be resubmitted, and whether an approver may return it for changes instead of rejecting it. Clarify whether approval applies to the current version of the request or to a particular set of values.

The rule that prevents self-approval needs a reliable actor and requester identity. A frontend check can hide the Approve button, but the API must enforce the rule too. The same applies to project membership, branch scope and dollar or quantity limits.

Approval should bind to the values that were reviewed

If a request's quantity, price or supplier changes after approval, the system should not quietly preserve the Approved state. Either block the edit, create a new version that needs approval, or explicitly define which fields do not invalidate the decision. Record the approved version or a snapshot of the relevant values.

A purchase order or goods receipt is a later workflow stage, not an edit to the approved request. Keeping those records linked makes it possible to compare what was requested, authorised, ordered and received without rewriting the earlier decision.

Plan for reversals and reassignment

People and assignments change. A submitted request may need reassignment when an approver is unavailable. A completed approval may need reversal if new information arrives. Represent these actions explicitly, with reasons and authorisation, instead of deleting a decision or editing its actor.

Notifications should be treated as prompts, not as the source of truth. A message can be delayed or duplicated. When someone opens the request, the server should return the current state and permitted actions.

How should a team test an approval workflow?

Test the normal path and the uncomfortable cases: requester attempts self-approval, two approvers act at once, an edit arrives after approval, an approver is reassigned, and an already-approved request is cancelled. Check both the visible status and the history a manager will need to explain the outcome.

Can the UI enforce approval rules by itself?

No. The API must validate actor, scope, current state and the requested transition at the time of the change. The UI can explain the allowed actions, but it cannot be the security boundary.

Why preserve rejected and cancelled requests?

They explain what happened and prevent a later reviewer from mistaking a missing record for an unsubmitted one. Keep the history according to the business's retention policy and show the current state clearly.

References

Author

Raktim Ranjit is a software engineer and the founder of NodeDR Infotech. He builds and maintains the software described here.

Have something in mind?

Let’s build something useful.

Tell me about the idea, product, or workflow you’re working through.

Tap to say hello