Custom Package Total Calculation

The sample Apex class calculates the total price for all components in a quote line and then stores that value in a custom field.

Required Editions
Available in: Salesforce CPQ Winter ’16 and later

Salesforce CPQ no longer provides support for Legacy Quote Calculator plugins. Check out the Javascript Quote Calculator Plugin for support and improved features.

Note

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

Note

Example 

1global class QCPWinter16Legacy implements SBQQ.QuoteCalculatorPlugin, SBQQ.QuoteCalculatorPlugin2 {
2
3    /* NOTE: the getReferencedFields method is no longer required if you use the ReferencedFields field set on
4 the Quote Line object. 
5             This field set must be created as it's not a managed one.
6       NOTE: if you need to access Quote fields, you can create the ReferencedFields field set on the Quote object as well.
7       NOTE: if you do not use the getReferencedFields method, you can remove SBQQ.QuoteCalculatorPlugin2 from the class declaration.
8    */
9    global Set<String> getReferencedFields() {
10        return new Set<String>{
11            /* Note: add fields using the following format - Only add fields referenced
12                               
13               by the plugin and not in the Line Editor field set on the Quote Line object
14            String.valueOf(SBQQ__QuoteLine__c.My_Field_API_Name__c)
15            */
16            String.valueOf(SBQQ__QuoteLine__c.Component_Custom_Total__c),
17            
18            String.valueOf(SBQQ__QuoteLine__c.SBQQ__ProratedListPrice__c),
19            String.valueOf(SBQQ__QuoteLine__c.SBQQ__PriorQuantity__c),
20            String.valueOf(SBQQ__QuoteLine__c.SBQQ__PricingMethod__c),
21            String.valueOf(SBQQ__QuoteLine__c.SBQQ__DiscountScheduleType__c),
22            String.valueOf(SBQQ__QuoteLine__c.SBQQ__Renewal__c),
23            String.valueOf(SBQQ__QuoteLine__c.SBQQ__Existing__c),
24            String.valueOf(SBQQ__QuoteLine__c.SBQQ__SubscriptionPricing__c)
25        };
26    }
27
28    global void onBeforePriceRules(SObject quote, SObject[] lines) {
29    }
30    
31    global void onAfterPriceRules(SObject quote, SObject[] lines) {
32    }
33    
34    global void onBeforeCalculate(SObject quote, SObject[] lines) {
35    }
36    
37    global void onAfterCalculate(SObject quote, SObject[] lines) {
38        for(SObject line : lines) {
39            SObject parent = line.getSObject(SBQQ__QuoteLine__c.SBQQ__RequiredBy__c.getDescribe().getRelationshipName());
40            if(parent != null) {
41              Decimal pComponentCustomTotal = (Decimal)parent.get(String.valueOf(SBQQ__QuoteLine__c.Component_Custom_Total__c));
42              
43              Decimal cListPrice = (Decimal)line.get(String.valueOf(SBQQ__QuoteLine__c.SBQQ__ProratedListPrice__c));
44              Decimal cQuantity = (Decimal)line.get(String.valueOf(SBQQ__QuoteLine__c.SBQQ__Quantity__c));
45              Decimal cPriorQuantity = (Decimal)line.get(String.valueOf(SBQQ__QuoteLine__c.SBQQ__PriorQuantity__c));
46              String cPricingMethod = (String)line.get(String.valueOf(SBQQ__QuoteLine__c.SBQQ__PricingMethod__c));
47              String cDiscountScheduleType = (String)line.get(String.valueOf(SBQQ__QuoteLine__c.SBQQ__DiscountScheduleType__c));
48              Boolean cRenewal = (Boolean)line.get(String.valueOf(SBQQ__QuoteLine__c.SBQQ__Renewal__c));
49              Boolean cExisting = (Boolean)line.get(String.valueOf(SBQQ__QuoteLine__c.SBQQ__Existing__c));
50              String cSubscriptionPricing = (String)line.get(String.valueOf(SBQQ__QuoteLine__c.SBQQ__SubscriptionPricing__c));
51              
52              pComponentCustomTotal = (pComponentCustomTotal == null) ? 0 : pComponentCustomTotal;
53              
54              cListPrice = (cListPrice == null) ? 0 : cListPrice;
55              cQuantity = (cQuantity == null) ? 1 : cQuantity;
56              cPriorQuantity = (cPriorQuantity == null) ? 0 : cPriorQuantity;
57              cPricingMethod = (cPricingMethod == null) ? 'List' : cPricingMethod;
58              cDiscountSCheduleType = (cDiscountSCheduleType == null) ? '' : cDiscountSCheduleType;
59              cRenewal = (cRenewal == null) ? false : cRenewal;
60              cExisting = (cExisting == null) ? false : cExisting;
61              cSubscriptionPricing = (cSubscriptionPricing == null) ? '' : cSubscriptionPricing;
62              
63              Decimal cTotalPrice = getTotal(cListPrice, cQuantity, cPriorQuantity, cPricingMethod, cDiscountScheduleType, cRenewal, cExisting, cSubscriptionPricing, cListPrice);
64              pComponentCustomTotal += cTotalPrice;
65              
66              parent.put(SBQQ__QuoteLine__c.Component_Custom_Total__c, pComponentCustomTotal);
67              
68            }
69        }
70    }
71    
72    global void onInit(SObject[] lines) {
73        for(SObject line : lines) {
74            line.put(SBQQ__QuoteLine__c.Component_Custom_Total__c, 0);
75        }
76    }
77    
78    private Decimal getTotal(Decimal price, Decimal quantity, Decimal priorQuantity, String pricingMethod, String discountScheduleType, Boolean renewal, Boolean existing, String subscriptionPricing, Decimal ListPrice) {
79        price = (price == null) ? 0 : price;
80        renewal = (renewal == null) ? false : renewal;
81        existing = (existing == null) ? false : existing;
82        
83        if(renewal == true && existing == false && priorQuantity == null) {
84            return 0;
85        } else {
86            return price * getEffectiveQuantity(quantity, priorQuantity, pricingMethod, discountScheduleType, renewal, existing, subscriptionPricing, listPrice);
87        }
88        
89    }
90    
91    private Decimal getEffectiveQuantity(Decimal quantity, Decimal priorQuantity, String pricingMethod, String discountScheduleType, Boolean renewal, Boolean existing, String subscriptionPricing, Decimal ListPrice) {
92        Decimal result = 0;
93        Decimal deltaQuantity = 0;
94        
95        quantity = (quantity == null) ? 0 : quantity;
96        priorQuantity = (priorQuantity == null) ? 0 : priorQuantity;
97        pricingMethod = (pricingMethod == null) ? '' : pricingMethod;
98        discountScheduleType = (discountScheduleType == null) ? '' : discountScheduleType;
99        subscriptionPricing = (subscriptionPricing == null) ? '' : subscriptionPricing;
100        renewal = (renewal == null) ? false : renewal;
101        existing = (existing == null) ? false : existing;
102        listPrice = (listPrice == null) ? 0 : listPrice;
103        
104        deltaQuantity = quantity - priorQuantity;
105        
106        if(pricingMethod == 'Block' && deltaQuantity == 0) {
107            result = 0;
108        } else {
109            if(pricingMethod == 'Block') {
110                result = 1;
111            } else {
112                if(discountScheduleType == 'Slab' && (deltaQuantity == 0 || (quantity == 0 && renewal == true))) {
113                    result = 0;
114                } else {
115                    if(discountScheduleType == 'Slab') {
116                        result = 1;
117                    } else {
118                        if(existing == true && subscriptionPricing == '' && deltaQuantity < 0) {
119                            result = 0;
120                        } else {
121                            if(existing == true && subscriptionPricing == 'Percent Of Total' && listPrice != 0 && deltaQuantity >= 0) {
122                                result = quantity;
123                            } else {
124                                if(existing == true) {
125                                    result = deltaQuantity;
126                                } else {
127                                    result = quantity;
128                                }
129                            }
130                        }
131                    }
132                }
133            }
134        }
135        
136        return result;
137    }
138    
139}