Best Practices for Using Scriptable Cart with SuiteCommerce or SCA

Working with Scriptable Cart presents a challenge that is different from typical SuiteCommerce customizations. To be successful, you have to develop knowledge of SuiteScript using the resources made available by NetSuite. Therefore, Scriptable Cart customizations are not something that a beginner should attempt to implement on a live Commerce website without training or experience.

The guidelines in the following sections can help make your Scriptable Cart code better, faster, and more efficient.

Always Include a Custom Recalc Function

If your script is relatively small and only makes a line change, you may think it is fine to run checks only on modifications of that line. However, several issues can occur with Scriptable Cart customizations when no checks are performed during recalculation. Accessing only a line during checkout will likely cause problems, so be sure to always include a custom recalc function.

Build and Use a Cache Object

Calling records is expensive in terms of performance. Try to find ways to limit these calls so that your script is as close to pure JavaScript and SuiteScript as possible. One practice to consider is to build local cache objects rather than repeatedly calling the server for the same record.

For example, if you need to access item pricing information, you can save it as a session object as shown in the following sample:

            var context = nlapiGetContext();
var ITEM_PRICING = context.getSessionObject('ITEM_PRICING');
context.setSessionObject('ITEM_PRICING', JSON.stringify(ITEM_PRICING)); 

          

Saving item pricing as a session object enables you to call your local variable when you need pricing information. This works with records, searches, and Suitelets too.

Use a Global Variable to Prevent Recursion

It is possible that no matter how well you write your code, you may end up processing the same records, lines, and fields multiple times. Unfortunately, this is not optimal.

Recursion typically occurs when you write some code in a recalc function, which then triggers a line change event, which then requires a recalc event, and so on. For example, you might change an item rate in a recalc function and because you are changing a field, it triggers a fieldChange event. Because the field has changed, it triggers a recalc.

To avoid recursion, you should lock your code so that you process it serially and prevent any loops. To lock your code, you can use flags that cause functions to end and avoid loops.

So, for example, you can write a custom recalc function like this:

            // Create a variable to be used as a boolean flag
var IS_PROCESSING = false;

function customRecalc (type, action)
{
  // As is good practice, check to see if you are in the webstore. If not, the function ends and does not run any additional code
  if (nlapiGetContext().getExecutionContext() !== 'webstore') {return true}

  // Check what type and action you are dealing with
  if (type === 'item' && (action == 'commit' || action == 'remove'))
  {
    // Check to see if you are already processing some code; if so, stop and don't run any more code
    if (IS_PROCESSING) {return true}
    
    // If not, then run the code related to this function
    try
    {
      // You are now processing code, so flag it to true for now. If another function (or this function) is called again, it won't process until this one is done.
      IS_PROCESSING = true;

      // Now you can run the function you want to run
      theFunctionWeWantToRun();
    }
    
    // Error handling
    catch (e)
    {
      nlapiLogExecution('ERROR', 'Error', e);
    }

    // The last thing to do is set the variable back to false
    finally
    {
      IS_PROCESSING = false;
    }
  }
} 

          

The comments in the preceding sample provide more information about this approach. The main idea is that you include a global variable, IS_PROCESSING in this example, that is set to false until you are processing code, and then it is set to true. Then, throughout your script, you include checks for the IS_PROCESSING global variable.

fieldChanged and postSourcing Functions

A fieldChanged event occurs when a field is changed by the user or by a client-side API call. For example, if you use rules to control when shipping should not be charged, and this functionality cannot be accomplished using standard shipping items or promo codes. In a case like this, you need to listen for a shippingcost field change, and if the conditions are met, set it to 0.

A postSourcing event is similar, except that it listens for changes to fields that have their values sourced from sublists. For example, to listen for changes to shippingtaxcode, you have to use a custom postSourcing function. Another crucial difference is that postSourcing is called only after all sourcing is completed—it waits for any dependent or cascaded field changes to complete before calling the user-defined function. Therefore, the event handler is not triggered by field changes for a field that has no dependent fields.

Consider the following example that provides free shipping:

            function customFieldChange (type, name)
{
  if (nlapiGetContext().getExecutionContext() !== 'webstore') {return true}
  
  if (name === 'shippingcost')
  {
    if (IS_PROCESSING) {return true}

    IS_PROCESSING = true;
    
    // ie theFunctionWeWantToRun();
    nlapiSetFieldValue('shippingcost', 0);
    
    IS_PROCESSING = false;
  }
} 

          

You can do something similar to the preceding example using postSourcing. In the following example, the business case we want to support is that shipping tax does not need to be calculated in the web store because it has already been included in the pricing on the shipping cost. So, you can use the postSourcing function and listen for the shippingtaxcode field.

            function customPostSourcing(type, name) {
  if(nlapiGetContext().getExecutionContext() !== 'webstore') {return true}

  if (name === 'shippingtaxcode')
  {
    if (IS_PROCESSING) {return true}

    IS_PROCESSING = true;

    // ie theFunctionWeWantToRun();
    nlapiSetFieldValue('shippingtax1rate', 0);

    IS_PROCESSING = false;
  }
} 

          

Related Topics

Scriptable Cart Fundamentals and Set Up
Start Using Scriptable Cart with SuiteCommerce or SCA
Basic Custom Functions
Scriptable Cart Gift Card Example for SuiteCommerce or SCA
Debugging Scriptable Cart for SuiteCommerce or SCA

General Notices