{"id":2638,"date":"2024-01-30T12:02:19","date_gmt":"2024-01-30T17:02:19","guid":{"rendered":"https:\/\/morecpq.com\/?p=2638"},"modified":"2024-02-14T14:09:25","modified_gmt":"2024-02-14T19:09:25","slug":"cpq-quote-monthly-recurring-revenue-double-calculate-issues","status":"publish","type":"post","link":"https:\/\/morecpq.com\/index.php\/2024\/01\/30\/cpq-quote-monthly-recurring-revenue-double-calculate-issues\/","title":{"rendered":"CPQ Quote &#8211; Monthly Recurring Revenue &#8211; Double Calculate Issues"},"content":{"rendered":"\n<p>This is a post about how to configure the calculation of the ever fun loving MRR field!  Every customer calculates a field like this (MRR, ARR, NRR, etc) differently!  And their tech stack that does the actual calculation is usually a conglomeration of various automations that probably don&#8217;t work well together.  Below is an example of such a build.  There are rollup fields, user editable fields, formula fields, flow injected fields and price rule injected fields. Normally, when I encounter a setup like the example below, I would just redesign the calculation from scratch and remove the existing setup.  But we&#8217;ll go through the motions of a progressive change as a routine, to illustrate what an admin could do as an iterative rollout.<\/p>\n\n\n\n<p>As a review, here is a basic list of how the CPQ line editor calculates things.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Price Rules<\/li>\n\n\n\n<li>Formula Fields<\/li>\n\n\n\n<li>Save Button<\/li>\n\n\n\n<li>Flow Injections<\/li>\n<\/ol>\n\n\n\n<p>Let&#8217;s see how the below setup affects how the intended field is calculated.<\/p>\n\n\n\n<p class=\"has-medium-font-size\"><strong>Current Setup<\/strong><\/p>\n\n\n\n<p>Intended Field: Quote -&gt; Monthly Recurring Revenue<\/p>\n\n\n\n<p>Here is how the Monthly Recurring Revenue field value gets set for a renewal (the quote type of the example quote).<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Rollup Summary Field<\/strong>: Quote -&gt; MRR__c\n<ul class=\"wp-block-list\">\n<li>Quote -&gt; MRR__c = SUM(Quote Line -&gt; Net Total WHERE Quote Line -&gt; Recurring Revenue = TRUE and Quote Line -&gt; Quantity != 0)<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>User Edited Field<\/strong>: Quote -&gt; SBQQ__SubscriptionTerm__c\n<ul class=\"wp-block-list\">\n<li>Quote -&gt; SBQQ__SubscriptionTerm__c = User Input Value<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Formula Field<\/strong>: Quote -&gt; MRR_Monthly__c\n<ul class=\"wp-block-list\">\n<li>Quote -&gt; MRR_Monthly__c = IF( ISPICKVAL(SBQQ__Type__c, &#8216;Amendment&#8217;), 1, <strong><em>MRR__c \/ SBQQ__SubscriptionTerm__c<\/em><\/strong>)<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Flow<\/strong>: Quote: Record Created &#8211; V3\n<ul class=\"wp-block-list\">\n<li>Quote -&gt; Contract_MRR__c = {!$Record.SBQQ__Opportunity2__r.SBQQ__RenewedContract__c}.Customer_Contracted_MRR__c<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Price Rule<\/strong>: Inject SUM of Renewal MRR Change\n<ul class=\"wp-block-list\">\n<li>Quote -&gt; Quote_MRR_Change__c = Quote -&gt; MRR_Monthly__c &#8211; Quote -&gt; Contract_MRR__c<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Price Rule<\/strong>: MRR for Renewal\n<ul class=\"wp-block-list\">\n<li>Quote -&gt; Monthly_Recurring_Revenue__c = Quote -&gt; Quote_MRR_Change__c<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<p>Then, here is what the user needs to do to get this to calculate properly.  I&#8217;ve even ordered it in the most efficient way, with &#8220;Calculate Immediately&#8221; being set in the package settings.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>User: Click the &#8220;Add Products&#8221; button and add a product<\/li>\n\n\n\n<li>System: Calculate #1 (happens automatically with &#8220;Calculate Immediately&#8221;)\n<ul class=\"wp-block-list\">\n<li>Fills #1: Quote -&gt; MRR__c (Rollup Summary)<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>User: Fill in Subscription Term\n<ul class=\"wp-block-list\">\n<li>Fills #2: Quote -&gt; SBQQ__SubscriptionTerm__c<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>User: Calculate #2\n<ul class=\"wp-block-list\">\n<li>Fills #3: Quote -&gt; MRR_Monthly__c<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>User: Click the &#8220;Save&#8221; button\n<ul class=\"wp-block-list\">\n<li>Fills #4: Quote -&gt; Contract_MRR__c<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>User: Calculate #3\n<ul class=\"wp-block-list\">\n<li>Fills #5: Quote -&gt; Quote_MRR_Change__c<\/li>\n\n\n\n<li>Fills #6: Quote -&gt; Monthly_Recurring_Revenue__c<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>User: Click the &#8220;Save&#8221; button\n<ul class=\"wp-block-list\">\n<li>Saves the final value<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n\n<p>So, in summary, the user has to: Add a product, fill in subscription term, click calculate, click save, click calculate, and click save.  Maybe the two calculates would happen when clicking the save button but you&#8217;d still need to save twice before you got an accurate number in the field.<\/p>\n\n\n\n<p class=\"has-medium-font-size\"><strong>Suggested Changes to get to one calculate<\/strong><\/p>\n\n\n\n<p>Each of these things can be done by itself and rolled out separately.  The more you do, the more efficiency gained.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Calculate a &#8220;Net Total&#8221; field with a Price Rule.<\/strong>\n<ul class=\"wp-block-list\">\n<li>Create a new field on the Quote Line to hold a value for &#8220;Net Total&#8221;.  <\/li>\n\n\n\n<li>Below is a formula you can put into a price action to set this new field. (<em><strong>does not include calculations for contracted prices or discount schedules<\/strong><\/em>)<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>(\n\t(\n\t\tIF(\n\t\t\tRecurring_Revenue__c &amp;&amp; !SBQQ__Bundled__c &amp;&amp; \n\t\t\tIF(\n\t\t\t\tOR(ISPICKVAL(SBQQ__DiscountScheduleType__c, 'Slab'),ISPICKVAL(SBQQ__PricingMethod__c, 'Block')),\n\t\t\t\tIF(\n\t\t\t\t\tOR(AND(!SBQQ__Existing__c, !SBQQ__CarryoverLine__c, SBQQ__Quantity__c == 0),AND(OR(SBQQ__Existing__c, SBQQ__CarryoverLine__c),OR(SBQQ__Quantity__c == SBQQ__PriorQuantity__c - IF(ISBLANK(SBQQ__UpgradedQuantity__c), 0, SBQQ__UpgradedQuantity__c),AND(!SBQQ__AllowAssetRefund__c, ISPICKVAL(SBQQ__SubscriptionPricing__c, ''), SBQQ__Quantity__c &lt; SBQQ__PriorQuantity__c - IF(ISBLANK(SBQQ__UpgradedQuantity__c), 0, SBQQ__UpgradedQuantity__c))))),\n\t\t\t\t\t0,\n\t\t\t\t\t1\n\t\t\t\t),\n\t\t\t\tIF(\n\t\t\t\t\tAND(!SBQQ__Existing__c,!SBQQ__CarryoverLine__c),\n\t\t\t\t\tSBQQ__Quantity__c,\n\t\t\t\t\tIF(\n\t\t\t\t\t\tSBQQ__Quantity__c >= SBQQ__PriorQuantity__c - IF(ISBLANK(SBQQ__UpgradedQuantity__c), 0, SBQQ__UpgradedQuantity__c),\n\t\t\t\t\t\tIF(\n\t\t\t\t\t\t\tISPICKVAL(SBQQ__SubscriptionPricing__c, 'Percent Of Total'),\n\t\t\t\t\t\t\tSBQQ__Quantity__c,\n\t\t\t\t\t\t\tSBQQ__Quantity__c - SBQQ__PriorQuantity__c + IF(ISBLANK(SBQQ__UpgradedQuantity__c), 0, SBQQ__UpgradedQuantity__c)\n\t\t\t\t\t\t),\n\t\t\t\t\t\tIF(\n\t\t\t\t\t\t\tAND(!SBQQ__AllowAssetRefund__c, ISPICKVAL(SBQQ__SubscriptionPricing__c, '')),\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\tSBQQ__Quantity__c - SBQQ__PriorQuantity__c + IF(ISBLANK(SBQQ__UpgradedQuantity__c), 0, SBQQ__UpgradedQuantity__c)\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t) != 0,\n\t\t\tIF(\n\t\t\t\tAND(SBQQ__Renewal__c, !SBQQ__Existing__c, ISBLANK(SBQQ__PriorQuantity__c)), \n\t\t\t\t0,\n\t\t\t\t(\n\t\t\t\t\t(\n\t\t\t\t\t\t(\n\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\tIF(ISBLANK(TEXT(SBQQ__SpecialPriceType__c)), SBQQ__ListPrice__c, SBQQ__SpecialPrice__c) + IF(ISBLANK(SBQQ__Uplift__c),0,SBQQ__Uplift__c * IF(ISBLANK(TEXT(SBQQ__SpecialPriceType__c)), SBQQ__ListPrice__c,SBQQ__SpecialPrice__c))\n\t\t\t\t\t\t\t) - (\n\t\t\t\t\t\t\t\tIF(ISBLANK(SBQQ__AdditionalDiscountAmount__c), 0, SBQQ__AdditionalDiscountAmount__c \/ SBQQ__ProrateMultiplier__c)\n\t\t\t\t\t\t\t) - ((\n\t\t\t\t\t\t\t\t\tIF(ISBLANK(TEXT(SBQQ__SpecialPriceType__c)), SBQQ__ListPrice__c, SBQQ__SpecialPrice__c) + IF(ISBLANK(SBQQ__Uplift__c),0,SBQQ__Uplift__c * IF(ISBLANK(TEXT(SBQQ__SpecialPriceType__c)), SBQQ__ListPrice__c,SBQQ__SpecialPrice__c))\n\t\t\t\t\t\t\t\t) * (\n\t\t\t\t\t\t\t\t\tIF(ISBLANK(SBQQ__Discount__c), 0, SBQQ__Discount__c)\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t) - (\n\t\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t\tIF(ISBLANK(TEXT(SBQQ__SpecialPriceType__c)), SBQQ__ListPrice__c, SBQQ__SpecialPrice__c) + IF(ISBLANK(SBQQ__Uplift__c),0,SBQQ__Uplift__c * IF(ISBLANK(TEXT(SBQQ__SpecialPriceType__c)), SBQQ__ListPrice__c,SBQQ__SpecialPrice__c))\n\t\t\t\t\t\t\t\t) * (\n\t\t\t\t\t\t\t\t\tIF(ISBLANK(SBQQ__PartnerDiscount__c), 0, SBQQ__PartnerDiscount__c)\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t) - (\n\t\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t\tIF(ISBLANK(TEXT(SBQQ__SpecialPriceType__c)), SBQQ__ListPrice__c, SBQQ__SpecialPrice__c) + IF(ISBLANK(SBQQ__Uplift__c),0,SBQQ__Uplift__c * IF(ISBLANK(TEXT(SBQQ__SpecialPriceType__c)), SBQQ__ListPrice__c,SBQQ__SpecialPrice__c))\n\t\t\t\t\t\t\t\t) * (\n\t\t\t\t\t\t\t\t\tIF(ISBLANK(SBQQ__DistributorDiscount__c), 0, SBQQ__DistributorDiscount__c)\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\t) * \n\t\t\t\tSBQQ__ProrateMultiplier__c * \n\t\t\t\tIF(\n\t\t\t\t\tOR(ISPICKVAL(SBQQ__DiscountScheduleType__c, 'Slab'),ISPICKVAL(SBQQ__PricingMethod__c, 'Block')),\n\t\t\t\t\tIF(\n\t\t\t\t\t\tOR(AND(!SBQQ__Existing__c, !SBQQ__CarryoverLine__c, SBQQ__Quantity__c == 0),AND(OR(SBQQ__Existing__c, SBQQ__CarryoverLine__c),OR(SBQQ__Quantity__c == SBQQ__PriorQuantity__c - IF(ISBLANK(SBQQ__UpgradedQuantity__c), 0, SBQQ__UpgradedQuantity__c),AND(!SBQQ__AllowAssetRefund__c, ISPICKVAL(SBQQ__SubscriptionPricing__c, ''), SBQQ__Quantity__c &lt; SBQQ__PriorQuantity__c - IF(ISBLANK(SBQQ__UpgradedQuantity__c), 0, SBQQ__UpgradedQuantity__c))))),\n\t\t\t\t\t\t0,\n\t\t\t\t\t\t1\n\t\t\t\t\t),\n\t\t\t\t\tIF(\n\t\t\t\t\t\tAND(!SBQQ__Existing__c,!SBQQ__CarryoverLine__c),\n\t\t\t\t\t\tSBQQ__Quantity__c,\n\t\t\t\t\t\tIF(\n\t\t\t\t\t\t\tSBQQ__Quantity__c >= IF(ISBLANK(SBQQ__PriorQuantity__c), 0, SBQQ__PriorQuantity__c) - IF(ISBLANK(SBQQ__UpgradedQuantity__c), 0, SBQQ__UpgradedQuantity__c),\n\t\t\t\t\t\t\tIF(\n\t\t\t\t\t\t\t\tISPICKVAL(SBQQ__SubscriptionPricing__c, 'Percent Of Total'),\n\t\t\t\t\t\t\t\tSBQQ__Quantity__c,\n\t\t\t\t\t\t\t\tSBQQ__Quantity__c - IF(ISBLANK(SBQQ__PriorQuantity__c), 0, SBQQ__PriorQuantity__c) + IF(ISBLANK(SBQQ__UpgradedQuantity__c), 0, SBQQ__UpgradedQuantity__c)\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tIF(\n\t\t\t\t\t\t\t\tAND(!SBQQ__AllowAssetRefund__c, ISPICKVAL(SBQQ__SubscriptionPricing__c, '')),\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\tSBQQ__Quantity__c - IF(ISBLANK(SBQQ__PriorQuantity__c), 0, SBQQ__PriorQuantity__c) + IF(ISBLANK(SBQQ__UpgradedQuantity__c), 0, SBQQ__UpgradedQuantity__c)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t),\n\t\t\t0\n\t\t) \/ SBQQ__ProrateMultiplier__c\n\t) * IF(ISPICKVAL(SBQQ__Quote__r.SBQQ__Type__c, 'Amendment'), IF(SBQQ__Quantity__c > 0, 1, -1), 1)\n) - IF(ISBLANK(SBQQ__RenewedSubscription__c)||ISBLANK(SBQQ__RenewedSubscription__r.Item_MRR__c),0,SBQQ__RenewedSubscription__r.Item_MRR__c)<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Rollup Summary Field<\/strong>: MRR__c: Convert to Price Rule (Use above field in Summary Variable)<\/li>\n\n\n\n<li><strong>Formula Field<\/strong>: MRR_Monthly__c: Convert to Price Rule<\/li>\n\n\n\n<li><strong>Flow<\/strong>: Quote: Record Created &#8211; V3: Convert to Price Rule<\/li>\n\n\n\n<li>Smartly order and calculation event your Price Rules to fire in the correct order.<\/li>\n<\/ul>\n\n\n\n<p class=\"has-medium-font-size\"><strong>Better MRR Design<\/strong><\/p>\n\n\n\n<p>This is a design for an MRR value from the ground up.  The spaghetti has been unravelled.  Well&#8230; aside from the formula for Net Total, pulled from various SBQQ formula fields and CPQ documentation pages. \ud83d\udc4d\ud83c\udffb<\/p>\n\n\n\n<ul class=\"wp-block-list\" id=\"block-320b9833-dc20-4f83-859d-c5d127044830\">\n<li><strong>Price Rule: Quote Line &#8211; Before Calculate &#8211; Inject Recurring Revenue<\/strong>\n<ul class=\"wp-block-list\">\n<li>Price Action: Calculate a &#8220;Net Total&#8221; field.\n<ul class=\"wp-block-list\">\n<li>Create a new field on the Quote Line to hold a value for &#8220;Net Total&#8221;.<\/li>\n\n\n\n<li>Below is a formula you can put into a price action to set this new field. (<em><strong>does not include calculations for contracted prices or discount schedules<\/strong><\/em>)<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>IF(\n\t\t\tRecurring_Revenue__c &amp;&amp; !SBQQ__Bundled__c &amp;&amp; \n\t\t\tIF(\n\t\t\t\tOR(ISPICKVAL(SBQQ__DiscountScheduleType__c, 'Slab'),ISPICKVAL(SBQQ__PricingMethod__c, 'Block')),\n\t\t\t\tIF(\n\t\t\t\t\tOR(AND(!SBQQ__Existing__c, !SBQQ__CarryoverLine__c, SBQQ__Quantity__c == 0),AND(OR(SBQQ__Existing__c, SBQQ__CarryoverLine__c),OR(SBQQ__Quantity__c == SBQQ__PriorQuantity__c - IF(ISBLANK(SBQQ__UpgradedQuantity__c), 0, SBQQ__UpgradedQuantity__c),AND(!SBQQ__AllowAssetRefund__c, ISPICKVAL(SBQQ__SubscriptionPricing__c, ''), SBQQ__Quantity__c &lt; SBQQ__PriorQuantity__c - IF(ISBLANK(SBQQ__UpgradedQuantity__c), 0, SBQQ__UpgradedQuantity__c))))),\n\t\t\t\t\t0,\n\t\t\t\t\t1\n\t\t\t\t),\n\t\t\t\tIF(\n\t\t\t\t\tAND(!SBQQ__Existing__c,!SBQQ__CarryoverLine__c),\n\t\t\t\t\tSBQQ__Quantity__c,\n\t\t\t\t\tIF(\n\t\t\t\t\t\tSBQQ__Quantity__c >= SBQQ__PriorQuantity__c - IF(ISBLANK(SBQQ__UpgradedQuantity__c), 0, SBQQ__UpgradedQuantity__c),\n\t\t\t\t\t\tIF(\n\t\t\t\t\t\t\tISPICKVAL(SBQQ__SubscriptionPricing__c, 'Percent Of Total'),\n\t\t\t\t\t\t\tSBQQ__Quantity__c,\n\t\t\t\t\t\t\tSBQQ__Quantity__c - SBQQ__PriorQuantity__c + IF(ISBLANK(SBQQ__UpgradedQuantity__c), 0, SBQQ__UpgradedQuantity__c)\n\t\t\t\t\t\t),\n\t\t\t\t\t\tIF(\n\t\t\t\t\t\t\tAND(!SBQQ__AllowAssetRefund__c, ISPICKVAL(SBQQ__SubscriptionPricing__c, '')),\n\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\tSBQQ__Quantity__c - SBQQ__PriorQuantity__c + IF(ISBLANK(SBQQ__UpgradedQuantity__c), 0, SBQQ__UpgradedQuantity__c)\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t) != 0,\n\t\t\tIF(\n\t\t\t\tAND(SBQQ__Renewal__c, !SBQQ__Existing__c, ISBLANK(SBQQ__PriorQuantity__c)), \n\t\t\t\t0,\n\t\t\t\t(\n\t\t\t\t\t(\n\t\t\t\t\t\t(\n\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\tIF(ISBLANK(TEXT(SBQQ__SpecialPriceType__c)), SBQQ__ListPrice__c, SBQQ__SpecialPrice__c) + IF(ISBLANK(SBQQ__Uplift__c),0,SBQQ__Uplift__c * IF(ISBLANK(TEXT(SBQQ__SpecialPriceType__c)), SBQQ__ListPrice__c,SBQQ__SpecialPrice__c))\n\t\t\t\t\t\t\t) - (\n\t\t\t\t\t\t\t\tIF(ISBLANK(SBQQ__AdditionalDiscountAmount__c), 0, SBQQ__AdditionalDiscountAmount__c \/ SBQQ__ProrateMultiplier__c)\n\t\t\t\t\t\t\t) - ((\n\t\t\t\t\t\t\t\t\tIF(ISBLANK(TEXT(SBQQ__SpecialPriceType__c)), SBQQ__ListPrice__c, SBQQ__SpecialPrice__c) + IF(ISBLANK(SBQQ__Uplift__c),0,SBQQ__Uplift__c * IF(ISBLANK(TEXT(SBQQ__SpecialPriceType__c)), SBQQ__ListPrice__c,SBQQ__SpecialPrice__c))\n\t\t\t\t\t\t\t\t) * (\n\t\t\t\t\t\t\t\t\tIF(ISBLANK(SBQQ__Discount__c), 0, SBQQ__Discount__c)\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t) - (\n\t\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t\tIF(ISBLANK(TEXT(SBQQ__SpecialPriceType__c)), SBQQ__ListPrice__c, SBQQ__SpecialPrice__c) + IF(ISBLANK(SBQQ__Uplift__c),0,SBQQ__Uplift__c * IF(ISBLANK(TEXT(SBQQ__SpecialPriceType__c)), SBQQ__ListPrice__c,SBQQ__SpecialPrice__c))\n\t\t\t\t\t\t\t\t) * (\n\t\t\t\t\t\t\t\t\tIF(ISBLANK(SBQQ__PartnerDiscount__c), 0, SBQQ__PartnerDiscount__c)\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t) - (\n\t\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t\tIF(ISBLANK(TEXT(SBQQ__SpecialPriceType__c)), SBQQ__ListPrice__c, SBQQ__SpecialPrice__c) + IF(ISBLANK(SBQQ__Uplift__c),0,SBQQ__Uplift__c * IF(ISBLANK(TEXT(SBQQ__SpecialPriceType__c)), SBQQ__ListPrice__c,SBQQ__SpecialPrice__c))\n\t\t\t\t\t\t\t\t) * (\n\t\t\t\t\t\t\t\t\tIF(ISBLANK(SBQQ__DistributorDiscount__c), 0, SBQQ__DistributorDiscount__c)\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\t) * \n\t\t\t\tSBQQ__ProrateMultiplier__c * \n\t\t\t\tIF(\n\t\t\t\t\tOR(ISPICKVAL(SBQQ__DiscountScheduleType__c, 'Slab'),ISPICKVAL(SBQQ__PricingMethod__c, 'Block')),\n\t\t\t\t\tIF(\n\t\t\t\t\t\tOR(AND(!SBQQ__Existing__c, !SBQQ__CarryoverLine__c, SBQQ__Quantity__c == 0),AND(OR(SBQQ__Existing__c, SBQQ__CarryoverLine__c),OR(SBQQ__Quantity__c == SBQQ__PriorQuantity__c - IF(ISBLANK(SBQQ__UpgradedQuantity__c), 0, SBQQ__UpgradedQuantity__c),AND(!SBQQ__AllowAssetRefund__c, ISPICKVAL(SBQQ__SubscriptionPricing__c, ''), SBQQ__Quantity__c &lt; SBQQ__PriorQuantity__c - IF(ISBLANK(SBQQ__UpgradedQuantity__c), 0, SBQQ__UpgradedQuantity__c))))),\n\t\t\t\t\t\t0,\n\t\t\t\t\t\t1\n\t\t\t\t\t),\n\t\t\t\t\tIF(\n\t\t\t\t\t\tAND(!SBQQ__Existing__c,!SBQQ__CarryoverLine__c),\n\t\t\t\t\t\tSBQQ__Quantity__c,\n\t\t\t\t\t\tIF(\n\t\t\t\t\t\t\tSBQQ__Quantity__c >= IF(ISBLANK(SBQQ__PriorQuantity__c), 0, SBQQ__PriorQuantity__c) - IF(ISBLANK(SBQQ__UpgradedQuantity__c), 0, SBQQ__UpgradedQuantity__c),\n\t\t\t\t\t\t\tIF(\n\t\t\t\t\t\t\t\tISPICKVAL(SBQQ__SubscriptionPricing__c, 'Percent Of Total'),\n\t\t\t\t\t\t\t\tSBQQ__Quantity__c,\n\t\t\t\t\t\t\t\tSBQQ__Quantity__c - IF(ISBLANK(SBQQ__PriorQuantity__c), 0, SBQQ__PriorQuantity__c) + IF(ISBLANK(SBQQ__UpgradedQuantity__c), 0, SBQQ__UpgradedQuantity__c)\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\tIF(\n\t\t\t\t\t\t\t\tAND(!SBQQ__AllowAssetRefund__c, ISPICKVAL(SBQQ__SubscriptionPricing__c, '')),\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\tSBQQ__Quantity__c - IF(ISBLANK(SBQQ__PriorQuantity__c), 0, SBQQ__PriorQuantity__c) + IF(ISBLANK(SBQQ__UpgradedQuantity__c), 0, SBQQ__UpgradedQuantity__c)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t),\n\t\t\t0\n\t\t)<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\" id=\"block-320b9833-dc20-4f83-859d-c5d127044830\">\n<li>Price Action: Calculate a Quote Line -&gt; MRR\n<ul class=\"wp-block-list\">\n<li>This will be your new Net Total field and then any adjustments to it based on your requirements.  <\/li>\n\n\n\n<li>Sometimes people want to see MRR minus existing MRR from an existing subscription record.<\/li>\n\n\n\n<li>Put your special super sauce calculation here.<\/li>\n\n\n\n<li>(Custom Net Total  \/ SBQQ__ProrateMultiplier__c ) * IF(ISPICKVAL(SBQQ__Quote__r.SBQQ__Type__c, &#8216;Amendment&#8217;), IF(SBQQ__Quantity__c > 0, 1, -1), 1) ) &#8211; IF(ISBLANK(SBQQ__RenewedSubscription__c)||ISBLANK(SBQQ__RenewedSubscription__r.Item_MRR__c),0,SBQQ__RenewedSubscription__r.Item_MRR__c)<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Summary Variable: SUM(MRR__c)<\/strong><\/li>\n\n\n\n<li><strong>Price Rule: Quote &#8211; On Calculate &#8211; Inject Recurring Revenue<\/strong>\n<ul class=\"wp-block-list\">\n<li>Price Action: Roll up MRR from Lines\n<ul class=\"wp-block-list\">\n<li>This will be injecting a value into the Quote-level MRR field with the value of the above Summary Variable.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p>Please note this is not the definitive <\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is a post about how to configure the calculation of the ever fun loving MRR field! Every customer calculates a field like this (MRR, ARR, NRR, etc) differently! And their tech stack that does the actual calculation is usually a conglomeration of various automations that probably don&#8217;t work well together. Below is an example &hellip;<br \/><a href=\"https:\/\/morecpq.com\/index.php\/2024\/01\/30\/cpq-quote-monthly-recurring-revenue-double-calculate-issues\/\" class=\"more-link pen_button pen_element_default pen_icon_arrow_double\">Continue reading <span class=\"screen-reader-text\">CPQ Quote &#8211; Monthly Recurring Revenue &#8211; Double Calculate Issues<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-2638","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"jetpack_featured_media_url":"","jetpack-related-posts":[],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/morecpq.com\/index.php\/wp-json\/wp\/v2\/posts\/2638","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/morecpq.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/morecpq.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/morecpq.com\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/morecpq.com\/index.php\/wp-json\/wp\/v2\/comments?post=2638"}],"version-history":[{"count":66,"href":"https:\/\/morecpq.com\/index.php\/wp-json\/wp\/v2\/posts\/2638\/revisions"}],"predecessor-version":[{"id":2735,"href":"https:\/\/morecpq.com\/index.php\/wp-json\/wp\/v2\/posts\/2638\/revisions\/2735"}],"wp:attachment":[{"href":"https:\/\/morecpq.com\/index.php\/wp-json\/wp\/v2\/media?parent=2638"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/morecpq.com\/index.php\/wp-json\/wp\/v2\/categories?post=2638"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/morecpq.com\/index.php\/wp-json\/wp\/v2\/tags?post=2638"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}