Basic Atarc Process


Real World Example : Automated Opportunity Pricebook Assignment

Business Story: A company has nation wide operations and it has recently implemented Salesforce into their sales processes. They have a picklist field in the opportunity object to determine what is the market and depending on the market selected in the opportunity they want to automatically assign the appropriate pricebook as each market has its own pricebook.

We will do this automation using an Atarc Process, it should be smart enough to take what is the pricebook for a particular opportunity market.

Configuration

We are going to have specific opportunity market-pricebook mapping information stored in a custom metadata type so that its easy to maintain and we can use it in our automation which will be done using an Atarc Process.

  1. Create a new opportunity field:
    • Field Label: Market, Field Name: Market, Data Type: Picklist, Required: Checked, Picklist Data:
      Orlando
      Philadelphia
      Internationals
  2. Create three new Pricebook records with the following information:
    • Pricebook Name: Orlando Pricebook, Active: True
    • Pricebook Name: Philadelphia Pricebook, Active: True
    • Pricebook Name: Internationals Pricebook, Active: True
  3. Create a custom metadata type object with the following information:
    • Singular Label: Opportunity Market Pricebook Mapping
    • Plural Label: Opportunity Market Pricebook Mappings
    • Object Name: Opportunity_Market_Pricebook_Mapping
    • Visibility: Public
  4. Create the following fields in the Opportunity Market Pricebook Mapping custom metadata type:
    • Field Label: IsActive, Field Name: IsActive, Data Type: Checkbox, Default Value: Unchecked
    • Field Label: PricebookId,Field Name: PricebookId, Data Type: Text, Length: 18, Required: Checked
  5. Add the following Entries in the Opportunity Market Pricebook Mapping custom metadata type:
    Label
    Opportunity Market Pricebook Mapping Name
    IsValid
    PricebookId
    Internationals Mapping
    Internationals
    True
    Use the Id from the Internationals Pricebook record inserted previously
    Orlando Mapping
    Orlando
    True
    Use the Id from the Orlando Pricebook record inserted previously
    Philadelphia Mapping
    Philadelphia
    True
    Use the Id from the Philadelphia Pricebook record inserted previously

Code

After completing all the previous steps, now we know from where we need to pull the mapping information and we can proceed with creating the actual Atarc Process, let's start with the apex helper class:


/*
 * Created By : anyei
 * Created Date: 03/07/2020
 * ATARC Process: OpptyPricebookMgr
 * Trigger Event: Before Insert (only)
 * Unit Test OpportunityPricebookManager_AP_Test
 */ 
public class OpportunityPricebookManager_AP extends AsyncTriggerArc.AsyncTriggerArcProcessBase {
    
    @TestVisible static List<Opportunity_Market_Pricebook_Mapping__mdt> opptyPricebookMappingList;
    Map<string, Opportunity_Market_Pricebook_Mapping__mdt> opptyPricebookMapping;
    
    public OpportunityPricebookManager_AP(){
        opptyPricebookMappingList = (opptyPricebookMappingList == null ? [select DeveloperName, PricebookId__c from Opportunity_Market_Pricebook_Mapping__mdt where IsActive__c=true ] : opptyPricebookMappingList);
        opptyPricebookMapping = new  Map<string, Opportunity_Market_Pricebook_Mapping__mdt>();
        for(Opportunity_Market_Pricebook_Mapping__mdt mappingRecord :opptyPricebookMappingList ){
                opptyPricebookMapping.put(mappingRecord.DeveloperName, mappingRecord);
         }
    }
    public override object execute( AsyncTriggerArc.AsyncTriggerArcContext context){
        List<Opportunity> oppties = (List<Opportunity>) context.newList;
        
        context.debug('Total mapping entries loaded '+ opptyPricebookMapping.size());
        context.debug(opptyPricebookMapping);
        
        //update the Pricebook2Id from the opportunity only if a mapping exists 
        for(Opportunity opptyRecord : oppties){
            if( opptyRecord.Market__c != null && opptyPricebookMapping.containsKey(opptyRecord.Market__c)) opptyRecord.Pricebook2Id=opptyPricebookMapping.get(opptyRecord.Market__c).PricebookId__c;
        }
        
        return null;
    }

}

One important thing is that, if you pay attention to the variable declarations, we are trying to avoid to dependency between the map opptyPricebookMapping and the soql query fetching the mapping information and we are actually creating a list static variable opptyPricebookMappingList and making sure its visible by test classes with the @TestVisible attribute, this will extremely useful later when doing a unit test for this apex class, see Unit Test for Basic Atarc Process tutorial

Another thing is, making sure you have one opportunity trigger with ATARC, if you don't just create a new trigger as follow:


trigger ATARCOpportunityTrigger on Opportunity (before insert, before update, before delete, after insert, after update, after delete, after undelete) {
    
    new AsyncTriggerArc().start();

}
  

ATARC Process Settings

Last part as usual, we need a record entry in the ATARC Process Settings custom metadata type:

Label
ATARC Process Setting Name
ApexHelperClassName
SObject
Event
IsActive
IsAsync
Order
DependsOnSuccess
DependsOnFailure
Debug
DebugLevel
breakIfError
Isolate
General Availability
Opportunity Pricebook Manager
OpptyPricebookMgr
OpportunityPricebookManager_AP
Opportunity
BeforeInsert
true
false
1
true
DEBUG
false
false
true

Now the development is pretty much complete, you can test it out by creating a new opportunity record, the Market and depending on the value you select in this field the Atarc Process should be able to determine the Pricebook2Id field as long as there is a mapping for it in the Opportunity Market Pricebook Mapping custom metadata type.

For example, create a new opportunity, you can add any information you want in any of the fields, but in the Market field select Orlando. To make sure the functionality is working as expected, run the follwoing query in the developer console and confirm the pricebook name showing in the result is actually Orlando for the created opportunity: select Id, Pricebook2.Name, name from Opportunity order by createddate desc limit 10


Expected Results:

Any opportunity created having the market field populated should automatically assign the pricebook based on the mapping defined in the custom metadata type Opportunity Market Pricebook Mapping