SuiteScript 2.x Custom Module Tutorial

A custom module script holds logic that can be used by other scripts. If you have logic that is used in multiple scripts, you can create a custom module script to hold that logic. This approach is more efficient than copying the logic into each script where it is needed.

This tutorial walks you through the process of creating a custom module script and modifying an entry point script so that it uses the custom module.

This tutorial includes and overview and several tasks:

Sample Script Overview

The custom module script in this tutorial automatically creates a phone call record. After you create this module and upload it to your NetSuite File Cabinet, you can call this module from an entry point script.

When you have finished the updates to the entry point script (as described in this tutorial), the custom module script is triggered each time a new employee record is created. If the new employee record includes values in the Phone and Supervisor fields, the custom module schedules a phone call between the supervisor and the new employee.

Deploy the Prerequisite Script

If you have not deployed the user event script described in SuiteScript 2.x User Event Script Tutorial, deploy it now.

Create the Custom Module Script File

Copy and paste the following code into the text editor of your choice. Save the file and name it phoneCall.js.

            /** 
 * phoneCall.js
 * @NApiVersion 2.x
 * @NModuleScope Public 
 */


// This script create a record, so it loads the N/record module.

define (['N/record'] ,

    // The next line marks the beginning of the callback
    // function. The 'record' argument is an object that 
    // represents the record module.

    function (record) {

        // The next line marks the beginning of the entry point
        // function.
   
        function scheduleCall (context) { 
            var newPhoneCall = record.create({
                type: record.Type.PHONE_CALL,
                isDynamic: true
            });
 
            newPhoneCall.setValue({
                fieldId: 'title',
                value: context.phoneCallTitle
            });
 
            newPhoneCall.setValue({
                fieldId: 'assigned',
                value: context.phoneCallOwner
            });
 
            newPhoneCall.setText({
                fieldId: 'phone',
                text: context.phoneNumber
            });
 
            try {
                var newPhoneCallId = newPhoneCall.save();
                  
                log.debug({
                    title: 'Phone call record created successfully', 
                    details: 'New phone call record ID:  ' + newPhoneCallId
                });

            } catch (e) {
                log.error({
                    title: e.name,
                    details: e.message
                });
            }
        }

    // Add the return statement that identifies the entry point funtion.
    return {
        schedule: scheduleCall, 
    }
}); 

          

Review the Script (Optional)

If you want to understand more about how this script is structured, review the following subsections. Note that these images do not show the entire script. For more details, refer to the comments in Create the Custom Module Script File.

JSDoc Tags

A custom module script is not required to have JSDoc tags, but you should use them. The following illustration shows this sample’s JSDoc block.

Custom module script JSDoc block.

Callout

Description

1

The title of the file that holds this script. This annotation is not required, but it can be useful to list here. Any script that loads this module must refer to the name of the file.

2 and 3

The @NApiVersion tag and its value. This tag is not required in a custom module script, but you may want to include it to prevent compatibility problems with scripts that use future versions of SuiteScript. Valid values for this tag are 2.0, 2.x, and 2.X.

4 and 5

The @NModuleScope tag and its value. This tag is optional - you may want to use it to limit the access of other scripts to this module. For more information about this tag, see Controlling Access to Scripts and Custom Modules.

Entry Point Function

Every custom module script must define an object that is returned when the script’s entry point is invoked. This object could be a static value, such as a string. However, it is far more common for custom module scripts to return a function, as is the case with this script. Because of the way the Return Statement is set up, the entry point function shown in the following diagram is invoked when the script’s schedule entry point is invoked.

As with an entry point function in a standard entry point script, this function takes a context object as its argument.

Custom module script entry point function section with context object.

Callout

Description

1

The context object that is made available when the schedule entry point is invoked. The values of this object’s properties are defined in the script that calls this custom module.

2

This statement uses the record.create(options) method to begin the process of creating a phone call record.

3

These statements set fields on the phone call record. They use the properties of the context object, along with the Record.setValue(options) and Record.setText(options) methods.

The values of the context object — phoneCallTitle, phoneCallOwner, and phoneCallNumber — must be defined in the script that calls the custom module.

