# NetSuite Workflow Action Script Generator for SuiteFlow Custom Actions

> Source: https://netray.co/tools/netsuite-workflow-action-script-generator
> Publisher: Netray (netray.co), AI and integration engineering for ERP and manufacturing systems.
> Section: Free Tools

## Short answer

Generate a working workflow action script that reads a threshold parameter, looks up an approver and returns a value your workflow can store in a field.

## Category

developer

## Erp

NetSuite

## Audience

- SuiteScript developer
- NetSuite administrator
- SuiteFlow designer

## Tool

**Kind:** template

**Output:** code

**Language:** javascript

**Fields:**

#### Purpose (comment only)

**Key:** purpose

**Type:** text

**Default:** Return the next approver for bills above the threshold

#### Record type the workflow runs on

**Key:** record_type

**Type:** text

**Default:** vendorbill

#### Threshold script parameter id

**Key:** param_id

**Type:** text

**Default:** custscript_wa_threshold

#### Fallback threshold if parameter is empty

**Key:** threshold_default

**Type:** number

**Default:** 5000

#### Current approver field id

**Key:** approver_field

**Type:** text

**Default:** nextapprover

#### Return Type set on the script record

**Key:** return_type

**Type:** select

**Options:**

- List/Record (Employee)
- Free-Form Text
- Integer Number
- Check Box

**Default:** List/Record (Employee)

**Blocks:**

#### Workflow action script

**Body:** /**
 * @NApiVersion 2.1
 * @NScriptType WorkflowActionScript
 *
 * Purpose: {{purpose}}
 * Record type: {{record_type}}
 * Return Type on the script record: {{return_type}}
 */
define(['N/runtime', 'N/search', 'N/log'], (runtime, search, log) => {

  const onAction = (scriptContext) => {
    const rec = scriptContext.newRecord;
    const script = runtime.getCurrentScript();

    const paramValue = script.getParameter({ name: '{{param_id}}' });
    const threshold = paramValue ? Number(paramValue) : {{threshold_default}};
    const total = Number(rec.getValue({ fieldId: 'total' }) || 0);
    const currentApprover = rec.getValue({ fieldId: '{{approver_field}}' });

    log.debug({
      title: 'onAction',
      details: 'workflowId=' + scriptContext.workflowId + ' type=' + scriptContext.type +
        ' record=' + rec.type + ':' + rec.id + ' total=' + total + ' threshold=' + threshold
    });

    // At or below the threshold keep the current approver
    if (total <= threshold) {
      return currentApprover || '';
    }

    // Above the threshold route to the supervisor of the user running the workflow
    const userId = runtime.getCurrentUser().id;
    const lookup = search.lookupFields({
      type: search.Type.EMPLOYEE,
      id: userId,
      columns: ['supervisor']
    });
    const supervisor = (lookup.supervisor && lookup.supervisor.length) ? lookup.supervisor[0].value : '';

    log.audit({ title: 'escalated', details: 'user ' + userId + ' -> supervisor ' + supervisor });
    return supervisor || currentApprover || '';
  };

  return { onAction };
});

#### Script record and workflow setup

**Table:**

**Columns:**

- Step
- Where
- Setting

**Rows:**

**0:** 1

**1:** Customization > Scripting > Scripts > New

**2:** Upload the file, script type Workflow Action

**0:** 2

**1:** Script record, Parameters

**2:** Add {{param_id}} (Decimal Number or Integer) and set the default on the deployment

**0:** 3

**1:** Script record

**2:** Set Return Type to {{return_type}}; for List/Record also set the list or record to Employee

**0:** 4

**1:** Script deployment

**2:** Applies To: {{record_type}}, Status Released, Log Level Debug while testing

**0:** 5

**1:** Workflow state

**2:** New Action, choose the custom action by script name, set trigger and condition

**0:** 6

**1:** Custom action, Store Result In

**2:** Pick a workflow field or record field of a matching type (e.g. Next Approver)

**Notes:** Verify on your release: the 1,000 usage unit limit for workflow action scripts is shared by all actions in the same workflow state. The returned value must match the Return Type on the script record, and a List/Record return must be an internal id of the declared record type. Test with a user who has a supervisor set.

