Calculating True End Date and Subscription Term
Use JavaScript to make a Quote Line Calculator plugin that calculates values and
stores maximum values for the custom quote line fields True Effective End Date and True
Effective Term.
| Available in: Salesforce CPQ Winter ’16 and later |
- On the quote line object, create the following custom fields.
- A date field with the API name True_Effective_End_Date__c
- A number field with the API name True_Effective_Term__c
- Create a custom script record with a name of your choosing.
- In the Quote Line Fields field, add True_Effective_End_Date__c and True_Effective_Term__c.
- In the Code field, provide Javascript code that exports all of the
methods that the calculator looks for and documents their parameters and
return types. Save your custom script and add its name to the Quote
Calculator Plugin field in the Plugins tab of Salesforce CPQ package
settings. We've provided a sample custom script
below.
1export function onAfterCalculate(quote, lineModels) { 2 var maxEffectiveEndDate = null; 3 var maxEffectiveTerm = 0; 4 if (lineModels != null) { 5 lineModels.forEach(function (line) { 6 var trueEndDate = calculateEndDate(quote, line); 7 var trueTerm = getEffectiveSubscriptionTerm(quote, line); 8 if (maxEffectiveEndDate == null || (maxEffectiveEndDate < trueEndDate)) { 9 maxEffectiveEndDate = trueEndDate; 10 } 11 if (maxEffectiveTerm < trueTerm) { 12 maxEffectiveTerm = trueTerm; 13 } 14 line.record["True_Effective_End_Date__c"] = toApexDate(trueEndDate); 15 line.record["True_Effective_Term__c"] = trueTerm; 16 }); 17 quote.record["True_Effective_End_Date__c"] = toApexDate(maxEffectiveEndDate); 18 quote.record["True_Effective_Term__c"] = maxEffectiveTerm; 19 } 20 return Promise.resolve() 21} 22 23function calculateEndDate(quote, line) { 24 var sd = new Date(line.record["SBQQ__EffectiveStartDate__c"]); 25 var ed = new Date(line.record["SBQQ__EffectiveEndDate__c"]); 26 if (sd != null && ed == null) { 27 ed = sd; 28 ed.setUTCMonth(ed.getUTCMonth() + getEffectiveSubscriptionTerm(quote, line)); 29 ed.setUTCDate(d.getUTCDate() - 1); 30 } 31 return ed; 32} 33 34function getEffectiveSubscriptionTerm(quote, line) { 35 var sd = new Date(line.record["SBQQ__EffectiveStartDate__c"]); 36 var ed = new Date(line.record["SBQQ__EffectiveEndDate__c"]); 37 if (sd != null && ed != null) { 38 ed.setUTCDate(ed.getUTCDate() + 1); 39 return monthsBetween(sd, ed); 40 } else if (line.SubscriptionTerm__c != null) { 41 return line.SubscriptionTerm__c; 42 } else if (quote.SubscriptionTerm__c != null) { 43 return quote.SubscriptionTerm__c; 44 } else { 45 return line.DefaultSubscriptionTerm__c; 46 } 47} 48 49/** 50 * Takes a JS Date object and turns it into a string of the type 'YYYY-MM-DD', which is what Apex is expecting. 51 * @param {Date} date The date to be stringified 52 * @returns {string} 53 */ 54function toApexDate(/*Date*/ date) { 55 if (date == null) { 56 return null; 57 } 58 // Get the ISO formatted date string. 59 // This will be formatted: YYYY-MM-DDTHH:mm:ss.sssZ 60 var dateIso = date.toISOString(); 61 62 // Replace everything after the T with an empty string 63 return dateIso.replace(new RegExp('[Tt].*'), ""); 64} 65 66function monthsBetween(/*Date*/ startDate, /*Date*/ endDate) { 67 // If the start date is actually after the end date, reverse the arguments and multiply the result by -1 68 if (startDate > endDate) { 69 return -1 * this.monthsBetween(endDate, startDate); 70 } 71 var result = 0; 72 // Add the difference in years * 12 73 result += ((endDate.getUTCFullYear() - startDate.getUTCFullYear()) * 12); 74 // Add the difference in months. Note: If startDate was later in the year than endDate, this value will be 75 // subtracted. 76 result += (endDate.getUTCMonth() - startDate.getUTCMonth()); 77 return result; 78}