UserScripting
UserScripting
2024.2
This software and related documentation are provided under a license agreement containing restrictions
on use and disclosure and are protected by intellectual property laws. Except as expressly permitted
in your license agreement or allowed by law, you may not use, copy, reproduce, translate, broadcast,
modify, license, transmit, distribute, exhibit, perform, publish, or display any part, in any form, or by any
means. Reverse engineering, disassembly, or decompilation of this software, unless required by law for
interoperability, is prohibited.
The information contained herein is subject to change without notice and is not warranted to be error-
free. If you find any errors, please report them to us in writing.
If this is software, software documentation, data (as defined in the Federal Acquisition Regulation), or
related documentation that is delivered to the U.S. Government or anyone licensing it on behalf of the
U.S. Government, then the following notice is applicable:
U.S. GOVERNMENT END USERS: Oracle programs (including any operating system, integrated software,
any programs embedded, installed, or activated on delivered hardware, and modifications of such
programs) and Oracle computer documentation or other Oracle data delivered to or accessed by
U.S. Government end users are "commercial computer software," "commercial computer software
documentation," or "limited rights data" pursuant to the applicable Federal Acquisition Regulation and
agency-specific supplemental regulations. As such, the use, reproduction, duplication, release, display,
disclosure, modification, preparation of derivative works, and/or adaptation of i) Oracle programs
(including any operating system, integrated software, any programs embedded, installed, or activated
on delivered hardware, and modifications of such programs), ii) Oracle computer documentation and/
or iii) other Oracle data, is subject to the rights and limitations specified in the license contained in the
applicable contract. The terms governing the U.S. Government's use of Oracle cloud services are defined
by the applicable contract for such services. No other rights are granted to the U.S. Government.
This software or hardware is developed for general use in a variety of information management
applications. It is not developed or intended for use in any inherently dangerous applications, including
applications that may create a risk of personal injury. If you use this software or hardware in dangerous
applications, then you shall be responsible to take all appropriate fail-safe, backup, redundancy, and other
measures to ensure its safe use. Oracle Corporation and its affiliates disclaim any liability for any damages
caused by use of this software or hardware in dangerous applications.
Oracle®, Java, MySQL, and NetSuite are registered trademarks of Oracle and/or its affiliates. Other names
may be trademarks of their respective owners.
Intel and Intel Inside are trademarks or registered trademarks of Intel Corporation. All SPARC trademarks
are used under license and are trademarks or registered trademarks of SPARC International, Inc. AMD,
Epyc, and the AMD logo are trademarks or registered trademarks of Advanced Micro Devices. UNIX is a
registered trademark of The Open Group.
This software or hardware and documentation may provide access to or information about content,
products, and services from third parties. Oracle Corporation and its affiliates are not responsible for and
expressly disclaim all warranties of any kind with respect to third-party content, products, and services
unless otherwise set forth in an applicable agreement between you and Oracle. Oracle Corporation and
its affiliates will not be responsible for any loss, costs, or damages incurred due to your access to or use
of third-party content, products, or services, except as set forth in an applicable agreement between you
and Oracle.
This documentation is in pre-General Availability status and is intended for demonstration and preliminary
use only. It may not be specific to the hardware on which you are using the software. Oracle Corporation
and its affiliates are not responsible for and expressly disclaim all warranties of any kind with respect to
this documentation and will not be responsible for any loss, costs, or damages incurred due to the use of
this documentation.
The information contained in this document is for informational sharing purposes only and should be
considered in your capacity as a customer advisory board member or pursuant to your pre-General
Availability trial agreement only. It is not a commitment to deliver any material, code, or functionality, and
should not be relied upon in making purchasing decisions. The development, release, timing, and pricing
of any features or functionality described in this document may change and remains at the sole discretion
of Oracle.
This document in any form, software or printed matter, contains proprietary information that is the
exclusive property of Oracle. Your access to and use of this confidential material is subject to the terms
and conditions of your Oracle Master Agreement, Oracle License and Services Agreement, Oracle
PartnerNetwork Agreement, Oracle distribution agreement, or other license agreement which has
been executed by you and Oracle and with which you agree to comply. This document and information
contained herein may not be disclosed, copied, reproduced, or distributed to anyone outside Oracle
without prior written consent of Oracle. This document is not part of your license agreement nor can it be
incorporated into any contractual agreement with Oracle or its subsidiaries or affiliates.
Documentation Accessibility
For information about Oracle's commitment to accessibility, visit the Oracle Accessibility Program website
at http://www.oracle.com/pls/topic/lookup?ctx=acc&id=docacc
Oracle customer access to and use of Oracle support services will be pursuant to the terms and
conditions specified in their Oracle order for the applicable services.
Sample Code
Oracle may provide sample code in SuiteAnswers, the Help Center, User Guides, or elsewhere through
help links. All such sample code is provided "as is” and “as available”, for use only with an authorized
NetSuite Service account, and is made available as a SuiteCloud Technology subject to the SuiteCloud
Terms of Service at www.netsuite.com/tos, where the term “Service” shall mean the SuiteProjects Pro
Service.
Oracle may modify or remove sample code at any time without notice.
As the Service is a multi-tenant service offering on shared databases, Customer may not use the Service
in excess of limits or thresholds that Oracle considers commercially reasonable for the Service. If Oracle
reasonably concludes that a Customer’s use is excessive and/or will cause immediate or ongoing
performance issues for one or more of Oracle’s other customers, Oracle may slow down or throttle
Customer’s excess use until such time that Customer’s use stays within reasonable limits. If Customer’s
particular usage pattern requires a higher limit or threshold, then the Customer should procure a
subscription to the Service that accommodates a higher limit and/or threshold that more effectively aligns
with the Customer’s actual usage pattern.
Table of Contents
Introduction ........................................................................................................................... 1
User Scripting Overview ....................................................................................................... 1
Getting Started ................................................................................................................... 4
Logs .................................................................................................................................. 6
Reporting ......................................................................................................................... 11
Platform Role Permissions .................................................................................................. 13
Scripting and SuiteProjects Pro Mobile .................................................................................. 15
Scripting and NetSuite Integration ....................................................................................... 15
User Scripting ....................................................................................................................... 17
Scripting Center ................................................................................................................ 17
Scripting Workflow ......................................................................................................... 21
Creating Form Scripts .................................................................................................... 22
Testing Form Scripts ...................................................................................................... 23
Deploying Form Scripts .................................................................................................. 24
Creating Scheduled Scripts ............................................................................................. 25
Testing Scheduled Scripts ............................................................................................... 26
Deploying Scheduled Scripts ........................................................................................... 28
Scheduled Scripts and Scheduled Queue Status ................................................................. 29
Creating Library Scripts .................................................................................................. 29
Creating Parameters ...................................................................................................... 32
Creating Solutions ......................................................................................................... 34
Accessing Terminology ................................................................................................... 36
Scripting Studio ................................................................................................................. 38
Scripting Studio Tools and Settings .................................................................................. 39
SOAP Explorer .............................................................................................................. 40
Functions Explorer ......................................................................................................... 41
OData Explorer ............................................................................................................. 41
Script Parameters .......................................................................................................... 42
Terminology ................................................................................................................. 43
Form Schema ............................................................................................................... 43
Testing and Debugging .................................................................................................. 46
Editor .......................................................................................................................... 47
Scripting Studio Options ................................................................................................. 49
Entrance Function ............................................................................................................. 50
Events .............................................................................................................................. 51
Scripting Governance ......................................................................................................... 53
SOAP API ......................................................................................................................... 55
Making SOAP Calls ......................................................................................................... 56
Using SOAP Results ....................................................................................................... 61
Handling SOAP Errors .................................................................................................... 62
Outbound Calling .............................................................................................................. 63
Request ....................................................................................................................... 64
Response ..................................................................................................................... 64
Limits .......................................................................................................................... 64
Password Script Parameters ............................................................................................ 65
Scripting Approvals ............................................................................................................ 65
Working with the Approvals System .................................................................................. 66
Using Approval Results ................................................................................................... 68
Handling Approval Errors ................................................................................................ 68
Custom Fields ................................................................................................................... 69
Creating Custom Fields .................................................................................................. 69
Reading Custom Fields ................................................................................................... 71
Updating Custom Fields ................................................................................................. 72
NSOA Functions ................................................................................................................ 73
NSOA.context.getAllParameters() ...................................................................................... 75
NSOA.context.getAllTerms() ............................................................................................. 76
NSOA.context.getLanguage() ........................................................................................... 76
NSOA.context.getParameter(name) ................................................................................... 77
NSOA.context.getTerm(termid) ......................................................................................... 78
NSOA.context.isTestMode() .............................................................................................. 79
NSOA.context.parseTerminology(message) ........................................................................ 80
NSOA.context.remainingTime() ......................................................................................... 80
NSOA.context.remainingUnits() ........................................................................................ 81
NSOA.form.confirmation(message) ................................................................................... 82
NSOA.form.error(field, message) ...................................................................................... 83
NSOA.form.getAllValues() ................................................................................................ 84
NSOA.form.getLabel(field) ............................................................................................... 85
NSOA.form.getName(field) .............................................................................................. 86
NSOA.form.getNewRecord() ............................................................................................. 87
NSOA.form.getOldRecord() .............................................................................................. 88
NSOA.form.getValue(field) ............................................................................................... 89
NSOA.form.get_value(field) .............................................................................................. 90
NSOA.form.setValue(field, value) ....................................................................................... 91
NSOA.form.warning(message) .......................................................................................... 95
NSOA.https.delete(request) ............................................................................................. 96
NSOA.https.get(request) ................................................................................................. 97
NSOA.https.patch(request) .............................................................................................. 98
NSOA.https.post(request) .............................................................................................. 100
NSOA.https.put(request) ................................................................................................ 101
NSOA.listview.data(listviewId) ......................................................................................... 102
NSOA.listview.list() ........................................................................................................ 104
NSOA.meta.alert(message) ............................................................................................ 105
NSOA.meta.log(severity, message) .................................................................................. 106
NSOA.meta.sendMail(message) ...................................................................................... 107
NSOA.NSConnector.integrateAllNow() .............................................................................. 109
NSOA.NSConnector.integrateRecord() .............................................................................. 110
NSOA.NSConnector.integrateWorkflowGroup(name) .......................................................... 111
NSOA.record.<complex type>( [id] ) ................................................................................. 112
NSOA.report.data(reportId,optionalParameters) ................................................................ 114
NSOA.report.list() ......................................................................................................... 115
NSOA.wsapi.add(objects) ............................................................................................... 117
NSOA.wsapi.approve(approveRequest) ............................................................................ 118
NSOA.wsapi.delete(objects) ............................................................................................ 119
NSOA.wsapi.disableFilterSet( [ flag] ) ................................................................................ 119
NSOA.wsapi.enableLog( [ flag] ) ...................................................................................... 120
NSOA.wsapi.modify(attributes, objects) ............................................................................ 122
NSOA.wsapi.read(readRequest) ...................................................................................... 123
NSOA.wsapi.reject(rejectRequest) .................................................................................... 124
NSOA.wsapi.remainingTime() ......................................................................................... 125
NSOA.wsapi.submit(submitRequest) ................................................................................ 125
NSOA.wsapi.unapprove(unapproveRequest) ..................................................................... 126
NSOA.wsapi.upsert(attributes,objects) .............................................................................. 127
NSOA.wsapi.whoami() ................................................................................................... 128
Code Samples ................................................................................................................. 129
Comparing Date Fields ................................................................................................. 129
Validating Numeric Fields .............................................................................................. 130
Requiring Minimum Values ............................................................................................ 130
Creating Error Log Entries ............................................................................................. 130
Sending email ............................................................................................................. 131
SOAP API — Prevent closing a project with an open issue .................................................. 131
SOAP API — Append notes to a project ........................................................................... 132
SOAP API — Require task assignment ............................................................................. 132
Submitting a Timesheet for Approval .............................................................................. 133
Outbound Calling — SOAP Call Using HTTPS POST ............................................................ 134
Outbound Calling — Post a Slack Message ...................................................................... 134
Outbound Calling — HTTPS GET with Authorization ........................................................... 135
JavaScript ............................................................................................................................ 137
JavaScript Overview .......................................................................................................... 137
Variables ........................................................................................................................ 137
Variable Scope ............................................................................................................ 138
Dynamic Data Types ..................................................................................................... 139
Arrays ............................................................................................................................ 140
Associative Array .......................................................................................................... 141
Objects .......................................................................................................................... 142
Functions ........................................................................................................................ 143
Loops ............................................................................................................................. 144
for ............................................................................................................................. 145
for in ......................................................................................................................... 145
forEach ...................................................................................................................... 145
do while ..................................................................................................................... 146
while .......................................................................................................................... 146
Conditional Statements ..................................................................................................... 146
if ... else ...................................................................................................................... 147
switch ........................................................................................................................ 148
Error Handling ................................................................................................................ 148
References ...................................................................................................................... 149
JavaScript Objects ........................................................................................................ 149
JavaScript Operators ..................................................................................................... 156
Reserved Words .......................................................................................................... 158
Escape Sequences ....................................................................................................... 159
Scripting Best Practices ........................................................................................................ 160
Real World Use Cases ........................................................................................................... 163
Validation ....................................................................................................................... 165
Ensure value of multiple commissions fields equals 100% ................................................... 165
Require notes field to be populated on time entries when more than 8 hours in a day ............. 167
When submitting an expense report, validate each ticket has an attachment (for example,
scanned receipt) .......................................................................................................... 169
Ensure resource time entry matches booking planning and project worked hours .................. 171
Automation ..................................................................................................................... 174
Optionally create a new Customer PO when editing a project .............................................. 174
Create time entries from task assignments when the user creates a new timesheet ................ 178
Control budgeted hours for a project using the transactional budget feature and a custom hours
field ........................................................................................................................... 182
Workflow ........................................................................................................................ 184
Prevent a booking from being created if the selected resource has approved time off during the
booking period ............................................................................................................ 184
Prevent closing a project that has open issues ................................................................. 187
Automatically create a new issue when project stage is "at risk" and prevent project stage from
changing until this issue is resolved ................................................................................ 189
Send an alert email when a scheduled script completes ..................................................... 192
Send a Slack notification when issues are created or (re)assigned ........................................ 193
User Scripting Release History ............................................................................................... 206
Introduction 1
Introduction
User scripts are written in the industry standard JavaScript language. SuiteProjects Pro is compliant with
ECMAScript 5.
To ensure the security and stability of SuiteProjects Pro, constraints and checks are placed on user
scripting, see Scripting Governance. User scripting is prevented from accessing DOM methods, the file
system, and sockets. Access to SuiteProjects Pro is made available through NSOA Functions.
Scripts are stored in a Dedicated Scripting Workspace used exclusively for scripting and can only be
altered through the Scripting Center. Scripts can be edited from the integrated Scripting Studio or
by an external editor. To use the Scripting Center or Scripting Studio you need to be signed in as an
administrator.
Before you begin writing scripts, you should review Scripting Best Practices.
Tip: For a quick reference, see the User Scripting Reference Card.
Scripting Switches
There are four switches used to control scripting:
■ Enable user scripts to be executed by forms — enables the Scripting Center with the Forms tab
and enables you to create Form Scripts. This switch also enables the Script deployment detail report
section with the Form script deployment logs report, see Reporting.
■ Enable scheduled script deployments — enables the Scripting Center with the Scheduled tab and
enables you to create Scheduled Scripts. This switch also enables the Script deployment detail report
section with the Scheduled script deployment logs report, see Reporting.
■ Enable user script support for https methods — enables you to access NSOA.https functions and
call external APIs. See Outbound Calling.
■ Enable user script support for Web Service API methods — enables you to access the SOAP API
(Web Services) through the NSOA.wsapi functions. SOAP API.
■ There is a View the script deployment log report role permission to enable non-administrators to
view script deployment log reports, see Reporting.
Form Scripts
Form scripts are triggered to run by Events. When you create a form script it must be associated with a
specific form.
User Scripting
User Scripting Overview 2
Note: Form scripts are executed within the context of the user who is signed in, see
NSOA.wsapi.disableFilterSet( [ flag] )
Important: Form scripts may be triggered by an event associated with user interaction —
when a user clicks Save, for example.
Form scripts can also be triggered by an event associated with a process utilizing the form
software logic — when importing project records from NetSuite using the NetSuite integration,
for example, depending on the integration configuration. For more information, see Scripting and
NetSuite Integration.
Scheduled Scripts
Scheduled scripts are created in a similar same way to form scripts and follow the same scripting
workflow. The main differences are that scheduled scripts are not associated with a form, have higher
Scripting Governance limits, and are executed according to a schedule defined when they are deployed.
Scripts are executed one at a time from a single first in first out (FIFO) queue.
User Scripting
User Scripting Overview 3
Tip: Two or more scripts with the same schedules times that need to run in a specific order
should be merged into a single script, that is merge into one script with one Entrance Function
calling each of the three functions in the desired order.
Note: Scheduled scripts are executed within the context of a user. You need to specify the user
under which the script is to be executed when you deploy the script.
Tip: By default scheduled triggers are disabled on sandboxes. If you need to test scheduled
triggers in your sandbox account, create a support case in SuiteAnswers and request the
run_schedule_script trigger to be enabled for your sandbox account.
Library Scripts
Library scripts are created in a similar same way to form and scheduled scripts and follow the same
scripting workflow.
Library scripts allow you to package the complexity of a scripted solution into calling scripts and
supporting functions resulting in scripts that are easier to build and maintain. You can build libraries
of proven functions to reduce the cost of development and maintenance. Libraries are seamlessly
integrated into the Scripting Studio to boost developer productivity.
Script Parameters
Script parameters allow developers to create scripts that can be configured without needing to change
the script. Parameters are created and set in the same way as custom fields.
Script Terminology
Administrators can customize the terminology used in SuiteProjects Pro to meet the unique needs
of their company. For example, one company may use the word project to describe work to be
accomplished. Another company may call it a case, job, or assignment. See Interface: Terminology
in Administrator Guide Chapter 6 "Administration - Global Settings" for more information about
customizing terminology in SuiteProjects Pro.
The terminology set for an account can be directly accessed and used in scripts to create results that
meet the unique needs of the company.
Scripts can be written to immediately reflect any terminology changes made by an administrator without
the need to adjust the scripts in any way.
Platform Solutions
You can create scripts and store them with all their dependent libraries and parameters in a single
solution (XML) file. You can then apply the solution directly to another account. Solutions are stored in
XML files to facilitate reading, transfering, archiving, and comparing them.
User Scripting
User Scripting Overview 4
Tip: All of the examples described in Real World Use Cases are provided as solutions, see
Creating Solutions.
You can access the reports and lists published using the Business Intelligence Connector feature with the
following functions:
These functions give you access to the same information available when you use Business Intelligence
tools to access your SuiteProjects Pro OData feed.
You can use published lists like custom queries and read the latest list data in your form and scheduled
scripts.
Note: The Business Intelligence Connector feature must be enabled for your account to use
NSOA.listview and NSOA.report functions. The Business Intelligence Connector feature is a
licensed add-on. To enable this feature, contact your SuiteProjects Pro account manager.
For more information about publishing lists and reports to the SuiteProjects Pro OData service,
see Business Intelligence Connector.
Getting Started
With scripting enabled the Scripting Center section is available in Administration, see Scripting Switches.
Note: This also enables the Scripts section in Modify the form permissions forms and in
Administration > Customization.
Quick Start
Note: Make sure you have the necessary switches enabled, see Scripting Switches.
2. Create a new script from the Create Button. See Creating Form Scripts and Creating Scheduled
Scripts.
You need to specify a unique filename for the script in the Dedicated Scripting Workspace. You can
optionally select a document that already has the script you need otherwise an empty script file will
be created. If you specify a document to upload then a new script file is created from the specified
file and the original file left untouched.
Note: An individual script can only be associated with one form. The same script cannot
be triggered by two different forms or even form events. An individual form may trigger as
many scripts as necessary.
3. Click on the Script link in the Scripting Center to open the script in the Scripting Studio.
User Scripting
Getting Started 5
4. Type the script into the editor and then fill out the fields in the Scripting Studio Tools and Settings:
a. Select the user that the script will run for ‘In testing’ state, see Testing and Debugging.
b. Select any libraries referenced by this script.
c. Select the Event to trigger the script, see Events.
d. Select the Entrance function, the name of your function to run in the editor, see Entrance
Function.
e. Use the Code revision comments to comment the script changes made.
f. Click SAVE.
Note: The act of saving a script in the ”Inactive” state will move the script to the ”In testing”
state, see Scripting Workflow.
5. The script will now run when the SAVE button is pressed on the form to which it has been
deployed.
6. To deploy the script, select the Deploy option from the Status menu, see Scripting Workflow.
User Scripting
Getting Started 6
Logs
Script logs are the primary means for Testing and Debugging a script and for monitoring the health of a
deployed script. Any errors that occur during run time are written to the script log.
Scripts can write to the log using the NSOA.meta.log(severity, message) and NSOA.meta.alert(message)
functions. Detailed SOAP API request and response messages can also be logged by calling the
NSOA.wsapi.enableLog( [ flag] ) function from within a script.
Each log entry contains the following information:
■ Severity — The supplied severity: "Fatal", "Error", "Warning", "Info", "Debug", or "Trace".
■ Timestamp — The time the message was logged.
■ Generated by — For example, whether the message was generated by your script or by SuiteProjects
Pro.
■ Message — The full message text.
Note: SuiteProjects Pro adds a log entry when one of the following script properties is
changed, with an indication of what was changed: Source code, Event, Entrance function,
Deployed status, Employee.
Tip: If you load the script into an Editor you can quickly find the line number reported in the log
message, see Testing Form Scripts.
View Log
You can view any log messages a script has generated by clicking the "View Log" link from the Scripting
Center and Scripting Studio, see also Reporting.
User Scripting
Logs 7
The log view has the following standard SuiteProjects Pro features:
Note: Errors generated by a library are reported into the calling form or scheduled script.
Libraries do not have separate logs.
Administrators can control the messages that are written to deployed scripts by setting the Log Severity
for the script.
You can see how many log entries are part of a log without having to open each log with the “Display the
number of logs at 'View logs' link” feature. This feature shows a count of log entries as part of the "View
Log" link for Form and Scheduled Script Deployments.
User Scripting
Logs 8
The number of logs also appears next to the "View Log" link in the Scripting Editor.
To use this feature, go to the User Menu > Personal Settings > Scripting Studio Options and select the
"Display the number of logs at 'View logs' link" option.
Log Severity
Script logs recognize the following severities: "Fatal", "Error", "Warning", "Info", "Debug", or "Trace".
Note: If a severity is used that the log system does not recognize then it is written as an "Info"
severity.
The NSOA.meta.log(severity, message) function takes two parameters, the first is severity and the second
is the message to log. The NSOA.meta.alert(message) function takes a message parameter and writes
"Info" severity message.
Severity is case insensitive so the following calls are all treated as the same:
NSOA.meta.log('debug',"message");
NSOA.meta.log('Debug',"message");
NSOA.meta.log('DEBUG',"message");
NSOA.meta.log('myseverity',"message");
NSOA.meta.log('Info',"message");
User Scripting
Logs 9
NSOA.meta.alert("message");
If you trigger a script that is either "In testing" (or "Active revising" and you are signed in as the test user)
then ALL log messages are logged.
If you trigger a script that is "Active" (or "Active revising" and you are not signed in as the test user) then
the log messages written are controlled by the Log severity set for the script in the Scripting Center.
Non-deployed scripts log all messages but deployed scripts log messages according to the Log severity
setting.
Calls to NSOA.meta.log(severity, message) with the severity parameter set to "Debug" or "Trace" do not
consume units but are limited to a maximum of 1000 per script.
The default Log severity level for deployed scripts is "Error". This means that only "Error” and "Fatal"
severities are written to log. In this case "Trace", "Debug", “Info”, and “Warning” messages are simply
ignored.
Administrators can set the Log severity level for deployed scripts.
Note: "Fatal" and system generated messages are ALWAYS logged! A system Info message is
written to the log when the log severity is changed.
Tip: You can set the log severity to "Warning" or "Error" to save space and improve system
performance for scripts that are operating correctly and generating log information that you are
sure you don’t need.
Tip: You can set the log severity of a deployed script to "Debug" to track down errors that only
occur for a deployed script.
User Scripting
Logs 10
User Scripting
Logs 11
The delete logs task is available from Administration > Global Settings > Account > Maintenance Settings.
Tip: Use this maintenance task when your system is not busy and ensure not to delete log
entries that you may need.
Reporting
This section contains the Form script deployment logs report and the Scheduled script deployment logs
report.
To view the Form script deployment logs detail report you need the Enable user scripts to be
executed by forms switch enabled.
To view the Scheduled script deployment logs details report you need the Enable scheduled script
deployments switch enabled.
Non-administrators can see the reports if they have been assigned the View the script deployment log
report role permission.
User Scripting
Reporting 12
This report allows you to view all the log messages for all form script deployments. See
NSOA.meta.log(severity, message) for more details.
You can also see the SOAP request and response messages if NSOA.wsapi.enableLog( [ flag] ) is used in a
script.
To view this report, you need the Enable user scripts to be executed by forms switch enabled.
There is a View the script deployment log report role permission for non-administrators to view this
report.
This report allows you to view all the log messages generated by all scheduled script deployments. See
NSOA.meta.log(severity, message) for more details.
User Scripting
Reporting 13
To view this report, you need the Enable scheduled script deployments switches enabled.
There is a View the script deployment log report role permission for non-administrators to view this
report.
0 OK/Success
■ Script Administrator
■ Script Developer
■ Script QA
■ Script Deploy
■ View Scripting Center — allows you to access and view the Scripting Center by navigating to
Administration > Scripting Center.
■ Create script — allows you to create a new script.
■ Change script log level — allows you to set what types of information to log.
■ View script in Scripting Studio — allows you to view a script in the Scripting Studio.
■ View and modify script in Scripting Studio — allows you to view a script and make changes to it in the
Scripting Studio.
■ Enable script testing — allows you to move a script to “In testing” status.
■ Upload script revision code — allows you to upload new code revisions after a script has been
deployed.
■ Disable script testing — allows you to move an “In testing” script to “Inactive” status.
■ Discard script changes — allows you to discard any script changes made since the last save.
User Scripting
Platform Role Permissions 14
■ Deploy new script — allows you to save a new script and move it to “Active” status.
■ Deploy script changes — allows you to save changes to an “In testing” script and move it to “Active”
status.
■ Undeploy script — allows you to move an “Active” script to “In testing” status.
■ Delete script — allows you to delete a script.
■ Set form script “Execute As Employee” — set an employee for script deployment when running a script
under another user.
■ Run schedule script test code — allows you to run schedule script test code in either “In testing” or
“Active: revising” states.
■ Run schedule script code — allows you to run currently deployed script code.
■ Cancel schedule script queued runs — allows you to cancel any previously-scheduled runs waiting for
processing in the queue.
■ View script parameters — allows you to view, create, and modify script parameters.
■ View and modify script parameters — allows you to view, create, and modify script parameters.
■ Set script parameter value — allows you to use the “Set” link for the script parameter value.
■ View solutions — allows you to view solutions, but not edit them.
■ View and modify solutions — allows you to view, create, and modify solutions.
■ Export solution — allows you to export a solution based on a particular script deployment.
■ Upload solution — allows you to upload a solution XML file.
■ Apply solution — allows you to create all objects specified in a solution and create a log file.
■ Delete solution — allows you to delete a solution, all of its history, and logs.
We suggest creating the following roles and assigning them these permissions:
Create script — —
Undeploy script — —
Delete script — —
User Scripting
Platform Role Permissions 15
View solutions —
Create solution —
Upload solution
Download solution
Apply solution
Delete solution — — —
■ All form scripts associated with the expense report and receipt entity forms.
■ "Before approval" and "After approval" scripts associated with the timesheet entity form.
Note: “On submit,” “Before save,” or “After save” scripts associated with the timesheet entity
form are not supported.
For an example of script that is executed both in SuiteProjects Pro and SuiteProjects Pro Mobile, see
■ NSOA.NSConnector.integrateAllNow() — Use this function to import and export records in bulk from
your scheduled scripts. The run will include all integration workflows that are active at the time the run
is triggered. See NSOA.NSConnector.integrateAllNow().
■ NSOA.NSConnector.integrateWorkflowGroup(name) — Use this function to import and export records
in bulk from your scheduled scripts. The run will include only integration workflows in the workflow
group specified by name. See NSOA.NSConnector.integrateWorkflowGroup(name).
■ NSOA.NSConnector.integrateRecord() — Use this function to export a single record from your form
scripts. See NSOA.NSConnector.integrateRecord().
User Scripting
Scripting and NetSuite Integration 16
If you are using the NetSuite integration, and depending on the integration configuration, the integration
may use software logic associated with the Project form when importing project records from NetSuite
to SuiteProjects Pro. In this case, form scripts associated with the Project form and triggered by an “On
submit”, “Before save”, or “After save” event will run for each imported project record. This will impact the
performance of your integration runs and may result in errors related to scripting governance limits. For
more information about configuration options that result in the integration triggering form scripts, see
NetSuite Integration.
User Scripting
User Scripting 17
User Scripting
Scripting Center
The Scripting Center is accessed from Administration > Scripting Center and gives administrators
complete control over all script deployments and development activities from a central location.
From the Scripting Center you can launch the Scripting Studio by clicking on a script link.
Scripts are moved through the Scripting Workflow from the Status menu.
Note: Customers that choose not to use the Scripting Studio in favor or another editor are still
fully supported from the Scripting Center.
You can view any log messages the script has generated using the “View Log” link, see Logs.
User Scripting
Scripting Center 18
You can clear all log entries for a specific script from the Scripting Center using the Clear log option in
the Status dropdown list. See Clear Log Entries for a Specific Script.
■ Script — This is the script to run on the event, click to edit the script in the Scripting Studio.
■ Status — Indicates the state of the script in the Scripting Workflow.
■ Entrance Function — This is the entrance function to call in the script, see Entrance Function.
■ Event — This is the event that will trigger the script to run, see Events.
■ Form name — This is the form that will trigger the script, see Creating Form Scripts.
The Started and Duration [sec] columns on the Scripting Center > Scheduled tab allows administrators
to monitor the processing of scheduled scripts in the queue. Refresh the page to see the progress. The
Started and Duration [sec] columns are cleared when the script completes.
Manage libraries
User Scripting
Scripting Center 19
You can specify the libraries a script references by selecting Manage libraries from the Scripting Center
Status menu. This performs the same function as selecting libraries in the Scripting Studio Tools and
Settings and is provided for developer using an external editor.
Note: You can only manage the libraries of ”In testing” and “Active: revising” scripts.
Important: You cannot select an ”Inactive” library and you cannot deploy a script that is
referencing a library that has not been deployed.
Manage parameters
You can specify the parameters a script uses by selecting Manage parameters from the Scripting Center
Status menu. This performs the same function as selecting parameters in the Script Parameters section
of the Scripting Studio and is provided for developer using an external editor.
Note: You can only manage the parameters of ”In testing” and “Active: revising” scripts.
View history
The script deployment history is available by selecting View history from the Scripting Center Status
menu. From this form you can browse through each revision of deployed code and download a selected
document revision. For each version of a deployed script (document revision), the Script deployment
history page shows:
User Scripting
Scripting Center 20
Important: A new history entry is only created when you Deploy a script. A new history entry is
not created every time you SAVE your script changes.
User Scripting
Scripting Center 21
Scripting Workflow
Note: * Edit is actioned by clicking the script link and saving from the Scripting Studio
A color coded status indicator shows the position of the script in the scripting workflow:
Depending on the scripts status in the workflow a list of options are available by clicking on the status.
Status Actions
■ Test — Prompts for test settings and on SAVE moves the script to In testing.
■ Delete — Prompts for confirmation and on OK deletes the script code and all associated history.
■ View history — see View history.
User Scripting
Scripting Center 22
■ Click the script link to make changes in the Scripting Studio. On SAVE the script moves to In
testing.
■ Deploy — Prompts for confirmation and on SAVE moves the script to Active.
■ Disable testing — Prompts for confirmation and on OK moves the script to In active.
■ Manage libraries — see Manage libraries.
■ Manage parameters — see Manage parameters.
■ View history — see View history.
■ Export solution — see Creating Solutions.
■ Click the script link to make changes in the Scripting Studio. On SAVE the status in not changed.
■ Revise — Prompts for a new JS file with the required content and then launches the Scripting
Studio with this new content. On SAVE the script is moved to Active: revising.
■ Undeploy — Prompts for confirmation and on OK moves the script to In testing.
■ View history — see View history.
■ Create solution — see Creating Solutions.
■ Click the script link to make changes in the Scripting Studio. On SAVE the script moves to Active:
revising.
■ Deploy changes — Prompts for confirmation and on SAVE moves the script to Active.
■ Discard changes — Prompts for confirmation and on OK moves the script to Active ignoring any
changes made.
■ Manage libraries — see Manage libraries.
■ Manage parameters — see Manage parameters.
■ Undeploy — Prompts for confirmation and on OK moves the script to In testing.
■ View history — see View history.
■ Create solution — see Creating Solutions.
■ Click the script link to make changes in the Scripting Studio. On SAVE the script moves to Active:
revising.
Note: An individual script can only be associated with one form. The same script cannot be
triggered by two different forms or even form events. An individual form may trigger as many
scripts as necessary.
User Scripting
Scripting Center 23
3. Enter a Filename.
4. If you want to import an already written script, click Choose File and select the script file.
5. Click Save.
The form script list appears and includes your new form script.
6. Click the name of the new script.
The script opens in the Scripting Studio.
7. Enter the script in the editor and change the information in the Tools and Settings form.
a. Select the user that the script will run for ‘In testing’ state, see Testing and Debugging.
b. Select any libraries referenced by this script.
c. Select whether the script is executed On Submit, Before save, or After save.
d. Select the Entrance function, the name of your function to run in the editor, see Entrance
Function.
e. Use the Code revision comments to comment the script changes made.
f. Click SAVE.
Note: The act of saving a script in the ”Inactive” state will move the script to the ”In testing”
state, see Scripting Workflow.
After a script is created, you can edit the script by clicking on the script link, move the script through the
Scripting Workflow, or view any log messages the script has generated using the “View Log” link, see
Testing Form Scripts.
Tip: To reduce the errors in your scripts, see Scripting Best Practices.
Scripts need to be carefully tested before being deployed to production. See Testing Form Scripts and
Scripting Workflow for details.
For more details see:
■ Syntax errors — These errors can be caught before your script is executed. Syntax errors are
displayed in the Editor.
For example:
SuiteProjects Pro checks scripts for correct syntax before allowing them to be deployed. An error is
displayed if you attempt to deploy a script with syntax errors.
User Scripting
Scripting Center 24
Note: This error is caused because Var had been typed in place of var, JavaScript is case
sensitive. See Variables for more details.
■ Runtime errors — These errors occur during run time. SuiteProjects Pro report runtime errors in the
log.
Click on the View Log link to see the log messages. See also Reporting.
This error was caused because the script attempted to call a method that doesn’t exist, that is,
NSOA.form.getLabel2 does not exist.
function test() {
var value = NSOA.form.getValue('budget_time');
var label = NSOA.form.getLabel2('budget_time');
}
Tip: If you load the script into the Editor you can quickly find the line number reported in the
log.
■ Logic errors — These errors are the most difficult type to track down. They are not the result of a
syntax or runtime error. Instead, they occur when you make a mistake in the logic that drives your
script and you do not get the result you expected.
Tip: You can use the NSOA.meta.alert(message) function to log debugging information.
1. Go to Administration > Scripting Center > Form. The list for form scripts appears.
User Scripting
Scripting Center 25
2. In the status column, click the drop-down list for the form script you want to deploy and select
“Deploy”. A deploy script dialog appears.
3. Add notes for the script deployment (optional).
4. Select an employee to execute the script.
Tip: Create a dedicated user with the minimum necessary permissions to execute the script for
the “Select user to execute script deployment” feature.
User Scripting
Scripting Center 26
Scheduled scripts are created in a similar same way to form scripts and follow the same Scripting
Workflow. Notice that scheduled scripts have additional menu options available from the Status menu:
■ Run script deployment — Prompts for confirmation and on OK will add a one-time schedule event to
the platform script deployment job queue.
■ Cancel queued runs — Prompts for confirmation and on OK will cancel any jobs queued to run for
this script.
Scheduled scripts are not associated with a form and cannot access the NSOA.form functions.
Note: The act of saving a script in the ”Inactive” state will move the script to the ”In testing”
state, see Scripting Workflow.
User Scripting
Scripting Center 27
Important: By default scheduled triggers are disabled on sandboxes. If you need to test
scheduled triggers in your sandbox account, create a support case in SuiteAnswers and request
the run_schedule_script trigger to be enabled for your sandbox account.
There are three types of errors you need to remove from your scripts.
■ Syntax errors — These errors can be caught before your script is executed. Syntax errors are
displayed in the Editor.
For example:
SuiteProjects Pro checks scripts for correct syntax before allowing them to be deployed. An error is
displayed if you attempt to deploy a script with syntax errors.
Note: This error is caused because Var had been typed in place of var, JavaScript is case
sensitive. See Variables for more details.
■ Runtime errors — These errors occur during run time. SuiteProjects Pro report runtime errors in the
log.
Click on the View Log link to see the log messages. See also Reporting.
User Scripting
Scripting Center 28
This error was caused because the script attempted to call a method that doesn’t exist, that is,
NSOA.form.getLabel2 does not exist.
function test() {
var value = NSOA.form.getValue('budget_time');
var label = NSOA.form.getLabel2('budget_time');
}
Tip: If you load the script into the Editor you can quickly find the line number reported in the
log.
■ Logic errors — These errors are the most difficult type to track down. They are not the result of a
syntax or runtime error. Instead, they occur when you make a mistake in the logic that drives your
script and you do not get the result you expected.
Tip: You can use the NSOA.meta.alert(message) function to log debugging information.
1. To deploy a scheduled script, select the Deploy option from the Status menu, see Scripting
Workflow.
Scheduled scripts are executed within the context of a user. You need to specify the user under
which the script is to be executed when you deploy the script.
As of the April 16, 2016 release, you can select a non-administrator user who acts as a proxy
to execute a script deployment. This is especially useful when a user does not have the access
permissions a script needs to run successfully. With this feature, you need only assign the
minimum-necessary permissions.
User Scripting
Scripting Center 29
1st of the month at 12am 00 On the first day of every month at 00:00
Monday at 11am Every 15th minute Every Monday at 11:15, 11:30, and 11:45
Monday at Every hour 00 Every Monday at the top of each hour, for example 00:00, 01:00, ... ,
22:00, 23:00
User Scripting
Scripting Center 30
allowed. Libraries are automatically available when form and / or scheduled scripts are enabled, see
Scripting Switches.
Library scripts are created in a similar way to form and scheduled scripts and follow the same Scripting
Workflow.
Library scripts are not associated with a form or event and can only access NSOA.form functions if called
from a form script.
References to libraries can be set from the Scripting Center Manage libraries or from the Scripting Studio
Scripting Studio Tools and Settings.
User Scripting
Scripting Center 31
Create functions in the same way as for form and scheduled script and then use exports to make
the function available. You have the option to change the name of the function that is exported.
Important: Functions created in a library are private to that library by default. You need
to use the exports keyword to make the function available to scripts calling the library.
Tip: If you don’t see a function you are expecting in the Functions Explorer check that the
function has been exported and that the library does not contain any syntax errors.
8. Fill out the fields in the Scripting Studio Tools and Settings:
a. Select the user that the script will run for ‘In testing’ state, see Testing and Debugging.
b. Select any libraries referenced by this library.
c. Use the Code revision comments to comment the script changes made.
d. Click SAVE.
Note: The act of saving a script in the ”Inactive” state will move the script to the ”In testing”
state, see Scripting Workflow.
Important: You cannot deploy a script that references a library that is not deployed.
User Scripting
Scripting Center 32
2. Reference the library either from the Scripting Center Manage libraries or from the Scripting Studio
Tools and Settings.
3. Use the library in the script.
Creating Parameters
Script Parameters are accessed from the Parameters tab of the Scripting Center. Parameters can be
used by form, scheduled, and library scripts. Parameters are automatically available when form and / or
scheduled scripts are enabled, see Scripting Switches.
Parameters have account wide scope, changing the value for a parameter will affect all scripts using that
parameter.
References to parameters can be set from the Scripting Center Manage parameters or from the Scripting
Studio Script Parameters section.
To create a parameter:
User Scripting
Scripting Center 33
Note: You cannot delete a parameter or change the name of a parameter that is
Referenced by a script.
c. Click on the Referenced by script to open the script in the Scripting Studio.
To use a parameter:
4. Administrators can change the script values from the calling script in the Scripting Center.
User Scripting
Scripting Center 34
Important: A parameter can be referenced by more than one script. Changing the
value affects all scripts referencing the parameter. Form, scheduled, and library scripts can
reference parameters.
Creating Solutions
Platform solutions are accessed from the Solutions tab of the Scripting Center. Solutions can be created
for form, scheduled, and library scripts. Solutions can also be used to create custom fields, script libraries,
and script parameters. Solutions are automatically available when form and / or scheduled scripts are
enabled, see Scripting Switches.
Solutions are stored in XML files so you can read, transfer, archive, and compare them. Solutions contain
a version tag to allow SuiteProjects Pro to check that the solution file is compatible before applying.
A log is created when a solution is applied to show exactly what the solution created and to record any
errors.
Tip: Add the “Solutions” column on the “Form” or “Scheduled” lists to see which scripts are
contained in a solution.
Solution Status
A solution can be in one of three states:
User Scripting
Scripting Center 35
Solutions create a log when they are applied to an account. For ‘Applied’ solutions you can view the log to
see which objects (scripts or parameters) the solution created. For ‘Failed’ solutions you can also see the
errors that occurred when the solution was applied.
Solution Actions
■ Apply — Creates all objects specified in the solution and creates a log file. If successful the solution
status changes to ‘Applied’. If unsuccessful an error message is displayed and the solution status
changes to ‘Failed’. See To apply a platform solution:.
Note: This action is only available for solutions with the ‘Not applied’ status.
■ Delete — Deletes the solution with all its history and logs.
Important: This does not delete any objects created by the solution.
To create a solution:
Note: You only need to select additional custom fields and parameters. When you select a script,
the solution will automatically pull in the script’s required libraries and parameters. SuiteProjects
Pro ignores duplicate selections.
User Scripting
Scripting Center 36
Note: Make sure you have the necessary switches enabled, see Scripting Switches.
2. Go to the Form, Scheduled, or Library script you want to create the solution for.
3. Select the Export solution option from the script status menu.
Note: You can create a solution for any script that is not ‘Inactive’. See Scripting Workflow.
4. Enter the name, title, and description for the solution file and SAVE.
Tip: The solution will contain all library scripts and parameters referenced by the script. To create
a solution without a certain reference, first remove the reference from the script and then create
the solution.
Accessing Terminology
Remember, all terminology can be customized to meet the unique needs of your company, see Script
Terminology. You can allow for changes in terminology by using terminology phrases in your script.
A terminology phrase takes the form "%project%" which is the internal ID for the term surrounded by ‘%’
characters. Use the Terminology section in the Scripting Studio to lookup the internal identifiers to use.
Notice that there are two forms for a term. For example, project and A_project. The second form will
return the correct indefinite article (a/an) required for the term.
User Scripting
Scripting Center 37
■ NSOA.context.getAllTerms()
■ NSOA.context.getTerm(termid)
■ NSOA.context.parseTerminology(message)
■ NSOA.form.error(field, message)
■ NSOA.meta.alert(message)
■ NSOA.meta.log(severity, message)
1. Administrator set account terminology from Administration > Global Settings > Display > Interface:
Terminology.
Note: You only need to enter the replacement term in its singular form. SuiteProjects Pro
automatically generates the plural term where applicable.
3. Users see the messages displayed with the correct account terminology.
User Scripting
Scripting Studio 38
Scripting Studio
The Scripting Studio is accessed by clicking on a script link in the Scripting Center.
From the Scripting Studio a script developer can quickly create scripts with a full-screen editor supported
by intuitive tools with drag-and-drop:
You can view any log messages the script has generated by clicking on the View Log link at the top—left
of the editor, see also Testing Form Scripts
User Scripting
Scripting Studio 39
■ Association — An individual script can only be associated with one form and this is set when the
script is created. The same script cannot be triggered by two different forms or even form events. An
individual form may trigger as many scripts as necessary.
■ Employee — This is the user that will test the script, see Testing and Debugging for more details.
■ References — Select the libraries that are used by this script.
■ Event — This is the event that will trigger the script to run, see Events.
■ Entrance function — This is the name of the function to run, see Entrance Function.
■ Code revision comments — These are optional notes that the developer can add.
User Scripting
Scripting Studio 40
SOAP Explorer
From the SOAP explorer you can browse through the SOAP API objects and attributes, and view examples
of usage. Select a SOAP object, then select an attribute to view a code example using information for that
object and attribute.
You can drag and drop code examples directly into the editor. See also the Auto List & Complete feature.
User Scripting
Scripting Studio 41
Functions Explorer
The functions explorer acts as an online cheat sheet showing the syntax for all the available NSOA
functions and for any selected library. Select a function to view an example of usage.
You can drag and drop code examples directly into the editor. See also the Auto List & Complete feature.
OData Explorer
Use the OData explorer to browse your published reports and lists, and the columns available in these
resources. Select the resource type (published list or published report), the resource, and the column, to
view a code example using information in that resource and column. Select and drag the code example
into the editor pane to use the snippet in your script.
The OData explorer shows both the OData resource ID and the saved list or saved report title. This helps
you identify and reference the correct OData resource by ID directly from the scripting studio.
See also Business Intelligence Connector and the following user scripting functions:
User Scripting
Scripting Studio 42
Note: This functionality is available only if the Business Intelligence Connector feature is enabled
for your account. The Business Intelligence Connector feature is a licensed add-on. To enable this
feature, contact your SuiteProjects Pro account manager.
For more information about publishing lists and reports to the SuiteProjects Pro OData service,
see Business Intelligence Connector.
Script Parameters
From the script parameters section you can see all the parameters available in the account and select
parameters used in the script.
User Scripting
Scripting Studio 43
Click on a selected parameter to see an example. You can drag and drop code examples directly into the
editor.
Note: Referencing a parameter prevents the parameter from being deleted or changed in a way
that will affect the script. See also the Auto List & Complete feature.
Terminology
From the terminology section you can browse through all the terminology available in SuiteProjects Pro
and see the terms set for the current account.
Select a term to see an example. You can drag and drop code examples directly into the editor.
Form Schema
The Form schema allows you to explore the form you are creating the script for. This provides vital
information as you need to know the names of the fields and the structure of the objects so you can
reference them in your scripts.
The Fields drop-down list at the top gives a complete list of the available fields on the form. You can select
between View by param or View by label by clicking on the link.
■ If View by label is selected (default), each entry in the drop-down list has the following format:
Label [Field] <Data Type>
User Scripting
Scripting Studio 44
□ Budget_time is the field name you need to use when calling NSOA Functions.
□ Budget (hours) is the label the user sees on the form.
□ Number is the internal data type JavaScript will use for a variable created for this field. See
Dynamic Data Types.
Tip: If you have added a new custom field and this is not listed in the Form schema, open the
form with the new custom field to refresh the custom field list, and then open the Scripting Studio
again. See Custom Fields for more details.
Note: When editing a form script associated with the Receipt form, the hidden fields Receipt
subtype [subtype] <String> and Envelope [envelope_id] <Number> are available in addition to
the fields visible on the form:
■ The subtype field indicates whether the receipt is a Mileage receipt , a regular Receipt or
Foreign currency receipt. The receipt subtype is determined by the type of the associated
expense item.
□ The function NSOA.form.getValue(‘subtype’) will return a string with the value ‘M’ if it is a
Mileage receipt, and ‘R’ otherwise (regular Receipt or Foreign currency receipt.
□ The functions NSOA.form.getOldRecord() and NSOA.form.getNewRecord() will return an
object of type oaTicket with the associated expense item referenced by ID oaTicket.item_id.
You can also use the item type field oaItem.type to determine the subtype of a receipt.
■ The envelope_id field is the ID of the envelope the receipt is associated to.
□ The function NSOA.form.getValue(‘envelope_id’) will return the envelope ID.
□ The functions NSOA.form.getOldRecord() and NSOA.form.getNewRecord() will return an
object of type oaTicket with the associated envelope referenced by ID oaTicket.envelopeid.
When you select a field from the drop down list the Data structure/types & Examples area is filled.
The Data structure/types & Examples area has two text fields.
User Scripting
Scripting Studio 45
The text field on the left shows the data type or data structure (if the data type is an object) for the field.
See Object Fields.
The text field on the right shows correctly formatted code samples using the NSOA functions for the
selected field. You can directly copy and paste these samples into your script. See Object Fields.
Object Fields
Fields with the Object type expose properties that allow you to access their internal data structure.
For example, consider the Loaded hourly cost form section.
All these fields are exposed through one loaded_cost field <Object>.
Notice the way the Loaded hourly cost fields map to the data structure you need for your script.
User Scripting
Scripting Studio 46
The data structure has three blocks that correspond to the three rows of fields in Loaded hourly cost
form section.
1. First you need to get the object variable for the field:
2. Then you can use the object variable to get the value:
Each row in the data structure is accessed in the same way as an array, that is, loaded_cost_obj[0] is this
first row. Each column of the row is accessed by the field name that is loaded_cost_obj[0].cost_0 is the
“Primary loaded cost” for the first row.
This is referencing "loaded_cost" in the same way as a simple field and then using [0].cost_0 to view the
required property of the returned object.
From the Scripting Studio Tools and Settings you must specify a test user. You can determine if your script
is running in Test mode within your script by calling NSOA.context.isTestMode().
Tip: Calls to NSOA.meta.log(severity, message) with a “debug” or “trace” severity are only
executed in Test mode and do not consume Scripting Governance units but are limited to a
maximum of 1000 per script.
If you are seeing a problem that is only happening with a particular user you can select that user to be the
one that the test code runs for.
User Scripting
Scripting Studio 47
Note: The named user will also be able to access error debug detail.
For more information about Testing & Debugging, see Testing Form Scripts.
Editor
Editor Features:
■ Auto List & Complete — Type ‘.’ after “NSOA” and the Auto List window appears showing all the
available options, see Auto List & Complete.
■ Color coding — Keywords, variables, literals, comments, etc. are highlighted in different colors to aid
correct coding.
■ Line numbers — Line numbers are listed in the left margin to assist in development and debugging.
■ Line highlighting — The line the cursor is on is highlighted to assist in editing the code.
■ Syntax checking — Errors and warning are displayed as you type into the editor.
■ Bracket completion — If you type an opening bracket the matching closing bracket is automatically
created.
■ Matching brackets If you place your cursor next to a bracket then the matching brackets are
highlighted
■ Full-screen — Click into the editor and press <Ctrl> + F11 to full-screen the script editor
User Scripting
Scripting Studio 48
While working in full-screen mode you can still continue using the Auto List & Complete feature.
Press Esc to exit full-screen mode and save your changes in the usual way.
■ Search and Replace Functions — Search through scripts using simple or regexp search expressions.
Use the following key shortcuts for searches within the Script Editor:
□ Start a Search — Ctrl+F / Cmd+F
□ Find Next — Ctrl+G / Cmd+G
□ Find Previous — Shift+Ctrl+G / Shift+Cmd+G
□ Replace — Shift+Ctrl+F / Cmd+Option+F
□ Replace All — Shift+Ctrl+R / Shift+Cmd+Option+F
These shortcuts can also be found in the Tips menu from within the Script editor.
You can use regexp to search for more complex strings. For example, entering /envelope|ticket/ in
the search field searches for both “envelope” and “ticket”.
After a search dialog is opened, press Escape to exit it without searching.
■ Jump to Line Functions — You can move through your scripts quickly by entering Jump to Line
functions. Press Alt+G to open the Jump to Line dialog. Then, enter the script line you want to move
the cursor to. The following input formats are accepted:
□ Line — enter the line to move the cursor to. For example, entering 25 in the Jump to Line field
moves the cursor to line 25
□ Line:column — enter both the line and column separated by a colon. For example, entering 25:9
moves the cursor to line 25, column 9.
□ +/-Line — enter how many lines forward or backward to move your cursor. For example, if the
cursor is at line 5, and you enter +5 into the Jump to Line field, the cursor moves to line 10.
□ Scroll% — enter a percent of the document to move the cursor to. For example, entering 50%
in the Jump to Line field moves the cursor 50%, to the middle of the script. Add + or _ to the
User Scripting
Scripting Studio 49
percentage to move forward or backward. For example, if the cursor is at the end of the script, —
50% moves the cursor backward to the middle of the script.
After the Jump to Line dialog is opened, press Esc to exit it without moving the cursor.
■ Click on the required item with the mouse and double-click to select it.
■ Use the up and down arrow keys to select the required item and then hit ‘Enter’ to select it.
■ Type the first character of the required item (for example ‘m’) to highlight it and then hit ‘Enter’ to
select it. If more than one item starts with the same letter then the first item will be highlighted and
the list of options filtered.
■ Hit ‘Esc’ to close the Auto List window and type as normal. Clicking outside of the editor window will
also close the Auto List window.
Tip: Press <Ctrl> + <Space> to show the Auto List window at any point in the editor.
On selecting an item from the Auto List window, the value will be copied into the editor and typing
continues after the inserted value.
Tip: Auto List & Complete is enabled by default. You can change your settings from User Menu
> Personal settings.
■ Editor Theme — choose from a variety of color schemes for the script editor
■ Indent Unit — select whether an indent unit is a space or a tab in the script editor
■ Font Size — select the size of the text font in the script editor
■ Tab Size — set how many spaces a tab uses in the script editor
User Scripting
Scripting Studio 50
Entrance Function
An Entrance function serves as the starting point in your script. For more on functions see Functions.
The Entrance function is associated with a form event in the Scripting Studio Tools and Settings options,
see Events.
Note: The Entrance function field value is the name of the function without parenthesis (or
parameter, if used).
User Scripting
Entrance Function 51
■ ‘unapprove’ — this is passed when a record is unapproved, and is supported by bookings, booking
requests, expense reports, invoices, purchase orders, purchase requests, schedule requests, and
timesheets.
Note: To enable the Unapprove type, contact SuiteProjects Pro Support and ask them to
enable the “Enable user scripts to use an unapproval context in the after approval event”
switch.
The type value will be the same regardless of the form Event. For example, if you call your entrance
function on “After save” when creating a new form you will still be passed a type value of ‘new’.
Events
Scripts are triggered by events. The required Event is specified in the Scripting Studio Tools and Settings
options.
You should select the Event according to the purpose of the Entrance Function, see the diagram below.
User Scripting
Events 52
Note: Only forms that can take part in an approval process receive approval events.
■ On submit — Always executed. This is the first event that occurs when the user click SAVE.
■ Before save — Always executed. This is where you should check that any special conditions on the
form are valid and raise form errors if required by calling NSOA.form.error(field, message).
Note: The record does not exist in the database at this stage so you can’t call wsapi functions
to change any of the record values.
■ After save — Executed if no form errors are raised. This is where you should call wsapi functions to
modify the data held on this or related records.
■ Before approval — This is where you can perform additional checks and prevent a record from being
sent for approval by calling NSOA.form.error(field, message).
■ After approval — This is where you can perform additional actions following a record approval or
reject.
User Scripting
Events 53
Note: The SuiteProjects Pro Mobile app does not support “On submit,” “Before save,” or “After
save” scripts associated with the timesheet entity form.
■ All form scripts associated with the expense report and receipt entity forms.
■ "Before approval" and "After approval" scripts associated with the timesheet entity form.
For an example of script that is executed both in SuiteProjects Pro and SuiteProjects Pro Mobile,
see
Important: Form scripts may be triggered by an event associated with user interaction —
when a user clicks Save, for example.
Form scripts can also be triggered by an event associated with a process utilizing the form
software logic — when importing project records from NetSuite using the NetSuite integration,
for example, depending on the integration configuration. For more information, see Scripting and
NetSuite Integration.
Scripting Governance
To prevent scripts from consuming excessive resources or running out of control, limitations are placed
on scripts:
■ Time Limit — If a form script runs for more than 5 seconds (not including wsapi call time) it is
automatically terminated with a form error. If a request (all scripts triggered by the same form save)
uses more than 60 seconds of wsapi time it will also be automatically terminated.
Note: Scheduled scripts are allowed 1 hour of JS runtime and 1 hour of wsapi.
■ Units Limit — NSOA functions are assigned a unit value. Each time an NSOA function is called its unit
value is consumed. A script is allowed to consume a maximum of 1000 units with each run before it is
automatically terminated with a form error. You can determine how many units you have remaining by
calling NSOA.context.remainingUnits(). See the table below for the unit value of each NSOA function.
■ SendMail Limit — Additional limits are placed on the NSOA.meta.sendMail(message) function. Form
Scripts are allowed to send a maximum of 3 emails. Scheduled Scripts are allowed to send a maximum
of 100 emails. The email subject is trimmed to the first line passed.
User Scripting
Scripting Governance 54
Important: There is a maximum body length set for your emails sent by form and
scheduled scripts. Email messages with bodies above that maximum body length are not sent.
The maximum body length is set to 30,000 characters by default and can be changed to suit
your requirements. To review or to increase the maximum body length set for your account,
contact SuiteProjects Pro Support.
■ NSOA.context.getParameter(name) 1
■ NSOA.form.confirmation(message)
■ NSOA.form.error(field, message)
■ NSOA.form.getLabel(field)
■ NSOA.form.getName(field)
■ NSOA.form.getNewRecord()
■ NSOA.form.getOldRecord()
■ NSOA.form.getValue(field)
■ NSOA.form.get_value(field)
■ NSOA.form.warning(message)
■ NSOA.listview.list()
■ NSOA.report.list()
■ NSOA.wsapi.disableFilterSet( [ flag] )
■ NSOA.wsapi.enableLog( [ flag] )
■ NSOA.wsapi.whoami()
■ NSOA.context.parseTerminology(message) 4
■ NSOA.meta.alert(message)
Note: Calls to NSOA.meta.log(severity, message)
■ NSOA.meta.log(severity, message)
with the severity parameter set to “debug” or “trace”
do not consume units but are limited to a maximum
of 1000 per script.
■ NSOA.context.getAllParameters() 10
■ NSOA.context.getAllTerms()
■ NSOA.form.getAllValues()
■ NSOA.https.get(request)
■ NSOA.https.post(request)
■ NSOA.https.put(request)
■ NSOA.https.patch(request)
■ NSOA.https.delete(request)
■ NSOA.meta.sendMail(message)
■ NSOA.NSConnector.integrateRecord()
User Scripting
Scripting Governance 55
■ NSOA.wsapi.read(readRequest) 20
■ NSOA.wsapi.add(objects) +10 for each additional object passed.
■ NSOA.wsapi.delete(objects)
■ NSOA.wsapi.submit(submitRequest)
■ NSOA.wsapi.approve(approveRequest)
■ NSOA.wsapi.reject(rejectRequest)
■ NSOA.wsapi.unapprove(unapproveRequest)
■ NSOA.wsapi.modify(attributes, objects) 40
■ NSOA.wsapi.upsert(attributes,objects) +20 for each additional object passed.
■ NSOA.NSConnector.integrateAllNow() 1000
■ NSOA.NSConnector.
integrateWorkflowGroup(name)
SOAP API
User scripting provides access to the SOAP API (Web Services) through the NSOA.wsapi functions, see
NSOA Functions. Before you begin using these functions, consult the API documentation. See XML
API & SOAP API.
User Scripting
SOAP API 56
Important: You should review API Best Practice Guidelines carefully before you start using
NSOA.wsapi functions.
Tip: All SuiteProjects Pro Complex types start with “oa”, for example “oaCategory”. You can look
up the SuiteProjects Pro Complex Types and their properties from the SuiteProjects Pro WSDL
available from the following URL https://<account-domain>/wsdl.pl.
If you strip away the “oa” you are left with the table name, for example “Issue”. You can look up
tables in the SuiteProjects Pro Data Dictionary. To access the SuiteProjects Pro Data Dictionary,
use the link in the navigation bar of the SuiteProjects Pro Help Center or use the following URL
https://<account-domain>/database/single_user.html.
Note: You need the Enable user script support for Web Service API methods switch enabled
to use the NSOA.wsapi functions, see Scripting Switches.
Tip: Scripts are executed within the context of a user. This means that the user filter sets for the
signed in user will be applied unless disabled, see NSOA.wsapi.disableFilterSet( [ flag] ).
■ You pass in an array of SuiteProjects Pro Complex Type objects as a parameter. An error will be
returned if the array contains more than 1000 objects.
Note: You create a complex type object with the NSOA.record.<complex type>( [id] ) function.
For the list of supported object types, see the help topic XML and SOAP API Business Object
Reference.
■ Some functions also require an array of Attribute objects as the first parameter.
■ Functions return either an object or array of objects:
□ NSOA.record.<complex type>( [id] ) returns a SuiteProjects Pro Complex Type object.
□ NSOA.wsapi.read(readRequest) returns an array of ReadResult objects.
□ NSOA.wsapi.add(objects), NSOA.wsapi.delete(objects), NSOA.wsapi.modify(attributes, objects), and
NSOA.wsapi.upsert(attributes,objects) return an array of UpdateResult objects.
User Scripting
SOAP API 57
Important: The updated and created fields are maintained automatically by SuiteProjects Pro.
You can read these values, but they cannot be modified.
Tip: It is more efficient to batch a series of objects together into a single SOAP API call rather
than making a separate call for each object. The objects in the array are processed according to
their order in the array.
Adding data
You add data to SuiteProjects Pro by creating one or more SuiteProjects Pro Complex Type objects,
placing them into an array, and passing the array to the NSOA.wsapi.add(objects) function. You
must specify all the required fields for the objects passed. The ID, updated and created fields are set
automatically by SuiteProjects Pro.
// To turn an object into an array of object, simply place it inside square brackets
var objects = [category]; // or just pass [category]
Modifying data
You modify data to SuiteProjects Pro by creating one or more SuiteProjects Pro Complex Type objects,
placing them into an array, and passing the array to the NSOA.wsapi.modify(attributes, objects) function.
In each object passed, you need to specify the internal id and only the properties (fields) in the objects
that you want to change. The updated field is set automatically by SuiteProjects Pro.
2. Fill out the internal ID for the object and the properties you want to change, see Objects.
User Scripting
SOAP API 58
// To turn an object into an array of object, simply place it inside square brackets
var objects = [category]; // or just pass [category]
Deleting data
You delete data from SuiteProjects Pro by creating one or more SuiteProjects Pro Complex Type objects,
placing them into an array, and passing the array to the NSOA.wsapi.delete(objects) function. In each
object passed, you need to specify the internal id.
Important: You cannot delete an entity (database record) that has dependent records. You
must first delete all the dependent records.
category.id = 79;
// To turn an object into an array of object, simply place it inside square brackets
var objects = [category]; // or just pass [category]
Reading data
You read data from SuiteProjects Pro by creating a ReadRequest object and passing it to the
NSOA.wsapi.read(readRequest) function.
User Scripting
SOAP API 59
1. Create a SuiteProjects Pro Complex Type object with the NSOA.record.<complex type>( [id] )
function and fill out the properties for the object to specify the search criteria.
var attribute = {
name : "limit",
value : "0,1000"
}
var readRequest = {
type : "User",
method : "equal to", // return only records that match search criteria
fields : "id, nickname, updated", // specify fields to be returned
attributes : [ attribute ], // Limit attribute is required; type is Attribute
objects : [ user ] // One object with search criteria
}
See also the SOAP API — Prevent closing a project with an open issue code sample.
ReadRequest
The ReadRequest object is used to specify the required data to return in the
NSOA.wsapi.read(readRequest) function.
// example read request - assumes attribute and user objects have been defined
var readRequest = {
type : "User",
method : "equal to", // return only records that match search criteria
fields : "id, nickname, updated", // specify fields to be returned
attributes : [ attribute ], // Limit attribute is required; type is Attribute
objects : [ user ] // One object with search criteria
}
type Any SuiteProjects Pro Complex Type without the oa prefix for example “Issue”.
Note: Use this cautiously as too many records may be requested for the server or client
to handle.
User Scripting
SOAP API 60
fields Comma separated list of fields to be returned for example "id, nickname, updated”.
For more information about supported fields, see the help topic XML and SOAP API Business Object
Reference or the SuiteProjects Pro WSDL available from the following URL https://<account-domain>/
wsdl.pl.
objects Array of SuiteProjects Pro Complex Type objects, see NSOA.record.<complex type>( [id] ).
Attribute
The attribute object is used to set additional criteria in the following NSOA methods:
■ NSOA.wsapi.modify(attributes, objects)
■ NSOA.wsapi.read(readRequest)
■ NSOA.wsapi.upsert(attributes,objects)
var attribute = {
name : "limit",
value : "10"
}
See the table below for valid combinations of name and value.
name value
“limit” A single value (for example “500”) or range (for example “0, 1000”).
Single value: "1", "500", "1000" - simply restricts the number of records returned.
Range: "0, 1000" - the first integer specifies the offset of the first record to return and the
second integer limits the number of records to return.
To request data in consecutive batches, only the first part of the limit attribute should be
incremented - "0,1000", "1000,1000", "2000,1000", etc. Sequence requests should be submitted
until the result comes back empty or has less than 1000 items.
“filter” ■ “newer-than”
■ “not-exported”
■ “older-than”
Note: Options can be placed into a comma separated list, for example "newer-
than,older-than,not-exported".
”update_custom” Set to ”1” to enable the updating of custom fields. See Updating Custom Fields.
User Scripting
SOAP API 61
ReadResult
The NSOA.wsapi.read(readRequest) function returns the ReadResult object.
For example, if the fields to be returned were "id, nickname, updated”, the objects property for the
returned ReadResult object would be:
// example ReadResult object - assumes the fields to be returned were "id, nickname, updated"
[
{
"errors": null,
"objects": [
{
"id": "26",
"nickname": "mcollins",
"updated": "2019-10-03 15:42:23",
"return_fields": {
"id": "1",
"nickname": "1",
"updated": "1"
}
},
{
"id": "33",
"nickname": "jadmin",
"updated": "2019-09-03 09:12:46",
"return_fields": {
"id": "1",
"nickname": "1",
"updated": "1"
}
}
]
}
]
Property Value
objects Array of Complex Type objects, each with the following properties:
■ One property for each field to be returned as listed in the ReadRequest object. Each property has:
□ key: field_name — name of the field to be returned
□ value: field_value — returned field value
■ return_fields — object with the following properties for each field to be returned:
□ key: field_name — name of the field to be returned
□ value: 1
UpdateResult
Thefollowing functions return the UpdateResult object.
User Scripting
SOAP API 62
■ NSOA.wsapi.add(objects)
■ NSOA.wsapi.delete(objects)
■ NSOA.wsapi.modify(attributes, objects)
■ NSOA.wsapi.upsert(attributes,objects)
Property Value
■ For calls to NSOA.record.<complex type>( [id] ), only check that an object was returned.
■ For all other calls you need to check that a result was returned and did not contain any errors.
This is a two step process:
□ First check that you have an array of responses.
if (!result || !result[0])
□ If OK, then check if you have an errors property and you have at least one error.
oaError
An array of oaError objects is returned in the ReadResult and UpdateResult objects.
User Scripting
SOAP API 63
Note: In this version, only the code property is available from user script.
Property Value
Tip: For the full list of errors, see the help topic Error Codes.
Who Am I
You can get information about the currently signed in user by calling the NSOA.wsapi.whoami() function.
function test() {
var user = NSOA.wsapi.whoami();
NSOA.meta.alert( "User ID " + user.id + " saved this record");
}
oaUser
The oaUser object has more than 100 attributes defining user specific information. See User.
Outbound Calling
User Scripting
Outbound Calling 64
User scripting enables calls to external APIs through the NSOA.https functions, see NSOA Functions. Calls
to REST, XML and SOAP APIs are supported.
Note: You need the Enable user script support for https methods switch enabled to use the
NSOA.https functions, see Scripting Switches.
The following request methods are currently supported for form and scheduled scripts:
The functions take the Request object as a single parameter and return the Response object.
Request
The request object is used to set the request parameters.
url string required The HTTPS URL being requested. Parameters can be passed
as part of the URL using a query string.
body array|object|string optional The data passed to the server. If the data is passed as an
array or object, it will be JSON serialized and URL encoded
automatically. Nested arrays and objects are supported. If
the data is passed as a string, it must be encoded correctly
by the user.
headers object optional The HTTPS headers. The MIME type is set automatically to
application/json when body is an array or object.
Response
NSOA.https functions return the response object.
Limits
The following limits apply to all NSOA.https functions:
User Scripting
Outbound Calling 65
■ The requested URL must use the HTTPS protocol and the server certificate must be validated.
■ The functions will follow redirects up to a maximum of 7.
■ If the client doesn’t start receiving a response from the server within 45 seconds of the request being
fully sent, a connection timeout occurs. If the request times out, a response object is returned with a
standard HTTP Status Code (500) and a "Client-Warning" header set.
■ The response must not exceed 1MB in size.
■ The functions use 10 units per call. See Scripting Governance.
The value is hidden both on the form used to set the parameter value and in the parameters list.
You can use the NSOA.context.getParameter(name) function to read the value for the specified password
parameter in your outbound calling scripts.
■ Parameters need to be referenced before they can be used in a given script. This is done from
the Scripting Studio.
■ Password script parameter definitions may be saved as part of a platform solution. See
Creating Solutions.
Scripting Approvals
You can use scripts to submit, approve, reject, and unapprove bookings, timesheets, invoices, and
envelopes in SuiteProjects Pro. The approvals workflow is shown below:
User Scripting
Scripting Approvals 66
submitRequest
The NSOA.wsapi.submit(submitRequest) function takes an array of up to 1000 submitRequest objects.
Each submitRequest object contains an oaBooking, oaTimesheet, oaEnvelope, or oaInvoice object to
submit and additional approval process information passed to an oaApproval object.
approval oaApproval
approveRequest
The NSOA.wsapi.approve(approveRequest) function takes an array of up to 1000 approveRequest objects.
Each approveRequest object contains an oaBooking, oaTimesheet, oaEnvelope, or oaInvoice object to
approve and additional approval process information passed to an oaApproval object.
User Scripting
Scripting Approvals 67
approval oaApproval
rejectRequest
The NSOA.wsapi.reject(rejectRequest) function takes an array of up to 1,000 rejectRequest objects. Each
rejectRequest object contains an oaBooking, oaTimesheet, oaEnvelope, or oaInvoice object to submit and
additional approval process information passed to an oaApproval object. The rejectRequest object is
used to specify the required data to return in the NSOA.wsapi.reject(rejectRequest) function.
approval oaApproval
unapproveRequest
The unapproveRequest object is used to specify the required data to return in the
NSOA.wsapi.unapprove(unapproveRequest) function.
User Scripting
Scripting Approvals 68
approval oaApproval
ApprovalResult
The following functions return the ApprovalResult object.
■ NSOA.wsapi.submit(submitRequest)
■ NSOA.wsapi.approve(approveRequest)
■ NSOA.wsapi.reject(rejectRequest)
■ NSOA.wsapi.unapprove(unapproveRequest)
Property Value
■ “O” — Open
■ “S” — Submitted
■ “A” — Approved
■ “R” — Rejected
■ “X” — Archived
User Scripting
Scripting Approvals 69
if (!result || !result[0])
■ If OK, then check if you have an errors property and you have at least one error.
The following example checks for errors when using the NSOA.wsapi.approve(approveRequest) function:
Custom Fields
User Scripting
Custom Fields 70
12. If you check the box for Add Notes, a text box displays under the custom field for employees to add
any additional notes.
13. If you check the box for Divider, a divider line displays before the custom field. You can also type
Divider text that displays in the Divider Line.
Note: You may want to use Divider lines when you are defining a new section that needs
to stand out on the form. For example, a series of custom fields defining a topic such as
contract management may start with a Contract received box. The divider line indicates the
start of the contract management fields.
14. Click Save. After you save the form, a Position field displays. Position determines the order of the
custom field on the entity's form. To change the position, adjust the value using the drop-down list
and click Save.
See the Administrator Guide for more details on creating customer fields.
Tip: If you have added a new custom field and this is not listed in the Form Schema of the
Scripting Studio, open the form with the new custom field to refresh the custom field list, and then
open the Scripting Studio again.
User Scripting
Custom Fields 71
Note: This custom field is referred to in the code examples that follow.
You can read the custom field value and label in the same way as for standard fields.
// Read the date value and log the value if the date is not empty
function logReviewDate(){
var reviewDate = NSOA.form.getValue('ReviewDate__c');
if( reviewDate !== null ) {
NSOA.meta.alert(reviewDate.toString());
}
}
Note: The old approach to reading custom fields using custom_ with the internally assigned
custom field number appended is d. Use the custom fields name followed by __c (underscore
underscore c) instead.
User Scripting
Custom Fields 72
1. Create a SuiteProjects Pro record object with the NSOA.record.<complex type>( [id] ),
NSOA.form.getNewRecord() or NSOA.form.getOldRecord() functions.
2. The custom field name is the Field name defined for the custom field with the special ‘__c’ suffix
appended to identify it as a custom field.
3. Use the name to access the custom field value in the record object.
Important: It is not possible to rename, change, or delete a custom field which is being used
by an active script. This prevents unintended script problems.
1. Create a SuiteProjects Pro record object with the NSOA.record.<complex type>( [id] ),
NSOA.form.getNewRecord() or NSOA.form.getOldRecord() functions.
2. Use the correct name format for the custom field, that is Field name defined for the custom field +
‘__c’.
var attribute = {
name : 'update_custom',
value : "1"
}
User Scripting
NSOA Functions 73
NSOA Functions
The following functions are provided to allow you to interact with SuiteProjects Pro:
■ NSOA.context
□ NSOA.context.getAllParameters()
□ NSOA.context.getAllTerms()
□ NSOA.context.getLanguage()
□ NSOA.context.getParameter(name)
□ NSOA.context.getTerm(termid)
□ NSOA.context.isTestMode()
□ NSOA.context.parseTerminology(message)
□ NSOA.context.remainingTime()
□ NSOA.context.remainingUnits()
■ NSOA.form
User Scripting
NSOA Functions 74
□ NSOA.form.confirmation(message)
□ NSOA.form.error(field, message)
□ NSOA.form.getAllValues()
□ NSOA.form.getLabel(field)
□ NSOA.form.getName(field)
□ NSOA.form.getNewRecord()
□ NSOA.form.getOldRecord()
□ NSOA.form.getValue(field)
□ NSOA.form.get_value(field)
□ NSOA.form.setValue(field, value)
□ NSOA.form.warning(message)
■ NSOA.https
□ NSOA.https.delete(request)
□ NSOA.https.get(request)
□ NSOA.https.patch(request)
□ NSOA.https.post(request)
□ NSOA.https.put(request)
■ NSOA.listview
□ NSOA.listview.data(listviewId)
□ NSOA.listview.list()
■ NSOA.meta
□ NSOA.meta.alert(message)
□ NSOA.meta.log(severity, message)
□ NSOA.meta.sendMail(message)
■ NSOA.NSConnector
□ NSOA.NSConnector.integrateAllNow()
□ NSOA.NSConnector.integrateRecord()
□ NSOA.NSConnector.integrateWorkflowGroup(name)
■ NSOA.record
NSOA.record.<complex type>( [id] )
■ NSOA.report
□ NSOA.report.data(reportId,optionalParameters)
□ NSOA.report.list()
■ NSOA.wsapi
□ NSOA.wsapi.add(objects)
□ NSOA.wsapi.approve(approveRequest)
□ NSOA.wsapi.delete(objects)
□ NSOA.wsapi.disableFilterSet( [ flag] )
□ NSOA.wsapi.enableLog( [ flag] )
□ NSOA.wsapi.modify(attributes, objects)
User Scripting
NSOA Functions 75
□ NSOA.wsapi.read(readRequest)
□ NSOA.wsapi.reject(rejectRequest)
□ NSOA.wsapi.remainingTime()
□ NSOA.wsapi.submit(submitRequest)
□ NSOA.wsapi.unapprove(unapproveRequest)
□ NSOA.wsapi.upsert(attributes,objects)
□ NSOA.wsapi.whoami()
NSOA.context.getAllParameters()
Use this function to get an Associative Array of all the script parameters and values set for the script.
Parameters
(none)
Returns
An Associative Array of all the script parameters and values for the script.
Units Limit
10 units
Since
April 18, 2015
Example
This example creates a local variable called allParams with an Associative Array of all the script
parameters and values for the script. It then uses a for in loop to log each parameter name and current
value.
See NSOA.meta.alert(message).
User Scripting
NSOA Functions 76
NSOA.context.getAllTerms()
Use this function to get an Associative Array of all the terminology identifiers and values set for the
account.
Parameters
(none)
Returns
An Associative Array of all the terminology identifiers and values for the account.
Units Limit
10 units
Since
April 18, 2015
Example
This example creates a local variable called allTerms with an Associative Array of all the terminology and
values for the account. It then uses a for in loop to log each term and current value.
NSOA.context.getLanguage()
Use this function to get the user’s display language preference. You can then adapt your form scripts
according to the user’s language preference and show translated versions of the same message, for
example.
Parameters
(none)
User Scripting
NSOA Functions 77
Returns
A two-character string — the ISO 639–1 two-letter code for the language selected in the authenticated
users’s personal settings, or xx, if the Show language keys view option is in use.
Note: If the Multilanguage feature is not enabled, the function returns en.
Chinese (Simplified) zh
Czech cs
English en
French fr
German de
Japanese ja
Spanish es
Units Limit
0 units
Since
April 9, 2022
Example
This example creates a local variable called lang with the user’s language preference. It then uses
conditional branching to display a message in the user’s preferred language.
if (lang == 'cs') {
// display messages in the Czech language"
}
if (lang == 'en') {
// display messages in the English language"
}
NSOA.context.getParameter(name)
Use this function to get the value set for the specified parameter.
User Scripting
NSOA Functions 78
Parameters
name {string} [required] — The name of the parameter.
Note: Use the Script Parameters section in the Scripting Studio or the Scripting Center to lookup
the parameter name to use.
Returns
The value of the specified parameter.
Units Limit
1 unit
Since
April 18, 2015
Example
This example shows a field value being checked against a parameter value.
NSOA.context.getTerm(termid)
Use this function to get the term used for the specified terminology identifier.
Parameters
termid {string} [required] — The internal identifier for the term.
Note: Use the Terminology section in the Scripting Studio to lookup the parameter names to
use.
Returns
The term used for the specified terminology identifier.
User Scripting
NSOA Functions 79
Units Limit
0 units
Since
April 18, 2015
Example
This example shows what would be returned if the account terminology had redefined project to job.
NSOA.context.isTestMode()
Use this function to determine if the script is being run in test mode.
Parameters
(none)
Returns
Boolean true if the script is running in test mode and false otherwise.
Units Limit
0 units
Since
November 16, 2013
Example
This example shows some code that only runs in “Test mode”, for example an assertion.
User Scripting
NSOA Functions 80
NSOA.context.parseTerminology(message)
Use this function to convert a string containing terminology phrases (terminology identifiers surrounded
by ‘%’ characters) into a string using the correct terminology set for the account.
Parameters
message {string} [required] — The message containing terminology phrases to replace with terms used in
the account.
Returns
The passed string with all the terminology phrases replaced by the terms used in the account.
Units Limit
4 units
Note: Calls to NSOA.meta.log(severity, message) with the severity parameter set to “debug” or
“trace” do not consume units but are limited to a maximum of 1000 per script.
Since
April 18, 2015
Example
This example shows what would be returned if the account terminology had redefined project to job.
NSOA.context.remainingTime()
Use this function to determine how much time your script has remaining to execute (excluding wsapi call
time) before it is terminated by Scripting Governance.
You can use this function to help you create more efficient scripts and also to take corrective action if a
script is at risk of consuming excessive resources.
Parameters
(none)
User Scripting
NSOA Functions 81
Returns
Amount of time remaining allowed for the script to execute in milliseconds (excluding wsapi call time).
Tip: Always try to reduce the amount of time your scripts take to execute.
Units Limit
0 units
Since
October 18, 2014
Example
This example logs the amount of time remaining for the script to execute in milliseconds (excluding wsapi
call time).
NSOA.context.remainingUnits()
Use this function to determine how many units your script has left before it will be halted by SuiteProjects
Pro. Each script is allowed to consume a maximum of 1000 units.
Parameters
(none)
Returns
The number of units remaining.
Tip: Always try to reduce the number of units your scripts consume. Notice that NSOA.record
functions consume zero units, but NSOA.wsapi functions consume 10 units for each call.
Units Limit
0 units
User Scripting
NSOA Functions 82
Since
August 17, 2013
Example
This example displays the number of units consumed at the top of the form as an error message when
executing a from scripts.
NSOA.form.confirmation(message)
Use this function to print a confirmation message on the form. The message that appears will look exactly
like the system-generated confirmation messages.
Note: This function will only have an affect on the After save and After approval events, see
Events.
Parameters
message {string} [required] — The confirmation message to display on the form.
Note: This message will be displayed instead of the system-generated confirmation message for
the form.
Returns
True if the function was successful and false otherwise.
Units Limit
1 unit
Since
October 17, 2015
User Scripting
NSOA Functions 83
Example
This example displays the confirmation message 'A confirmation message' at the top of the form after the
form is saved.
NSOA.form.error(field, message)
Use this function to print an error message associated to the selected form field on the form. The first
argument is the field name on the form where you want the message to show up. The message that
appears will look exactly like the system-generated errors.
Note: The is function has no affect on the After save form event, see Events.
Parameters
■ field {string} [required] — The name of the field on the form to display the error next to, or an empty
string to display the message at the top of the form.
Note: This is not the label the user sees displayed next to the field on the form. Use the Form
Schema to find the correct field name value.
Returns
True if the function was successful and false otherwise.
Units Limit
1 unit
Since
August 17, 2013
Example
■ This example displays the error message 'An error message' next to the budget_time field.
User Scripting
NSOA Functions 84
■ This example displays the error message 'An error message' at the top of the form.
NSOA.form.getAllValues()
Use this function to get an Associative Array of all the fields and values on the form. Keep in mind, any
pick lists (for example Customer:Project, Employee, Expense item) will return an internal_id and not a text
value. In this release, only fields directly related to the form are available (for example no related table
lookups are available now). See also NSOA.form.getValue(field).
User Scripting
NSOA Functions 85
Parameters
(none)
Returns
An Associative Array of all the fields and values on the form. Use the Form Schema to find the names and
data types returned.
Note: Some fields return an object. See Object Fields for more details.
Units Limit
10 units
Since
August 17, 2013
Example
■ This example creates a local variable called allValues with an Associative Array of all the fields and
values on the form. It then reads the project_name and start_date from the allValues variable.
Note: Some fields return an object. See Object Fields for more details.
■ You can loop through the keys of an associative array with the for in loop.
NSOA.form.getLabel(field)
Use this function to get the label the user sees for a field on the form.
User Scripting
NSOA Functions 86
Parameters
field {string} [required] — The name of the field on the form.
Note: This is not the label the user sees displayed next to the field on the form. Use the Form
Schema to find the correct field name value.
Returns
The text value the users sees for specified field.
Note: Some fields return an object. See Object Fields for more details.
Units Limit
1 unit
Since
August 17, 2013
Example
■ This example gets the label for the date field on the form the script is attached to.
■ This example gets the label for a field that returns an object. See Object Fields for more details.
NSOA.form.getName(field)
Use this function to get the parameter name of the field.
Note: This is generally the same as the field name, that is, the required parameter to call this
function. The function is useful when working with Object Fields.
Parameters
field {string} [required] — The name of the field on the form.
User Scripting
NSOA Functions 87
Note: This is not the label the user sees displayed next to the field on the form. This is the name
of the field displayed in the Form Schema.
Returns
The parameter name needed to refer to this field in user scripts.
Units Limit
1 unit
For more information, see Scripting Governance.
Since
August 17, 2013
Example
■ In this example the name returned is the same as the field name passed in, that is, budget_time.
■ In this example the name is the field name for the row and column specified for the loaded_cost
object. See Object Fields for more details.
NSOA.form.getNewRecord()
Use this function to get the entity record for a form with the newly saved values, for example oaProject.
This function should be called on the After save event, see Events.
See also NSOA.form.getOldRecord().
Parameters
(none)
Returns
SuiteProjects Pro Complex Type object, see NSOA.record.<complex type>( [id] ).
Note: This function will return null if called before the form has been saved.
Units Limit
1 unit
User Scripting
NSOA Functions 88
Since
November 16, 2013
Example
This example modifies the project notes after the project has been saved.
Note: This script would be called on the "After save" event for the Project form
Note: This simple example does not show error checking, see Handling SOAP Errors.
NSOA.form.getOldRecord()
Use this function to get the entity record for a form with the current (not yet saved) values, for example
oaProject.
Tip: An Entrance Function can optionally receive a type string parameter. Check if the value of
this parameter is ‘update’ to determine if the form is being modified.
Parameters
(none)
Returns
SuiteProjects Pro Complex Type object, see NSOA.record.<complex type>( [id] ).
Note: This function will return null if called for a form that is being created.
Units Limit
1 unit
User Scripting
NSOA Functions 89
Since
November 16, 2013
Example
This example checks to see if the project name has been modified.
Note: This simple example does not show error checking, see Handling SOAP Errors.
NSOA.form.getValue(field)
Use this function to get the value of the field on the form. Keep in mind, any pick lists (for example
Customer:Project, Employee, Expense item) will return an internal_id and not a text value. In this release,
only fields directly related to the form are available (for example no related table lookups are available
now). See also NSOA.form.getAllValues() and NSOA.form.get_value(field).
Parameters
field {string} [required] — The name of the field on the form.
Note: This is not the label the user sees displayed next to the field on the form. Use the Form
Schema to find the correct field name value.
Returns
The value in the specified field. Use the Form Schema to find the data type of the returned value.
Note: Some fields return an object. See Object Fields for more details.
Units Limit
1 unit
Since
August 17, 2013
User Scripting
NSOA Functions 90
Example
■ This example creates a local variable called receiptDate and sets its value to the content of the date
field on the form the script is attached to.
■ This sample gets a value from a field that returns an object. See Object Fields for more details.
// First get the object variable for the field and then get the cost_0 value for the first row
var loaded_cost_obj = NSOA.form.getValue("loaded_cost");
var value = loaded_cost_obj[0].cost_0;
NSOA.form.get_value(field)
Use this function to get the value of the field on the form. Keep in mind, any pick lists (for example
Customer:Project, Employee, Expense item) will return an internal_id and not a text value. In this release,
only fields directly related to the form are available (for example no related table lookups are available
now).
Parameters
field {string} [required] — The name of the field on the form.
Returns
The value of the field on the form as a string.
Units Limit
1 unit
Since
March 17, 2012
Example
This example creates a local variable called receiptDate and sets its value to the content of the date field
on the form the script is attached to.
User Scripting
NSOA Functions 91
NSOA.form.setValue(field, value)
Use this command to set form values on the submit scripting event and to update values as part of the
main form save, without needing to write WSAPI (SOAP) calls. The effect is the same as a user making
manual changes to a field.
Full validation from your other scripts or rules is applied after the changes are made, ensuring your
changes are safe. Form default values are applied before the script is run, and any permission rules or
"After save" scripts are applied after the "On submit" script runs.
Error messages can be raised on the submit event. If errors are raised, the script will still run to
completion, and the errors will be logged.
The NSOA.form.setValue function supports the following field types: text, text area, date, numeric,
currency, days, hours, ratio, checkbox, dropdown, dropdown and text, pick list and radio group. The
following field types are not supported: password, sequence and multiple selection.
Parameters
■ field {string} [required] — The name of the field on the form to set the value for
User Scripting
NSOA Functions 92
■ value {permitted value type for field} [required] — The value to set in the field. May be text, numbers,
date values or ISO-8601-formatted strings, the NSOA.form.getValue command, true or false, or null
values, depending on the field affected.
Note: You can reference custom fields using either to the user-defined custom field name
suffixed with _c (for example my_custom_radio_group_c or the internal custom field ID prefixed by
custom_ and the (for example, custom_42). You should reference custom fields by their user-defined
names to ensure your scripts are portable.
Returns
True if the function was successful and false otherwise. If the function fails, it writes a descriptive message
to the script log.
Units Limit
1 unit
Since
April 15, 2017
Examples
■ Text field
□ This example enters a text string into a "Notes" field.
NSOA.form.setValue('notes', '');
Note: The example above only uses single quotes, not double quotes.
NSOA.form.setValue('notes', null);
NSOA.form.setValue('notes', NSOA.form.getValue('name'));
■ Numeric field
□ Numeric values must be written using the base U.S. number format, for example, "23.67". Number
values are displayed according to the user's settings in Regional Settings > Number format.
User Scripting
NSOA Functions 93
NSOA.form.setValue("prj_sales_rep_ratio_1__c", 23.67);
NSOA.form.setValue("prj_sales_rep_ratio_1__c", null);
■ Date field
□ SetValue can set the value of <date> fields using date values or ISO-8601-formatted strings, for
example, YYYY-MM-DD. Date values are displayed according to the user's settings in Regional
Settings > Date format.
NSOA.form.setValue('start_date', '2017-01-23');
Note: An error is logged when you attempt to set a date field with an invalid date string.
NSOA.form.setValue('start_date', null);
■ Checkbox field
□ Use true or false values to set checkboxes.
NSOA.form.setValue("active", true);
NSOA.form.setValue("active", false);
Note: If you use setValue to set a null value for a checkbox, an error will be logged.
NSOA.form.setValue("currency", "EUR");
NSOA.form.setValue("tax_location_id", "Select...");
□ When using NSOA.form.setValue to set a value for a dropdown field, an error is logged if the value
parameter is not one of the available dropdown options.
User Scripting
NSOA Functions 94
Tip: To find the internal identifier for meta values, you can use developer tools on your
browser. Point to the pick list, right-click and select Inspect element to display the HTML
for the pick list element. You can retrieve the name of the field from the name attribute of
the <select> element and the internal identifier from the value attribute of the <option>
element.
NSOA.form.setValue("ta_approver_choice", "-3");
□ When using NSOA.form.setValue to set a value for a dropdown field, an error is logged if the value
parameter is not one of the dropdown options.
□ Set the value to "BLANK" to clear any selected value.
NSOA.form.setValue("ta_approver_choice", "BLANK");
□ An error is logged if the value parameter is not the internal identifier for one of the available pick
list options.
■ Radio group field
□ Set a radio group field value by the radio button name.
Note: You can reference custom fields using the user-defined name — for example
prj_radio_group_c — or the internal reference — for example custom_42. Always reference
custom fields by their the user-defined names to create portable scripts.
NSOA.form.setValue("prj_radio_group_c", "three");
or
NSOA.form.setValue("custom_42", "three");
User Scripting
NSOA Functions 95
□ Set the value to an empty string "" or to null to clear any selected value.
NSOA.form.setValue("prj_radio_group_c", "");
or
NSOA.form.setValue("prj_radio_group_c", null);
□ An error is logged if the value parameter is invalid. Radio button values, as displayed on the form,
null and an empty string "" are the only valid values.
NSOA.form.warning(message)
Use this function to print a warning message on the form. The message that appears will look exactly like
the system-generated warning messages.
Note: This function will only have an affect on the After save and After approval events, see
Events.
Parameters
message {string} [required] — The warning message to display on the form.
Note: This message will be displayed instead of the system-generated warning message for the
form.
Returns
True if the function was successful and false otherwise.
Units Limit
1 unit
Since
October 17, 2015
User Scripting
NSOA Functions 96
Example
This example displays the warning message 'A warning message' at the top of the form after the form is
saved.
NSOA.https.delete(request)
Use this function to send an HTTPS DELETE request to delete resources on a server. In general, DELETE
requests support both query string parameters and a request body. The exact use of DELETE requests
and what data is returned depends on the implementation of the server. The function will return an error
if the URL requested does not use the HTTPS protocol. The function will follow redirects up to a maximum
of 7. The response must not exceed 1MB in size.
Note: If the client doesn’t start receiving a response from the server within 45 seconds of the
request being fully sent, a connection timeout occurs. If the request times out, a response object is
returned with a standard HTTP Status Code (500) and a "Client-Warning" header set.
Parameters
request {object} [required] — The request object is used to set the DELETE request parameters
body array|object|string optional The DELETE data. If the data is passed as an array or
object, it will be automatically JSON serialized and URL
encoded.
Returns
response {object} [read-only] — The NSOA.https.delete function returns the response object.
Units Limit
10 units
User Scripting
NSOA Functions 97
Since
October 12, 2019
Example
This example sends an HTTPS DELETE request, converts the response to a JSON string, displays it in a
confirmation message and stores it as a log entry.
function main(type) {
NSOA.meta.alert(JSON.stringify(response));
NSOA.form.confirmation(JSON.stringify(response));
NSOA.https.get(request)
Use this function to send an HTTPS GET request to retrieve data from a server. The data is identified by
a unique URL and parameters can be passed to the server using query string parameters. What data
is returned depends on the implementation of the server. The function will return an error if the URL
requested does not use the HTTPS protocol. The function will follow redirects up to a maximum of 7. The
response must not exceed 1MB in size.
Note: If the client doesn’t start receiving a response from the server within 45 seconds of the
request being fully sent, a connection timeout occurs. If the request times out, a response object is
returned with a standard HTTP Status Code (500) and a "Client-Warning" header set.
Parameters
request {object} [required] — The request object is used to set the GET request parameters
Returns
response {object} [read-only] — The NSOA.https.get function returns the response object.
User Scripting
NSOA Functions 98
Units Limit
10 units
Since
April 13, 2019
Example
■ This example sends an HTTPS GET request, converts the response to a JSON string, displays it in a
confirmation message and stores it as a log entry.
function main(type) {
NSOA.meta.alert(JSON.stringify(response));
NSOA.form.confirmation(JSON.stringify(response));
■ This example sends an HTTPS GET request to an endpoint simulating a basic-auth protected endpoint.
It converts the response to a JSON string, stores it as a log entry and displays a confirmation message
if the authentication is succesful.
function main(type) {
NSOA.https.patch(request)
Use this function to send an HTTPS PATCH request to update or to make partial modifications to
resources on a server. PATCH requests may support both query string parameters and a request body.
User Scripting
NSOA Functions 99
The exact use of PATCH requests and what data is returned depends on the implementation of the
server. The function will return an error if the URL requested does not use the HTTPS protocol. The
function will follow redirects up to a maximum of 7. The response must not exceed 1MB in size.
Note: If the client doesn’t start receiving a response from the server within 45 seconds of the
request being fully sent, a connection timeout occurs. If the request times out, a response object is
returned with a standard HTTP Status Code (500) and a "Client-Warning" header set.
Parameters
request {object} [required] — The request object is used to set the PATCH request parameters
body array|object|string optional The PATCH data. If the data is passed as an array or
object, it will be automatically JSON serialized and URL
encoded.
headers object optional The HTTPS headers. The MIME type is set automatically
to application/json when body is an array or object.
Returns
response {object} [read-only] — The NSOA.https.patch function returns the response object.
Units Limit
10 units
Since
October 12, 2019
Example
This example sends form data to an endpoint using the HTTPS PATCH method, converts the response to a
JSON string, displays it in a confirmation message and stores it as a log entry.
User Scripting
NSOA Functions 100
function main(type) {
});
NSOA.meta.alert(JSON.stringify(response));
NSOA.form.confirmation(JSON.stringify(response));
NSOA.https.post(request)
Use this function to send an HTTPS POST request to transfer data to a server (and elicit a response).
Parameters can be passed to the server using query string parameters, as well as the request body. What
data is returned depends on the implementation of the server. The function will return an error if the URL
requested does not use the HTTPS protocol. The function will follow redirects up to a maximum of 7. The
response must not exceed 1MB in size.
Note: If the client doesn’t start receiving a response from the server within 45 seconds of the
request being fully sent, a connection timeout occurs. If the request times out, a response object is
returned with a standard HTTP Status Code (500) and a "Client-Warning" header set.
Parameters
request {object} [required] — The request object is used to set the POST request parameters
body array|object|string optional The POST data. If the data is passed as an array or
object, it will be automatically JSON serialized and URL
encoded.
headers object optional The HTTPS headers. The MIME type is set automatically
to application/json when body is an array or object.
Returns
response {object} [read-only] — The NSOA.https.post function returns the response object.
User Scripting
NSOA Functions 101
Units Limit
10 units
Since
April 13, 2019
Example
This example sends form data to an endpoint using the HTTPS POST method, converts the response to a
JSON string, displays it in a confirmation message and stores it as a log entry.
function main(type) {
NSOA.meta.alert(JSON.stringify(response));
NSOA.form.confirmation(JSON.stringify(response));
NSOA.https.put(request)
Use this function to send an HTTPS PUT request to update or replace data on a server (and elicit a
response). Parameters can be passed to the server using query string parameters, as well as the request
body. What data is returned depends on the implementation of the server. The function will return an
error if the URL requested does not use the HTTPS protocol. The function will follow redirects up to a
maximum of 7. The response must not exceed 1MB in size.
Note: If the client doesn’t start receiving a response from the server within 45 seconds of the
request being fully sent, a connection timeout occurs. If the request times out, a response object is
returned with a standard HTTP Status Code (500) and a "Client-Warning" header set.
Parameters
request {object} [required] — The request object is used to set the PUT request parameters
body array|object|string optional The PUT data. If the data is passed as an array or object,
it will be automatically JSON serialized and URL encoded.
User Scripting
NSOA Functions 102
headers object optional The HTTPS headers. The MIME type is set automatically
to application/json when body is an array or object.
Returns
response {object} [read-only] — The NSOA.https.put function returns the response object.
Units Limit
10 units
Since
October 12, 2019
Example
This example sends form data to an endpoint using the HTTPS PUT method, converts the response to a
JSON string, displays it in a confirmation message and stores it as a log entry.
function main(type) {
NSOA.meta.alert(JSON.stringify(response));
NSOA.form.confirmation(JSON.stringify(response));
NSOA.listview.data(listviewId)
Use this function to read the published list data available to the user running the script. The function
returns a specialized list data iterator (length, index, next, each).
User Scripting
NSOA Functions 103
■ The data read by your scripts is the same as the data you can see in your list at any given time.
■ Accessing published lists using the NSOA.listview.data(listviewId) and NSOA.listview.list() user
scripting functions does not use any of your allocated OData requests.
■ For more information, see Business Intelligence Connector. See also OData Explorer
to browse available OData resources and get started with a sample code, and
NSOA.report.data(reportId,optionalParameters) to read published report data.
Tip: Use published lists like custom queries and read only the necessary list data in your scripts.
Note: The Business Intelligence Connector feature must be enabled for your account to use
NSOA.listview and NSOA.report functions. The Business Intelligence Connector feature is a
licensed add-on. To enable this feature, contact your SuiteProjects Pro account manager.
For more information about publishing lists and reports to the SuiteProjects Pro OData service,
see Business Intelligence Connector.
Parameters
listviewId — the published list OData resource ID (integer).
Returns
A specialized list data iterator (length, index, next, each).
Units Limit
10 units for each 1000-item page loaded into iterator on-demand. Consumes 10 units for the first fetch
even when the page is empty.
Since
April 18, 2020
Example
User Scripting
NSOA Functions 104
// it consumes 10 units for each 1000-item page loaded into iterator on-demand
// * 'length' - number of items
// * 'index' - index of last returned item
// * 'next' - returns next item from iterator or undefined when iterator is done
// * 'each' - calls specified function for each item in the iterator
var iterator = NSOA.listview.data(7);
// stop iterating
return false;
}
});
NSOA.listview.list()
Use this function to read the list of published lists available from the SuiteProjects Pro OData service.
Returns the list of published lists.
Note: The Business Intelligence Connector feature must be enabled for your account to use
NSOA.listview and NSOA.report functions. The Business Intelligence Connector feature is a
licensed add-on. To enable this feature, contact your SuiteProjects Pro account manager.
For more information about publishing lists and reports to the SuiteProjects Pro OData service,
see Business Intelligence Connector.
Parameters
N/A
Returns
The list of published lists. Each item in the list has the following properties:
User Scripting
NSOA Functions 105
Units Limit
1 unit
Since
April 18, 2020
Example
NSOA.meta.alert(message)
Use this function to store an Info log entry. This is a short version of NSOA.meta.log(severity, message).
Parameters
message {string} [required] — The message to be written to the log.
Returns
True if the function was successful and false otherwise.
User Scripting
NSOA Functions 106
Units Limit
4 units
Since
August 17, 2013
Example
This sample writes the ‘info’ severity message 'Form error - travel date is after receipt date' to the log.
NSOA.meta.log(severity, message)
Use this function to store a log entry. The supported severities match those of the Log4j project.
■ Severity — The supplied severity: “fatal”, “error”, “warning”, “info”, “debug”, or “trace”.
■ Timestamp — The time the message was logged.
■ Generated by — For example, whether the message was generated by your script or by SuiteProjects
Pro
■ Message — The full message text.
■ User — For example, the user that was saving the form when the error occurred.
Note: If you have a syntax error or a runtime error you will see an error in the log generated by
SuiteProjects Pro.
Parameters
■ severity {string} [required] — The severity of the message: “fatal”, “error”, “warning”, “info”, “debug”, or
“trace”.
User Scripting
NSOA Functions 107
Note: The “debug” and “trace” messages are only executed in test mode, see Testing and
Debugging. The “debug”, and “trace” messages do not consume Scripting Governance units
but are limited to a maximum of 1000 per script.
Returns
True if the function was successful and false otherwise.
Units Limit
4 units
Since
August 17, 2013
Example
This sample writes the ‘error’ severity message 'Form error - travel date is after receipt date' to the log.
NSOA.meta.sendMail(message)
Use this function to send email messages from a form, library, or scheduled script. Form scripts are
allowed to send a maximum of 3 emails and scheduled scripts a maximum of 100 email by Scripting
Governance.
Parameters
msg {object} [required] — An email message object with the following properties:
■ format — [optional] if “HTML” the body will be treated as HTML. If this is set to any other value or
omitted then the body will be treated as plain text.
User Scripting
NSOA Functions 108
■ subject — [optional] string holding the email subject. The subject is trimmed to the first line if carriage
return characters are used.
Important: There is a maximum body length set for your emails sent by form and
scheduled scripts. Email messages with bodies above that maximum body length are not sent.
The maximum body length is set to 30,000 characters by default and can be changed to suit
your requirements. To review or to increase the maximum body length set for your account,
contact SuiteProjects Pro Support.
Tip: If the format is set to ”HTML” any tags you can place within the <body></body> section
of an HTML file are valid.
■ author — [optional] use to set one SuiteProjects Pro user ID as the author of the emails.
Returns
True if the email was placed in the queue for sending and false otherwise.
Units Limit
10 units
Since
October 17, 2015
Example
■ This sends a plain text email.
NSOA.meta.sendMail(msg);
User Scripting
NSOA Functions 109
var msg = {
to: ["[email protected]"],
subject: "Project Assignment",
format: "HTML",
body: "<b>Client:</b> Altima Technologies</br>" +
"<b>Project:</b> CRM Implementation</br>" +
"<b>Project Manager:</b> Collins, Marc"
};
NSOA.meta.sendMail(msg);
NSOA.NSConnector.integrateAllNow()
This function lets you trigger the integration to run for all active integration workflows from your
scheduled scripts. It is equivalent to clicking the Run button on the main NetSuite Connector page
and selecting all workflows. For more information about running the integration, see NetSuite
Integration.
Parameters
(none)
Returns
Boolean true if integration was triggered and false if integration was not triggered.
Units Limit
1000 units
Since
April 16, 2016
Example
This example triggers the NetSuite integration for all fields using a scheduled script.
User Scripting
NSOA Functions 110
function main() {
var records = NSOA.wsapi.read(...);
// check if result is OK
if (!records || !records[0])
return;
Note: This simple example does not show error checking, see Handling SOAP Errors.
NSOA.NSConnector.integrateRecord()
This function let you export a single record from SuiteProjects Pro to NetSuite from your form scripts. It is
equivalent to clicking the Export/Send links in the Tips menu for a selected record. For more information
about exporting a single record from SuiteProjects Pro to NetSuite, see NetSuite Integration.
This function applies only to the SuiteProjects Pro records available for export to NetSuite. It will perform
an action only if called for one of the following forms:
■ Envelope
■ Invoice
■ Revenue Recognition Transaction
■ Customer
■ Timesheet
■ Purchase Request
■ Project
■ Project Task
Parameters
(none)
Returns
Boolean true if integration was triggered and false if integration was not triggered.
User Scripting
NSOA Functions 111
Units Limit
10 units
Since
April 16, 2016
Example
This example presents a common use case for after-approval events with envelopes.
function main() {
// integrate current form object to NetSuite
NSOA.NSConnector.integrateRecord();
NSOA.NSConnector.integrateWorkflowGroup(name)
The NetSuite integration lets you create workflow groups to include only the integration workflows you
need in each scheduled integration run. For more information about workflow groups, see NetSuite
Integration.
This function lets you trigger the integration to run for a specific workflow group from your user scripts.
Parameters
name (string) — The name of the workflow group. It must match exactly the name of an existing workflow
group.
Returns
Boolean true if integration was triggered and false if integration was not triggered.
Units Limit
1000 units
User Scripting
NSOA Functions 112
Since
■ October 9, 2021
Example
This example triggers the NetSuite integration for the workflow group ’ Timesheets Custom Export‘ using
a scheduled script.
function main() {
NSOA.NSConnector.integrateWorkflowGroup('Timesheets Custom Export');
Note: This simple example does not show error checking, see Handling SOAP Errors.
User Scripting
NSOA Functions 113
oaEstimatemarkup oaPurchaseorder
Tip: You can look up the SuiteProjects Pro Complex Types and their properties from the
SuiteProjects Pro WSDL available from the following URL https://<account-domain>/wsdl.pl.
SuiteProjects Pro Complex Type objects are required in the following wsapi functions:
■ NSOA.wsapi.add(objects)
■ NSOA.wsapi.delete(objects)
■ NSOA.wsapi.modify(attributes, objects)
■ NSOA.wsapi.read(readRequest)
■ NSOA.wsapi.upsert(attributes,objects)
Note: For more information about the SOAP API (Web Services), see XML API & SOAP API.
Parameters
id {var} [optional] — If specified, this (internal) ID will be used to populate the new object.
Returns
SuiteProjects Pro Complex Type object.
Units Limit
0 units
Since
November 16, 2013
User Scripting
NSOA Functions 114
Example
■ This sample creates a customer object populates with the current values in the database.
NSOA.report.data(reportId,optionalParameters)
Use this function to read published report data available to the user executing the script. The function
returns a specialized report data iterator (length, index, next, each).
For more information, see Business Intelligence Connector. See also OData Explorer to browse available
OData resources and get started with a sample code, and NSOA.listview.data(listviewId) to read published
list data.
Note: The Business Intelligence Connector feature must be enabled for your account to use
NSOA.listview and NSOA.report functions. The Business Intelligence Connector feature is a
licensed add-on. To enable this feature, contact your SuiteProjects Pro account manager.
For more information about publishing lists and reports to the SuiteProjects Pro OData service,
see Business Intelligence Connector.
Parameters
■ reportId — the ID number of the report (integer).
■ (optional) optionalParameters — an object with the following properties:
□ (optional) select — the list of columns to return (string array).
□ (optional) filter — a logical expression defining the criteria items must match to be included in
the response (string).
For information about column names and filter expression syntax and guidelines, see Business
Intelligence Connector.
Returns
■ A specialized report data iterator (length, index, next, each).
□ length — number of items
□ index — index of last returned item
User Scripting
NSOA Functions 115
□ next — returns next item from iterator or undefined when iterator is done
□ each — calls specified function for each item in the iterator
Units Limit
10 units for each 1000-item page loaded into iterator on-demand. Consumes 10 units for the first fetch
even when the page is empty.
Since
October 13, 2018
Example
// get the iterator for report data; it has following members
// it consumes 10 units for each 1000-item page loaded into iterator on-demand
// * 'length' - number of items
// * 'index' - index of last returned item
// * 'next' - returns next item from iterator or undefined when iterator is done
// * 'each' - calls specified function for each item in the iterator
//
// optionalParameters:
// * 'select' - list of field names to be returned
// * 'filter' - limiting condition
var iterator = NSOA.report.data(
7,
{
select: ["Name", "Remaining Budget"],
filter: "Name eq 'Nathan Brown'"
}
);
// stop iterating
return false;
}
});
NSOA.report.list()
Use this function to read the list of reports published using the Business Intelligence Connector feature.
The list contains the same data as the “list” report available in your business intelligence tool.
For more information, see Business Intelligence Connector. See also NSOA.listview.list() to read the list of
published lists.
User Scripting
NSOA Functions 116
Note: The Business Intelligence Connector feature must be enabled for your account to use
NSOA.listview and NSOA.report functions. The Business Intelligence Connector feature is a
licensed add-on. To enable this feature, contact your SuiteProjects Pro account manager.
For more information about publishing lists and reports to the SuiteProjects Pro OData service,
see Business Intelligence Connector.
Parameters
N/A
Returns
The list of published reports. Each item in the list has the following properties:
■ ID — The report ID
■ Name — The name of the report
■ Rows — The number of rows of data in the report
■ PublishType — The scope of use specified for the published report.
■ Last published — The date the report was last published
Units Limit
1 unit
Since
October 13, 2018
Example
// get the list of published reports
var reports = NSOA.report.list();
User Scripting
NSOA Functions 117
}
}
NSOA.wsapi.add(objects)
Use this function to add data to SuiteProjects Pro. The function returns an error if more than 1000 objects
are passed in.
Note: For more information about the SOAP API (Web Services), see XML API & SOAP API.
Parameters
objects {var} [required] — Array of SuiteProjects Pro Complex Type objects, see NSOA.record.<complex
type>( [id] ).
Returns
Array of UpdateResult objects.
Units Limit
20 units
Since
November 16, 2013
Example
This sample creates a new category in SuiteProjects Pro.
User Scripting
NSOA Functions 118
Note: This simple example does not show error checking, see Handling SOAP Errors.
NSOA.wsapi.approve(approveRequest)
Use this function to approve bookings, timesheets, invoices, and envelopes. It can take an array of up to
1,000 approve request objects.
Parameters
approveRequest{object} [required] — approveRequest object
Returns
Array of ApprovalResult objects.
Units Limit
20 units
Since
October 15, 2016
Example
In this example, the script creates the approval object, then prepares the timesheet with timesheet ID 45
for approval, defines the approve requests, and invokes the action call.
Note: This simple example does not show error checking, see Handling Approval Errors
User Scripting
NSOA Functions 119
NSOA.wsapi.delete(objects)
Use this function to delete data in SuiteProjects Pro based on an internal ID. The function returns an error
if more than 1000 objects are passed in
Note: For more information about the SOAP API (Web Services), see XML API & SOAP API.
Parameters
objects {var} [required] — Array of SuiteProjects Pro Complex Type objects, see NSOA.record.<complex
type>( [id] ).
Returns
Array of UpdateResult objects.
Units Limit
20 units
Since
November 16, 2013
Example
This sample deletes a customer from SuiteProjects Pro.
Note: This simple example does not show error checking, see Handling SOAP Errors.
NSOA.wsapi.disableFilterSet( [ flag] )
Use this function to check, enable, or disable user filter sets.
User Scripting
NSOA Functions 120
Note: Scripts are executed within the context of the user who is signed in. This means that the
user filter sets for the signed in user will be applied unless disabled.
Tip: Disabling user filter sets allows you to write more generic scripts.
Parameters
flag {Boolean} [optional] — If true is passed the user filter sets are disabled, if false is passed the user
filter sets are enabled, and if no parameter is passed the function returns the current filter setting.
Returns
Boolean true if filter sets are disabled and false if user filter sets are enabled.
Units Limit
1 unit
Since
November 16, 2013
Example
■ Disable user filter sets on .wsapi requests.
NSOA.wsapi.disableFilterSet(true);
NSOA.wsapi.disableFilterSet(false);
Note: This the default SuiteProjects Pro behavior, that is, user filter sets enabled.
if( NSOA.wsapi.disableFilterSet()) {
// The user filter sets are disabled
}
NSOA.wsapi.enableLog( [ flag] )
Use this function to see the SOAP API request and response messages generated by NSOA.wsapi function
calls.
User Scripting
NSOA Functions 121
Every call between enableLog(true) and enableLog(false) is logged and available for viewing in the same
place as the NSOA.meta.log(severity, message) function.
Note: This function only works in test mode and is ignored in production due to the size of the
messages. See Testing and Debugging.
Parameters
flag {Boolean} [optional] — If true is passed then wsapi logging is enabled, if false is passed then wsapi
logging is disabled, and if no parameter is passed the function returns the current wsapi logging setting.
Returns
Boolean true if wsapi logging is enabled and false if wsapi logging is disabled.
Units Limit
1 unit
Since
February 15, 2014
Example
■ Enable wsapi logging.
NSOA.wsapi.enableLog(true);
NSOA.wsapi.enableLog(false);
Note: This is the default SuiteProjects Pro behavior, that is, wsapi logging disabled.
if( NSOA.wsapi.enableLog()) {
// wsapi logging is enabled
}
User Scripting
NSOA Functions 122
NSOA.wsapi.modify(attributes, objects)
Use this function to modify data in SuiteProjects Pro. The function returns an error if more than 1000
objects are passed in.
You need to specify the internal ID for each object passed, as well as the properties you want to modify.
Note: For more information about the SOAP API (Web Services), see XML API & SOAP API.
Parameters
■ attributes {var} [required] — Array of Attribute objects.
■ objects {var} [required] — Array of SuiteProjects Pro Complex Type objects, see NSOA.record.<complex
type>( [id] ).
Returns
Array of UpdateResult objects.
Units Limit
40 units
Since
November 16, 2013
Example
This sample changes a customer’s email address in SuiteProjects Pro.
Note: This simple example does not show error checking, see Handling SOAP Errors.
User Scripting
NSOA Functions 123
NSOA.wsapi.read(readRequest)
Use this function to retrieve data from SuiteProjects Pro. The function returns an error if the response
would exceed 1000 objects.
Note: For more information about the SOAP API (Web Services), see XML API & SOAP API.
Parameters
readRequest {object} [required] — Array of ReadRequest objects.
Returns
Array of ReadResult objects.
Units Limit
20 units
Since
November 16, 2013
Example
This sample creates a new category in SuiteProjects Pro.
User Scripting
NSOA Functions 124
Note: This simple example does not show error checking, see Handling SOAP Errors.
NSOA.wsapi.reject(rejectRequest)
Use this function to reject bookings, timesheets, invoices, and envelopes. It can take an array of up to
1,000 reject request objects.
Parameters
rejectRequest{object} [required] — rejectRequest object
Returns
Array of ApprovalResult objects.
Units Limit
20 units
Since
October 15, 2016
Example
In this example, the script creates the approval object, then prepares the timesheet with timesheet ID 45
for rejection, defines the reject requests, and invokes the action call.
Note: This simple example does not show error checking, see Handling Approval Errors
User Scripting
NSOA Functions 125
NSOA.wsapi.remainingTime()
Use this function to determine how much time your script has remaining to execute inside wsapi
functions before it is terminated by Scripting Governance.
You can use this function to help you create more efficient scripts and also to take corrective action if a
script is at risk of consuming excessive resources.
Parameters
(none)
Returns
Amount of time remaining allowed for the script to execute inside wsapi calls in milliseconds.
Tip: Always try to reduce the amount of time your scripts take to execute.
Units Limit
0 units
Since
October 18, 2014
Example
This example logs the amount of wsapi time remaining for the script to execute in milliseconds.
NSOA.wsapi.submit(submitRequest)
Use this function to submit bookings, timesheets, invoices, and envelopes. It can take an array of up to
1,000 submit request objects.
Parameters
submitRequest{object} [required] — submitRequest object
User Scripting
NSOA Functions 126
Returns
Array of ApprovalResult objects.
Units Limit
20 units
Since
October 15, 2016
Example
In this example, the script creates the approval object, then prepares the timesheet with timesheet ID 45
for submitting, defines the submit requests, and invokes the action call.
Note: This simple example does not show error checking, see Handling Approval Errors
NSOA.wsapi.unapprove(unapproveRequest)
Use this function to unapprove bookings, timesheets, invoices, and envelopes. It can take an array of up
to 1,000 unapprove request objects.
Parameters
unapproveRequest{object} [required] — unapproveRequest object
Returns
Array of ApprovalResult objects.
User Scripting
NSOA Functions 127
Units Limit
20 units
Since
October 15, 2016
Example
In this example, the script creates the approval object, then prepares the timesheet with timesheet ID 45
for unapproval, defines the unapprove requests, and invokes the action call.
Note: This simple example does not show error checking, see Handling Approval Errors
NSOA.wsapi.upsert(attributes,objects)
Use this function to add or modify data in SuiteProjects Pro based on lookup attributes. The function
returns an error if more than 1000 objects are passed in.
You can use an externalid field as a foreign key and add a record without querying first for an internal ID.
Note: For more information about the SOAP API (Web Services), see XML API & SOAP API.
Parameters
■ attributes {var} [required] — Array of Attribute objects.
■ objects {var} [required] — Array of SuiteProjects Pro Complex Type objects, see NSOA.record.<complex
type>( [id] ).
User Scripting
NSOA Functions 128
Returns
Array of UpdateResult objects.
Units Limit
40 units
Since
November 16, 2013
Example
This sample creates a new category in SuiteProjects Pro.
// Specify that the lookup is done by external_id and not by (default) internal ID
var attribute = {
name : "lookup",
value : "externalid"
};
Note: This simple example does not show error checking, see Handling SOAP Errors.
NSOA.wsapi.whoami()
Use this function to add or modify data in SuiteProjects Pro based on lookup attributes. The function
returns an oaUser object, see Who Am I.
Note: For more information about the SOAP API (Web Services), see XML API & SOAP API.
Parameters
(none)
Returns
An oaUser object.
User Scripting
NSOA Functions 129
Units Limit
1 unit
Since
November 16, 2013
Example
This sample logs the name of the user running the script.
function logUser() {
var user = NSOA.wsapi.whoami();
NSOA.meta.alert( "User ID " + user.id + " saved this record");
}
Note: This simple example does not show error checking, see Handling SOAP Errors.
Code Samples
The following code samples are provided:
User Scripting
Code Samples 130
See also:
■ NSOA.form.getValue(field)
■ NSOA.form.error(field, message)
See also:
■ NSOA.form.getValue(field)
■ NSOA.form.error(field, message)
See also:
■ NSOA.form.getValue(field)
■ NSOA.form.error(field, message)
User Scripting
Code Samples 131
See also:
■ NSOA.form.getValue(field)
■ NSOA.form.error(field, message)
■ NSOA.meta.log(severity, message)
Sending email
function sendAlert() {
// TODO Add Your Code Here
NSOA.meta.sendMail(msg);
}
//Read request
var issue = new NSOA.record.oaIssue();
issue.project_id = NSOA.form.getValue('id');
issue.issue_stage_id = 1;
var readRequest = {
type : "Issue",
method : "equal to", // return only records that match search criteria
fields : "id, date", // specify fields to be returned
attributes : [ // Limit attribute is required; type is Attribute
{
name : "limit",
value : "10"
}
],
objects : [ // One object with search criteria; type implied by rr 'type'
issue
]
};
var arrayOfreadResult = NSOA.wsapi.read(readRequest);
if (!arrayOfreadResult || !arrayOfreadResult[0])
NSOA.form.error('', "Internal error analyzing project. Contact account administrator.");
else if (arrayOfreadResult[0].errors === null && arrayOfreadResult[0].objects)
arrayOfreadResult[0].objects.forEach(
function(o) {
NSOA.form.error('', "Can't close project with open issues.");
}
User Scripting
Code Samples 132
);
}
See also:
■ NSOA.form.getValue(field)
■ NSOA.record.<complex type>( [id] )
■ NSOA.wsapi.read(readRequest)
■ NSOA.form.error(field, message)
NSOA.wsapi.disableFilterSet(true);
var arrayOfupdateResult = NSOA.wsapi.modify([], [project]);
NSOA.meta.alert("Got modify status: " + arrayOfupdateResult[0].status);
}
See also:
■ NSOA.form.getNewRecord()
■ NSOA.record.<complex type>( [id] )
■ NSOA.wsapi.modify(attributes, objects)
■ NSOA.meta.alert(message)
var readRequest = {
type : "Projecttaskassign",
method : "equal to", // return only records that match search criteria
fields : "id", // specify fields to be returned
attributes : [ // Limit attribute is required; type is Attribute
{
name : "limit",
value : "1"
}
],
objects : [ // One object with search criteria
pta
]
};
// Run query
NSOA.wsapi.disableFilterSet(true); // disable the current user's filter for read query
var result = NSOA.wsapi.read(readRequest);
User Scripting
Code Samples 133
See also:
function main(type) {
See also:
User Scripting
Code Samples 134
Note: Refer to the API you are calling for details on the expected request and response formats.
/**
* SOAP call to get data center URLs using HTTPS POST method.
* @param {Str} accountID ID of a NetSuite account.
* @return {Obj} An https.post response object.
*/
function getDataCenterUrls(accountID){
var headers = {
'SOAPAction': 'getDataCenterUrls',
'Content-type': 'application/javascript'
};
var request = {
url : url,
headers: headers,
body: body
};
return response;
}
/**
* Post a message to slack using a webhook URL.
User Scripting
Code Samples 135
var body = {
text: text
};
// If attachments param is provided, and it is of type Array (isArray method isn't supported...)
if (attachments && Object.prototype.toString.call(attachments) === '[object Array]') { body.attachments = attachments; }
var headers = {
'Content-type': 'application/json'
};
return response;
}
See also:
■ NSOA.https.post(request)
■ NSOA.meta.log(severity, message)
/**
* Get a protected resource from a URL.
* @param {Str} url API URL (required)
* @return {Obj} An https.get response object.
*/
function getProtectedResource(url) {
// Check that url parameter has a value, otherwise return
url = url || '';
if (!url || url.length === 0) { return null; }
var headers = {
'Authorization': 'Bearer ' + api_token
};
User Scripting
Code Samples 136
});
return response;
}
See also:
■ NSOA.context.getParameter(name)
■ NSOA.https.get(request)
User Scripting
JavaScript 137
JavaScript
JavaScript Overview
SuiteProjects Pro user scripts are external JavaScript files. SuiteProjects Pro is compliant with ECMAScript
5.
Important: For SuiteProjects Pro to use an external JavaScript file, it must be stored in a
Workspace as an ASCII text file with the file extension .js.
Key Points
■ Semicolons to end statements are optional in JavaScript, but for clarity you are advised to always use
them.
■ JavaScript ignores extra white space. Use white space to make your scripts more readable.
var receiptDate=NSOA.form.getValue('date');
var receiptDate = NSOA.form.getValue('date');
var receiptDate;
var ReceiptDate;
■ JavaScript supports single and multliline comments. Use comments to make your scripts maintainable!
/*
This is a multiline comment
*/
Tip: You can comment out lines of script to prevent them from being executed. This is a
useful debugging technique.
Variables
Variables are usually declared in JavaScript with the var keyword.
var price;
User Scripting
Variables 138
Note: JavaScript is an untyped language, you cannot declare a variable to be a string or number.
Variables can hold any type and data types are converted automatically behind the scenes. See
Dynamic Data Types
Tip: If you don’t use var the variable will be declared as global. You should avoid using global
variables as they can result in unwanted side effects and are a frequent source of bugs! See
Variable Scope.
price = 500;
price = null;
If you re-declare a variable, the variable will not lose its value.
Important: If you assign a value to variable that has not been declared with var, the variable
will automatically be declared as a global variable. See Variable Scope.
Variables names must start with a letter or underscore and cannot use any Reserved Words.
Tip: Use short names for variables which you use only in nearest code.
Multi-word names add precision from right to left, adjectives are always at the left side.
Use camel-case.
Variable Scope
Variables in JavaScript can have local or global scope. The scope of a variable refers to the variable's
visibility within a script. Variables accessible to a restricted part of a script are said be local. Variables that
are accessible from anywhere, are said to be global.
Global variables can be created anywhere in JavaScript code, simply by assigning initial values to them.
Once created, global variables can be accessed from any part of the script and retain their values until the
script ends.
In JavaScript, newly created variables are assumed to be global, regardless of where they are created,
unless explicitly defined with the var keyword.
User Scripting
Variables 139
Important: Ambiguity can arise when a global variable and local variable have the same names.
JavaScript resolves this ambiguity by giving priority to local variables.
■ String
■ Number
■ Boolean
■ null
■ undefined
String
A string in JavaScript is series of characters enclosed in quotation marks. A string must be delimited by
quotation marks of the same type, either single quotation marks ' or double quotation marks ".
You can use quotes inside a string, as long as they don't match the quotes surrounding the string.
Number
JavaScript has only one type of number. Large numbers can be written in scientific (exponential) notation.
User Scripting
Variables 140
var pi = 3.14;
var amount = 314e5; // 31400000
var factor = 314e-5; // 0.00314
JavaScript interprets numeric constants as octal if they are preceded by a zero, and as hexadecimal if they
are preceded by a zero and x.
Important: When you assign a number to a variable, do not put quotes around the value. If
you put quotes around a numeric value, the variable content will be treated as a string.
Never write a number with a leading zero, unless you want an octal conversion.
Boolean
Booleans can only have two values: true or false.
null
null is a special keyword denoting an empty value.
travelType = null;
undefined
This is a special keyword denoting an undefined value.
Arrays
In JavaScript an array is created as follows:
// Creating an array
var priority = new Array();
priority[0] = "Low";
priority[1] = "Normal";
priority[2] = "High";
// Literal array
User Scripting
Arrays 141
Associative Array
An associative array is a set of key value pairs. The value is stored in association with its key and if you
provide the key the array will return the value.
Note: The key is always a string, but the value can be any type. See Dynamic Data Types and
Objects.
You can loop through the keys of an associative array with the for in loop.
User Scripting
Arrays 142
See also:
■ NSOA.form.getAllValues()
■ NSOA.meta.alert(message)
You can add a new key/value pair by assigning to a property that doesn't exist.
Objects
An object is just a special kind of data, with Properties and Methods.
// To declare an object
var person={ firstname : "John", lastname : "Smith", age: 25};
The object (person) in the example above has 3 properties: firstname, lastname, and age.
Properties
Properties are the values associated with an object.
objectName.propertyName
This example uses the length property of the String object to find the length of a string:
User Scripting
Objects 143
Methods
Methods are the actions that can be performed on objects.
objectName.methodName()
This example uses the toUpperCase() method of the String object, to convert a text to uppercase:
The value of x, after execution of the code above will be “HELLO WORLD!”.
Functions
Functions are declared with the function keyword, they can be passed Arguments and can Return Values.
Function names must start with a letter or underscore and cannot use any Reserved Words.
// Declaring a function
function calcSum (x,y) {
return x + y;
}
// Calling a function
var result = calcSum(15,25);
Note: Variables declared inside a function as var are local to the function. Variables defined
inside a function without the var are global variables.
Arguments
Functions do not need arguments.
function validateTravelDates() {
var receiptDate = NSOA.form.getValue('date');
var travelDate = NSOA.form.getValue('TravelDate__c');
User Scripting
Functions 144
See also:
■ NSOA.form.getValue(field)
■ NSOA.form.error(field, message)
Important: If you declare a function with arguments then the function must be called with all
the arguments in the expected order.
Return Values
Functions do not need to return a value.
function logFormError(message) {
NSOA.meta.log('error', 'Form error - ' + message);
}
See also:
■ NSOA.meta.log(severity, message)
You can use the return statement to immediately exit a function. The return value is optional.
var result = x - y;
return result;
}
Loops
JavaScript supports the following types of loop:
■ for
■ for in
■ forEach
■ do while
■ while
Key Points
■ Use the break statement to terminate the current while or for loop and continue executing the
statements after the loop..
User Scripting
Loops 145
■ Use the continue statement to stop executing the current iteration and continue with the next
iteration.
Important: Be careful not to create endless loops. Make sure your loops always have an exit
condition!
for
The for loop executes a block of code a specified number of times.
Syntax
Example
for in
The for in loop is for iterating through the enumerable properties of an object. See Objects and
Associative Array.
Syntax
Example
var person={firstName:"John",lastName:"Smith",age:21};
for (i in person) {
s = s + person[i];
}
forEach
The forEach loop has the benefit that you don't have to declare indexing and entry variables in the
containing scope, as they're supplied as arguments to the iteration function, and so nicely scoped to just
that iteration.
See also:
User Scripting
Loops 146
■ NSOA.meta.alert(message)
do while
The do while loop is a variant of the while loop. This block is first executed and then repeated as long as
the condition is true.
Syntax
do {
// statements
}
while (condition)
Example
var i=0;
do {
x = x + "The number is " + i;
i++;
}
while ( i < 5 )
while
The while loop iterates through a block of code as long as a specified condition is true.
Syntax
while (condition) {
// statements
}
Example
var i = 0;
while ( i < 5 ) {
x = x + "The number is " + i;
i++;
}
Conditional Statements
JavaScript supports if ... else and switch conditional statements.
if (condition) {
statements_1
} else {
statements_2
}
switch syntax
User Scripting
Conditional Statements 147
switch (expression) {
case label_1:
statements_1
[break;]
case label_2:
statements_2
[break;]
default:
statements_n
[break;]
}
if ... else
if is the fundamental control statement that allows JavaScript to make decisions and execute statements
conditionally.
If the expression is true (i.e. today < endDate) then the block following if is executed.
If the expression is false (i.e. today < endDate in not true) the optional block following else is executed.
Tip: Rather than creating a long if .. else chain, use the switch statement.
Note: This is just a series of if statements, where each if is part of the else clause of the previous
statement. Each condition is evaluated in sequence. The first block with its condition to evaluate
true is executed and then the whole chain is exited. If no condition is true then the final else block
is executed.
See also:
User Scripting
Conditional Statements 148
■ NSOA.form.getValue(field)
switch
The switch statements compares an expression against a list of case values. Execution jumps to the first
case that matches. If nothing matches, execution jumps to the default condition.
Note: The break statements ends the case and execution jumps to the next statement after the
switch block. If the break is omitted execution continues with the next case.
Error Handling
JavaScript supports try and catch blocks to handle errors. When something goes wrong, JavaScript will
throw an error.
Syntax
try {
// The code to run
}
catch(err) {
// Code to handle any errors
}
Example
try {
var receiptDate = NSOA.form.getValue('date');
var travelDate = NSOA.form.getValue('TravelDate__c');
See also:
■ NSOA.form.getValue(field)
■ NSOA.form.error(field, message)
■ NSOA.meta.log(severity, message)
User Scripting
Error Handling 149
Key points:
throw
When an exception occurs JavaScript will throw an error that you can catch.
You can use the throw statement to raise your own custom exceptions. These exceptions can be captured
and appropriate action taken.
Note: You can throw different types, e.g. String, Number, and Object.
References
JavaScript Objects
Array
An Array object is used to store multiple values in a single variable.
// Creating an array
var priority = new Array();
priority[0] = "Low";
priority[1] = "Normal";
priority[2] = "High";
User Scripting
References 150
var x = priority.length
Array Properties
Property Description
constructor Returns the function that created the Array object's prototype.
Array Methods
Method Description
concat() Joins two or more arrays, and returns a copy of the joined arrays.
indexOf() Search the array for an element and returns its position.
lastIndexOf() Search the array for an element, starting at the end, and returns its position.
pop() Removes the last element of an array, and returns that element.
push() Adds new elements to the end of an array, and returns the new length.
shift() Removes the first element of an array, and returns that element
unshift() Adds new elements to the beginning of an array, and returns the new length.
Boolean
A Boolean object is used to convert a non-Boolean value to a Boolean value (true or false).
Boolean Properties
Property Description
constructor Returns the function that created the Boolean object's prototype.
User Scripting
References 151
Property Description
Boolean Methods
Method Description
toString() Converts a Boolean value to a string, and returns the result (either “true” or ”false”).
bool.toString()
valueOf() Returns the primitive value of a Boolean object (either true or false).
bool.valueOf()
Date
A Date object is used to work with dates and times.
Date Properties
Property Description
constructor Returns the function that created the Date object's prototype.
User Scripting
References 152
Date Methods
Method Description
getTimezoneOffset() Returns the time difference between UTC time and local time, in minutes.
getUTCDate() Returns the day of the month, according to universal time (from 1-31).
getUTCDay() Returns the day of the week, according to universal time (from 0-6).
parse() Parses a date string and returns the number of milliseconds since midnight of January 1,
1970.
setTime() Sets a date and time by adding or subtracting a specified number of milliseconds to/from
midnight January 1, 1970.
setUTCDate() Sets the day of the month of a date object, according to universal time.
setUTCFullYear() Sets the year of a date object, according to universal time (four digits).
User Scripting
References 153
Method Description
toDateString() Converts the date portion of a Date object into a readable string
toLocaleDateString() Returns the date portion of a Date object as a string, using locale conventions.
toLocaleTimeString() Returns the time portion of a Date object as a string, using locale conventions.
UTC() Returns the number of milliseconds in a date string since midnight of January 1, 1970,
according to universal time.
Math
The Math object allows you to perform mathematical tasks.
Math Properties
Property Description
User Scripting
References 154
Property Description
Math Methods
Method Description
atan(x) Returns the arctangent of x as a numeric value between -PI/2 and PI/2 radians.
Number
A Number object is an object wrapper for primitive numeric values.
Note: If the value parameter cannot be converted into a number, it returns NaN (Not-a-Number).
Number Properties
Property Description
constructor Returns the function that created the Number object's prototype.
User Scripting
References 155
Property Description
Number Methods
Method Description
toFixed(x) Formats a number with x numbers of digits after the decimal point.
String
A String object is used to manipulate a series of characters.
String Properties
Property Description
constructor Returns the function that created the String object's prototype.
String Methods
User Scripting
References 156
Method Description
concat() Joins two or more strings, and returns a copy of the joined strings.
indexOf() Returns the position of the first found occurrence of a specified value in a string.
lastIndexOf() Returns the position of the last found occurrence of a specified value in a string.
match() Searches for a match between a regular expression and a string, and returns the matches.
replace() Searches for a match between a substring (or regular expression) and a string, and replaces the
matched substring with a new substring.
search() Searches for a match between a regular expression and a string, and returns the position of the
match.
substr() Extracts the characters from a string, beginning at a specified start position, and through the
specified number of character.
substring() Extracts the characters from a string, between two specified indices.
JavaScript Operators
= is used to assign values.
JavaScript Operators:
■ Arithmetic Operators
■ Assignment Operators
■ Comparison Operators
■ Logical Operators
Note: JavaScript also contains a conditional operator that assigns a value to a variable based on
a condition.
User Scripting
References 157
packingCost=(quantity>1000)?largePacket:smallPacket;
Arithmetic Operators
Arithmetic operators are used to perform arithmetic between variables and/or values.
+ Addition x=y+2;
- Subtraction x=y-2;
* Multiplication x=y*2;
/ Division x=y/2;
++ Pre-Increment x=++y;
Post-Increment x=y++;
-- Pre-Decrement x=--y;
Post-Decrement x=y--;
Assignment Operators
Assignment operators are used to assign values to JavaScript variables.
= x=y;
+= x+=y; x=x+y;
-= x-=y; x=x-y;
*= x*=y; x=x*y;
/= x/=y; x=x/y;
%= x%=y; x=x%y;
Comparison Operators
Comparison operators are used in logical statements to determine equality or difference between
variables or values.
Operator Description
== equal to
!= not equal
User Scripting
References 158
Operator Description
Logical Operators
Logical operators are used to determine the logic between variables or values.
Reserved Words
The following words cannot be used as JavaScript variables, functions, methods, or object names:
■ JavaScript Keywords
■ JavaScript Reserved Keywords
JavaScript Keywords
catch if typeof
continue in var
do return with
this
User Scripting
References 159
super
Escape Sequences
An escape sequence in created using a backslash to identify the special character.
\” Double quote
\\ Backslash
\b Backspace
\f Form feed
\n New line
\r Carriage return
\t Horizontal tab
\v Vertical tab
Note: If you include the backslash in front of any other character than those shown in the table,
JavaScript will ignore the backslash.
User Scripting
Scripting Best Practices 160
Development
■ Confirm that your development and production accounts have the necessary switches enabled.
You must have the “Enable user script support for Web Service API methods” feature to use the
NSOA.wsapi functions. See Scripting Switches.
User Scripting
SOAP / WSAPI 161
SOAP / WSAPI
■ Always check that any SOAP API call was successful before using the results. See Handling SOAP
Errors.
■ Where possible, batch a series of objects together into a single SOAP API call rather than making a
separate call for each object. See Making SOAP Calls.
■ The updated and created fields are maintained automatically by SuiteProjects Pro. You can read these
values, but they cannot be modified. See Making SOAP Calls.
■ You cannot delete an entity (database record) which has dependent records. You must first delete all
the dependent records. See Deleting data.
■ You must specify a limit attribute to read data. Make this limit as small as possible if you will only
access the first record (for example, set the limit attribute to 1). See Attribute and Reading data.
■ Don’t forget to specify the ‘update_custom’ attribute to update a custom field. See Updating Custom
Fields.
Logs
■ Use log messages to verify your script is executing as expected and to help you to troubleshoot scripts
which behave unexpectedly. Logs.
■ Set the log severity to “Warning” or “Error” to save space and improve system performance. See Log
Severity.
■ Set the log severity of a deployed script to "Debug" or "Trace" to track down errors which only occur
for a deployed script. See Log Severity.
■ Use the “delete log entries” maintenance task to delete log entries which are no longer needed. Use
this maintenance task when your system is not busy and be careful not to delete log entries which you
may need. See Delete Log Entries.
■ Always keep at least the last 30 days of logs. See Delete Log Entries.
Data Access
■ Make sure your script can run correctly for any user that may trigger the script. Form scripts are
executed within the context of the user who is signed in. See NSOA.wsapi.disableFilterSet( [ flag] ).
■ When setting “Select user to execute a script deployment”, create a dedicated user with the minimum
necessary permissions dedicated to this purpose. See Platform Role Permissions.
Governance
■ Make sure that none of the execution paths through your script will exceed the allowed units limit. See
Scripting Governance.
User Scripting
Maintainable Scripts 162
■ Don’t try to do too much in a script (especially in a form script). Make sure your script can finish well
within the allowed time limits. Your script needs to be able to run successfully even when the server is
under load. See Scripting Governance.
■ Always try to reduce the number of units your scripts consume. Notice that NSOA.record functions
consume zero units, but NSOA.wsapi functions consume 10 units for each call. See NSOA Functions.
Maintainable Scripts
■ Access custom fields using the __c notation (note the two underscore characters). The old approach
to read custom fields using custom_ with the internally assigned custom field number appended is
still supported but NOT recommended. In addition, scripts using the custom_ notation may not be
portable between environments, for example, from sandbox to production. See Reading Custom
Fields.
■ Reference custom fields used by the script. This will prevent changes to custom fields from
unintentionally breaking a script. See Updating Custom Fields.
■ Reference parameters used by the script. Referencing a parameter prevents the parameter from
being deleted or changed in a way which will affect the script. See Creating Parameters.
■ Use library scripts to package the complexity of a scripted solution into calling scripts and supporting
functions. This will result in scripts which are easier to build and maintain. You can build libraries of
proven functions to reduce the cost of future development and maintenance. See Creating Library
Scripts.
■ Use script parameters to create scripts which can be configured without needing to change the script.
See Creating Parameters.
■ Use script terminology to allow scripts to immediately reflect any terminology changes made by the
administrator. See Accessing Terminology.
■ Use platform solutions to package all the elements of a script into a single file. See Creating Solutions.
User Scripting
Real World Use Cases 163
Important: Oracle may provide sample code in SuiteAnswers, SuiteProjects Pro Help Center,
User Guides, or elsewhere through help links. All such sample code is provided "as is” and “as
available”, for use only with an authorized SuiteProjects Pro Service account, and is made available
as a SuiteCloud Technology subject to the SuiteCloud Terms of Service at www.netsuite.com/tos
where the term “Service” shall mean the SuiteProjects Pro Service.
Oracle may modify or remove sample code at any time without notice.
■ Validation
□ Ensure value of multiple commissions fields equals 100%
□ Require notes field to be populated on time entries when more than 8 hours in a day
□ When submitting an expense report, validate each ticket has an attachment (for example, scanned
receipt)
□ Ensure resource time entry matches booking planning and project worked hours
■ Automation
□ Optionally create a new Customer PO when editing a project
□ Create time entries from task assignments when the user creates a new timesheet
□ Control budgeted hours for a project using the transactional budget feature and a custom hours
field
■ Workflow
□ Prevent a booking from being created if the selected resource has approved time off during the
booking period
□ Prevent closing a project that has open issues
□ Automatically create a new issue when project stage is "at risk" and prevent project stage from
changing until this issue is resolved
□ Send an alert email when a scheduled script completes
□ Send a Slack notification when issues are created or (re)assigned
Note: Find these examples on the Platform Solutions catalog page in SuiteProjects Pro Help
Center. See Platform Solutions Catalog.
Note: You need to be signed in as an administrator to work with the development environment.
User Scripting
Platform Solutions Catalog 164
Tip: Save time by using the solution file link provided at the top of each setup section,
see Creating Solutions.
To view the platform solutions catalog, go to User Menu > Help Center > Platform Solutions. The page
lists all the real world user scripting examples described in this guide. Solutions are color coded by
category — Validation, Automation, Workflow — with a visual representation and a short summary to
indicate the purpose of each solution.
■ To save the solution XML file, click the DOWNLOAD link. You can then import the solution file from the
Scripting Center in SuiteProjects Pro.
■ To read the help topic describing the solution, click the LEARN MORE link.
User Scripting
Validation 165
Validation
A new custom Commission section has been added to the project form. A user script is triggered as the
project saves to validate the commission values entered.
Follow the steps below or download the solutions file, see Creating Solutions for details.
Setup
User Scripting
Validation 166
5. Set up the required number of custom field pairs for Project. The first in each pair is a Pick List
with a List source of User. The second in each pair is a Ratio. You can set the Divider text for the
first custom field to Commission to place the custom fields in their own section.
6. Use the Form schema to identify the correct param names for the custom fields and change the
array at the top of the script accordingly.
User Scripting
Validation 167
Tip: If the new custom fields are not listed in the Form schema, go to Projects, open a
project form (this with will refresh the custom field list), and then open the Scripting Studio
again.
Program Listing
// ADD YOUR REP AND RATIO CUSTOM FORM FIELD NAMES TO THE ARRAY BELOW
var repCompFlds = [
'prj_sales_rep_1__c', 'prj_sales_rep_ratio_1__c', // Use Form schema to find param names
'prj_sales_rep_2__c', 'prj_sales_rep_ratio_2__c'
];
function checkCommish(type) {
try {
var _len = repCompFlds.length,
_i = 1, // Skip over sales rep name
_j = 0,
totalComp = 0;
NSOA.form.error(
'',
'The total sales commission ' + totalCompRound +
' (' + round(totalCompPercent, 2) + '%) must equal 100%!'
);
} catch (e) {
NSOA.meta.log('fatal', "Error running the script: " + e);
}
User Scripting
Validation 168
Follow the steps below or download the solutions file, see Creating Solutions for details.
Setup
Program Listing
function require_timeentry_notes_daily_overtime() {
var readRequest = {
type: "Task",
fields: "id, date, decimal_hours, notes",
method: "equal to",
objects: [task],
attributes: [{
name: "limit",
value: "1000"
}]
};
User Scripting
Validation 169
Note: The Enable the missing paper receipt feature switch needs to be enabled for this
option.
Follow the steps below or download the solutions file, see Creating Solutions for details.
Setup
User Scripting
Validation 170
Program Listing
function check_receipt_has_attachments(type) {
var readRequest = {
type: "Ticket",
fields: "id, attachmentid, reference_number, missing_receipt",
method: "equal to",
objects: [ticket],
attributes: [{
name: "limit",
value: "250"
}]
};
if (missingAttachment.length > 0) {
NSOA.form.error('',
User Scripting
Validation 171
"The following receipts (by reference number) are missing an attachment: " +
missingAttachment.join(", "));
}
}
Follow the steps below or download the solutions file, see Creating Solutions for details.
Setup
1. Create a new Timesheet [Edit] form script deployment.
2. Enter a Filename and click SAVE. The extension ‘.js’ is automatically appended if not supplied.
3. Click on the script link to launch the Scripting Studio.
4. (1) Copy the Program Listing below into the editor, (2) set the Before approval event, and set
verify_timeentry_policy as the Entrance Function.
Program Listing
function verify_timeentry_policy(type) {
var timesheet = NSOA.form.getOldRecord();
// Only check on approval request and if current user is the timesheet owner
if (type != 'approve_request' || timesheet.userid != NSOA.wsapi.whoami().id)
return;
User Scripting
Validation 172
});
else
return; // assume no data found
// Now load and analyze project task assignments (one read request)
if (Object.keys(ptaFilters).length > 0) {
var equalTo = [];
for (var i = 0; i < Object.keys(ptaFilters).length; i++)
equalTo.push("equal to");
var ptaFilter = [];
Object.keys(ptaFilters).forEach(function(k) {
ptaFilter.push(ptaFilters[k]);
});
var pta_readRequest = {
type: "Projecttaskassign",
fields: "id, planned_hours, userid, projecttaskid",
method: equalTo.join(', or '),
User Scripting
Validation 173
objects: ptaFilter,
attributes: [{
name: "limit",
value: "1000"
}, {
name: "filter",
value: "current-user"
}]
};
NSOA.meta.log('debug', "pta_readRequest=" + JSON.stringify(pta_readRequest));
var pta_arrayOfreadResult = NSOA.wsapi.read(pta_readRequest);
NSOA.meta.log('debug', "pta_arrayOfreadResult=" + JSON.stringify(pta_arrayOfreadResult));
var worked_hours = 0;
if (!task_arrayOfreadResult || !task_arrayOfreadResult[0])
NSOA.form.error('', "Internal error loading %timeentry% assignment details.");
else if (task_arrayOfreadResult[0].errors === null && task_arrayOfreadResult[0].objects)
task_arrayOfreadResult[0].objects.forEach(function(task) {
worked_hours += parseFloat(task.decimal_hours);
});
User Scripting
Validation 174
if (Object.keys(bookingFilters).length > 0) {
var equalTo = [];
for (var i = 0; i < Object.keys(bookingFilters).length; i++)
equalTo.push("equal to");
var bookingFilter = [];
Object.keys(bookingFilters).forEach(function(k) {
bookingFilter.push(bookingFilters[k]);
});
var booking_readRequest = {
type: "Booking",
fields: "id, enddate, userid, project_taskid, projectid",
method: equalTo.join(', or '),
objects: bookingFilter,
attributes: [{
name: "limit",
value: "1000"
}, {
name: "filter",
value: "current-user"
}]
};
NSOA.meta.log('debug', "booking_readRequest=" + JSON.stringify(booking_readRequest));
var booking_arrayOfreadResult = NSOA.wsapi.read(booking_readRequest);
NSOA.meta.log('debug', "booking_arrayOfreadResult=" + JSON.stringify(booking_arrayOfreadResult));
if (!booking_arrayOfreadResult || !booking_arrayOfreadResult[0])
NSOA.form.error('', "Internal error loading %project_task% assignment details.");
else if (booking_arrayOfreadResult[0].errors === null && booking_arrayOfreadResult[0].objects)
booking_arrayOfreadResult[0].objects.forEach(function(booking) {
var uniqueKey = booking.project_taskid;
NSOA.meta.log('debug', uniqueKey + "," + JSON.stringify(tasks_by_uniqueKey));
var tasks = tasks_by_uniqueKey[uniqueKey];
if (!tasks)
return;
tasks.forEach(function(task) {
var taskDate = new Date(task.date.substr(0, 10));
taskDate.setDate(taskDate.getDate() + 1);
NSOA.meta.log('debug', JSON.stringify(task));
var bookingDate = new Date(booking.enddate.substr(0, 10));
NSOA.meta.log('debug', "Check: " + taskDate + '>' + bookingDate);
if (taskDate && bookingDate) {
if (taskDate > bookingDate) {
var pt = NSOA.record.oaProjecttask(booking.project_taskid);
NSOA.form.error('', "Task on date " + df.userDateFormat(taskDate) + " exceeds booking end date "
+ df.userDateFormat(bookingDate) + " for for %project% '" + NSOA.record.oaProject(pt.projectid).name + "' %project_task% '" +
pt.name + "'.");
return;
}
}
});
});
}
}
Automation
User Scripting
Automation 175
A new custom Quick Customer PO section has been added to the project form. A user script is triggered
as the project saves to create the specified customer PO.
The Create Customer PO box signals that a new customer PO record is to be created and the customer
PO fields cleared allowing the user to quickly create additional customer POs. When the project is saved
the specified Customer PO is then created.
Follow the steps below or download the solutions file, see Creating Solutions for details.
Setup
User Scripting
Automation 176
5. Set up the following custom fields for Project. You can set the Divider text for the first custom
field to Quick Customer PO to place the custom fields in their own section.
Program Listing
function createCustomerPO(type) {
try {
var FLD_CUSTPO_NUM = 'prj_custpo_num__c',
FLD_CUSTPO_AMT = 'prj_custpo_amt__c',
FLD_CUSTPO_DATE = 'prj_custpo_date__c',
User Scripting
Automation 177
FLD_CREATE_PO = 'prj_create_po__c';
// currency custom fields return ISO-#.##; remove the ISO code and dash
var cleanAmt = updPrj[FLD_CUSTPO_AMT].replace(/-\w{3}/, '');
recCustPO.currency = updPrj.currency;
recCustPO.customerid = updPrj.customerid;
recCustPO.active = 1;
if (!custPOResults || !custPOResults[0]) {
NSOA.meta.log('error', 'Unexpected error! Customer PO was not created.');
} else if (custPOResults[0].errors) {
custPOResults[0].errors.forEach(function(err) {
NSOA.meta.log('error', 'Error: ' + err.code + ' - ' + err.comment);
});
} else {
// new customer po to project link object
var recCustPOtoProj = new NSOA.record.oaCustomerpo_to_project();
recCustPOtoProj.customerpoid = custPOResults[0].id;
recCustPOtoProj.customerid = updPrj.customerid;
recCustPOtoProj.projectid = updPrj.id;
recCustPOtoProj.active = '1';
if (!custPOtoProjResults || !custPOtoProjResults[0]) {
NSOA.meta.log('error',
'Unexpected error! Customer PO was not linked to the project.');
} else if (custPOtoProjResults[0].errors) {
custPOtoProjResults[0].errors.forEach(function(err) {
NSOA.meta.log('error', 'Error: ' + err.code + ' - ' + err.comment);
});
}
User Scripting
Automation 178
if (!projResults || !projResults[0]) {
NSOA.meta.log('error', 'Unexpected error! Project was not updated.');
} else if (projResults[0].errors) {
projResults[0].errors.forEach(function(err) {
NSOA.meta.log('error', 'Error: ' + err.code + ' - ' + err.comment);
});
}
} else {
NSOA.meta.log('debug', 'Customer po creation was skipped.');
}
} catch (e) {
NSOA.meta.log('error', 'Uncaught error: ' + e);
}
}
When the user creates a new timesheet, toggle checkbox to have it prefilled with data fetched from the
current task assignments.
User Scripting
Automation 179
Follow the steps below or download the solutions file, see Creating Solutions for details.
Setup
User Scripting
Automation 180
Tip: If the new custom field is not listed in the Form schema, go to Timesheets, create
a new Timesheet form without saving (this with will refresh the custom field list), and then
open the Scripting Studio again.
Program Listing
var CUST_FIELD = 'ts_prefill_from_task_assignments__c'; // Use Form schema to find param name
function prepopulate_ts_from_assignments(type) {
var ts = NSOA.form.getValue(CUST_FIELD);
timesheet.id = newr.id;
timesheet.default_per_row = defaultPerRow;
//find the assignments for this user and return a string for timesheet.default_per_row
function find_assignments(userid) {
var readTasksAssign = {
type: "Projecttaskassign",
method: "equal to",
fields: "projecttaskid",
attributes: [{
name: "limit",
User Scripting
Automation 181
value: "0,1000"
}],
objects: [taskAssign]
};
var CSV = {
pt_id: [],
cp_id: []
};
var resultTaskAssign = NSOA.wsapi.read(readTasksAssign);
// iterate through all the task assignments and filter only current ones
// retrieve all tasks that belong to user, started in the past and percent_complete < 100
if (resultTaskAssign[0].errors === null && resultTaskAssign[0].objects) {
var readTask = {
type: "Projecttask",
method: "equal to",
fields: "calculated_starts,starts,percent_complete,customerid,id,projectid",
attributes: [{
name: "limit",
value: "0,1000"
}],
objects: [projectTask]
};
// do we have results?
if (resultTask[0].errors === null && resultTask[0].objects) {
for (var k = 0; k < resultTask[0].objects.length; k++) {
// do we have a date?
// NSOA.meta.alert('currentdate=' + currentDate + ' starts='+starts);
User Scripting
Automation 182
Note: Requires "Transactional budgets" feature enabled. For more information about the
transactional budget feature, see the help topic Transactional Budget.
Follow the steps below or download the solutions file, see Creating Solutions for details.
Setup
5. Set up an Hours custom field for Project and an Hours custom field for Budget.
User Scripting
Automation 183
Program Listing
function updateTransactionalBudgetHours(type) {
try {
// DEBUG: Remove the comment marks for next line to enable XML logging
// var wsLog = NSOA.wsapi.enableLog(true);
// list all fields used in script
var FLD_PRJ_ID = 'id',
FLD_PRJ_BUD_HRS = 'prj_budget_time__c',
FLD_BUD_PID = 'projectid';
User Scripting
Automation 184
[{
name: "update_custom",
value: "1"
}], [prjRec]
);
if (!prjResults || !prjResults[0]) {
NSOA.meta.log('error', 'Unexpected error! Project was not updated.');
} else if (prjResults[0].errors !== null && prjResults[0].errors.length > 0) {
prjResults[0].errors.forEach(function(err) {
var fullError = err.code + ' - ' + err.comment + ' ' + err.text;
NSOA.meta.log('error', 'Error: ' + fullError);
});
return;
}
} catch (e) {
NSOA.meta.log('error', 'Try/catch error: ' + e);
}
}
Workflow
Follow the steps below or download the solutions file, see Creating Solutions for details.
Setup
User Scripting
Workflow 185
4. (1) Copy the Program Listing below into the editor, (2) set the Before save event, and set
validate_vacation as the Entrance Function.
6. Use the Form schema to identify the correct param names for the custom fields and change the
array at the top of the script accordingly.
User Scripting
Workflow 186
Tip: If the new custom fields are not listed in the Form schema, go to Resources, open a
booking form (this with will refresh the custom field list), and then open the Scripting Studio
again.
Program Listing
// timetype_id depends on account settings
var CUST_FIELD = 'bk_override_vacation__c';
var CUST_FIELD_NOTES = 'bk_override_vacation_notes__c';
function validate_vacation() {
// To support exception situations where booking should be allowed over scheduled timeoff,
// new checkbox custom field with associated notes field has been added to Booking form.
// When that field is checked, we want the notes field to be required, so we validate the
// custom fields settings at the start.
var override = NSOA.form.getValue(CUST_FIELD);
var req_notes = NSOA.form.getValue(CUST_FIELD_NOTES);
// Pull the start and end dates for Schedulerequests that match our criteria
var aPTO = NSOA.wsapi.read({
type: 'Schedulerequest', // The SOAP API complex type
method: 'equal to',
fields: 'startdate,enddate', // start & end fields for Schedulerequest complex type
attributes: [{
name: 'limit', // ReadRequest objects must have a limit specified
value: '100' // '100' returns up to 100, '50,100' returns 50 - 100
}],
objects: [approvedSchedReq] // The previously created search object
});
User Scripting
Workflow 187
■ Enforces workflow requirement that all open issues be addressed before a project can be closed
Follow the steps below or download the solutions file, see Creating Solutions for details.
Setup
User Scripting
Workflow 188
The List source for the ProjectClosedStage Pick List parameter is “Project stage”.
The List source for the IssueOpenStage Pick List parameter is “Stage”.
2. Create a new Project form script deployment.
3. Enter a Filename and click SAVE. The extension ‘.js’ is automatically appended if not supplied.
4. Click on the script link to launch the Scripting Studio.
5. (1) Copy the Program Listing below into the editor, (2) set the Before save event, and set
test_prevent_project_close_with_open_issue as the Entrance Function.
Program Listing
var readRequest = {
type: "Issue",
fields: "id, date",
User Scripting
Workflow 189
if (!arrayOfreadResult || !arrayOfreadResult[0])
NSOA.form.error('', "Internal error analyzing project issues.");
Follow the steps below or download the solutions file, see Creating Solutions for details.
Note: You will still need to create the custom fields described in Setup 1 — Custom Field
Important: This example requires you to create a Project Stage. See the Administrator
Guide for more details on Project Stages.
User Scripting
Workflow 190
var readRequest = {
type: "Issue",
fields: "id, name, date",
User Scripting
Workflow 191
User Scripting
Workflow 192
function proj_at_risk_beforesave_validate() {
var PROJECT_STAGE_AT_RISK = NSOA.context.getParameter('ProjectAtRiskStage');
var ISSUE_STAGE_OPEN = NSOA.context.getParameter('IssueOpenStage');
var readRequest = {
type: "Issue",
fields: "id, name, date",
method: "equal to",
objects: [issue],
attributes: [{
name: "limit",
value: "1"
}]
};
if (!arrayOfreadResult || !arrayOfreadResult[0])
NSOA.form.error('', "Internal error analyzing project issues.");
Follow the steps below or download the solutions file, see Creating Solutions for details.
Setup
User Scripting
Workflow 193
Program Listing
function main() {
// TODO Add Your Code Here
NSOA.meta.sendMail(msg);
}
User Scripting
Workflow 194
The script also sends a direct message from the Slack app bot to notify employees whenever an issue has
been assigned to them.
Two different methods are used to post the messages. An incoming webhook is used to post messages
on a specific Slack channel. Slack API methods conversations.open and chat.postMessage are used
User Scripting
Workflow 195
to post direct messages to users from the app bot user. The script also uses the Slack API method
users.lookupByEmail to identify the Slack users direct messages should posted to.
Follow the steps below or download the solutions file, see Creating Solutions for details.
Note: You will need to create, configure and install a Slack app associated to your workspace.
See Setup 1 — Create, Configure and Install a Slack App.
■ Configure the Slack App used by the scripts to send notifications. See Setup 1 — Create, Configure and
Install a Slack App.
■ Define and set 3 parameters used by the library script. See Setup 2 — Script Parameters.
■ Create a library script to be used by the two form scripts. See Setup 3 — Slack Notification Library
Script.
■ Create scripts associated to the Issue and the Project Issue forms. See Setup 4 — Issue After Save /
Project Issue After Save
1. Open the Slack desktop application and sign in to your Slack workspace using an Administrator
account.
2. Click your workspace name in the top left.
3. Select Tools & Settings > Manage apps.
The Installed apps directory for your workspace opens on a new tab in your default web browser.
4. Click Build on the top right.
Either the Your Apps page or the Slack API documentation page appears.
5. Click Create New App or Start Building.
The Create an app window appears.
6. Select From scratch.
The Name app & choose workspace window appears
7. Enter the name of your application and the workspace associated with the app.
User Scripting
Workflow 196
User Scripting
Workflow 197
User Scripting
Workflow 198
19. Scroll back to the top of the page and click Install to <Workspace name> under OAuth Tokens.
The authorization page appears.
20. Review the permission scopes for the app you are about to install and select the channel wher
eyou want the app to post messages using the Incoming Webhook under Where should <App
name> post?.
Note: In this example, Slack users are identified using their email address. This requires
adding the permission scopes users:read and users:read.email. The users:read
permission scope enables the app to access profile information for all users on the Slack
workspace. If this is not desirable, an alternative method to identify users for sending direct
messages would be to use a custom field in SuiteProjects Pro to store a Slack user ID in the
employee records.
User Scripting
Workflow 199
23. Click Incoming Webhooks under Features in the app configuration menu.
The Incoming Webhooks page appears.
24. Take a note of the Webhook URL under Webhook URLs for Your Workspace. You will need this
when setting the script parameters in Setup 2 — Script Parameters.
Posting messages on a specified Slack channel as an app bot user can be done using a Webhook URL.
To post direct messages to Slack users as an app bot user, a Bot User OAuth Token is required. You will
need to set these as script parameters in Setup 2 — Script Parameters.
User Scripting
Workflow 200
The parameters created will be referenced in the library script created in Setup 3 — Slack Notification
Library Script.
/*
LIBRARY SCRIPT USED FOR ISSUE AND PROJECT ISSUE FORM SCRIPTS
*/
/**
* Post a message to slack after creating or modifying an issue.
* @param {Str} type Standard entrance function type.
*/
function postIssuesOnSlack(type) {
User Scripting
Workflow 201
// Get user, project, issue severity and issue stage records associated with the issue
var user = NSOA.record.oaUser(issue.user_id);
var project = NSOA.record.oaProject(issue.project_id);
var issueseverity = NSOA.record.oaIssueSeverity(issue.issue_severity_id);
var issuestage = NSOA.record.oaIssueStage(issue.issue_stage_id);
if (issuestage.considered_closed) {
messagetext = 'Issue *' + issue.name + '* is ' + issuestage.name + '.';
attachmenttitle = 'Issue ' + issuestage.name;
attachmentcolor = 'good';
issNotes = issue.resolution_notes;
attachmenticon = 'https://www.pngrepo.com/download/167754/checked.png';
}
var fields = [
{
title: 'Issue',
value: issName + ': ' + issDescr,
short: false
},
{
title: 'Customer : Project',
value: prjCustName + ' : ' + prjName,
short: false
},
{
title: 'Severity',
value: issSeverity,
short: true
},
{
title: 'Stage',
value: issStage,
short: true
},
{
User Scripting
Workflow 202
var issueattachment = {
fallback: messagetext,
color: attachmentcolor,
author_name: attachmenttitle,
author_icon: attachmenticon,
fields: fields,
footer: 'User Scripting API',
footer_icon: 'https://www.pngrepo.com/download/36709/programming-code-signs.png',
ts: createdEpoch
};
var assignedmessagetext = 'Issue *' + issue.name + '* has been assigned to you.';
var issueassignedattachment = {
fallback: assignedmessagetext,
color: 'danger',
author_name: 'Issue Assigned',
author_icon: 'https://www.pngrepo.com/download/30662/warning.png',
fields: fields,
footer: 'User Scripting API',
footer_icon: 'https://www.pngrepo.com/download/36709/programming-code-signs.png',
ts: createdEpoch
};
exports.postIssuesOnSlack = postIssuesOnSlack;
/**
* Post a message to a slack channel using a webhook URL.
* @param {Str} url The webhook url to post a message on a specific channel (required).
* @param {Str} text Text to display on message (required).
* @param {Array} attachments Array of attachment objects - must be provided if text param empty (optional).
* @return {Obj} An https.post response object.
*/
function postMessageToSlackChannel (url, text, attachments) {
// If attachments param is provided, and it is of type Array (isArray method isn't supported...)
User Scripting
Workflow 203
var headers = {
'Content-Type': 'application/json'
};
return response;
}
/**
* Post a Direct Message on Slack as bot using the Slack Web API.
* @param {Str} url The url for the slack workspace (required).
* @param {Str} auth Authorization token (required)
* @param {Str} text Text to display on message (required).
* @param {Str} recipient The email address of the recipient (required).
* @param {Array} attachments Array of attachment objects - must be provided if text param empty (optional).
* @return {Obj} An https.post response object.
*/
//Construct headers
var headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + auth
};
// Open Conversation and get Slack Channel ID - return if Slack Channel not identified
var request = {
url : url + '/api/conversations.open',
body: { users: recipientId },
headers: headers
};
//Construct body
var body = {channel: channelId};
// If attachments param is provided, and it is of type Array (isArray method isn't supported...), append to body
if (attachments && Object.prototype.toString.call(attachments) === '[object Array]') { body.attachments = attach
ments; }
request = {
url: url + '/api/chat.postMessage',
body: body,
headers: headers
};
User Scripting
Workflow 204
response = NSOA.https.post(request);
return response;
}
/**
* Lookup Slack user ID by email.
* @param {Str} url The url for the slack workspace (required).
* @param {Str} auth Authorization token (required)
* @param {Str} email The email address of the user (required).
* @return {Str} A Slack user ID.
*/
var request = {
url: url + '/api/users.lookupByEmail?token=' + auth + '&email=' + email,
headers: {'Content-type': 'application/x-www-form-urlencoded'}
};
/**
* Converts a datetime string into a javascript date object.
* @private
* @param {Str} dateStr Datetime string.
* @return {Obj} Date object.
*/
function _convertStringToDateParts(dateStr) {
var regEx = /^(\d{4})-(\d{2})-(\d{2}) (\d{1,2}):(\d{1,2}):(\d{1,2})$/;
var match = regEx.exec(dateStr);
return d;
}
/**
* Converts a datetime string to epoch time.
* @param {Str} dateStr A datetime string.
* @return {Int} An epoch date value.
*/
function convertTimestampToEpoch(dateStr) {
var d = _convertStringToDateParts(dateStr);
return d.getTime() / 1000;
}
/**
User Scripting
Workflow 205
5. Click Save.
The library script will be referenced by the two form scripts created in Setup 4 — Issue After Save / Project
Issue After Save.
function afterSaveIssue(type) {
var SlackMessageReIssues = require('SlackMessageReIssues');
SlackMessageReIssues.postIssuesOnSlack(type);
}
User Scripting
User Scripting Release History 206
October 7, 2024
—
October 8, 2022
■ Added Clear Log Entries for a Specific Script — Clear all log entries for a specific script from the
Scripting Center.
■ Updated NSOA.meta.sendMail(message) — Increase the maximum body length of email messages
that can be sent from your form or scheduled scripts.
April 9, 2022
■ Added OData Explorer — Browse OData resources and columns available in these resources when
creating your scripts in the scripting studio.
■ Updated NSOA.report.data(reportId,optionalParameters) — Use select and filter query options to
target exactly the information you need from published reports.
■ Added NSOA.context.getLanguage() — Get the user’s display language preference from your form
scripts.
October 9, 2021
■ Added NSOA.NSConnector.integrateWorkflowGroup(name)
■ Updated NSOA.report.list() — Each item in the returned list has an additional property: PublishType —
The scope of use specified for the published report.
User Scripting
April 18, 2020 207
User Scripting
April 15, 2017 208
User Scripting