Custom Package Total Calculation

The sample JavaScript script can be used in the Quote Line Calculator to calculate the total price for all components in a quote line and then store that value in a custom field.
Available in: Salesforce CPQ Winter ’16 and later

This sample JavaScript code exports all of the methods that the calculator looks for, and documents their parameters and return types.

The sample script assumes the Salesforce admin created a custom field Component Custom Total on the Quote Line object.

Note

Javascript

1export function onInit(lines) {
2    if (lines != null) {
3        lines.forEach(function (line) {
4            line.record["Component_Custom_Total__c"] = 0;
5        });
6    }
7};
8
9export function onAfterCalculate(quoteModel, quoteLines) {
10    if (quoteLines != null) {
11        quoteLines.forEach(function (line) {
12            var parent = line.parentItem;
13            if (parent != null) {
14                var pComponentCustomTotal = parent.record["Component_Custom_Total__c"] || 0;
15                var cListPrice = line.ProratedListPrice__c || 0;
16                var cQuantity = line.Quantity__c == null ? 1 : line.Quantity__c;
17                var cPriorQuantity = line.PriorQuantity__c || 0;
18                var cPricingMethod = line.PricingMethod__c == null ? "List" : line.PricingMethod__c;
19                var cDiscountScheduleType = line.DiscountScheduleType__c || '';
20                var cRenewal = line.Renewal__c || false;
21                var cExisting = line.Existing__c || false;
22                var cSubscriptionPricing = line.SubscriptionPricing__c || '';
23
24                var cTotalPrice = getTotal(cListPrice, cQuantity, cPriorQuantity, cPricingMethod, cDiscountScheduleType, cRenewal, cExisting, cSubscriptionPricing, cListPrice);
25                pComponentCustomTotal += cTotalPrice;
26
27                parent.record["Component_Custom_Total__c"] = pComponentCustomTotal;
28            }
29        });
30    }
31};
32
33function getTotal(price, qty, priorQty, pMethod, dsType, isRen, isExist, subPricing, listPrice) {
34    if ((isRen === true) && (isExist === false) && (priorQty == null)) {
35        // Personal note: In onAfterCalculate, we specifically make sure that priorQuantity can't be null.
36        // So isn't this loop pointless?
37        return 0;
38    } else {
39        return price * getEffectiveQuantity(qty, priorQty, pMethod, dsType, isRen, isExist, subPricing, listPrice);
40    }
41}
42
43function getEffectiveQuantity(qty, priorQty, pMethod, dsType, isRen, exists, subPricing, listPrice) {
44    var delta = qty - priorQty;
45
46    if (pMethod == 'Block' && delta == 0) {
47        return 0;
48    } else if (pMethod == 'Block') {
49        return 1;
50    } else if (dsType == 'Slab' && (delta == 0 || (qty == 0 && isRen == true))) {
51        return 0;
52    } else if (dsType == 'Slab') {
53        return 1;
54    } else if (exists == true && subPricing == '' && delta < 0) {
55        return 0;
56    } else if (exists == true && subPricing == 'Percent Of Total' && listPrice != 0 && delta >= 0) {
57        return qty;
58    } else if (exists == true) {
59        return delta;
60    } else {
61        return qty;
62    }
63}