Knowledge Center

Knowledge Center > Zuora CPQ > Zuora CPQ Development Resources > Zuora CPQ Component Library > Zuora CPQ Global Components > SelectProduct Component > Quote Rules Engine Plugin Example

Quote Rules Engine Plugin Example

Table of contents
No headers

This article describes the process of creating a sample custom Quote Rules Engine Plugin on the SelectProduct component

For additional sample plugin and a sample test class, see  Zuora for Salesforce Sample Code Suite.

To implement and register a new custom Quote Rules Engine Plugin on the SelectProduct component:

  1. Implement the custom plugin by using the below code to create a new class.
  2. On the Zuora Config tab, click Component Registration.
  3. On the Component Registration page, click Edit for the SelectProduct component. 
  4. In the Update component section, enter the plugin class name, RulesEngineTest, in the Class Name field of the Quote Rule Engine Plugin.
  5. Click Update.
  6. When you create or edit a quote, the rules created in the below sample code will be applied to your product and rate plan selection.

Use the following code to implement the custom plugin in this example.

global class RulesEngineSampleController implements 
  zqu.ZQuoteRulesEngine.QuoteRulesEnginePlugin {
 
  public Boolean runValidationRules(zqu__Quote__c quote, 
    List zcgs, List logs){
  
    // Validate rate plans only after quote has been created.
    if(quote.Id != null){
      Set ratePlanIds = new Set();
      Map<string,> ratePlanNameMap = new Map<string,>();
       
      // Get 3 rate plans randomly in the sample code
      // Replace them to your real rate plan ids
      String ratePlanA = zcgs.size()>1 ? zcgs.get(1).productRatePlanId : '';
      String ratePlanB = zcgs.size()>2 ? zcgs.get(2).productRatePlanId : '';
      String ratePlanC = zcgs.size()>0 ? zcgs.get(0).productRatePlanId : '';
        
      for(zqu.ZChargeGroup zcg : zcgs){
        ratePlanIds.add(zcg.productRatePlanId);
        ratePlanNameMap.put(zcg.productRatePlanId, zcg.ratePlanName);
      }
        
      // Case1 : Rate plan A and B cannot be added together
      if(ratePlanIds.contains(ratePlanA) && ratePlanIds.contains(ratePlanB)){
        zqu.ZQuoteRulesEngine.ChangeLog log = new zqu.ZQuoteRulesEngine.ChangeLog();
        log.description = 'The following rate plans cannot be added together : ' + 
          ratePlanNameMap.get(ratePlanA) + ',' + ratePlanNameMap.get(ratePlanB);
        logs.add(log);
        return false;
      }
       
      // Case2 : Rate plan C must be added to the quote, cannot remove it
      if(!ratePlanIds.contains(ratePlanC)){
        zqu.ZQuoteRulesEngine.ChangeLog log = new zqu.ZQuoteRulesEngine.ChangeLog();
        log.description = 'The following rate plan must be added : ' + ratePlanC;
        logs.add(log);
        return false;
      }
    }
      
    // Validate quote itself
    // Case3 : Quote start date cannot be today
    if(quote.zqu__StartDate__c == Date.today()){
      zqu.ZQuoteRulesEngine.ChangeLog log = new zqu.ZQuoteRulesEngine.ChangeLog();
      log.description = 'Quote start date cannot be today.';
      logs.add(log);
      return false;
    }
      
    return true;
  }
    
  
 public void runPriceRules(List zcgs, 
   List logs){
      
     for(zqu.ZChargeGroup zcg : zcgs){
       List chargeObjectList = new List();
       List zChargeList = new List();
       for(zqu.zCharge zc : zcg.zCharges){
          
         // Create zqu__QuoteRatePlanCharge__c object instance from zCharge
         zqu__QuoteRatePlanCharge__c qrpc = new zqu__QuoteRatePlanCharge__c();
         qrpc.Name = zc.Name;
         qrpc.zqu__ListPrice__c = Decimal.valueOf(zc.LIST_PRICE);
         qrpc.zqu__ListTotal__c = Decimal.valueOf(zc.LIST_TOTAL);
         qrpc.zqu__Quantity__c = 
           zc.isQuantityEditable ? Decimal.valueOf(zc.QUANTITY) : null;
         qrpc.zqu__EffectivePrice__c = zc.isEffectivePriceEditable ?
           Decimal.valueOf(zc.EFFECTIVE_PRICE) : null;
         qrpc.zqu__Discount__c = 
           zc.isDiscountEditable ? Decimal.valueOf(zc.DISCOUNT) : null;
         qrpc.zqu__Total__c = 
           zc.isTotalEditable ? Decimal.valueOf(zc.TOTAL) : null;
         qrpc.zqu__IncludedUnits__c = zc.IsIncludedUnitsEditable ?
          Decimal.valueOf(zc.INCLUDED_UNITS) : null;
         qrpc.zqu__ProductRatePlanCharge__c = zc.PRODUCT_RATE_PLAN_CHARGE_SFDC_ID;
         
         chargeObjectList.add(qrpc);
         zChargeList.add(zc);
       }
               
       // Put all changed field names into map : 
       // Map<charge.zqu__productrateplancharge__c,>>
       Map<string,>> changedFieldMap = new Map<string,>>();

       for(Integer index = 0; index < chargeObjectList.size(); index++){
         SObject charge = chargeObjectList.get(index);
         zqu.zCharge zc = zChargeList.get(index);

         String productRatePlanChargeId = String.valueOf(charge.get(
           'zqu__ProductRatePlanCharge__c'));

         // Modify List Price 
         if(Boolean.valueOf(zc.isListPriceEditable())){
           charge.put('zqu__ListPrice__c', 40);
           zc.overRideListPrice(40);
                   
           // Store changed field name for List Price
           if(!changedFieldMap.containsKey(productRatePlanChargeId)){
             changedFieldMap.put(productRatePlanChargeId, new List());
           }
           changedFieldMap.get(productRatePlanChargeId).add(
             'LIST_PRICE');

           // Add change log
           zqu.ZQuoteRulesEngine.ChangeLog log = new zqu.ZQuoteRulesEngine.ChangeLog();
           log.description = String.valueOf(charge.get('Name')) + ' : ' +
             'List Price is changed to 40';
           logs.add(log);
          }

         // Modify Discount
         if(Boolean.valueOf(zc.isDiscountEditable)){
           charge.put('zqu__Discount__c', 50);
           zqu.zQuoteUtil.recalculatePriceFields(zc, charge,
             zqu.ZQuoteRulesEngine.PRICE_FIELD_DISCOUNT, '');
                    
           // Store changed field name for Discount
           if(!changedFieldMap.containsKey(productRatePlanChargeId)){
             changedFieldMap.put(productRatePlanChargeId, new List());
           }
           changedFieldMap.get(productRatePlanChargeId).add(
             zqu.ZQuoteRulesEngine.PRICE_FIELD_DISCOUNT);

           // Add change log
           zqu.ZQuoteRulesEngine.ChangeLog log = new zqu.ZQuoteRulesEngine.ChangeLog();
           log.description = String.valueOf(charge.get('Name')) + ' : ' +
             zqu.ZQuoteRulesEngine.PRICE_FIELD_DISCOUNT + ' is changed to 50';
           logs.add(log);
         }
       }
        
       // Update zChargeGroup from charge object list
       zqu.zQuoteUtil.updateZChargeGroupFromSObject(zcg, chargeObjectList, 
         changedFieldMap, '');
   }
  }  

  public Map<string,>> runProductRules(zqu__Quote__c quote, 
    List ratePlanIds, List logs){
  
    Map<string,>> relatedRatePlanIdMap = new Map<string,>>();
    relatedRatePlanIdMap.put(zqu.ZQuoteRulesEngine.PRODUCT_RULE_TYPE_ADDED_ENABLED, 
      new List());
    relatedRatePlanIdMap.put(zqu.ZQuoteRulesEngine.PRODUCT_RULE_TYPE_ADDED_DISABLED, 
      new List());
    relatedRatePlanIdMap.put(zqu.ZQuoteRulesEngine.PRODUCT_RULE_TYPE_REMOVED_ENABLED, 
      new List());
     
    // Replace the follwing rate plans to your real rate plan ids
    String ratePlanA = 'ratePlanAId';
    String ratePlanB = 'ratePlanBId';
    String ratePlanC = 'ratePlanCId';
     
    Set existingRatePlans = new Set();
    if(ratePlanIds != null){
      existingRatePlans.addAll(ratePlanIds);
    }
     
    // Change log
    zqu.ZQuoteRulesEngine.ChangeLog log;
     
    // Case 1 : If rate plan A is required and has not been added to quote, 
    // add it to ZQuoteRulesEngine.PRODUCT_RULE_TYPE_ADDED_DISABLED, 
    // the rate plan A will be added to quote automatically and cannot be removed
    if(!existingRatePlans.contains(ratePlanA)){
      relatedRatePlanIdMap.get(
        zqu.ZQuoteRulesEngine.PRODUCT_RULE_TYPE_ADDED_DISABLED).add(ratePlanA);
      // Add log
      log = new zqu.ZQuoteRulesEngine.ChangeLog();
      log.description = 'Required Rate plan ' + ratePlanA + ' is added automatically.';
      logs.add(log);
    }
      
    // Case 2 : If add rate plan B to 
    // ZQuoteRulesEngine.PRODUCT_RULE_TYPE_ADDED_ENABLED, 
    // the rate plan B will be added to quote automatically and can be removed
    relatedRatePlanIdMap.get(
      zqu.ZQuoteRulesEngine.PRODUCT_RULE_TYPE_ADDED_ENABLED).add(ratePlanB);
     
    // Add log
    log = new zqu.ZQuoteRulesEngine.ChangeLog();
    log.description = 'Rate plan ' + ratePlanB + ' is added automatically.';
    logs.add(log);
      
    // Case 3 : If rate plan C has been added to quote, 
    // add it to ZQuoteRulesEngine.PRODUCT_RULE_TYPE_REMOVED_ENABLED, 
    // the rate plan C will be removed from quote automatically
    if(existingRatePlans.contains(ratePlanC)){
      relatedRatePlanIdMap.get(
        zqu.ZQuoteRulesEngine.PRODUCT_RULE_TYPE_REMOVED_ENABLED).add(ratePlanC);
      // Add log
      log = new zqu.ZQuoteRulesEngine.ChangeLog();
      log.description = 'Rate plan ' + ratePlanC + ' is removed automatically.';
      logs.add(log);
    }
    return relatedRatePlanIdMap;
  }   
}
Last modified

Tags

This page has no custom tags.

Classifications

(not set)