Note: This release is in preview. Features described here don’t become generally available until the latest general availability date that Salesforce announces for this release. Before then, and where features are noted as beta, pilot, or developer preview, we can’t guarantee general availability within any particular time frame or at all. Make your purchase decisions only on the basis of generally available products and features.

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}