---
schema_version: "1"
id: b88649682527f8a6ec96c9673410b33ac0928da7eb2cad993d9a20990d545fc2
title: Annual Pricing Variable
collection: developer
version: current
locale: en-us
portal_url: https://docs.salesforce.com/developer/current/en-us/industries/cme/guides/comms-annual-pricing-variable.md
canonical_url: https://developer.salesforce.com/docs/industries/cme/guide/comms-annual-pricing-variable.html
source_site: developer.salesforce.com
content_type: documentation
content_hash: e2d8ac16b9c9780b613d4fb8c0500f066323c21220e63cb15ff202f0924722c7
products:
  - Communications, Media, Energy and Utilities APIs (Managed Package)
  - Industries Developer Documentation
---
# Annual Pricing Variable

A custom field with a defined pricing variable alone isn't sufficient for annual prices. Rollups are needed for both the line items and the order header. The order total must incorporate the annual prices, and these prices must be capable of handling adjustments, discounts, and other modifications.

Annual pricing variable enables users to specify an annual price for products within the Enterprise Product Catalog (EPC). This pricing detail can then be utilized in both the Industries Configure, Price, Quote (CPQ) Cart and the Standard Digital Commerce API.

## Initial Setup

### Create Custom Fields on Order Item

| Field Label             | Field Name                 | Data Type       | Purpose                                             |
| ----------------------- | -------------------------- | --------------- | --------------------------------------------------- |
| Annual Charge           | AnnualCharge\_\_c          | Currency(16, 2) | Store base annual price from PLE or ABP             |
| Annual Calculated Price | AnnualCalculatedPrice\_\_c | Currency(16, 2) | Net price, if discount is present                   |
| Annual Effective Total  | AnnualEffectiveTotal\_\_c  | Currency(16, 2) | Annual total for root items (Bundle Total)          |
| Annual Manual Discount  | AnnualManualDiscount\_\_c  | Percent(2, 2)   | Discount percentage field                           |
| Annual Total            | AnnualTotal\_\_c           | Currency(16, 2) | Total for calculated price and rollup with quantity |

### Create Custom Fields on Order

| Field Label             | Field Name                | Data Type                                | Formula                                                                                                                                                                                                                                                   |
| ----------------------- | ------------------------- | ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Total: Annual Charges   | AnnualTotal\_\_c          | Roll-Up Summary (Annual Total)           | -                                                                                                                                                                                                                                                         |
| Effective Total: Annual | AnnualEffectiveTotal\_\_c | Roll-Up Summary (Annual Effective Total) | -                                                                                                                                                                                                                                                         |
| Order Total             | OrderTotal2\_\_c          | Formula                                  | vlocity_cmt\_\_OneTimeTotal\_\_c + vlocity_cmt\_\_Tax\_\_c +( vlocity_cmt\_\_RecurringTotal\_\_c \* vlocity_cmt\_\_NumberOfContractedMonths\_\_c )+(AnnualTotal\_\_C\*(vlocity_cmt\_\_NumberOfContractedMonths\_\_c/12))                                  |
| Effective Order Total   | EffectiveOrderTotal2\_\_c | Formula                                  | vlocity_cmt\_\_EffectiveOneTimeTotal\_\_c + vlocity_cmt\_\_Tax\_\_c +( vlocity_cmt\_\_EffectiveRecurringTotal\_\_c \* vlocity_cmt\_\_NumberOfContractedMonths\_\_c ) + (AnnualEffectiveTotal\_\_c \* (vlocity_cmt\_\_NumberOfContractedMonths\_\_c) / 12) |

**note:** The total formulas use the vlocity_cmt\_\_NumberOfContractedMonths\_\_c field to prorate Annual totals. This can be adjusted or changed independently without affecting the rest of the configuration.

### Create Annual Pricing Variable

