Skip to main content

Product Selector JavaScript Plugin

Zuora

Product Selector JavaScript Plugin

In Zuora Quotes, you can implement a custom JavaScript plugin to programmatically set values of the standard and custom fields on the charge rows in the Lightning Guided Product Selector. When you write a custom JavaScript file that implements predefined functions and upload that file into Salesforce, Zuora Quotes executes the custom code when your user updates a value on a charge line item in the Product Selector.

The JavaScript plugin is only available in the new Lightning Guided Product Selector of the version 7.0 and later. The Titanium Product Selector does not support the JavaScript plugin.

Update Charge

Signature

zquGlobalPlugin.updateZCharge(zCharge)

Description

The zquGlobalPlugin.updateZCharge method triggers an update of the field values on the input parameter charge as below:

  • Non-pricing fields on the input Quote Rate Plan Charge. You can update multiple non-pricing fields with the plugin. Updating these fields do not trigger a recalculation of the price.
  • One pricing field at a time

The plugin can set one of the following field values on the Quote Rate Plan Charge object. Setting these fields will trigger a recalculation.

  • Quantity
  • Discount
  • Effective Price
  • Total

The zquGlobalPlugin.updateZCharge method will return an error if more than one pricing field was updated between the current charge and previous version of the charge.

Number of pricing fields updated 

Behavior

2 Throws an error "Multiple pricing fields updated on zCharge {zCharge.Id}: {zCharge.Name}"
1 Updates the pricing field in addition to custom field and non-pricing fields
0 Updates custom fields and non-pricing fields
  • If the Orders feature is enabled in your org, the updates by the plugin trigger a cascade recalculation against future segments of the charge.

    This feature is only available if you have the Orders feature enabled. 

Post Recalculation

Signature

ProductSelectorPlugin.postRecalculateZCharge(

   previousCharge,

   currentCharge,

   zChargeGroup,

   quote,

   allChargeGroups)

Description

In your JavaScript plugin, define ProductSelectorPlugin.postRecalculateZCharge and make the call to the zquGlobalPlugin.updateZCharge method inside the function.

Inject Custom JavaScript

To inject a custom JavaScript:

  1. Implement your custom JavaScript.
  2. Browse to Setup > Develop > Static Resources.
  3. Click New.
  4. Specify the following field values:
    • Name: Specify ProductSelectorPlugin. Only the JavaScript with the exact name is recognized in the Product Selector.
    • In the File field, Upload the JavaScript file you created in the Step #1.
    • Cache Control: Set to Public

Sample Code

The below is a sample code for Product Selector Plugin.

// Define the plugin method as a global object
var ProductSelectorPlugin = function(){
    return {
        postRecalculateZCharge : function(previousZCharge, 
            currentZCharge, chargeGroup, quote, allChargeGroups) {
            // If the user sets the discount to 30, reset the discount to be 90
            if(currentZCharge['DISCOUNT'] == 30.00) {
                currentZCharge['DISCOUNT'] = '90';
                zquGlobalPlugin.updateZCharge(currentZCharge);
            }
            // If the quantity exceeds 1000, reset the value to exactly 1000
            else if(currentZCharge['QUANTITY'] > 1000) {
                currentZCharge['QUANTITY'] = 1000;
                zquGlobalPlugin.updateZCharge(currentZCharge);
            }
        }
    };
}();

The below is a sample code using custom fields in Product Selector Plugin.

var ProductSelectorPlugin = function(){
    return {
        postRecalculateZCharge : function(previousZCharge,
            currentZCharge, chargeGroup, quote, allChargeGroups) {
             
            // Plain charges receive 0% discount, Gold receive 10% discount, 
            // Platinum receive 20% discount
            if(currentZCharge.chargeObject['family__c'] == 'Plain') {
                currentZCharge['DISCOUNT'] = '0';
                zquGlobalPlugin.updateZCharge(currentZCharge);
            }
            else if(currentZCharge.chargeObject['family__c'] == 'Gold') {
                currentZCharge['DISCOUNT'] = '10';
                zquGlobalPlugin.updateZCharge(currentZCharge);
            }
            else if(currentZCharge.chargeObject['family__c'] == 'Platinum') {
                currentZCharge['DISCOUNT'] = '20';
                zquGlobalPlugin.updateZCharge(currentZCharge);
            }
        }
    };
}();

The sample code below implements the Product Selector Plugin that changes prices based on billing frequency. 

