netsuite

Topics related to netsuite:

Getting started with netsuite

Loading a record

Create a record

Executing a Search

Executing a Search

SS2.0 Suitelet Hello World

Sourcing

User Event: Before Load event

beforeLoad

The Before Load event is triggered by any read operation on a record. Any time a user, a script, a CSV import, or a web service request attempts to read a record from the database, the Before Load event gets fired.

Record actions that trigger a beforeLoad event:

  • Create
  • Edit
  • View / Load
  • Copy
  • Print
  • Email
  • QuickView

Typical Use Cases for beforeLoad

  • Modify the UI form before the user sees it
  • Set default field values
  • Data pre-processing

User Events do not chain

Code written in User Events will not trigger any User Events on other records. For example, loading the associated Customer record from the beforeLoad of a Sales Order record will not trigger the Customer record's beforeLoad. Even if you are loading another Transaction record, its User Events will not be fired.

NetSuite does this to avoid User Events triggering each other in an infinite loop. If you do need User Events to fire in a chained sequence, other script types (e.g. RESTlets, Suitelets, Scheduled Scripts) will need to be injected in between the events.

Event Handler returns void

The return type of the beforeLoad event handler is void. Any data returned from our event handler has no effect on the system. We do not need to return anything from our handler function as we cannot actually do anything with its returned value.

User Event: Before and After Submit events

beforeSubmit and afterSubmit

These two events are triggered by any database write operation on a record. Any time a user, a script, a CSV import, or a web service request attempts to write a record to the database, the Submit events get fired.

Record actions that trigger both Submit events:

  • Create
  • Edit
  • Delete
  • XEdit (inline edit)
  • Approve
  • Reject
  • Cancel
  • Pack
  • Ship

Record actions that trigger beforeSubmit only:

  • Mark Complete
  • Reassign (support cases)
  • Edit Forecast

Record actions that trigger afterSubmit only:

  • Dropship
  • Special Order
  • Order Items
  • Pay Bills

Typical Use Cases for beforeSubmit

  • Validate record before it is committed to database
  • Permission and restriction checks
  • Last-minute changes before database commit
  • Pull updates from external systems

Typical Use Cases for afterSubmit

  • Email notification of record changes
  • Browser redirection
  • Create/update dependent records
  • Push changes to external systems

User Events do not chain

Code written in User Events will not trigger any User Events on other records. For example, modifying the associated Customer record from the beforeSubmit of a Sales Order record will not trigger the Customer record's submit events.

NetSuite does this to avoid User Events triggering each other in an infinite loop. If you do need User Events to fire in a chained sequence, other script types (e.g. RESTlets, Suitelets, Scheduled Scripts) will need to be injected in between the events.

Event Handlers return void

The return type of the Submit event handlers is void. Any data returned from our event handler has no effect on the system. We do not need to return anything from our handler function as we cannot actually do anything with its returned value.

!! CAUTION !!

Be very cautious when comparing values between old and new records. Empty fields from the old record are returned as null, while empty fields from the new record are returned as an empty String. This means you cannot simply compare the old with the new, or you will get false positives. Any logic you write must handle the case where one is null and one is an empty String appropriately.

Governance

Governance

"Governance" is the name given to NetSuite's system for detecting and halting long-running, runaway, or resource-intensive scripts.

Each script type has governance limits that it cannot exceed, and there are four types of governance limits in place for each script type.

  • API usage limit
  • Instruction Count limit
  • Timeout limit
  • Memory usage limit

If a script exceeds its governance limit in any one of these four areas, NetSuite will throw an uncatchable exception and terminate the script immediately.

API Usage Limit

NetSuite limits the API usage of your scripts with a system based on "usage units". Some NetSuite API calls, particularly the ones that perform a read or write action on the database, cost a specific number of units each time they are invoked. Each script type then has a maximum number of units that can be used during each execution of the script.

If a script exceeds its API usage limit, NetSuite terminates the script by throwing an SSS_USAGE_LIMIT_EXCEEDED error.

Below are a few examples of unit costs for common operations. For an exhaustive list of Governance costs, see the article titled "API Governance" in NetSuite Help.

OperationUnit Cost
Loading a Saved Search5
Retrieving Search Results10
Scheduling a task10
Requesting a URL10
Sending an email10
Creating a custom record2
Creating an Employee record5
Creating a Sales Order record10
Saving a custom record4
Saving a Contact record10
Saving a Purchase Order record20

Different operations use different amounts of units, and certain operations cost a different amount based on the record type being used. The larger the number of units a function costs, typically the longer it will take to execute.

Transactions are the largest of the record types, so working with them costs the largest amount of units. Conversely, custom records are very lightweight, and so do not cost many units. Standard NetSuite records that are not Transactions, like Customers, Employees, or Contacts, sit in between the two in terms of cost.

These are the usage limits by script type:

Script TypeUsage Limit
Client1,000
User Event1,000
Suitelet1,000
Portlet1,000
Workflow Action1,000
RESTlet5,000
Scheduled10,000
Map/Reduce10,000
Bundle Installation10,000
Mass Update10,000 per record