| Pricing Variable Name                | Code                               | Aggregation | Charge Type | Frequency | Scope        | Applies To Variable                  | Pricing Variable Binding Name                | Object    | Field                      | Type  | Sub-Type | ValueType       |
| ------------------------------------ | ---------------------------------- | ----------- | ----------- | --------- | ------------ | ------------------------------------ | -------------------------------------------- | --------- | -------------------------- | ----- | -------- | --------------- |
| Annual Charge Adjustment Absolute    | ANNUAL_CHARGE_ADJ_ABS              | Unit        | Adjustment  | Yearly    | Line         | Annual Std Price                     |                                              |           |                            | Price | Standard | Pricing Element |
| Annual Charge Adjustment Percent     | ANNUAL_CHARGE_ADJ_PERC             | Unit        | Adjustment  | Yearly    | Line         | Annual Std Price                     |                                              |           |                            | Price | Standard | Pricing Element |
| Annual Std Price                     | ANNUAL_CHARGE                      | Unit        | Recurring   | Yearly    | Line         |                                      | Annual Std Price - OrderItem                 | OrderItem | AnnualCharge\_\_c          | Price | Standard | Pricing Element |
| Annual Std Price Calculated          | ANNUAL_STD_PRC_CALC                | Unit        | Recurring   | Yearly    | Line         |                                      | Annual Std Price Calculated - OrderItem      | OrderItem | AnnualCalculatedPrice\_\_c | Price | Standard | Calculated      |
| Annual Std Price Discount Pct Manual | ANNUAL_STD_PRC_DISC_PCT_MAN        | Unit        | Adjustment  | Yearly    | Line         | Annual Std Price                     |                                              |           |                            | Price | Standard | Calculated      |
| Annual Std Price Total               | ANNUAL_STD_PRC_TOTAL               | Quantity    | Recurring   | Yearly    | Line         |                                      | Annual Std Price Total - OrderItem           | OrderItem | AnnualTotal\_\_c           | Price | Standard | Calculated      |
| Effective Annual Std Price Total     | EFF_ANNUAL_STD_PRC_TOTAL           | Quantity    | Recurring   | Yearly    | Line         |                                      | Effective Annual Std Price Total - OrderItem | OrderItem | AnnualEffectiveTotal\_\_c  | Price | Standard | Calculated      |
| Group Rollup Annual Std Price Total  | GROUP_ROLLUP_ANNUAL_STD_PRC_TOTAL  | Quantity    | Recurring   | Yearly    | Group Rollup | Parent Rollup Annual Std Price Total |                                              |           |                            | Price | Standard | Calculated      |
| Parent Rollup Annual Std Price Total | PARENT_ROLLUP_ANNUAL_STD_PRC_TOTAL | Quantity    | Recurring   |           |              |                                      | Parent Rollup Annual Std Price Total - Order | OrderItem | AnnualEffectiveTotal\_\_c  | Price | Standard | Calculated      |
| Rollup Annual Std Price Total        | ROLLUP_ANNUAL_STD_PRC_TOTAL        | Quantity    | Recurring   |           | Rollup       | Annual Std Price Total               |                                              |           |                            | Price | Standard | Calculated      |

### Create Custom Pricing Hook

Here's the sample code for creating a custom pricing hook.

