Transaction hooks on the shop floor

Updated Oct 26, 2026
Shop Floor

Transaction hooks on the shop floor

Run your own scripts around Shop Floor's Plex writes and material moves: stop one that should not go to Plex, change what is sent, or start follow-on work once Plex has accepted it.

Every write Shop Floor sends to Plex, such as a workcenter status or a scrap booking, and every material move works the standard way. A hook adds one of your company's scripts to it. You set hooks up under Shop Floor → Setup → Data → Transaction hooks, which needs DataMagik - Shop Floor Admin and the Shop Floor license. Hooks belong to your company and run for every site, whether the write came from a person, a machine or an escalation.

A company with no hooks sees no change: every write and move goes to Plex as it always did.

The Transaction hooks page under Shop Floor setup, before any hook is added
The Transaction hooks page explains what a before hook and an after hook can do.

Before and after

  • Before hooks run in the background sender, just before the write or move is sent to Plex, and the send waits for them. Shop Floor's send-time plant rules, such as an operator being clocked in, are checked after the hooks, so a write a hook let through can still be refused by a plant rule. A before hook can let it go ahead, change what is sent, or stop it with a reason.
  • After hooks are queued once Plex has accepted the write or move, and run in the background. They cannot undo it. Use them for follow-on work, such as sending an email or updating another system.

A write that is Awaiting approval runs its before hooks only once it is approved and sent, not when it is submitted. See What people on the floor see.

The transactions you can hook

The Plex writes and Material moves you can hook, each with Before and After buttons
Press Before or After beside a transaction to add a hook to it.
TransactionWhat it isWhat a before hook can change
Set a workcenter statusA status write from Change status in Plex, a machine's status writeback or an escalation.Only the description.
Record scrapA scrap booking: the quantity, the reason and the container.The description and each field of the booking, such as quantity.
Record productionA production booking, which creates inventory in Plex.The description and each field of the booking.
Move a delivered containerMoving a container or master unit a material request delivered.Only the location.
Build a picked master unitBuilding a material pick's master unit in Plex.Nothing: a hook can stop it but not change it.

A write a person approved goes to Plex as they approved it: a before hook can stop it but not change it. A hook that returns a change for it, or for Build a picked master unit, has failed; if it is Required, that stops the write.

Several hooks on the same transaction run in the order the page lists them. Use the up and down arrows on a hook to change the order.

Setting up a hook

  1. Write the script under Script Engine → Scripts. It is an ordinary script with a main(context) function. The hook editor lists your company's active scripts.
  2. Open Shop Floor → Setup → Data → Transaction hooks and press Add hook, or press Before or After beside a transaction.
  3. Pick the Transaction, When it runs (Before or After) and the Script. Add a Note saying what the hook is for, so the next person knows.
  4. For a before hook, choose what happens If the script fails:
    • Required: if the script fails or runs out of time, the write or move is not sent and its result says why.
    • Advisory: the failure is noted on the write or move, and it goes ahead.
  5. For a before hook, set the Time limit, from 1 to 30 seconds. A hook that takes longer counts as failed. All the before hooks on one write share 30 seconds between them.
  6. Press Test this script to run it once before you save. See Testing a hook.
  7. Press Save hook.
The Edit hook dialog: Transaction, When it runs, Script, If the script fails, Time limit, Note and Turned on
The hook editor is the same for the phone and the shop floor. Here it is open on a phone transaction.

A new hook starts as Required with a 10-second Time limit, and is Turned on as soon as you save it. To save it without it running yet, switch off Turned on first. A hook that is off is kept but never runs. To remove a hook, press its trash can and confirm.

If the script fails and Time limit appear for every hook but apply to before hooks only. An after hook runs in the background with the script's own time limit, and its failure never affects the write.

What the script gets

FieldWhat it holds
context.eventThe hook's event: before. or after. and the transaction, for example before.shop_floor.scrap.
context.transactionshop_floor.status, shop_floor.scrap, shop_floor.production, shop_floor.container_move or shop_floor.master_unit_build.
context.companyId, context.siteIdYour company and the site, as text.
context.refThe record: write: and the write's id, or plex_move: and the move's id.
context.requestWhat a before hook may change; see the table above. It is empty for a write a person approved and for building a master unit.
context.detailsFacts that cannot change. For a write: its id, the kind, the workcenter and its Plex code, where it came from, the Plex status, event and detail reason keys, whether it was approved, and which attempt this is. For a move: its id, the kind, the container or master unit, and the material request.
context.resultAfter hooks only: what Plex answered. For a write, { state, resultCode, resultMessage, plexLogKey }. For a move, { status, result, readBack, dataSourceId }.
context.userWho submitted the write, as their first and last name. Empty for a machine, an escalation or a material move. In a test, it is your own user name.
context.surfaceWhere it came from: manual, plc, escalation or material, or setup_test for a test.
context.testtrue for a test.

