This article is relevant if you would like to understand how to automatically close a NetSuite Sales Order. This article is also meaningful if you are using a NetSuite Workflow and you need to act on Sublist lines.
Background
Our team is often asked to help produce NetSuite based best practices in our client organizations. Many times, after we make assessments of our client’s specific situations and then we suggest a better procedure for record management or transaction processing, some element of data clean up or preparation may be required.
In one recent NetSuite support engagement, our client needed a mechanism to automatically close a set of sales orders for which they were no longer were committed to fulfilling. Taking care of sales orders is generally a good idea because they are powerful transactions to help organizations understand backlog, pending delivery, and potential revenue. With good sales order practices, the organization can assess how well they deliver on their sales promises to their customers.
In our client’s case, they had a NetSuite administrator on staff who was comfortable with Workflow tools. We often see this. My firm’s general orientation to NetSuite workflows is to be judicious; we favor script because it gives us the maximum capacity to innovate. At the same time, script gives us better control over the challenges of “too much disconnected logic” in a NetSuite environment — when we are in that situation, we often need to consolidate scripts to optimize transaction processing performance. Finally, scripts give us the ability to use code management tools (e.g. GIT) to take care of our client’s configuration.
Since we previously wrote a NetSuite Custom Mass Update to solve this challenge, it was easy to make it a Custom NetSuite Workflow Action script — doing so gave our client NetSuite Administrator control over the manner for which they would clean up the sales orders.
Custom NetSuite Mass Update to Close Sales Orders
Below is SuiteScript 2.0 to close sales orders. Notice that the pattern is to loop over the line items and close them. Doing so will close the entire sales order.
/**
* @NApiVersion 2.x
* @NScriptType MassUpdateScript
*/
define(['N/record'],
function(record) {
var scriptName = "MU_CloseSO ";
"use strict";
//the assumption is that the mass update deployment is going against the sales order.
function each(params) {
var funcName = scriptName + + params.type + " " + params.id;
try {
var SO = record.load({type: params.type, id: params.id});
//here, we are checking for a specific order status; if you do not need this, then remove the conditional
if (SO.getValue("orderstatus") == "B") {
//loop through the lines
for(var i = 0; i < SO.getLineCount({'sublistId':'item'}); i++)
SO.setSublistValue({'sublistId':'item','fieldId':'isclosed','value':true, line: i});
}
SO.save();
log.debug(funcName, "updated/closed.");
} catch (e) {
log.error(funcName + "Unable to close error", e)
}
}
return {
each: each
};
}
);
Custom NetSuite Workflow Action Script to Close Sales Orders
With the NetSuite Mass Update Script above, we can follow a similar pattern for a NetSuite Workflow Action script. Below is SuiteScript 2.0 to close sales orders. Notice that the pattern to loop over the line items and close them. This looping over line items is often needed in Workflow situations because these tools like to work at the Main (Header) level.
/**
* @NApiVersion 2.x
* @NScriptType workflowactionscript
*/
define(['N/record'],
function(record) {
var scriptName = "WA_CloseSO ";
"use strict";
function onAction(context) {
var funcName = scriptName + "onAction " + context.newRecord.type + " " + context.newRecord.id;
log.debug(funcName, "Starting");
try {
var SO = record.load({type: context.newRecord.type, id: context.newRecord.id});
//here is our loop. Close all lines and the entire order will close
for(var i = 0; i < SO.getLineCount({'sublistId':'item'}); i++)
SO.setSublistValue({'sublistId':'item','fieldId':'isclosed','value':true, line: i});
SO.save();
log.debug(funcName, "updated/closed.");
} catch (e) {
log.error(funcName + "Unable to close error", e)
}
}
return {
onAction : onAction
};
});
Enhancing NetSuite to Automate Practices
My hope in crafting this article is to help you see that NetSuite script patterns are very similar — the hook up technology is a bit different depending on which NetSuite programming event area you want to use. Both the Mass Update and Workflow Action pass the record id (internalid) and thus you can act on the record you want to manipulate quickly.
Perhaps you need some workflow action scripts or other NetSuite utilities to automate work processes? We give all of our algorithms to our clients without license charge. The idea is that we can make day-to-day NetSuite usage better by shaping the database, the logic, and the user experience.
If you found this article valuable, feel free to get notifications of new articles. If you would like to extract more value out of your NetSuite investment, let’s have a conversation.


Great Blog to follow Netsuite Standard codding practices. Shared this blog to my fellows NetSuite Technicals.
This is great here. This is now possible using action inside of workflow on the line item to do same. No code. All one needs do is feed it a SS of internal ID of Sales Orders.
Thank you Jason for offer up workflow alternatives.
Marty
Wuld these mass update scripts work on a return authorization. If not, what would need to change?
Hello Joe. It should.
Hello, we need to have a sales order approved by 4 users before it goes into pending fullfillment.
So to solve this problem I created a custom field with 4 personalized status (Approved by 1,2,3,4) and a workflow which allows you to remove the default approval button and add two buttons: ‘Approved’ and ‘rejected’ which would allow each approver to approve.
The problem is that once the first approver has approved, when the second approver wants to approve we get the following error message: Invalid orderstatus reference key H.
I do not understand why.
Can you help me?
Hello Orneyla,
The nature of this article is about closing a sales order, not approving it. However, I would take a completely different approach for having 4 signatures for approval. Using our Record State Framework, we can easily create rules and states to reflect your request. See the article here:
https://blog.prolecto.com/2018/04/28/learn-how-to-build-scalable-netsuite-sales-order-practices/
What is powerful is that we don’t have to have a specific order in mind — yet we can have that if needed through states.
Marty