var ProductSelectorPlugin = function(){
    return {
        postRecalculateZCharge : function(previousZCharge,
            currentZCharge, chargeGroup, quote, allChargeGroups) {
            // Only proceed if the Effective Price is editable
            if(!currentZCharge.isEffectivePriceEditable) return;
            var updatedBillingFrequency = 
                currentZCharge.chargeObject['billingfrequency__c'];
            var previousBillingFrequency = 
                previousZCharge.chargeObject['billingfrequency__c'];
            // If there is no change in billing frequency, 
            // do not recalculate pricing fields
            if(updatedBillingFrequency == previousBillingFrequency) return;
            var priceMultiplier = 1;
             
            if(updatedBillingFrequency == 'Monthly') {
                if(previousBillingFrequency == 'Bi-Annually') priceMultiplier = 6;
                else if(previousBillingFrequency == 'Annually') priceMultiplier = 12;
            }
            else if(updatedBillingFrequency == 'Bi-Annually') {
                if(previousBillingFrequency == 'Monthly') priceMultiplier = 1/6;
                else if(previousBillingFrequency == 'Annually') priceMultiplier = 2;
            }
            else if(updatedBillingFrequency == 'Annually') {
                if(previousBillingFrequency == 'Monthly') priceMultiplier = 1/12;
                else if(previousBillingFrequency == 'Bi-Annually') 
                    priceMultiplier = 1/2;
            }
            // Calculate the new price and perform recalculation
            var updatedPrice = 
                parseFloat(currentZCharge.EFFECTIVE_PRICE) * priceMultiplier;
            currentZCharge['EFFECTIVE_PRICE'] = updatedPrice.toString();
            zquGlobalPlugin.updateZCharge(currentZCharge);
        }
    };
}();

The sample code below implements the Product Selector Plugin that updates all the charges in the charge groups being passed in.

var ProductSelectorPlugin = function () {

  return {
    postRecalculateZCharge: function (previousZCharge, currentZCharge, chargeGroup, quote, allChargeGroups) {
      var currentQuantity = currentZCharge['QUANTITY'];
      var currentModel = currentZCharge['MODEL'];
      var currentDiscount = currentZCharge['DISCOUNT'];

      try {
        // if the current discount is set to 100, alert the user and revert
        if (parseFloat(currentDiscount) === 100.0) {
          alert('Cannot set discount to 100%');
          currentZCharge['DISCOUNT'] = previousZCharge['DISCOUNT'];
          zquGlobalPlugin.updateZCharge(currentZCharge);
          return;
        }

        // for all zCharges of the same model, update to the same Quantity and Discount
        allChargeGroups.forEach(function (group) {
          group.zCharges.forEach(function (charge) {
            if (charge['MODEL'] === currentModel) {
              if(charge['QUANTITY'] !== '-' && charge['isQuantityEditable']) {
                charge['QUANTITY'] = currentQuantity;
              }
              if(charge['isDiscountEditable']) {
                charge['DISCOUNT'] = currentDiscount;
              }
              zquGlobalPlugin.updateZCharge(charge);
            }
          });
        });
      } catch (e) {
        alert('Error occurred: ' + e.message);
      }
    }
  };
}();

Fields impacted by Display Scale Settings

Use the below sample code to obtain the fields that are impacted by display scale settings:

var ProductSelectorPlugin = function(){
    return {
        postRecalculateZCharge : function(previousZCharge,
            currentZCharge, chargeGroup, quote, allChargeGroups) {
            allChargeGroups.forEach(function (group) {
          group.zCharges.forEach(function (charge) {
            if(charge['Id'] === currentZCharge['Id']){
              console.log('currentZCharge-->' , JSON.stringify(currentZCharge));
              //All fields that are impacted by Display Scale Settings will be displayed.
              }
          });
        });
       }
    };
}();

Fields not impacted by Display Scale Settings

Use the below sample code to obtain the fields that are not impacted by display scale settings:

var ProductSelectorPlugin = function(){
    return {
        postRecalculateZCharge : function(previousZCharge,
            currentZCharge, chargeGroup, quote, allChargeGroups) {
            allChargeGroups.forEach(function (group) {
          group.zCharges.forEach(function (charge) {
            if(charge['Id'] === currentZCharge['Id']){
              console.log('charge.zqc-->', JSON.Stringify(charge.zqc));
              //Inspect the log; fields prefixed with 'd_' like d_EffectivePrice will remain unaffected.
              }
          });
        });
       }
    };
}();

To retrieve a particular field while disregarding display scale settings, you can use the subsequent code snippet:

For instance, to acquire the effective price without adhering to display scale settings.
console.log(‘effective price-->’, charge.zqc.d_EffectivePrice));

Troubleshoot your implementation

If you encounter issues when using the Product Selector JavaScript plugin, try the following steps to facilitate troubleshooting:

  1. Check and ensure that you upload files in the .JS format. If you upload a file in the .JS format, the MIME type is text/javascript. If you upload a text file, the MIME type is text/plain, which can result in plugin errors.
  2. If you find that the plugin is not working, copy one of the preceding sample codes to a file, then upload the file and test if it is working. 
  3. To see all possible errors, enter the console of your browser and add logs to verify whether the passed-in values are correct. For example, enter console.log(currentZCharge.DISCOUNT + " charge discount").