---
schema_version: "1"
id: 795a65094bad4616bfc232d464a9f09ad7066ddd2309d20fca40f79553d861a7
title: Pricing Variable Calculation Hook
collection: admin
version: current
locale: en-us
portal_url: https://docs.salesforce.com/admin/current/en-us/ind/264-0-0/comms_t_pricing_variable_calculation_hook_189172.md
canonical_url: https://help.salesforce.com/s/articleView?id=ind.comms_t_pricing_variable_calculation_hook_189172.htm&release=264.0.0&type=5
source_site: help.salesforce.com
content_type: documentation
content_hash: 0e24f1d003cf106f553a1ff9918397e23791080cd4975980897769de0b919b0a
description: The pricing variable calculation hook allows you to add custom pricing variable calculations, or to override the out-of-the-box calculations.
products:
  - Communications
  - Media
  - Energy and Utilities
release: "264"
---
# Pricing Variable Calculation Hook

The pricing variable calculation hook allows you to add custom pricing variable calculations, or to override the out-of-the-box calculations.

![example](https://sf-zdocs-cdn-prod.zoominsoftware.com/tdta-ind-comms_media_energy_managed-264-0-0-production-enus/ff4079f6-a384-475c-b863-578bbbb0ef9b/images/icon_note.png)

example

Example of adding custom pricing variables

You could add a custom pricing variable called One Time Tax Percent with a code of OT\_TAX\_PCT and apply that to the `One Time Total` of each line item in the cart. The resulting taxed amount can then be saved in another custom pricing variable called One Time Total With Tax with a code of OT\_WITH\_TAX.

You could then calculate the taxed value in the hook as something similar to the following calculation, which you would save in the variable map: OT\_WITH\_TAX = OT\_STD\_PRC\_TOTAL + (OT\_STD\_PRC\_TOTAL \* OT\_TAX\_PCT/100)

The default calculation formulas for the pricing variables are implemented by the following class: `DefaultPricingVariableCalcImplementation`. You can use a hook to this class to override the calculations or to add calculations for custom pricing variables.

In this example, we will define the hook class to be `PricingVariableMapHookImplementation`. An instance of this class will be called both before and after the `DefaultPricingVariableCalcImplementation` calculate method is called, and the hook logic will append both .PreInvoke and .PostInvoke to the methods of the class being intercepted.

The `DefaultPricingVariableCalcImplementation` class only has a calculate method.

The order of execution is as follows:

1. `PricingVariableMapHookImplementation.invokeMethod('calculate.PreInvoke', input, output)`
2. `DefaultPricingVariableCalcImplementation.invokeMethod('calculate', input, output)`
3. `PricingVariableMapHookImplementation.invokeMethod('calculate.PostInvoke', input, output)`

Note that there are two separate instances of `PricingVariableMapHookImplementation` created by the InvokeService, but the input and output maps passed into their methods are the same instance. In fact, these maps are the same maps shared by all three invokeMethods.

## Input Map

The input map has the following information. This is default sample code and does not have usage pricing enabled.

```
{
  "paymentMode": null,
  "itemId": "80246000003urCpAAI",
  "isRoot": true,
  "parentItemEffectiveQuantity": null,
  "pricingLogDataMap": {
    
  },
  "pricingVariableMap": {
    "ROLLUP_OT_STD_PRC_TOTAL": 0.00,
    "ROLLUP_REC_MNTH_STD_PRC_TOTAL": 55.00,
    "OT_STD_PRC_CALC": 0.00,
    "OT_STD_PRC": 0.00,
    "REC_MNTH_STD_PRC_DISC_PCT_MAN": 0.00,
    "OT_STD_PRC_DISC_PCT_MAN": 0.00,
    "LINE_QUANTITY": 1.00,
    "REC_MNTH_STD_PRC_TOTAL": 0.00,
    "REC_MNTH_STD_PRC_CALC": 0.00,
    "REC_MNTH_STD_PRC": 0.00,
    "OT_STD_PRC_TOTAL": 0.00
  }
}
```

<table class="slds-table slds-table_bordered slds-max-medium-table_stacked slds-m-bottom_small " summary="Fields and descriptions of the input map">
        <colgroup>
          <col>
          <col>
        </colgroup>
        <thead class="slds-text-title_caps ">
          <tr class="">
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d367628e158">
              <p style="margin-bottom:0;">Field</p>
            </th>
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d367628e164">
              <p style="margin-bottom:0;">Description</p>
            </th>
          </tr>
        </thead>
        <tbody>
          <tr class="">
            <td data-label="Field" class="slds-cell-wrap" style="vertical-align:top;" headers="d367628e158 ">
              <p style="margin-bottom:0;">paymentMode</p>
            </td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d367628e164 ">
              <p style="margin-bottom:0;">This field's value is set to either <em>Currency</em> or <em>Loyalty</em> when LoyaltyMode is turned on in the system. This field's value comes from the <code>CurrencyPaymentMode__c field</code> of the line item.</p>
            </td>

          </tr>
          <tr class="">
            <td data-label="Field" class="slds-cell-wrap" style="vertical-align:top;" headers="d367628e158 ">
              <p style="margin-bottom:0;">itemId</p>
            </td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d367628e164 ">
              <p style="margin-bottom:0;">This field's value is the ID of the line item object (OpportunityLineItem, QuoteLineItem, or OrderItem) whose variable map is currently being calculated.</p>
            </td>

          </tr>
          <tr class="">
            <td data-label="Field" class="slds-cell-wrap" style="vertical-align:top;" headers="d367628e158 ">
              <p style="margin-bottom:0;">isRoot</p>
            </td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d367628e164 ">
              <p style="margin-bottom:0;">This field indicates whether this line item is the root of the line item hierarchy. It's either true or false.</p>
            </td>

          </tr>
          <tr class="">
            <td data-label="Field" class="slds-cell-wrap" style="vertical-align:top;" headers="d367628e158 ">
              <p style="margin-bottom:0;">parentItemEffectiveQuantity</p>
            </td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d367628e164 ">
              <p style="margin-bottom:0;">This field indicates the effectiveQuantity of the parent of the line item. The value is null when isRoot = true since the root line item does not have a parent. parentItemEffectiveQuantity is calculated by recursively multiplying the ancestor quantities from the root down to the current item's parent level.</p>
            </td>

          </tr>
          <tr class="">
            <td data-label="Field" class="slds-cell-wrap" style="vertical-align:top;" headers="d367628e158 ">
              <p style="margin-bottom:0;">pricingLogDataMap</p>
            </td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d367628e164 ">
              <p style="margin-bottom:0;">This map contains any message strings coming from the calculate method. This map is empty in the input but is filled in the output. It is keyed by the pricing variable code and contains a format string and the data to fill the string information. This information is shown in the price <strong class="uicontrol">Details</strong> popup for this pricing variable.</p>
            </td>

          </tr>
          <tr class="">
            <td data-label="Field" class="slds-cell-wrap" style="vertical-align:top;" headers="d367628e158 ">
              <p style="margin-bottom:0;">pricingVariableMap</p>
            </td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d367628e164 ">
              <p style="margin-bottom:0;">This map contains the current values of the pricing variables for the line item before they are calculated by the <code>DefaultPricingVariableCalcImplementation</code> calculate method. This map is keyed by the pricing variable codes.</p>
            </td>

          </tr>
        </tbody>
      </table>

## Output Map

The output map has the following information:

```
{
  "pricingLogDataMap": {
    "OT_LTY_TOTAL": {
      "data": [
        "OT_LTY_TOTAL",
        "0.00",
        "ROLLUP_OT_LTY_TOTAL",
        "0.00",
        "LINE_QUANTITY",
        "1.00"
      ],
      "format": "[{0} ({1}) + Rollup {2} ({3})] x {4} ({5})"
    },
    "REC_MNTH_STD_PRC_TOTAL": {
      "data": [
        "REC_MNTH_STD_PRC_CALC",
        "0.00",
        "REC_MNTH_STD_PRC_TOTAL",
        "55.00",
        "LINE_QUANTITY",
        "1.00"
      ],
      "format": "[{0} ({1}) + Rollup {2} ({3})] x {4} ({5})"
    },
    "REC_MNTH_STD_PRC_CALC": {
      "data": [
        "REC_MNTH_STD_PRC",
        "0.00",
        "REC_MNTH_STD_PRC_DISC_PCT_MAN",
        "0.00"
      ],
      "format": "{0} ({1}) - {2} ({3}%)"
    },
    "OT_STD_PRC_TOTAL": {
      "chargeTiming": "One-Time",
      "data": [
        "OT_STD_PRC_CALC",
        "0.00",
        "OT_STD_PRC_TOTAL",
        "0.00",
        "LINE_QUANTITY",
        "1.00"
      ],
      "format": "[{0} ({1}) + Rollup {2} ({3})] x {4} ({5})"
    },
    "OT_STD_PRC_CALC": {
      "data": [
        "OT_STD_PRC",
        "0.00",
        "OT_STD_PRC_DISC_PCT_MAN",
        "0.00"
      ],
      "format": "{0} ({1}) - {2} ({3}%)"
    }
  },
  "pricingVariableMap": {
    "DISP_OT_LTY": 0.00,
    "EFF_OT_LTY_TOTAL": 0.00,
    "ROLLUP_OT_LTY_TOTAL": 0.00,
    "OT_LTY_TOTAL": 0.00,
    "OT_LTY": 0.00,
    "EFFECTIVE_QUANTITY": 1.00,
    "DISP_OT_STD_PRC": 0.00,
    "EFF_REC_MNTH_STD_PRC_TOTAL": 55.00,
    "EFF_OT_STD_PRC_TOTAL": 0.00,
    "ROLLUP_OT_STD_PRC_TOTAL": 0.00,
    "ROLLUP_REC_MNTH_STD_PRC_TOTAL": 55.00,
    "OT_STD_PRC_CALC": 0.00,
    "OT_STD_PRC": 0.00,
    "REC_MNTH_STD_PRC_DISC_PCT_MAN": 0.00,
    "OT_STD_PRC_DISC_PCT_MAN": 0.00,
    "LINE_QUANTITY": 1.00,
    "REC_MNTH_STD_PRC_TOTAL": 55.00,
    "REC_MNTH_STD_PRC_CALC": 0.00,
    "REC_MNTH_STD_PRC": 0.00,
    "OT_STD_PRC_TOTAL": 0.00
  },
  "errorCode": "INVOKE-200",
  "error": "OK"
}
```

<table class="slds-table slds-table_bordered slds-max-medium-table_stacked slds-m-bottom_small " summary="Fields and descriptions of the output map">
        <colgroup>
          <col>
          <col>
        </colgroup>
        <thead class="slds-text-title_caps ">
          <tr class="">
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d367628e308">
              <p style="margin-bottom:0;">Field</p>
            </th>
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d367628e314">
              <p style="margin-bottom:0;">Description</p>
            </th>
          </tr>
        </thead>
        <tbody>
          <tr class="">
            <td data-label="Field" class="slds-cell-wrap" style="vertical-align:top;" headers="d367628e308 ">
              <p style="margin-bottom:0;">pricingLogDataMap</p>
            </td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d367628e314 ">
              <p>This map contains any message strings coming from the calculate method. It is keyed by the pricing variable code and contains a format string and the data to fill the string information. This information is shown in the price <strong class="uicontrol">Details</strong> popup for this pricing variable.</p>
              <p>The messages are for pricing variables whose values are calculated inside the calculate method. The format property is a string format with indexed placeholders to be filled in by the values in the data property.</p>
              <p>Any pricing variable code in the data is replaced by its bound field label, if any. See the example after this table.</p>
              <p>A simple message can be passed in for a pricing variable, as in the following example:</p>
              <p style="margin-bottom:0;">
                <code>"REC_MNTH_STD_PRC_TOTAL": { "data": [ "Some simple pricing message." ], "format": "{0}" }</code>
              </p>
            </td>

          </tr>
          <tr class="">
            <td data-label="Field" class="slds-cell-wrap" style="vertical-align:top;" headers="d367628e308 ">
              <p style="margin-bottom:0;">pricingVariableMap</p>
            </td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d367628e314 ">
              <p style="margin-bottom:0;">This map contains the calculated values of the pricing variables after it has gone through the DefaultPricingVariableCalcImplementation calculate method.</p>
            </td>

          </tr>
          <tr class="">
            <td data-label="Field" class="slds-cell-wrap" style="vertical-align:top;" headers="d367628e308 ">
              <p style="margin-bottom:0;">errorCode</p>
            </td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d367628e314 ">
              <p>An error code is returned by the InvokeService if there was any exception thrown.</p>
              <ul>
                <li>
                  <p><code>INVOKE-200</code> : No error.</p>
                </li>

                <li>
                  <p><code>INVOKECLASS-404</code> : The class being invoked is not found.</p>
                </li>

                <li>
                  <p><code>INVOKEMETHOD-405</code> : The method name is blank.</p>
                </li>

                <li>
                  <p><code>INVOKE-500</code> : There is an exception. Check the error property for the message.</p>
                </li>

              </ul>
            </td>

          </tr>
          <tr class="">
            <td data-label="Field" class="slds-cell-wrap" style="vertical-align:top;" headers="d367628e308 ">
              <p style="margin-bottom:0;">error</p>
            </td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d367628e314 ">
              <p style="margin-bottom:0;">OK if no exception. Otherwise the exception message is returned in this property.</p>
            </td>

          </tr>
        </tbody>
      </table>

![example](https://sf-zdocs-cdn-prod.zoominsoftware.com/tdta-ind-comms_media_energy_managed-264-0-0-production-enus/ff4079f6-a384-475c-b863-578bbbb0ef9b/images/icon_note.png)

example

Example for pricingLogData

Any pricing variable code in the data is replaced by its bound field label (if there is one). For example, for `REC_MNTH_STD_PRC_TOTAL`, it will appear as follows in the price **Details** popup for `REC_MNTH_STD_PRC_TOTAL` bound to the Recurring Total field:

**Price Details Popup**

![Recurring Calculated price of zero, plus Rollup Recurring Total of 55, times Quantity of 1 equals 55 dollars.](https://sf-zdocs-cdn-prod.zoominsoftware.com/tdta-ind-comms_media_energy_managed-264-0-0-production-enus/ff4079f6-a384-475c-b863-578bbbb0ef9b/resources-product/images/price_det_pop_up.png)

## Example Hook Class

In this example hook, we will change how `REC_MNTH_STD_PRC_TOTAL` is calculated.

**Introduction to the example**

It is currently calculated by `DefaultPricingVariableCalcImplementation` as:

`REC_MNTH_STD_PRC_TOTAL = (REC_MNTH_STD_PRC_CALC + ROLLUP_REC_MNTH_STD_PRC_TOTAL) * LINE_QUANTITY;`

We will change it to the following expression:

`REC_MNTH_STD_PRC_TOTAL = (REC_MNTH_STD_PRC_CALC * LINE_QUANTITY) + ROLLUP_REC_MNTH_STD_PRC_TOTAL;`

We will do a similar thing for `OT_STD_PRC_TOTAL`.

It is currently calculated as:

`OT_STD_PRC_TOTAL = (OT_STD_PRC_CALC + ROLLUP_OT_STD_PRC_TOTAL) * LINE_QUANTITY`

We will change it to the following expression:

`OT_STD_PRC_TOTAL = (OT_STD_PRC_CALC * LINE_QUANTITY) + ROLLUP_OT_STD_PRC_TOTAL`

We make our changes in calculate.PostInvoke since we want to override the default calculation.

**Rollup Logic**

Note that the calculate method is called first for all the leaf nodes of the line item hierarchy, and then for their parent level all the way up to the root. That is, each child line item has to be calculated first before their parents.

This is true because the `REC_MNTH_STD_PRC_TOTAL` and `OT_STD_PRC_TOTAL` of each child is rolled up to the `ROLLUP_REC_MNTH_STD_PRC_TOTAL` and `ROLLUP_OT_STD_PRC_TOTAL` of their parent line item.

This rollup logic is automatically done outside of the calculate method and is based on the rollup pricing variables' definitions where they are defined as having `Scope = Rollup` and `Applies To Variable`, which is the pricing variable on the child to rollup.

![example](https://sf-zdocs-cdn-prod.zoominsoftware.com/tdta-ind-comms_media_energy_managed-264-0-0-production-enus/ff4079f6-a384-475c-b863-578bbbb0ef9b/images/icon_note.png)

example

For example:

_ROLLUP\_REC\_MNTH\_STD\_PRC\_TOTAL, Scope = Rollup, Applies To Variable = Recurring Monthly Std Price Total_ means add the `REC_MNTH_STD_PRC_TOTAL` of each child to the `ROLLUP_REC_MNTH_STD_PRC_TOTAL` variable of its parent line item.

**The example hook class**

```
global with sharing class PricingVariableMapHookImplementation implements vlocity_cmt.VlocityOpenInterface{

    global Boolean invokeMethod(String methodName, Map<String, Object> input, Map<String, Object> output, Map<String, Object> options)  
    {
        try
        {
            System.debug('____ PricingVariableMapHookImplementation ' + methodName);

            if (methodName.equalsIgnoreCase('calculate.PreInvoke'))
            {
                // dump the input
                System.debug('--- calculate.PreInvoke input: ' + JSON.serialize(input));
            }
            else if (methodName.equalsIgnoreCase('calculate.PostInvoke'))
            {                
                // log the output
                System.debug('--- calculate.PostInvoke output: ' + JSON.serialize(output));

                // Retrieve the pricing variable map from the output
                Map<String, Object> pricingVariableCodeToValueMap = (Map<String, Object>)output.get('pricingVariableMap');

                // Retrieve the pricing log data map from the output
                Map<String, Object> pricingLogDataMap = (Map<String, Object>)output.get('pricingLogDataMap');

                // Retrieve the isRoot flag from the input
                Boolean isRoot = (Boolean)input.get('isRoot');

                // Get the Line quantity value
                Decimal LINE_QUANTITY = (Decimal)pricingVariableCodeToValueMap.get('LINE_QUANTITY');

                // Get the REC_MNTH_STD_PRC_CALC pricing variable value 
                Decimal REC_MNTH_STD_PRC_CALC = (Decimal)pricingVariableCodeToValueMap.get('REC_MNTH_STD_PRC_CALC');

                // Get the ROLLUP_REC_MNTH_STD_PRC_TOTAL pricing variable value 
                Decimal ROLLUP_REC_MNTH_STD_PRC_TOTAL = (Decimal)pricingVariableCodeToValueMap.get('ROLLUP_REC_MNTH_STD_PRC_TOTAL');

                // Override the default calculation formula. The formula being overridden is: 
                // REC_MNTH_STD_PRC_TOTAL = (REC_MNTH_STD_PRC_CALC + ROLLUP_REC_MNTH_STD_PRC_TOTAL) * LINE_QUANTITY;
                Decimal REC_MNTH_STD_PRC_TOTAL = (REC_MNTH_STD_PRC_CALC * LINE_QUANTITY) + ROLLUP_REC_MNTH_STD_PRC_TOTAL;

                // Save the new REC_MNTH_STD_PRC_TOTAL rounded to 2 decimals in the pricing variable map of the line item
                pricingVariableCodeToValueMap.put('REC_MNTH_STD_PRC_TOTAL', REC_MNTH_STD_PRC_TOTAL.setScale(2, RoundingMode.HALF_UP));

                // Set the new pricing details information for the REC_MNTH_STD_PRC_TOTAL
                pricingLogDataMap.put('REC_MNTH_STD_PRC_TOTAL', 
                    new Map<String, Object>{
                        'format'=>'[{0} ({1}) x {2} ({3})] + Rollup {4} ({5})',
                        'data'=>new List<String>{'REC_MNTH_STD_PRC_CALC',                      // replaces {0}
                                                  String.valueOf(REC_MNTH_STD_PRC_CALC),       // replaces {1}
                                                 'LINE_QUANTITY',                              // replaces {2}
                                                 String.valueOf(LINE_QUANTITY),                // replaces {3}
                                                 'REC_MNTH_STD_PRC_TOTAL',                     // replaces {4}
                                                 String.valueOf(ROLLUP_REC_MNTH_STD_PRC_TOTAL) // replaces {5}
                                             }});

                // If this is the root, then set the EFF_REC_MNTH_STD_PRC_TOTAL of the line item to be the same as
                // REC_MNTH_STD_PRC_TOTAL value. EFF_REC_MNTH_STD_PRC_TOTAL participates in a rollup summary field in the parent header
                if (isRoot)
                {
                    Decimal EFF_REC_MNTH_STD_PRC_TOTAL = REC_MNTH_STD_PRC_TOTAL;
                    pricingVariableCodeToValueMap.put('EFF_REC_MNTH_STD_PRC_TOTAL', EFF_REC_MNTH_STD_PRC_TOTAL.setScale(2, RoundingMode.HALF_UP));
                }

                // Do the same for OT_STD_PRC_TOTAL

                // Get the OT_STD_PRC_CALC pricing variable value 
                Decimal OT_STD_PRC_CALC = (Decimal)pricingVariableCodeToValueMap.get('OT_STD_PRC_CALC');

                // Get the ROLLUP_REC_MNTH_STD_PRC_TOTAL pricing variable value 
                Decimal ROLLUP_OT_STD_PRC_TOTAL = (Decimal)pricingVariableCodeToValueMap.get('ROLLUP_OT_STD_PRC_TOTAL');

                // Override the default calculation formula. The formula being overridden is: 
                // OT_STD_PRC_TOTAL = (OT_STD_PRC_CALC + ROLLUP_OT_STD_PRC_TOTAL) * LINE_QUANTITY;
                Decimal OT_STD_PRC_TOTAL = (OT_STD_PRC_CALC * LINE_QUANTITY) + ROLLUP_OT_STD_PRC_TOTAL;

                // Save the new OT_STD_PRC_TOTAL rounded to 2 decimals in the pricing variable map of the line item
                pricingVariableCodeToValueMap.put('OT_STD_PRC_TOTAL', OT_STD_PRC_TOTAL.setScale(2, RoundingMode.HALF_UP));

                // Set the new pricing details information for the OT_STD_PRC_TOTAL
                pricingLogDataMap.put('OT_STD_PRC_TOTAL', 
                    new Map<String, Object>{
                        'format'=>'[{0} ({1}) x {2} ({3})] + Rollup {4} ({5})',
                        'data'=>new List<String>{'OT_STD_PRC_CALC',                      // replaces {0}
                                                  String.valueOf(OT_STD_PRC_CALC),       // replaces {1}
                                                 'LINE_QUANTITY',                        // replaces {2}
                                                 String.valueOf(LINE_QUANTITY),          // replaces {3}
                                                 'OT_STD_PRC_TOTAL',                     // replaces {4}
                                                 String.valueOf(ROLLUP_OT_STD_PRC_TOTAL) // replaces {5}
                                             }});

                // If this is the root, then set the EFF_OT_STD_PRC_TOTAL of the line item to be the same as
                // OT_STD_PRC_TOTAL value. EFF_OT_STD_PRC_TOTAL participates in a rollup summary field in the parent header
                if (isRoot)
                {
                    Decimal EFF_OT_STD_PRC_TOTAL = OT_STD_PRC_TOTAL;
                    pricingVariableCodeToValueMap.put('EFF_OT_STD_PRC_TOTAL', EFF_OT_STD_PRC_TOTAL.setScale(2, RoundingMode.HALF_UP));
                }
            }
            return true;
        }
        catch (Exception ex)
        {
            System.debug('--- Exception: ' + ex.getMessage());
            System.debug('--- Stack Trace: ' + ex.getStackTraceString());
            throw ex;
        }
    }
}
```

## Setting Up the Hook

Create an Interface called DefaultPricingVariableCalcImplementaInterface and set `PricingVariableMapHookImplementation` as the implementation.

![Note](https://sf-zdocs-cdn-prod.zoominsoftware.com/tdta-ind-comms_media_energy_managed-264-0-0-production-enus/ff4079f6-a384-475c-b863-578bbbb0ef9b/images/icon_note.png)

Note

Note the name of the `DefaultPricingVariableCalcImplementaInterface` interface. The last part of the name is "ImplementaInterface" instead of "ImplementationInterface".

For an explanation of this naming convention, see Names of Elements.

**Interface Implementation**

![Interface Implementation](https://sf-zdocs-cdn-prod.zoominsoftware.com/tdta-ind-comms_media_energy_managed-264-0-0-production-enus/ff4079f6-a384-475c-b863-578bbbb0ef9b/resources-product/images/default_pricing_interface.png)

In our hook example, we set `DefaultPricingVariableCalcImplementaInterface` active implementation to be `PricingVariableMapHookImplementation` and `PricingInterface` active implementation to be `PricingPlanService`.

Now we test the hook and modified calculation by adding a product to the cart or forcing a pricing event by changing the quantity of a line item or changing attribute values. The new calculation formula is reflected in the `Recurring Totals` and `One Time Totals` in the CPQ interface. As well, the new detail message from the hook class appears in the totals details, as in the example below:

**Price Details Popup**

![Price Detail Popup](https://sf-zdocs-cdn-prod.zoominsoftware.com/tdta-ind-comms_media_energy_managed-264-0-0-production-enus/ff4079f6-a384-475c-b863-578bbbb0ef9b/resources-product/images/price_det_popup_hook.png)

![Note](https://sf-zdocs-cdn-prod.zoominsoftware.com/tdta-ind-comms_media_energy_managed-264-0-0-production-enus/ff4079f6-a384-475c-b863-578bbbb0ef9b/images/icon_note.png)

Note

We have changed the totaling behavior, which is reflected in the difference in overall totals (line-level totals, child total rollups and header totals) compared to the out of the box behavior.

To revert to the out of the box behavior, de-activate the `PricingVariableMapHookImplementation`or delete the `DefaultPricingVariableCalcImplementaInterface` in the Interface Implementation view.

## Names of Elements

Note the name of the `DefaultPricingVariableCalcImplementaInterface` interface. The last part of the name is "ImplementaInterface" instead of "ImplementationInterface".

Here's why:

The name of the class we are intercepting is `DefaultPricingVariableCalcImplementation`. The InvokeService appends `Hook` to this class name, making the new name: `DefaultPricingVariableCalcImplementationHook`.

However, this class name is too long and is truncated to 36 characters, making it: `DefaultPricingVariableCalcImplementa` (the last few letters are missing). Then the InvokeService appends Interface to that new name, arriving at the final name (`DefaultPricingVariableCalcImplementaInterface`), which is then used to look for the corresponding Active Implementation Name.

Whenever a new Interface Implementation and active Interface Implementation detail record is created or updated, the interface name (minus the Interface string) and the name of its active implementation class are cached in the Custom Class Implementation custom setting through the triggers of these objects. Doing so reduces SOQL queries to look for the implementation class names during runtime. Instead, they are retrieved from the Custom Class Implementation custom setting.

![example](https://sf-zdocs-cdn-prod.zoominsoftware.com/tdta-ind-comms_media_energy_managed-264-0-0-production-enus/ff4079f6-a384-475c-b863-578bbbb0ef9b/images/icon_note.png)

example

For example

If the `Interface Implementation` is `PricingInterface`, and the `Active Implementation Detail` is `PricingPlanService`, then under `Setup : Custom Settings : Custom Class Implementation : Manage`, there will be an entry for `Name = Pricing` (the Interface string is stripped off) and another entry for `Class Name = PricingPlanService`.

When we set up our hook interface, there is a corresponding custom setting created where `Name` is `DefaultPricingVariableCalcImplementa` (the Interface string is stripped off) and `Class Name` is `PricingVariableMapHookImplementation`.

The name of the interface has to fit within the maximum 40 character limit of the Custom Class Implementation custom setting name field. This is why the InvokeService truncates to 36 characters.

![Note](https://sf-zdocs-cdn-prod.zoominsoftware.com/tdta-ind-comms_media_energy_managed-264-0-0-production-enus/ff4079f6-a384-475c-b863-578bbbb0ef9b/images/icon_note.png)

Note

When you de-activate an active implementation, the custom setting class name value for the interface will be null. When you activate another implementation, the custom setting class name value for the interface is updated to the active implementation class name. The screenshot here shows the state of the Custom Class Implementation custom setting if the `PricingInterface` active implementation is `DefaultPricingImplementation` and `DefaultPricingVariableCalcImplementaInterface` active implementation is deactivated.

**Custom Class Implementation**

![Custom Class Implementation Example](https://sf-zdocs-cdn-prod.zoominsoftware.com/tdta-ind-comms_media_energy_managed-264-0-0-production-enus/ff4079f6-a384-475c-b863-578bbbb0ef9b/resources-product/images/custom_class_post_hook.png)