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.
-
Create a new opportunity field:
- Field Label: Market, Field Name: Market, Data Type: Picklist, Required: Checked, Picklist Data:
Orlando
Philadelphia
Internationals
- Field Label: Market, Field Name: Market, Data Type: Picklist, Required: Checked, Picklist Data:
-
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
-
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
-
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
-
Add the following Entries in the Opportunity Market Pricebook Mapping custom metadata type:
LabelOpportunity Market Pricebook Mapping NameIsValidPricebookIdInternationals MappingInternationalsTrueUse the Id from the Internationals Pricebook record inserted previouslyOrlando MappingOrlandoTrueUse the Id from the Orlando Pricebook record inserted previouslyPhiladelphia MappingPhiladelphiaTrueUse 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