๐งฉ Custom Workflow Actions in NetSuite (Extend SuiteFlow with SuiteScript)
Introduction
Workflows (SuiteFlow) are great for automating approvals and record changes โ but they have limits.
Sometimes you need advanced logic that workflows alone canโt handle โ like API calls, dynamic field lookups, or calculations.
Thatโs where Custom Workflow Actions come in โ allowing you to combine SuiteFlow + SuiteScript for smarter, dynamic automation.
๐ก Why Use Custom Workflow Actions?
Problem | Workflow Only | With Custom Workflow Action |
---|---|---|
Complex Logic | Limited formulas | Full JavaScript logic |
External Data | Not possible | Can call APIs via script |
Dynamic Updates | Restricted field options | Can loop, search, and update |
Logging | Minimal tracking | Full SuiteScript logging |
โ Combine the power of clicks and code in one flexible solution.
๐งฑ Step 1: Create a Custom Workflow Action Script
- Navigate to:
Customization โ Scripting โ Scripts โ New โ Workflow Action Script - Choose SuiteScript 2.1
- Add your script file (see example below)
- Deploy it
โ๏ธ Step 2: Sample Workflow Action Script (SuiteScript 2.1)
/**
* @NApiVersion 2.1
* @NScriptType WorkflowActionScript
*/
define(['N/record', 'N/log'], (record, log) => {
const onAction = (ctx) => {
try {
const rec = ctx.newRecord;
const recordId = rec.id;
const recordType = rec.type;
log.audit('Custom Workflow Action Triggered', { recordType, recordId });
// Example: Auto-fill custom field based on condition
const total = rec.getValue('total');
if (total > 5000) {
rec.setValue('custbody_approval_required', true);
} else {
rec.setValue('custbody_approval_required', false);
}
// Example: Return a message to Workflow Log
return 'Approval condition evaluated successfully';
} catch (e) {
log.error('Workflow Action Error', e);
return 'Error: ' + e.message;
}
};
return { onAction };
});
โ This script dynamically evaluates transaction data and updates workflow states automatically.
๐งฉ Step 3: Add the Script to a Workflow
- Open your target workflow (e.g., Invoice Approval Workflow).
- Add a State โ New Action โ Custom Action.
- Choose your script deployment.
- Set Trigger On: Entry or Transition.
- (Optional) Use workflow fields as input parameters.
โ Your workflow can now execute SuiteScript logic seamlessly.
๐ง Step 4: Example Use Cases
Use Case | Description |
---|---|
Dynamic Approval | Auto-route based on amount or department |
Data Validation | Prevent state change if required fields missing |
Email Notification | Send dynamic HTML emails (via N/email ) |
Record Update | Automatically set status or memo values |
External System Trigger | Push data to middleware or CRM (optional) |
๐งฎ Step 5: Pass Parameters to Workflow Action
Workflow โ Action โ Parameters โ Add
Example Parameter: custparam_threshold
Read in script:
const threshold = ctx.workflowActionContext.getParameter('custparam_threshold');
โ Makes your workflow action reusable across multiple workflows.
๐งฑ Step 6: Add Logging and Return Messages
Each Workflow Action can return text back to the SuiteFlow log:
return `Customer ${rec.getValue('entity')} processed successfully`;
โ Helps admins debug workflows directly from the log interface.
๐งฉ Step 7: Combine with Workflow Transitions
Example Flow:
- State 1: On Entry โ Custom Action: Check invoice amount
- Transition 1: If
custbody_approval_required = true
โ Manager Approval - Transition 2: Else โ Auto Approve
โ Creates hybrid automation without complex conditions.
โ๏ธ Step 8: Common Examples
Example 1: Auto-Populate Project Field
Automatically set the project based on customer:
const customer = rec.getValue('entity');
if (customer) {
const project = search.lookupFields({
type: 'customer', id: customer, columns: ['custentity_default_project']
}).custentity_default_project[0]?.value;
if (project) rec.setValue('custbody_project', project);
}
Example 2: Send Approval Email
email.send({
author: 123, // System user
recipients: approverId,
subject: 'Approval Needed',
body: `Invoice ${rec.getValue('tranid')} requires approval.`
});
Example 3: Validate Required Attachments
const attachments = rec.getLineCount({ sublistId: 'mediaitem' });
if (attachments === 0) throw Error('Missing required document attachment');
โ Add validations without blocking native record saving.
๐งฐ Step 9: Monitoring Workflow Actions
Create a Saved Search on Script Execution Logs:
- Filter by Script Type = Workflow Action Script
- Columns: Date, Record Type, Script, Status, Error Message
โ Gives administrators visibility into workflow automation activity.
๐งฉ Step 10: Best Practices
Category | Best Practice |
---|---|
Performance | Avoid heavy searches or long loops in Workflow Actions |
Governance | Keep actions short (< 1,000 units) or reschedule |
Testing | Always test in Sandbox โ transitions can behave differently |
Naming | Prefix with โWFA_โ (e.g., WFA_InvoiceApprovalLogic) |
Reusability | Parameterize conditions for multi-use deployment |
๐ Related Tutorials
- ๐ SuiteFlow Basics & Approval Workflows
- ๐ SuiteScript User Event vs Workflow Actions
- ๐ Custom Error Handling & Logging Framework
โ FAQ
Q1. Can I run searches in a Workflow Action?
Yes, but limit search size โ use filters and columns wisely.
Q2. Can I trigger multiple actions in one state?
Yes โ add multiple custom actions with defined order (priority).
Q3. Can I prevent workflow transition based on logic?
Yes โ throw an error or set a validation field that blocks transition.
Q4. Whatโs the difference between User Event and Workflow Action scripts?
Workflow Actions are workflow-driven (on state changes), while User Events are record-driven (on save/load).
๐งญ Summary
Custom Workflow Actions bridge the gap between SuiteFlow and SuiteScript.
They let you add advanced business logic, validations, and automation directly inside workflows โ no more workarounds or manual steps.
By combining conditional routing in SuiteFlow with script logic in Workflow Actions, you create powerful, no-code + low-code hybrid automation that scales with your business.
Leave a Reply