Parsware
Alle artikelen

Parsware Platform

Parallel sign-off

A purchase order goes to Finance and Legal at the same moment, two people decide on their own, and the process waits for both before it gives one answer. We ran it with Finance signing off and Legal refusing, and watched the run wait at the join in between.

Dit artikel is alleen in het Engels beschikbaar.

A purchase order run waiting at the join: Finance sign-off done, Legal sign-off here now, and Waiting on Legal sign-off, Legal (par_legal), next to the title "Parallel sign-off"

Some approvals don't need an order. A purchase order has to be agreed by Finance, who check the money, and by Legal, who check the contract. Neither needs the other's answer first. Asking them one after the other only adds the time the first one takes.

So the process asks both at once, and waits until both have answered. If either refuses, the order is refused.

Fork and join showed how that's drawn. This article runs it, with two different people. We used the Parallel Sign-Off sample from samples/solutions/bpms-parallel-sign-off.

The process

Four lanes: Buyer, Finance, Legal and System.

  1. Order raised, then a fork, Ask both at once, makes two routes.
  2. Finance sign-off and Legal sign-off are raised together, one per lane. Each has two buttons, Sign off and Refuse, and refusing needs a note.
  3. A refusal goes through a one-line script that records somebody refused, then on to the join.
  4. The join, Both have answered, waits for both routes.
  5. Did anyone refuse? marks the order approved or refused.

Who does what

We gave the sample's Finance role to Robin Park and its Legal role to Sam Taylor, under Users → Manage roles in the Admin Control Center. Both roles may read purchase orders, and nothing else: neither person can change the order they're signing off.

That read right is new. The roles only opened the app until we ran this as two people; see the two-step approval for what that looked like. If you imported the sample before October 2026, import it again.

Two inboxes, one moment

We raised an order for warehouse racking, 18,400 from Northern Shelving, and selected Send for sign-off on its form. Robin and Sam each had a task the same second:

Robin's My tasks: Parallel Sign-Off, Finance sign-off, assigned to Finance (par_finance), arrived 18:31

Sam's My tasks: Parallel Sign-Off, Legal sign-off, assigned to Legal (par_legal), arrived 18:31

Each sees only their own. Neither is waiting for the other.

Finance signs off

Robin opens his task. The order opens read-only, and Decide asks for a note and offers Sign off or Refuse:

The Finance sign-off panel with the note Within the warehouse budget for this quarter., and Cancel, Sign off and Refuse, over the purchase order

He signs off. His task leaves his list, and the order is still Out for sign-off.

Waiting at the join

This is the part worth watching. In the maker portal, the run's page shows Finance's route done and Legal's still open, and Waiting on says who the run is waiting for:

The run's page while running: the fork, Finance sign-off done, Legal sign-off marked here now, and Waiting on: Legal sign-off, Legal (par_legal), waiting 1 minute, with Hand on

The Finance route has reached Both have answered and stopped there. The join doesn't count arrows coming in; it counts the routes the fork made, two, and only one has arrived. If Sam were away, Hand on passes his task to somebody else.

Legal refuses

Sam opens his task and selects Refuse without writing anything. It's refused, and the panel says why:

The Legal sign-off panel with Fill in Note first. above an empty Note box, and Cancel, Sign off and Refuse

A refusal somebody has to act on needs a reason. He writes one, the contract has no installation warranty, and refuses again.

Now both routes are at the join. It releases, the branch sees that somebody refused, and the last script closes the order:

The Purchase orders list: Warehouse racking, Leeds, Northern Shelving Ltd, 18400, State Closed, Reason Refused

One refusal was enough, which is the rule this process was drawn to keep. Finance's sign-off wasn't wasted: it's on the order, in Finance's note, and in the history.

What happened

The run's history, after both answered:

What happened: Split into 2 routes, both tasks raised at 18:31, Task completed Sign off by Robin Park, Reached the join, Task completed Refuse by Sam Taylor, legalrefused, Joined, Branched via edge-decide-refused, markrefused, Run ended

Read it from the top and you have the story: Split, two tasks raised together, Robin signed off at 18:32, the Finance route Reached the join and stayed there, Sam refused at 18:33, his route went through legalrefused to the join, which Joined, and the branch took the refused way out.

How "somebody refused" crosses the fork

Each route after a fork carries its own copy of the record it's about, so one route can't leave a note on it for the other. A process variable is shared by every route, and that's how one route tells the rest of the process something. The sample's refused variable starts as false; each refusal script sets it to true; the branch after the join reads it. Process variables covers them.

Try it

Run it three times: both sign off, Finance refuses, both refuse. Each ends in one answer, and each history shows the two decisions in the order they were actually made.

Next: deadlines and timers, for the task nobody gets round to.