Timeout and Instruction Count Limits

NetSuite also uses the governance system to detect and halt runaway scripts by using a timeout mechanism and an instruction counter.

If a script takes too much time to run, NetSuite will stop it by throwing an SSS_TIME_LIMIT_EXCEEDED error.

In addition, runaway scripts can be detected and halted based on their "Instruction Count". If the defined instruction count limits are exceeded, NetSuite will stop the script by throwing an SSS_INSTRUCTION_COUNT_EXCEEDED error.

There is, unfortunately, no Help documentation that defines:

  • the timeout for each script type
  • the instruction count limits for each script type
  • what constitutes a single "instruction"

It is simply important to know that if you encounter either the SSS_TIME_LIMIT_EXCEEDED error or the SSS_INSTRUCTION_COUNT_EXCEEDED error in one of your scripts, you have processing that is taking too long. Focus your investigation on your loop structures to determine where optimizations may be made.

Memory Usage Limit

If your script exceeds the memory usage limit, NetSuite will terminate your script by throwing a SSS_MEMORY_USAGE_EXCEEDED error.

Every variable declared, every function defined, every Object stored contributes to the memory usage of your script.

Both the Scheduled Script and the Map/Reduce Script have documented 50MB memory limits. There is also a documented limit of 10MB for the size of any String passed in to or returned from a RESTlet. There is no other documentation on the specific limits for a given script.

Using the NetSuite Records Browser

Script Type Overview

Exploiting formula columns in saved searches

Script and Script Deployment Records

RestLet - Retrieve Data (Basic)

Understanding Transaction Searches

References:

  • NetSuite Help page: "Using Main Line in Transaction Search Criteria"

RESTlet - Process external documents

SuiteScript - Process Data from Excel

Mass Delete

Lookup Data from Related Records

Performance

A Lookup is just shorthand for performing a search that filters on the internal ID of a single record for the result. Under the hood, lookups are actually performing a search, so the performance will be similar to that of a search that returns a single record.

This also means that a lookup will perform faster than loading the record to retrieve the same information.

Limitations

Lookups can only be used to retrieve body field data. You cannot retrieve data from the sublists of a related record using a lookup. If you need sublist data, you will either need to perform a search or load the related record.

Inline Editing with SuiteScript

The submitFields functionality is a companion feature to the lookupFields functionality.

Performance and Limitations

submitFields performs significantly faster and uses less governance than making the same changes by loading and submitting the full record.

Multiple fields can be updated at once for the same cost as updating a single field. Updating more fields with submitFields does not incur a higher governance cost.

However, you must be aware that only certain fields on each record type are inline-editable, and the performance savings only applies to these inline-editable fields. If you use the submitFields function on any non-inline-editable field, the field will be updated correctly, but behind the scenes, NetSuite will actually load and submit the record, thus taking more time and using more governance. You can determine whether a field is inline-editable by referring to the "nlapiSubmitField" column in the Records Browser.

submitFields functionality is also limited to the body fields of a record. If you need to modify sublist data, you will need to load the record to make your changes, then submit the record.

References:

  • NetSuite Help: "Inline Editing and SuiteScript Overview"
  • NetSuite Help: "Inline Editing Using nlapiSubmitField"
  • NetSuite Help: "Consequences of Using nlapiSubmitField on Non Inline Editable Fields"
  • NetSuite Help: "Field APIs"
  • NetSuite Help: "record.submitFields(options)"

Working with Sublists

Sublist Indices

Each line item in a sublist has an index that we can use to reference it.

In SuiteScript 1.0, these indices are 1-based, so the first line item has index 1, the second has index 2, and so on.

In SuiteScript 2.0, these indices are 0-based, so the first line item has index 0, the second has index 1, and so on. This of course more closely matches Array indexing in most languages, including JavaScript.

Standard vs Dynamic Mode

The API we use for interacting with a sublist depends on whether we are working with the record in Standard or Dynamic mode.

The Standard-mode APIs simply let us provide the index of the line we want to work with as a parameter to the appropriate function.

The Dynamic-mode APIs follow a pattern:

  1. Select the line we want to work with
  2. Modify the selected line as desired
  3. Commit the changes to the line

In Dynamic Mode, if we do not commit the changes to each line we modify, then those changes will not be reflected when the record is saved.

Limitations

In order to work with sublist data via SuiteScript, we must have a reference in memory to the record. This means the record either needs to be retrieved from the script context, or we need to load the record from the database.

We cannot work with sublists via either lookup or submitFields functionality.

Static sublists do not support SuiteScript at all.

References:

  • NetSuite Help: "What is a Sublist?"
  • NetSuite Help: "Sublist Types"
  • NetSuite Help: "Scriptable Sublists"
  • NetSuite Help: "Working with Sublist Line Items"
  • NetSuite Help: "Sublist APIs"
  • NetSuite Help: "Working with Records in Dynamic Mode"

Requesting customField, customFieldList & customSearchJoin with PHP API Advanced Search

Searches with large number of results

Scripting searches with Filter Expressions