To see exactly what your script gets, press Test and open What the script was given.

What the script returns

A before hook returns one of these:

  • {}: it goes ahead as it is. Returning nothing is the same.
  • { veto: true, reason: "…" }: it is not sent. The Write Outbox lists it as Stopped by a hook, with Stopped by a hook: followed by your reason, or the hook gave no reason. if there is none.
  • { patch: { field: value } }: it goes ahead with those fields of request changed. A hook can change only fields the request already has. The change is saved on the write or move, which is checked again before it is sent. For example, a scrap booking changed to a quantity of zero is refused.

When a hook changes a write, its result says which fields, for example A hook changed quantity. A patch that names a field the request does not have counts as a failure of that hook.

Any other object without veto or patch, such as { done: true }, also lets it go ahead. If the script throws an error, runs out of time, or returns something that is not an object (text, a number, true/false or a list), the hook has failed, and its Required or Advisory setting decides what happens. A required hook that fails stops it with Not sent to Plex: hook … failed, and it is required: and the error. This is final: there is no Retry, so someone has to submit a new write once the script is fixed. Keep the Time limit of a required hook well above how long the script takes. An advisory hook that fails adds Hook … failed (…); it is advisory, so this went ahead. to the result. In these messages, "hook" is followed by the hook's number, not the script's name. What an after hook returns is not used. If an after hook cannot be queued, After hook … could not be queued is added to the result; the write is still sent.

If DataMagik cannot read your company's hooks at that moment, the write is not sent: it shows as Not sent with Not sent to Plex: the hooks could not be read, and a Shop Floor Admin can press Retry.

A write that is retried runs its before hooks again on the request as the last attempt left it. Write before hooks so they are safe to run twice.

Example: send large scrap to a supervisor

function main(context) {
  if (context.request.quantity > 500) {
    return { veto: true, reason: "Scrap over 500 parts needs a supervisor: book it in Plex." };
  }
  return {};
}

Example: after recording production

function main(context) {
  if (context.test) return {};
  email.sendWithTemplate("production-recorded", context.request, { to: "planning@example.com" });
  return {};
}

Testing a hook

Press Test on a hook in the list, or Test this script in the hook editor. Test runs a hook whether it is turned on or not. The script runs once, straight away, with the context a real run would get, built from your company's latest write or move of that kind. If there is none yet, the test uses a made-up one, with a sample booking for scrap and production.

A test result: It would stop the transaction, with the reason and what the script was given
A test result looks the same on the phone's and the shop floor's page. This one is from a phone transaction.

A test is marked so your script can tell: context.surface is setup_test and context.test is true. Nothing is sent to Plex, but anything the script itself does, such as sending an email, still happens unless it checks for a test.

The result shows what the script answered: go ahead, the changes it would make, or the reason it would stop the write. A change that would leave the request invalid is shown as a failure; the plant rules checked at send time run only on a real send. Test this script uses the Time limit in the editor; Test on a saved hook uses its saved one. An after hook runs straight away in a test so you can see what it does.

What people on the floor see

Hooks run in the background sender, not on the board or the machine, so nobody waits for one:

  • When a hook runs. After someone presses Change status in Plex or Book scrap, or a machine sends a write, the board shows the write as queued straight away. The hooks run when the sender picks it up, and for a write that needs approval, only once it is approved.
  • A stopped write. The Write Outbox lists it as Stopped by a hook, with the reason. It has no Retry: fix the cause and submit a new write.
  • A stopped material move. Its outcome is written in the material request's History, or, for a move a transport order made, on that transport order's history.
  • Tried again. A failed write is tried again only when a Shop Floor Admin presses Retry; a failed material move is tried again automatically, up to 3 tries. Either way its before hooks run again, so write them to be safe to run twice.

Seeing what a hook did

  • Write Outbox: a write a hook stopped is listed as Stopped by a hook, with the reason; the Rejected filter finds it. A hook's change, or an advisory hook that failed, is written on the write's result. See Writing back to Plex.
  • A material move's outcome, including a hook's, is written in its material request's History, or, for a move a transport order made, on that transport order's history.
  • Script Engine → Executions: every run of a hook, real or test, is kept with the script's runs, tagged transaction_hook. Open a run to see its Input, Console and Output. This is also where you see how an after hook ended.

Related

Was this page helpful?