π§ Introduction
NetSuite offers two powerful ways to automate record logic:
- SuiteScript User Event (UE) scripts β code that runs on record load/submit.
- Workflow Actions (WFA) β no/low-code actions inside SuiteFlow states and transitions.
Both can update fields, send emails, and enforce rules β but they shine in different situations. This guide shows how to choose the right tool, with checklists, examples, and hybrid patterns.
TL;DR Decision Matrix
Scenario | Best Choice | Why |
---|---|---|
Simple field updates, emails, approvals | Workflow Action | Visual, quick to maintain |
Complex validation, multi-step calculations | User Event | Full JS control & libraries |
Needs external module reuse/shared utils | User Event | Modular code, unit-testable |
Non-technical admin will maintain | Workflow Action | Clicks over code |
Requires external API/crypto/advanced search | User Event | HTTPS, Crypto, Search APIs |
Must run at specific timing (before submit) | User Event (beforeSubmit/afterSubmit) | Precise lifecycle hooks |
Multi-entity routing with dynamic logic | Hybrid (WFA + WFA Script) | SuiteFlow UX + code power |
Strict governance/perf tuning needed | User Event | Fine-grained control & caching |
π§© What Is a User Event Script?
User Event scripts execute during a recordβs lifecycle:
beforeLoad
β modify form/UI, add buttons, set default valuesbeforeSubmit
β validations, normalize data before saveafterSubmit
β post-save side effects (create related records, queue tasks)
Strengths
- Full access to SuiteScript modules (
record
,search
,runtime
,https
,crypto
,task
, etc.) - Reusable modules, robust error handling, version control
- Precise timing: run before the record is saved or after itβs committed
Limitations
- Requires developer maintenance & deployment
- Can be overkill for simple, visual processes
Micro-Example (2.1, beforeSubmit
)
/**
* @NApiVersion 2.1
* @NScriptType UserEventScript
*/
define(['N/record','N/error'], (record, error) => {
const beforeSubmit = (ctx) => {
const rec = ctx.newRecord;
if (!rec.getValue('entity')) {
throw error.create({name:'MISSING_CUSTOMER',message:'Customer is required.'});
}
if (rec.getValue('total') > 25000) {
rec.setValue('custbody_requires_cfo', true);
}
};
return { beforeSubmit };
});
π§© What Is a Workflow Action?
Workflow Actions (a.k.a. Custom Workflow Action Scripts or built-in actions) run inside SuiteFlow states/transitions. You can:
- Set field values, send emails, create records
- Gate transitions with conditions
- Add Approve/Reject buttons
Strengths
- Visual, fast to build/adjust
- Ideal for approvals & role-based routing
- Easy for admins to maintain
Limitations
- Limited for heavy logic & integrations (though Custom Workflow Action Script helps)
- Governance & debugging visibility can be less granular
Micro-Example (Custom Workflow Action Script)
/**
* @NApiVersion 2.1
* @NScriptType WorkflowActionScript
*/
define(['N/search'], (search) => {
const onAction = (ctx) => {
const rec = ctx.newRecord;
// Flag approval if open balance > 0
const openBal = search.lookupFields({
type: 'customer',
id: rec.getValue('entity'),
columns: ['balance']
}).balance || 0;
rec.setValue('custbody_hold_for_review', openBal > 0);
return `Open Balance = ${openBal}`;
};
return { onAction };
});
π§ Timing & Lifecycle Differences
Hook | User Event | Workflow Action |
---|---|---|
Before UI render | beforeLoad | (N/A) |
Before save (hard validations) | beforeSubmit | State entry can validate but post-UI |
After save (side effects) | afterSubmit | State/transition actions (post-save) |
Button clicks | Add via beforeLoad | Add buttons in SuiteFlow state |
Need hard stop before the record is saved? Prefer User Event
beforeSubmit
.
βοΈ Governance & Performance
- UE: Finer control; use
lookupFields
, caching (N/cache
), and batch post-save logic viatask
(Map/Reduce). - WFA: Keep actions light; offload heavy logic to a Custom Workflow Action Script or call a RESTlet/Map-Reduce indirectly.
Tip: If an action regularly exceeds ~500β700 units, consider moving the heavy logic to UE afterSubmit or a background task.
π§ͺ Debugging & Maintainability
Area | User Event | Workflow Action |
---|---|---|
Logs | Script Execution Log + custom records | Workflow History + Action return text |
Versioning | Strong with SDF/Git | Version by workflow revisions & XML export |
Ownership | Dev team | Admins/functional, plus dev for custom actions |
β Common Use Cases β Side-by-Side
Use Case | Pick | Notes |
---|---|---|
Approval routing by amount/department | Workflow | Visual, buttons, emails |
Strict field validation before save | UE (beforeSubmit) | Block save reliably |
Create related records after save | UE (afterSubmit) | Safer post-commit |
Add custom UI buttons/menus | UE (beforeLoad) | Full control |
Conditional emails on status change | Workflow or UE afterSubmit | Workflow for simple, UE for dynamic data pulls |
Complex calculations / multi-search | UE | Performance & libraries |
Non-dev team must tune rules | Workflow | Easy maintenance |
π Hybrid Pattern (Best of Both)
- Workflow handles states, transitions, emails, and buttons.
- Custom Workflow Action Script does light logic (set flags, lookup IDs).
- UE afterSubmit (or Map/Reduce) consumes flags and performs heavy lifting (mass updates, complex calculations, report generation).
Why: Visual business control + scalable code where it matters.
π§° Practical Examples
A) Auto-Approval Under Threshold (Workflow only)
- State: Pending β Approved
- Transition condition:
{total} < 5000
β Auto transition - Action: Set
custbody_approved_by = currentUser
B) Strict Required Field (User Event)
beforeSubmit
: if{custbody_shipmethod}
empty, throw user error- Guarantees no record saves without ship method
C) Manager/CFO Routing (Hybrid)
- Workflow calculates path, sets
custbody_requires_cfo
- UE
afterSubmit
logs an audit record & schedules an email summary or downstream process
π§© Checklist: Choose the Right Tool
- Is it pre-save validation? β User Event (beforeSubmit)
- Is it approval/UI flow with multiple states & emails? β Workflow
- Does business need to edit rules without devs? β Workflow
- Is logic complex, reusable, or integration-heavy? β User Event / Custom Module
- Do you need both clarity and power? β Hybrid (Workflow + UE/WFA Script)
π οΈ Setup & Deployment Tips
- Naming:
- UE:
UE_<Record>_<Purpose>_vX.Y.js
- Workflow:
WF_<Record>_<Purpose>_vX.Y
- WFA Script:
WFA_<Purpose>_vX.Y.js
- UE:
- SDF: Export both scripts and workflow XML for Git versioning.
- Testing: Cover create, edit, copy, CSV import, web services.
- Auditing: Log to a small Custom Record when key rules hit (flag, who, when).
π§― Troubleshooting
Symptom | Likely Cause | Fix |
---|---|---|
Workflow buttons donβt show | State not on View / audience mismatch | Enable βOn Viewβ, check roles |
Validation didnβt block save | Put logic in WFA post-save | Move to UE beforeSubmit |
Double emails | UE and Workflow both sending | Centralize in one layer; use flags |
Slow saves | Heavy searches in WFA/UE | Use lookupFields , cache, or defer to Map/Reduce |
π Related Tutorials
- π SuiteFlow Basics & Approval Workflows
- π Custom Workflow Actions
- π Advanced Approval Workflows
β FAQ
Q1. Can a record run multiple workflows and UEs?
Yes. NetSuite runs all applicable workflows and deployments; design to avoid conflicts.
Q2. Where should I send emails?
Workflow for simple notifications; UE afterSubmit for dynamic, data-rich, or attachment-heavy emails.
Q3. Can I simulate pre-save with Workflow?
Not reliably. Use UE beforeSubmit for guaranteed βblock saveβ behavior.
Q4. Can WFA call external APIs?
Indirectly via a Custom Workflow Action Script using N/https
, but keep it light; push heavy work to UE/Map-Reduce.
π§ Summary
- Use Workflow Actions for visual approvals, simple automation, and admin-friendly rules.
- Use User Event scripts for strict pre-save validation, complex logic, integrations, and performance control.
- For larger processes, adopt a hybrid: Workflow for orchestration + UE/WFA Script for heavy logic.
Leave a Reply