Background
The Opportunity Lightning components (API names FCRM.FCROppCreateAction and FCRM.FCROppNew) support gating of opportunity creation off contacts in Lightning. By default, it sets the value based on the opportunity gating query string in configuration. However, that query string is designed for use with the classic new opportunity page (using predefined field values such as opp5, opp6, etc.) and does not support setting values dynamically.
The Opportunity Lightning components allow developers to create a custom Apex class that overrides the initial opportunity field values when creating opportunities.
Defining the Override Class
Begin by creating a global class named FCROppCreateActionOverride that implements the system.Callable interface.
Implement the standard system.Callable call method.
The action parameter to process is 'oppcreatefieldsoverride'.
The args parameter has two entries:
- 'contactid' is the ID of the contact from which the action was called
- 'fieldvalues' is a Map<String,String> where the key is the opportunity field API name, and the value is the desired initial value.
The function should always return null
The fieldvalues map will already contain entries such as the primary campaign and originating contact that are required by response management or defined through the query string configuration. You may override those values in this function.
The following examples shows an implementation of an override function that clears any default values, then sets the initial opportunity account ID to the contact's account ID, and sets the initial opportunity close date to 30 days from today.
global inherited sharing class FCROppCreateActionOverride implements system.Callable{
global Object call(String action, Map<String, Object> args){
if(action=='oppcreatefieldsoverride'){
Map<String,String> fieldValues = (Map<String,String>)args.get('fieldvalues');
ID contactId = (ID)args.get('contactid');
List<Contact> cts = [Select ID, AccountID, Account.Name from Contact where ID = :contactId];
if(cts.size()==0) return null; // This should be impossible
fieldValues.put('AccountId', cts[0].AccountID);
fieldValues.put('CloseDate', String.ValueOf(Date.today().addDays(30)));
}
return null;
}
}
Testing the Override Class
The following examples shows a typical unit test for the override class.
@istest
public without sharing class FCROppCreateActionOverrideTest {
@istest
private static void TestOverrides(){
Account act = new Account(Name='testact');
insert act;
Contact ct = new Contact(FirstName = 'ctest1', LastName = 'ctest1', Email ='ctest1@ctest1.com',
AccountID = act.id);
insert ct;
Map<String,String> oppFieldNamesAndValuesMap = new Map<String, String>();
string typeclassname = 'FCROppCreateActionOverride';
Test.startTest();
System.Type thetype = Type.forName('',typeclassname); // Try resolving local class first
if(thetype==null) thetype = Type.forName(typeclassname); // Try the default
System.Assert(thetype!=null);
Object theobject = thetype.newInstance();
System.Assert(theobject instanceof System.Callable);
System.Callable overrideInstance = (System.Callable)theobject;
Map<String, Object> params = new Map<String,Object>{'contactid'=>ct.id, 'fieldvalues'=> oppFieldNamesAndValuesMap };
overrideInstance.call('oppcreatefieldsoverride', params);
system.assertEquals(act.id, oppFieldNamesAndValuesMap.get('AccountId'));
Test.stopTest();
}
}
Pre-Populating Record Types
In Lightning Experience, users are required to select a record type at the beginning of opportunity creation. Selecting the wrong record type can decrease the quality of your data. To minimize the chances of an incorrect choice, it is possible to treat the record type as a field. This enables the system to pre-populate the record type as a field value override, taking the decision out of the hands of the end user and helping to ensure data integrity.
To pre-populate a record type, you'll follow the same basic procedure that you would use to define an override class (see above). In the 'fieldvalues' map, specify the value associated with the record type you'd like to pre-populate under the key 'recordtypeid'.
Note: If the value in the record type ID is set to default, the default will be used. If that value does not correspond to an existing record type ID, the user will be prompted to choose the record type via the standard dropdown.
In this example, we're setting the record type associated with an opportunity based on the account type. Lines 10 – 13 contain the relevant additions:
global inherited sharing class FCROppCreateActionOverride implements system.Callable{
global Object call(String action, Map<String, Object> args){
if(action=='oppcreatefieldsoverride'){
Map<String,String> fieldValues = (Map<String,String>)args.get('fieldvalues');
ID contactId = (ID)args.get('contactid');
List<Contact> cts = [Select ID, AccountID, Account.Name, Account.Type from Contact where ID = :contactId];
if(cts.size()==0) return null; // This should be impossible
fieldValues.put('AccountId', cts[0].AccountID);
fieldValues.put('CloseDate', String.ValueOf(Date.today().addDays(30)));
if(cts[0].Account.Type=='Customer' || cts[0].Account.Type == 'Pending Customer'){
fieldValues.put('recordtypeid','012xxxxxxxxxxxxIAA'); // 18-Digit ID of the opportunity record type.
} else {
fieldValues.put('recordtypeid', 'default');
}
}
return null;
}
}
Version Information
Required version: 1.39.28 (November 2021) and beyond
Comments
0 comments
Please sign in to leave a comment.