```
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> option) {
        System.debug ('debug PricingVariableCalcHook: class called');
        if(methodName == 'calculate.PostInvoke') {
            calculatePostInvoke (input, output);
        }
        return true;
    }

    private void calculatePostInvoke(Map<String, Object> input,Map<String, Object> output) {

    // New code from here
        System.debug('?? initial output map: '+JSON.serialize(output));
        Boolean isRoot = (Boolean)input.get('isRoot');
        System.debug('?? isRoot: '+(Boolean)input.get('isRoot'));
        Map<string, Object> calculatedPricingLogDataMap = (Map<string, Object>)output.get('calculatedPricingLogData');
        Map<String, Object> pricingVariableCodeToValueMap = (Map<String,Object>)output.get('pricingVariableCodeValueMap');

        // Below 2 checks for apply promo scenario for cart API as apply promo is still uses classic flow
        // Should not be required for standard DC API
        if(calculatedPricingLogDataMap == null ) {
            calculatedPricingLogDataMap = (Map<String, Object>)output.get('pricingLogDataMap');
        }

        if(pricingVariableCodeToValueMap == null ) {
            pricingVariableCodeToValueMap = (Map<String, Object>)output.get('pricingVariableMap');
        }

        Decimal lineQuantity = getValueFromPVC(pricingVariableCodeToValueMap, 'LINE_QUANTITY');


        Decimal annualStdPrice = getValueFromPVC(pricingVariableCodeToValueMap,'ANNUAL_CHARGE');
        System.debug('?? annualStdPrice: ' + String.valueOf(annualStdPrice));

        Decimal annualStdPriceDiscPctManual = getValueFromPVC(pricingVariableCodeToValueMap,'ANNUAL_STD_PRC_DISC_PCT_MAN');

        Decimal rollupAnnualStdPriceTotal = getValueFromPVC(pricingVariableCodeToValueMap,'ROLLUP_ANNUAL_STD_PRC_TOTAL');
        System.debug('?? rollupAnnualStdPriceTotal: ' + String.valueOf(rollupAnnualStdPriceTotal));

        //getValueFromPVC(pricingVarCodeValueMap, PricingVariableCode.EFF_REC_MONTH_STD_PRICE_TOTAL);

        Decimal annualStdPriceCalc = annualStdPrice - (annualStdPrice * (annualStdPriceDiscPctManual / 100.0));

        Double annualStdPriceTotal = lineQuantity * (annualStdPriceCalc.doubleValue() + rollupAnnualStdPriceTotal.doubleValue());

        // Should consider rounding of value
        pricingVariableCodeToValueMap.put('ANNUAL_STD_PRC_TOTAL',annualStdPriceTotal);

        pricingVariableCodeToValueMap.put('ANNUAL_STD_PRC_CALC',annualStdPriceCalc);

        calculatedPricingLogDataMap.put('ANNUAL_STD_PRC_TOTAL',
                    new Map<String, Object>{
                        'format'=> '[%s (%s) + Rollup %s (%s)] x %s (%s)',
                        'data'=>new List<String>{'Annual Calculated Price',
                                                  String.valueOf(annualStdPriceCalc),
                                                  'Annual Total',
                                                  String.valueOf(rollupAnnualStdPriceTotal),
                                                 'LINE_QUANTITY',
                                                 String.valueOf(lineQuantity)
                                             }});

        if (isRoot) {
            pricingVariableCodeToValueMap.put('EFF_ANNUAL_STD_PRC_TOTAL',annualStdPriceTotal);
            System.debug('?? annualStdPriceTotal: ' + String.valueOf(annualStdPriceTotal));
        }24

        System.debug('?? final output map'+JSON.serialize(output));
        //logic for line item totals and rollups

        //Set line item level custom fields
        //Getting the cart document instance
        vlocity_cmt.CpqCartDocument cart = (vlocity_cmt.CpqCartDocument)input.get('cartDocument');
        String currentItemId = (String)input.get('itemId');
        System.debug('debug currentItemId:'+currentItemId);
        //method to get all the line items
        Map<String, Object> outputMap = cart.call('getAllItems', new Map<String, Object>{'hierarchyLevel'=>-1});
        Map<String, vlocity_cmt.CpqCartDocumentItem> allItemsMap = (Map<String, vlocity_cmt.CpqCartDocumentItem>) outputMap.get('result');

        //Getting the cartDocumentItem having id as currentItemId
        vlocity_cmt.CpqCartDocumentItem currentItem = allItemsMap.get(currentItemId);

        Map<String,Object> itemArgs = new Map<String, Object>();
        itemArgs.put('annualrecurringcharge', annualStdPrice);
        Double total = 0.0;
        itemArgs.put('annualtotal', annualStdPriceTotal);

        currentItem.call('setItemFields', new Map<String,Object>{'fieldValueMap' => itemArgs});
    }

    private Decimal getValueFromPVC(Map<String, Object> pricingVarCodeValueMap, String pricingVariableCode) {

        Object val = pricingVarCodeValueMap.get(pricingVariableCode);
        if (val == null) {
            pricingVarCodeValueMap.put(pricingVariableCode, 0.0);
        } else {
            pricingVarCodeValueMap.put(pricingVariableCode, val);
        }
        return Decimal.valueOf((Double) pricingVarCodeValueMap.get(pricingVariableCode));
    }
}
```

### Create Interface Implementation Record

First, create the interface. Then, associate the Active Implementation Class from the `Interface Implementation Detail` related list. The Active Implementation Class field will be automatically populated once the implementation record is created.

- Interface Name: `CpqPricingVariableCalcHook`
- Active Implementation Class: `PricingVariableMapHookImplementation`

## Enable Standard Digital Commerce

You need to enable standard digital commerce. See [Enable Standard Digital Commerce](https://developer.salesforce.com/docs/industries/cme/guide/comms-enable-standard-digital-commerce.html).

### Create Cart Mapping Entries for Annual Custom Fields

| Name                             | Destination Field name | Destination SObject Type | Source Field Name     | Source SObject Type | Source Field Type |
| -------------------------------- | ---------------------- | ------------------------ | --------------------- | ------------------- | ----------------- |
| OrderItem>CPQCartDocumentItem101 | AnnualCharge           | CpqCartDocumentItem      | AnnualCharge          | OrderItem           | string            |
| OrderItem>CPQCartDocumentItem102 | AnnualCalculatedPrice  | CpqCartDocumentItem      | AnnualCalculatedPrice | OrderItem           | string            |
| OrderItem>CPQCartDocumentItem103 | AnnualEffectiveTotal   | CpqCartDocumentItem      | AnnualEffectiveTotal  | OrderItem           | string            |
| OrderItem>CPQCartDocumentItem104 | AnnualManualDiscount   | CpqCartDocumentItem      | AnnualManualDiscount  | OrderItem           | string            |
| OrderItem>CPQCartDocumentItem105 | AnnualTotal            | CpqCartDocumentItem      | AnnualTotal           | OrderItem           | string            |

### Add Custom Fields to Basket

You need to add fields to the basket. See [Add Fields to the Basket](https://developer.salesforce.com/docs/industries/cme/guide/comms-t-add-fields-to-the-basket.html?_ga=2.238836163.29198268.1715680337-1254941895.1715671052).
