NetSuite CPQ Ecommerce Integration
Install NetSuite CPQ Configurator to use the NetSuite CPQ Ecommerce Integration. For more information, see Installing NetSuite CPQ SuiteApps.
With the NetSuite CPQ Ecommerce Integration, you can convert standard line items into configured line items and update transactions in the background using NetSuite CPQ Configurator products. For example, you can process transactions with line items added from SuiteCommerce web stores or other ecommerce platforms. You can use line items or information from custom line fields as materials, create a configuration with those materials, delete the existing line items on the transaction, and add the configured line item.
The transaction processing is handled by the CPQE-SC-BCL script (customscript_cpqe_sc_bcl), which is the scheduled script of the NetSuite CPQ Ecommerce Integration. To convert line items into a configured line item, create a server-side script to launch the CPQE-SC-BCL scheduled script and a NetSuite CPQ Configurator product.
The most common use case is launching the scheduled script from a user event script, which runs when users save or edit a transaction. The user event script contains a custom condition and the NetSuite CPQ Configurator product ID. The custom condition determines whether the scheduled script should be launched for a particular transaction.
Although the NetSuite CPQ Ecommerce Integration uses NetSuite CPQ Configurator products, it doesn't support some of their capabilities. See the following list:
-
Item creation records and creation records.
-
Setting transaction fields based on configuration data using mapping records.
-
Searching tables using SuiteQL.
-
Sourcing prices from materials.
-
Showing additional item prices in the Summary.
To convert line items into a configured line item:
-
Create a NetSuite CPQ Configurator product.
-
Create all required building blocks, such as materials and routing steps.
-
In the product, create actions that include the tasks to generate a configuration from the line items on the transaction.
Note:Follow JavaScript ES5 specifications to write the actions' code. The NetSuite CPQ Ecommerce Integration doesn't support JavaScript ES6 for actions.
Unlike NetSuite CPQ Configurator, the NetSuite CPQ Ecommerce integration doesn't distinguish between client-side and server-side actions; all actions run on the server. For this reason, don't use native JavaScript code that interacts with the browser window and the DOM.
If you want to use the same product in NetSuite CPQ Configurator and the NetSuite CPQ Ecommerce Integration, create separate actions for native JavaScript client-side code and add
X(SOLE/BC)as a rule. -
In the Rule field of the actions, enter the
SOLE/BCpredefined answer. With this predefined answer, the action will run only if the product is launched by the NetSuite CPQ Ecommerce Integration. -
Verify whether the product is correctly set up using the debugging tool. For more information, see Testing and Debugging the Conversion into Configured Items.
-
-
Create the script to launch the NetSuite CPQ Ecommerce Integration.
-
In SuiteScript 2.x, create one of the following server-side script types to launch the CPQE-SC-BCL scheduled script:
-
Suitelet
-
RESTlet
-
User-event
-
Scheduled
-
-
In the server-side script, pass the following parameters to the CPQE-SC-BCL script:
-
custscript_cpqe_scf_productid- Internal product ID.Note:To view the internal product ID, go to CPQ > Configurator > Product Maintenance. In the product list, find the product ID and view the value under the Internal ID column.
-
custscript_cpqe_scf_rectype- Transaction type. -
custscript_cpqe_scf_oid- Transaction ID. -
custscript_cpqe_scf_nosub(no submit) - Defines whether the transaction will be updated (trueorfalse). It's false by default, so the transaction will be updated if you omit the parameter.
See the following example:
define(['N/task'], (_nTask) => { // [...] _nTask.create({ taskType: _nTask.TaskType.SCHEDULED_SCRIPT, scriptId: 'customscript_cpqe_sc_bcl', params: { custscript_cpqe_scf_productid: '13', custscript_cpqe_scf_rectype: 'salesorder', custscript_cpqe_scf_oid: '1086', custscript_cpqe_scf_nosub: false } }); // [...] -
-
Add the custom condition that determines whether the transaction should be processed. For example, a certain field on the transaction has a certain value.
Note:If you don't want the transaction to be processed multiple times when it's edited, make sure you reset the custom condition. You can reset the custom condition in the server-side script or in actions in the NetSuite CPQ Configurator product.
-
-
Launch the CPQE-SC-BCL script (customscript_cpqe_sc_bcl) from the server-side script. As an example, see Starting the Conversion Process to Configured Item from a User-Event Script.
-
Deploy the server-side script on the transaction. For more information, see Deploying a Script by using the Deployments Sublist.
Starting the Conversion Process to Configured Item from a User-Event Script
The example shows a user event script deployed on the sales order record. This script runs when users or other scripts create or edit this transaction type. For this reason, the runAfterSubmit function in this example is assigned to the afterSubmit event. Because the scripts runs for edited transactions, the custom condition is reset to avoid processing the transaction multiple times.
This example also includes code to handle issues that prevent the request to be added to the task queue when the scheduled script is launched. The user event script creates the CPQE-BC-Launch-Request custom record with information about the launch request-also known as postponed launch record.
The CPQE-SC-ScanBCLTasks scheduled script runs every 15 minutes to verify whether there are launch request records. Then, this script launches the NetSuite CPQ Ecommerce Integration for every created postponed launch record. If the launch is successful, the postponed launch record is removed. Otherwise, if there are too many requests, the script will try again later.
/**
* @NApiVersion 2.1
* @NScriptType UserEventScript
*/
define(['N/log', 'N/runtime', 'N/record', 'N/task'], (_nLog, _nRuntime, _nRecord, _nTask) => {
const runAfterSubmit = (context) => {
const type = context.type;
_nLog.debug({ title: 'UE check', details: type });
// Runs when creating or updating existing transactions
if (type !== context.UserEventType.CREATE && type !== context.UserEventType.EDIT) {
return;
}
const rec = context.newRecord;
const recType = rec.type;
const recId = rec.id;
const productId = 18; // NetSuite CPQ Configurator product ID
if (checkLaunchCriteria(rec)) {
const data = {
custscript_cpqe_scf_productid: productId,
custscript_cpqe_scf_rectype: recType,
custscript_cpqe_scf_oid: recId,
custscript_cpqe_scf_nosub: false
};
_nLog.debug({ title: 'Now processing order', details: recId });
// Direct launch of the CPQE-SC-BCL scheduled script
const status = directLaunch(data);
if (status === _nTask.TaskStatus.QUEUED) {
resetLaunchCriteria(recType, recId);
} else {
_nLog.debug({ title: 'ERROR', details: 'Direct launch failed' });
// Postponed launch using the launch request record
const id = postponedLaunch(data);
if (id) {
_nLog.debug({ title: 'Postponed launch successful', details: id });
} else {
_nLog.debug({ title: 'ERROR', details: 'Postponed launch failed' });
}
}
}
};
// Verifies the custom condition
function checkLaunchCriteria(rec) {
const memo = rec.getValue({ fieldId: 'memo' });
return memo === 'bc';
}
// Resets the custom condition
function resetLaunchCriteria(recType, recId) {
_nRecord.submitFields({
type: recType,
id: recId,
values: {
memo: ''
}
});
}
// Launch of the scheduled script
function directLaunch(params) {
try {
const scheduledScriptTask = _nTask.create({
taskType: _nTask.TaskType.SCHEDULED_SCRIPT,
scriptId: 'customscript_cpqe_sc_bcl',
params: params
});
const taskId = scheduledScriptTask.submit();
_nLog.debug({ title: 'Direct launch status', details: 'QUEUED: ' + taskId });
return _nTask.TaskStatus.QUEUED;
} catch (e) {
_nLog.error({ title: 'Direct launch error', details: e.message });
return 'FAILED';
}
}
// Postponed launch (create launch request record)
function postponedLaunch(data) {
try {
const r = _nRecord.create({
type: 'customrecord_cpqe_bc_lrequest',
isDynamic: true
});
r.setValue({ fieldId: 'custrecord_cpqe_bc_lrequest_prodid', value: data.custscript_cpqe_scf_productid });
r.setValue({ fieldId: 'custrecord_cpqe_bc_lrequest_rec_type', value: data.custscript_cpqe_scf_rectype });
r.setValue({ fieldId: 'custrecord_cpqe_bc_lrequest_order_id', value: data.custscript_cpqe_scf_oid });
return r.save();
} catch (e) {
_nLog.error({ title: 'Postponed launch error', details: e.message });
return null;
}
}
// Assigns the runAfterSubmit function to the afterSubmit event
return { afterSubmit: runAfterSubmit };
});