4

This try/catch block attempts to save the new phone call record by using the Record.save(options) method. If the save attempt fails, the block catches and logs the error that caused the problem.

Return Statement

As with an entry point script, the callback function in a custom module script must include a return statement. The return statement must include at least one entry point.

Custom module script return statement.

Callout

Description

1

The custom module’s entry point. As with an entry point script, every custom module script must use at least one entry point. The difference is that an entry point script must use a standard entry point that is part of the script type used by the script. A custom module entry point is your creation, so you can use this return statement to give the entry point any name you prefer.

2

A reference to an object. This example references a function. This structure is probably the most common. However, the entry point could reference another object, such as a static value.

Whatever object is referenced, it must be defined within the same script file.

Upload the Custom Module Script File to NetSuite

After you create your custom module script file, upload it to your NetSuite File Cabinet.

To upload the script file:

  1. In the NetSuite UI, go to Documents > File > SuiteScripts.

  2. In the left pane, select the SuiteScripts folder and click Add File.

  3. Follow the prompts to locate the phoneCall.js file in your local environment and upload it to the SuiteScripts folder.

Note that even after you upload the file, you can edit it from within the File Cabinet, if needed. For details, see Editing Files in the File Cabinet.

Modify the Entry Point Script

After you upload a custom module script file, you do not need to take any other actions for it to be available. Unlike entry point scripts, you do not have to create a script record or script deployment record for it. However, for the custom module script to be used,it must be referenced by a script that has been deployed.

In the next procedure, you will modify an entry point script so that it uses the phoneCall.js module and you will update the user event script described in SuiteScript 2.x User Event Script Tutorial. To update the file, you can use either of the following approaches:

  • If you want to copy and paste the updated script directly from this help topic, skip ahead to Copy the Full Script.

  • If you want to read about how to make the needed edits yourself, refer to Update the Script.

Update the Script

This procedure tells you how to update createTask.js so that it uses the phoneCall.js custom module file.

To update the script:

  1. Open the createTask.js file for editing.

  2. Update the list of dependencies by adding /phoneCall.js to the first argument of the define function.

    Custom module define statement updated with ./phoneCall added as the third parameter to the first argument.
  3. Add an additional dependency to the callback function’s first argument. This object represents the phone call module. It can be used to access the phone call module’s API.

    Custom module define statement updated with phone added as the thrid argument to the function.
  4. In the script’s afterSubmit function, add logic to retrieve the employee’s phone number.

    Sample custom module afterSubmit function.
  5. Create a block of code that does the following:

    • Create a conditional test that checks to see whether the employee record has values in both the phone number and supervisor fields (Callout 1).

    • Create an object called phoneData that sets values for all fields needed by the phone call module’s schedule method (Callout 2).

    • Call the schedule method, passing in the phoneCall object as its argument (Callout 3).

    Custom module script setting phone data to be sent to the schedule method.
  6. Upload the revised script file to your NetSuite File Cabinet, overwriting the prior version.

Copy the Full Script

The following shows the fully updated user event script. If you haven’t already created the script file using the steps described in Create the Script Step by Step, copy and paste the following code into the text editor of your choice. Save the file and name it createTask.js.

              /**
 * 
 *@NApiVersion 2.x
 *@NScriptType UserEventScript
 */