## Content

**Intro:** This tool generates a SuiteScript 2.1 workflow action script for NetSuite SuiteFlow: an onAction entry point that reads a script parameter, inspects the record and returns a value the workflow stores in a field. The default example escalates vendor bills above a threshold to the running user's supervisor.

**Sections:**

#### How to use it

**Body:** Set the record type, the parameter id that holds the threshold, the fallback threshold and the field holding the current approver, then pick the Return Type you will set on the script record. Copy the code into a .js file, upload it, create the script record and deployment, and add it to a workflow state as a custom action. In the action, use Store Result In to write the returned value into a workflow field or record field. Workflow action scripts are the right tool when SuiteFlow conditions and formulas cannot express the logic, for example a lookup on another record, a calculation across lines or a call to a saved search.

**Bullets:**

- Script parameter ids must start with custscript.
- Give each action a clear trigger (Before Record Load, Before Record Submit, After Record Submit, or On Entry) and condition.

#### What the onAction context gives you

**Body:** The entry point receives scriptContext with newRecord (the record in the workflow), oldRecord (the previous version on edit), form (on before load triggers), type (the event type) and workflowId (the internal id of the running workflow). The script runs inside the workflow, under the same trigger as the action, so its record changes and returned value become part of that workflow step. If the action runs on After Record Submit, changes to newRecord are not saved automatically; return the value and let Store Result In or a Set Field Value action write it.

#### Governance and return types

**Body:** Oracle help gives workflow action scripts 1,000 usage units, and the limit applies to all actions in one workflow state combined. A single search.lookupFields call is cheap, but record.load and save calls inside a state that also sends email can exhaust it. The value returned must match the Return Type on the script record, which uses field types such as Free-Form Text, Integer Number, Check Box or List/Record; List/Record needs the record type set and the script returns an internal id. If the type does not match the Store Result In field, the action fails or stores nothing.

**Bullets:**

- Return an empty string, not null, when there is nothing to set.
- Log workflowId and type while testing so the execution log shows which workflow ran the script.

#### How to check it worked

**Body:** Create a test vendor bill above the threshold as a user with a supervisor. On the bill, open the Workflow History subtab (System Information) to see the state entered and the action run, then check the script deployment execution log for the onAction and escalated entries. Repeat just below the threshold and confirm the current approver is kept.

**Cta:** If you want approvers and AP staff to ask NetSuite about stuck approvals and workflow history in plain English, with answers grounded in your own records, we can set that up privately.

**Faq:**

#### What is a workflow action script in NetSuite?

**Answer:** It is a SuiteScript type with a single onAction entry point that SuiteFlow calls as a custom action inside a workflow state. It lets a workflow run logic that standard actions such as Set Field Value cannot express, and it can return a value that the workflow stores in a field through Store Result In.

#### Can a workflow set a field value without a script?

**Answer:** Yes. The standard Set Field Value action sets a static value, a value from another field, or a formula result, and covers most cases. Use a workflow action script only when the value needs a lookup on another record, a search, a line-level calculation or logic too long for a formula.

#### What is the governance limit for workflow action scripts?

**Answer:** Oracle help lists 1,000 usage units for workflow action scripts, applied per workflow state with all actions in that state combined. Plan the expensive calls accordingly, and move heavy processing such as transforming or saving many records to a scheduled or map/reduce script triggered by the workflow.

#### Where do I set the return type of a workflow action script?

**Answer:** On the script record, set the Return Type to match what onAction returns, and for a List/Record return choose the record type as well. Then, in the workflow custom action, set Store Result In to a field of the same type. A mismatch is the usual reason the stored value is blank.

## Search terms

netsuite workflow actions, netsuite workflow action script, netsuite workflow set field value, netsuite workflow examples, netsuite erp workflow customization, suitescript 2.1 onAction, workflow action script return value

---
Talk to an engineer: https://netray.co/contact?intent=erp_ai | Machine catalog: https://netray.co/agent/catalog.json
