Introduction
After mastering governance, debugging, and performance, it’s time to see SuiteScript in action.
This blog walks you through three practical scripts used in everyday NetSuite implementations:
- A User Event script for automatic field updates.
- A Map/Reduce process for mass data handling.
- A Suitelet for live API integration.
Each example includes a description, sample code, and best-practice notes.
🧩 Example 1 – User Event Script: Auto-Populate Fields
Scenario: When a Sales Order is created, set the Sales Rep automatically based on the selected customer’s default rep.
/**
* @NApiVersion 2.1
* @NScriptType UserEventScript
*/
define(['N/record','N/search'], (record,search)=>{
const beforeSubmit = (context)=>{
if(context.type !== context.UserEventType.CREATE) return;
const newRec = context.newRecord;
const custId = newRec.getValue('entity');
if(!custId) return;
const rep = search.lookupFields({
type: 'customer',
id: custId,
columns: ['salesrep']
}).salesrep[0];
if(rep) newRec.setValue('salesrep', rep.value);
};
return { beforeSubmit };
});
✅ Best Practice:
Use lookupFields()
instead of full record loads to save governance units.
🚀 Example 2 – Map/Reduce Script: Mass Status Update
Scenario: Update thousands of Invoices that remain “Open” to “Paid” if a related payment exists.
/**
* @NApiVersion 2.1
* @NScriptType MapReduceScript
*/
define(['N/search','N/record'], (search,record)=>{
const getInputData = ()=> search.create({
type:'invoice',
filters:[['status','anyof','CustInvc:A']],
columns:['internalid']
});
const map = (ctx)=>{
const inv = JSON.parse(ctx.value);
record.submitFields({
type:'invoice',
id:inv.id,
values:{ status:'CustInvc:B' } // Paid
});
};
return { getInputData, map };
});
✅ Best Practice:
Use Map/Reduce for scalable updates; it automatically handles rescheduling and governance yields.
🌐 Example 3 – Suitelet: Integrate with PayPal for Payment Links
Scenario: Create a Suitelet that generates a PayPal payment link for an Invoice.
/**
* @NApiVersion 2.1
* @NScriptType Suitelet
*/
define(['N/https','N/ui/serverWidget','N/record','N/url','N/runtime'],
(https,ui,record,url,runtime)=>{
const onRequest = async (ctx)=>{
if(ctx.request.method==='GET'){
const form = ui.createForm({title:'PayPal Payment Link'});
form.addField({id:'custpage_inv',type:ui.FieldType.TEXT,label:'Invoice ID'});
form.addSubmitButton('Generate Link');
ctx.response.writePage(form);
}else{
const invId = ctx.request.parameters.custpage_inv;
const invoice = record.load({type:'invoice',id:invId});
const amount = invoice.getValue('total');
const paypalApi = 'https://api-m.sandbox.paypal.com/v2/checkout/orders';
const body = JSON.stringify({intent:'CAPTURE',purchase_units:[{amount:{currency_code:'USD',value:amount}}]});
const headers = {
'Authorization':'Bearer YOUR_TOKEN',
'Content-Type':'application/json'
};
const res = await https.post.promise({url:paypalApi,headers,body});
const link = JSON.parse(res.body).links[1].href;
ctx.response.write(`<p>Generated PayPal Link:<br><a href="${link}" target="_blank">${link}</a></p>`);
}
};
return { onRequest };
});
✅ Best Practice:
Use async/await for external APIs, handle sandbox vs production with script parameters, and log responses securely.
🧠 Lessons Learned
Technique | Where Used | Benefit |
---|---|---|
lookupFields() | User Event | Save governance |
Map/Reduce | Mass updates | Handles rescheduling automatically |
Async/Await | Suitelet Integration | Clean, non-blocking code |
try/catch Logging | All scripts | Better debugging |
🧾 Pro Tip
Bundle these scripts into a custom SuiteApp or SDF project with proper manifest dependencies. It ensures versioning, easy deployment, and reusability across clients.
Conclusion
These examples represent the most common automation tiers you’ll face in real NetSuite projects — from lightweight workflows to full-scale integrations.
By combining the power of SuiteScript 2.1, Map/Reduce, and external API calls, you can build highly automated, resilient business processes.
Discover more from The NetSuite Pro
Subscribe to get the latest posts sent to your email.
Leave a Reply