Overwriting CatalogPriceCalculator script include

viktor_lukashov
Giga Contributor

The Wiki mentions that the ServiceNow default service catalog pricing model can be extended should a need be. However it does not provide much information on how this can be done. In the community there have been questions about that every once in a while but they tend to stay without answers. I've posted this same question to HI and then did some trial and error myself. Below is a summary of a working method how to extend the pricing model (keep in mind that it is not an official guide).

First, backup the OOB versions of the CatalogPriceCalculator and CatalogRecurringPriceCalculator script includes. You are going to overwrite them with custom versions so it's a good idea to keep OOB copies available in case you would need to restore them in some future upgrade. Set the 'active' flag to false on the both OOB script includes and keep them without any other modifications.

The idea is to create two custom fields on the catalog item table to be able to specify custom catalog price calculation scripts and to change the default scripts to check for these fields and either run OOB or custom calculations. Two different fields are necessary because the price calculation is divided into two parts: one for purchase price and another for recurring price.

The screenshots below show the definition of the 2 custom fields sc_cat_item.u_custom_price_calculator and sc_cat_item.u_custom_recurring_price_calculator. Both fields are references to the Script Include table.

u_custom_price_calculator.png

u_custom_recurring_price_calculator.png

The custom copy of the CatalogPriceCalculator script include looks as below. It checks if the custom field u_custom_price_calculator is defined on the catalog item and if so, tries to use the price calculator from that script include. If for any reason the custom price calculator class is not found, the OOB class is used instead (renamed to DefaultCatalogPriceCalculator).

On the ServiceNow versions starting from Fuji the system property glide.sc.use_custom_pricegenerator should be set to true in order to enable pricing calculations via script includes. When it's false all pricing calculations are handled inside ServiceNow in Java code completely out of reach for customization.

Note that when defining a custom price calculator class, its name should match the name of the script include where it is defined. An example will come further into the post.

// save a reference to the global scope

var __global = this;

/*

* For a given cart item, this routine will return the price

*/

var CatalogPriceCalculator = Class.create();

CatalogPriceCalculator.prototype = {

    initialize: function(/* GlideRecord */ gr) {

          var customPriceCalculatorSI = gr.cat_item.u_custom_price_calculator;

          if (customPriceCalculatorSI) {

                // gs.include() should define a class in the global scope

                // the class name shoudl be the same as the script include name

                gs.include(customPriceCalculatorSI.name);

                var CatalogPriceCalculatorImpl = __global[customPriceCalculatorSI.name];

          }

          if (typeof CatalogPriceCalculatorImpl !== 'function') {

                // by default use the out-of-the-box price calculator

                CatalogPriceCalculatorImpl = DefaultCatalogPriceCalculator;

          }

          this.cpc = new CatalogPriceCalculatorImpl(gr);

    },

    calcPrice : function() {

          return this.cpc.calcPrice();

    }

};

/*

* This is a [renamed] copy of the OOB CatalogPriceCalculator class.

*/

var DefaultCatalogPriceCalculator = Class.create();

DefaultCatalogPriceCalculator.prototype = {

  < full copy of the OOB CatalogPriceCalculator prototype goes here >

};

The custom copy of the CatalogRecurringPriceCalculator follows the same idea with the only difference being the name of the custom field on the catalog item.

All what has been explained so far was the preparation work. It does not actually change any price calculation logic on any catalog items. The actual custom pricing logic should be defined in a new script include (you can defined as many pricing models as necessary).

Here is an example (create a new script include)

  • Name: DynamicServerOrderPriceCalculator
  • API Name: global.DynamicServerOrderPriceCalculator
  • Client Callable: false
  • Application: Global
  • Accessible from: This application scope only

gs.include("CatalogPriceCalculator");

var DynamicServerOrderPriceCalculator = Class.create();

DynamicServerOrderPriceCalculator.prototype = Object.extendsObject(DefaultCatalogPriceCalculator, {

    calcPrice : function() {

          var base_price = this.cartItem.cat_item.price.getReferenceValue();

          var capacity = this.cartItem.variables['u_capacity'].getGlideObject().getValue();

          return 0.75 * base_price + 0.25 * capacity;

    }

});

To put this custom pricing script in use, it should be referenced from the u_custom_price_calculator field on a catalog item definition.

12 REPLIES 12

joaof
Mega Expert

Hi, I am trying to replace price by a variable / field user fills in, but this is not working for me:

var capacity = this.cartItem.variables['u_capacity'].getGlideObject().getValue();
return capacity;

however, if if enter return 500; it does work.

I am changing u_capacity by my variable's name.

Any idea? Thanks

Was able to solve this, that's how DynamicServerOrderPriceCalculator worked for me (change total_flight_hotel to match your variable's name):

gs.include("CatalogPriceCalculator");


var DynamicServerOrderPriceCalculator = Class.create();

DynamicServerOrderPriceCalculator.prototype = Object.extendsObject(DefaultCatalogPriceCalculator, {

	initialize: function(/* GlideRecord */ gr) {

		this.cartItem = gr;

	},



	calcPrice: function() {

		//var base_price = this.cartItem.cat_item.price.getReferenceValue();

		var tot_price = Number(this.cartItem.variables['total_flight_hotel']);

		return tot_price;

	},



	type : DynamicServerOrderPriceCalculator

});

Another thing in order for this to work correctly:
Do not leave Price for the Catalog Item as 0, leave something in there, e.g. 1,000.00.

RudhraKAM
Tera Guru

I know this is a bit old post, check out this article to fix this issue:

https://community.servicenow.com/community?id=community_article&sys_id=fbc250011b2d3c100ccc85176e4bc...