Loading
Get Started with Communications, Media, and Energy & Utilities (CME)...
Table of Contents
Select Filters

          No results
          No results
          Here are some search tips

          Check the spelling of your keywords.
          Use more general search terms.
          Select fewer filters to broaden your search.

          Search all of Salesforce Help
          Customize the MarginValidation Interface Implementation

          Customize the MarginValidation Interface Implementation

          This interface implementation is called by the default Margin Range Loader interface implementation. You can overwrite this class to customize the margin validation.

          • Using the Load Margin Ranges interface implementation, the pricing service queries the named calculation procedure to find the margin ranges for the product specified in the line item and passes it to the Margin Validation interface implementation.

          • Next, the Margin Validation interface implementation compares the line item's margin to determine whether the range is within the specified limits.

          • If the margin is outside the valid range, it returns an error message in the CPQ pricing message field to the Industries CPQ Cart.

          Note
          Note

          This step is optional. Skip it if you want to use the default MarginValidation interface implementation.

          Name

          Properties

          Interface Name

          Margin Validation

          Active Implementation Class

          DefaultMarginValidationImplementation

          Purpose

          Introduced in the Winter '19 release, this interface implementation is used to validate the margin range on individual line items.

          1. Specify your input and output parameters.

            Input Map Key

            Datatype

            Description

            Input Parameters

            parent

            sObject

            For order, opportunity, or quote

            lineItemList

            List<sObject>

            For OrderItem, QuoteLineItem, or OpportunityLineItem

            lineItemIdToMarginRangeMap

            Map<Id, Map <String, Object>>

            For each line item, a map with the following keys:

            • OneTimeMarginLowerBound

            • OneTimeMarginUpperBound

            • RecurringMarginLowerBound

            • RecurringMarginUpperBound

            Output Parameters: None

          2. Specify an error message in the 'CpqPricingMessage__c' field of the line items. Error messages for one-time margins and recurring margins are displayed for each line item in the Industries CPQ Cart when the margin ranges are violated.

            For example, the one-time margin must be between 5.0% to 10.0% is displayed in the cart for a line item when the validation.

          3. Customize the margin validation implementation using the sample implementation code.
            global class CustomMarginValidationImplementation implements vlocity_cmt.VlocityOpenInterface
            {
                private static String ONE_TIME_MARGIN_PREFIX = 'OneTimeMargin';
                private static String RECURRING_MARGIN_PREFIX = 'RecurringMargin';
                private static String nsp = 'vlocity_cmt__';
                /*
                 * invoke method.
                 */
                public Boolean invokeMethod(String methodName, Map<String, Object> input, Map<String, Object> output,
                                            Map<String, Object> options)
                {
                    if (methodName.equals('validateMarginRange'))
                    {
                        validateMarginRange(input, output, options);
                        return true;
                    }
                    return false;
                }
             
                /*
                 * validate margin ranges.
                 *
                 */
                private void validateMarginRange(Map<String, Object> input, Map<String, Object> output,
                                                 Map<String, Object> options)
                {
                    List<SObject> lineItemList = (List<SObject>) input.get('lineItemList');
                    //map, which has margin range details.
                    Map<Id, Map<String, Object>> itemIdTomarginRangeMap = (Map<Id, Map<String, Object>>)
                            input.get('lineItemIdToMarginRangeMap');
                    for (SObject item : lineItemList)
                    {
                        String oneTimeMarginMessage = null;
                        String recurringMarginMessage = null;
                        Id lineItemId = (Id) item.get('Id');
                        //margin range map also has all output columns of martix.
                        Map<String, Object> marginRangeMap = itemIdTomarginRangeMap.get(lineItemId);
                        if (marginRangeMap != null)
                        {
                            Decimal oneTimeMargin = (Decimal) item.get(nsp + 'OneTimeMargin__c');
                            Decimal recurringMargin = (Decimal) item.get(nsp + 'RecurringMargin__c');
                            Decimal oneTimeMarginLowerBound = (Decimal) marginRangeMap.get('OneTimeMarginLowerBound');
                            Decimal oneTimeMarginUpperBound = (Decimal) marginRangeMap.get('OneTimeMarginUpperBound');
                            Decimal recurringMarginLowerBound = (Decimal) marginRangeMap.get('RecurringMarginLowerBound');
                            Decimal recurringMarginUpperBound = (Decimal) marginRangeMap.get('RecurringMarginUpperBound');
                            if (oneTimeMarginLowerBound != null && oneTimeMarginUpperBound != null &&
                                    (oneTimeMargin > oneTimeMarginUpperBound || oneTimeMargin < oneTimeMarginLowerBound))
                            {
                                oneTimeMarginMessage = ONE_TIME_MARGIN_PREFIX + ':' + 'One time margin must be between ' + oneTimeMarginLowerBound +
                                                       ' and ' + oneTimeMarginUpperBound + '.';
                            }
                            if (recurringMarginLowerBound != null && recurringMarginUpperBound != null &&
                                    (recurringMargin > recurringMarginUpperBound || recurringMargin < recurringMarginLowerBound))
                            {
                                recurringMarginMessage = RECURRING_MARGIN_PREFIX + ':' + 'Recurring margin must be between ' + recurringMarginLowerBound
                                                         + ' and ' + recurringMarginUpperBound + '.';
                            }
                        }
             
                        //read previous message and update
                        String message = (String) item.get(nsp + 'CpqPricingMessage__c');
                        List<String> errorList = new List<String>();
                        if (String.isNotBlank(message))
                        {
                            List<String> messageList = message.split('\\|');
                            for (String m : messageList)
                            {
                                List<String> mList = m.split(':');
                                if (mList.size() > 1)
                                {
                                    if (!mList[0].equals(ONE_TIME_MARGIN_PREFIX) &&
                                            !mList[0].equals(RECURRING_MARGIN_PREFIX))
                                    {
                                        errorList.add(m);
                                    }
                                }
                            }
                        }
                        if (oneTimeMarginMessage != null)
                        {
                            errorList.add(oneTimeMarginMessage);
                        }
                        if (recurringMarginMessage != null)
                        {
                            errorList.add(recurringMarginMessage);
                        }
                        //update pricing message.
                        if (errorList.isEmpty())
                        {
                            item.put(nsp + 'CpqPricingMessage__c', null);
                        }
                        else
                        {
                            item.put(nsp + 'CpqPricingMessage__c', String.join(errorList, '|'));
                        }
                    }
                }
            }
           
          Loading
          Salesforce Help | Article