define (['N/record', 'N/ui/serverWidget',  './phoneCall'],
    function(record, serverWidget, phone) {

       // In the beforeLoad function, disable the 
       // Notes field on the record.
   
        function myBeforeLoad (context) {
            if (context.type !== context.UserEventType.CREATE)
                  return;
              var form = context.form;

              var notesField = form.getField({
                   id: 'comments'
              });
           
              notesField.updateDisplayType({
                   displayType: serverWidget.FieldDisplayType.DISABLED
              });
         }

        // In the beforeSubmit function, add a message to the Notes field.
       
        function myBeforeSubmit(context) {
            if (context.type !== context.UserEventType.CREATE)
                 return;
            var newEmployeeRecord = context.newRecord;
            newEmployeeRecord.setValue('comments', 'Orientation date TBD.');
        }

        // In the afterSubmit function, take several actions culiminating
        // in creating both a task record and a phone call record.
        
        function myAfterSubmit(context) {   

        // If the user is not creating a new record, then stop executing.

        if (context.type !== context.UserEventType.CREATE)
            return;

        // Use the context object's newRecord property to retrieve values
        // from the new record.

        var newEmployeeRecord = context.newRecord;
        var newEmployeeFirstName = newEmployeeRecord.getValue ({
              fieldId: 'firstname'
        });

        var newEmployeeLastName = newEmployeeRecord.getValue ({
            fieldId: 'lastname'
        });

        var newEmployeeSupervisor = newEmployeeRecord.getValue ({
            fieldId: 'supervisor'
        });

        var newEmployeePhoneNumber = newEmployeeRecord.getValue({
               fieldId: 'phone'
        });
            
        // If the user entered a value for the supervisor field,
        // create a task record for the supervisor.
 
        if (newEmployeeSupervisor) {
            var newTask = record.create({
                type: record.Type.TASK,
                isDynamic: true
            });
                
            newTask.setValue({
                fieldId: 'title',
                value: 'Schedule orientation session for ' +  
                newEmployeeFirstName +  ' ' + newEmployeeLastName
            });

            newTask.setValue({
                fieldId: 'assigned',
                value: newEmployeeSupervisor
            });    

            try {
                var newTaskId = newTask.save();
                log.debug({    
                      title: 'Task record created successfully', 
                       details: 'New task record ID:  ' + newTaskId
                });
                
             } catch (e) {
                 log.error({
                     title: e.name,
                        details: e.message
                 }); 
             } 
        } 

        // If the user entered values for both the supervisor and
        // phone number fields, use the phoneCall module to schedule a phone call.

        if (newEmployeeSupervisor && newEmployeePhoneNumber) {
            var phoneData =
                {
                    phoneNumber:  newEmployeePhoneNumber,
                       phoneCallOwner:   newEmployeeSupervisor,
                       phoneCallTitle:   'Welcome ' + newEmployeeFirstName +
                                ' ' + newEmployeeLastName
                   };
            phone.schedule(phoneData);
        } 
     }

    return {
        beforeLoad: myBeforeLoad,
        beforeSubmit: myBeforeSubmit,
       afterSubmit: myAfterSubmit
       
    };
}); 

            

Upload the Revised User Event Script

After you update the createTask.js file, upload it to your NetSuite File Cabinet.

To upload the script file:

  1. In the NetSuite UI, go to Documents > File > SuiteScripts.

  2. In the left pane, select the SuiteScripts folder and click Add File.

  3. Follow the prompts to locate the createTask.js file in your local environment and upload it to the SuiteScripts folder.

  4. When the system notifies you that a file with that name already exists, click OK to overwrite the existing file.

Test the Script

Now that the both files have been uploaded, you should verify that the custom module executes as expected.

To test the script:

  1. Begin the process of creating a new employee record by selecting Lists > Employees > Employees > New.

  2. In the new employee form, verify whether the Notes field is disabled. If the beforeSubmit entry point function works as expected, the field is gray and cannot be edited.

  3. Enter value for required fields. These fields may vary depending on the features enabled in your account and any customizations that exist. Minimally, they include:

    • Name — Enter a first name of Susan and last name Johnson.

    • Subsidiary — (OneWorld only) Choose a value from the dropdown list.

  4. To make sure that the custom module logic is used, enter values in the Supervisor and Phone fields.

  5. Click Save. A success message appears, and the system displays the new record in View mode.

  6. Verify that the phone call record was created successfully:

    1. Select Activities > Scheduling > Phone Calls.

    2. Check the filtering options to make sure that phone calls assigned to all employees are being displayed.

    3. Verify that a phone call was scheduled to welcome the new employee.

    Custom module script results verification that a phone call was scheduled to welcom the new employee.

Related Topics

SuiteScript 2.x Custom Modules
SuiteScript 2.x Anatomy of a Custom Module Script
Module Dependency Paths
Naming a Custom Module
Custom Module Examples
Troubleshooting Errors
Custom Modules Frequently Asked Questions

General Notices