Converting Transaction Line Items into Configured Items with a Single Scheduled Script Call

When converting transaction line items into configured items using NetSuite CPQ Ecommerce Integration, you should process as much line items as possible in a single call to the SuiteApp scheduled script (CPQE-SC-BCL script, ID customscript_cpqe_sc_bcl) for better performance.

When using the same product for the conversion, you should also keep the code modular and split into several actions to simplify code writing and maintenance. For this purpose, you can use the submitConfig() function with the restart parameter.

When using multiple products for the conversion, you can improve performance for large transactions by minimizing the calls to the NetSuite CPQ Ecommerce Integration scheduled script and, consequently, transaction saves-each call corresponds to a transaction save. To switch between multiple products in a single script call, you can prepare the conversion process using a common action that includes the submitConfig() function with the restart and product parameters. Alternatively, you can use the restartConfig() function in a dedicated product that only prepares the list of tasks for the conversion into configured items and delegates the rest of the processing to other products. See Preparing the Conversion Process Using a Common Action and Preparing the Conversion Process Using a Dedicated Product.

If you don't use the restart and product parameters for the submitConfig() function or the restartConfig() function with a dedicated product, you can only work with one product in a single script call and you must organize the product logic into a single action. This approach isn't optimized for code maintenance and performance. See Using the the submitConfig() Function without the restart and product Parameters.

Preparing the Conversion Process Using a Common Action

To make multiple submissions for different products in a single script call, you can create a common action in NetSuite CPQ Configurator and add it to every product. The common action will contain the code that prepares the list of conversion tasks. When writing the user event script that launches the NetSuite CPQ Ecommerce Integration script, make it call one of the products to which the common action is assigned and, then, the products will call each other. For more information about common actions, see Sharing Code with Common Actions.

You should use a common action and add it to every product because the product that will be started by the user event script isn't usually known beforehand. This way, no matter which product would be started by the user event script, the first task the products will perform will be analyzing the transaction and prepare the list of task. Then, other products will be launched one by one and perform the rest of the conversion process.

The following code snippets provide an example about organizing the actions' flow when using a common action to prepare the conversion process. For simplicity, the common action example uses fixed data. However, transaction line data is usually obtained through a getData() request that loads all transaction line items, analyzes them, and determines how many submission should be performed and which products to use.

In the common action, initializing the counter to restart the actions' processing multiple times is required. To process the next line, the counter is increased in the last action of the queue for each iteration.

            // Common action

window.tasks = window.tasks || [
    { materials: ['C1','C2'] },
    { product: 33, materials: ['C2','C3'] },
    { product: 34, materials: ['C1','C2','C3'] }
];
window.counter = window.counter === undefined ? 0 : window.counter; 

          

The second action reads the current task using the counter, clears any prior selections for the materials question, applies each material from the task, and writes a description to a transaction field.

            // Second action. Setting materials

var task = window.tasks[window.counter];

var description = 'Product: ' + (task.product || 'initial') + ', Materials: ';

reset('MATERIALS');

task.materials.forEach(function(material) {
    setValue('MATERIALS', material);
    description += material + ' ';
});

setValue('NS_ORDCOL','description', description); 

          

The last action logs the current task, increments the counter to move to the next transaction line, and determines if more tasks remain and which product to use next. Lastly, it submits the configuration. If more tasks remain, it requests a restart using the submitConfig() function and the processing flow begins again from the first before-event action, and continue to refresh building blocks, and run after-event actions. If a product ID is specified, the processing flow will switch to a different product. For more information, see submitConfig().

            // Third action. Submitting the configuration

var nextProduct, haveMoreTasks;
console.log('---> DOING TASK =', window.tasks[window.counter]);

window.counter++;

if (window.tasks[window.counter]) {
   haveMoreTasks = true;
   nextProduct = window.tasks[window.counter].product;
}

submitConfig({ afterSubmitAction: 'new', restart: haveMoreTasks, product: nextProduct }); 

          

Preparing the Conversion Process Using a Dedicated Product

As an alternative to the common action, you can use a dedicated product to prepare the conversion process. The user event script will call the dedicated product to prepare the transaction data without submitting any configuration. Then, the dedicated product will call the first product that will be used to convert the line items.

The dedicated product will contain a single action that loads the transaction lines, analyzes them, initializes the counter, prepares the list of tasks, and delegates the rest of the conversion process and the submissions to other products. To restart the processing flow without submitting the configuration, the dedicated product will use the restartConfig() function and pass the ID of the product to be used. For more information, see restartConfig().

This approach is useful if you prefer to keep the preparation logic separate from the submission logic that happens in the other products. However, one additional product launch increments a few seconds the transaction processing, but this added time won't be noticeable for large transactions.

See an example of a dedicated product single action:

            window.tasks = window.tasks || [
    { product: 32, materials: ['C1','C2'] },
    { product: 33, materials: ['C2','C3'] },
    { product: 34, materials: ['C1','C2','C3'] },
];
window.counter = window.counter === undefined ? 0 : window.counter;

restartConfig({ product: window.tasks[0].product }); 

          

Using the the submitConfig() Function without the restart and product Parameters

If you use the submitConfig() function without the restart and product parameters, you'll be able to only work with one product in the same script call and you'll need to organize the product logic into a single action. Using recalcRulesets() to refresh building blocks will also be required. For more information, see submitConfig().

The following snippet of code iteratively converts multiple transaction lines into configured items for the same product in one script call. However, you can't swap to different products within the same script call, which would decrease performance on mixed-product transactions.

            console.log('Loading lines...');
var items = getTransactionLines();
console.log('ITEMS', items);

items.forEach(function (item) {
   console.log('Submit configuration : line', item.line);
   setValue('SOLE', 'LINENUM', item.line);
   setValue('NS_ORDCOL', 'custcol_vt_config', 'PROCESSED');
   // Resets and sets the question and answer combinations: MATERIALS/C1, MATERIALS/C2, MATERIALS/C3
   reset('MATERIALS');
   var components = item.config.split(','); // "C1,C2,C3" -> ["C1","C2","C3"]
   console.log('Materials:', components);
   components.forEach(function (component) {
      setValue('MATERIALS', component);
   });
   recalcRulesets(); // Required. Updates additional items, materials, routing steps, prices
   submitConfig({ afterSubmitAction: 'new' });
});

// Gets all transaction lines with custom configurations: custcol_vt_config is populated and !== "PROCESSED"
function getTransactionLines() {
   var tranType = getValue('NS', 'RECTYPE');
   tranId = getValue('NS', 'TRANID'),
      lines = [];
   getData({
      type: tranType,
      filter: ['internalid', 'is', tranId],
      sublists: { item: ['custcol_vt_config'] },
      loadapi: true,
      async: false
   }).done(function (data) {
      data[0].sublists.item.forEach(function (item, index) {
         if (item.custcol_vt_config && item.custcol_vt_config !== 'PROCESSED') {
            lines.push({
               line: index + 1,
               config: item.custcol_vt_config
            });
         }
      });
   });
   return lines;
} 

          

Related Topics

General Notices