function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Susannah PSusannah P 

Need some help with apex class referencing custom metadata

Hi! I'm stuck on a bit of code that I hope someone might be able to help me with. Here's the problem I'm trying to solve:
 
I want to fill in 3 lookup fields on my custom object called "Approver 1", "Approver 2", "Approver 3". These custom fields are a lookup to the user record. I've created a custom metadata definition to store the mapping of owner of the record, to these approvers. Since custom metadata does not support entity definitions to the user record, I used a text field to store the owner Full name, Approver 1 full name, etc.
 
I've created a trigger and trigger handler to fill in these fields whenever a record is created. I'm stuck though in figuring out how to match up my custom metadata with the records being inserted. Essentially, for every record that is being inserted I want to see if there is a reference to the owner name in my custom metadata. If there is a match, I want the approver 1 lookup field on my custom object to be filled with the user that corresponds to the full name I put in my custom metadata. Here's what I have so far.


User-added image
 
I've attached a screenshot, and here's the gist: https://gist.github.com/Sunnydalelow/87cd1d66e1ac1c68f8f15f3390309749#file-gistfile1-txt

Here's a sample of one of my custom metadata records:
User-added image
Best Answer chosen by Susannah P
Debanjan SharmaDebanjan Sharma
Hi Susannah,

As per my understanding its better to use map than putting record owners in a set. Please see below approach and let me know if this helps.
 
//Instead of putting record owner in a list lets use a map of Record Owner and LATAM_Pricing_Approval_Hierarchy__mdt
Map<String,LATAM_Pricing_Approval_Hierarchy__mdt> recordOwnerApprovalMap = new Map<String,LATAM_Pricing_Approval_Hierarchy__mdt>();

for (LATAM_Pricing_Approval_Hierarchy__mdt approvalHierarchy : approvalHierarchies){
      
	  String owner = (String)approvalHierarchy.get(Schema.LATAM_Pricing_Approval_Hierarchy__mdt.Record_Owner__c);
      recordOwnerApprovalMap.put(owner,approvalHierarchy);
}

// Now this map can be used to assign approval in individual records

Price_Change_Request_Line_Item__c[] newPCRLIsWithOwnerName = [select id,Owner.Name from Price_Change_Request_Line_Item__c where id in :(newPCRLIs)];

for(Price_Change_Request_Line_Item__c eachPriceChangeRequestLine: newPCRLIsWithOwnerName){

	if(recordOwnerApprovalMap.containsKey(eachPriceChangeRequestLine.Owner.Name)){
		
		//Assign approvers to this record 
		//Find the approver using the key of map recordOwnerApprovalMap
		// eachPriceChangeRequestLine.approver1__c = (String)recordOwnerApprovalMap.get(eachPriceChangeRequestLine.Owner.Name).get(Schema.LATAM_Pricing_Approval_Hierarchy__mdt.Approver1__c);
	
	}
}

 

All Answers

Debanjan SharmaDebanjan Sharma
Hi Susannah,

As per my understanding its better to use map than putting record owners in a set. Please see below approach and let me know if this helps.
 
//Instead of putting record owner in a list lets use a map of Record Owner and LATAM_Pricing_Approval_Hierarchy__mdt
Map<String,LATAM_Pricing_Approval_Hierarchy__mdt> recordOwnerApprovalMap = new Map<String,LATAM_Pricing_Approval_Hierarchy__mdt>();

for (LATAM_Pricing_Approval_Hierarchy__mdt approvalHierarchy : approvalHierarchies){
      
	  String owner = (String)approvalHierarchy.get(Schema.LATAM_Pricing_Approval_Hierarchy__mdt.Record_Owner__c);
      recordOwnerApprovalMap.put(owner,approvalHierarchy);
}

// Now this map can be used to assign approval in individual records

Price_Change_Request_Line_Item__c[] newPCRLIsWithOwnerName = [select id,Owner.Name from Price_Change_Request_Line_Item__c where id in :(newPCRLIs)];

for(Price_Change_Request_Line_Item__c eachPriceChangeRequestLine: newPCRLIsWithOwnerName){

	if(recordOwnerApprovalMap.containsKey(eachPriceChangeRequestLine.Owner.Name)){
		
		//Assign approvers to this record 
		//Find the approver using the key of map recordOwnerApprovalMap
		// eachPriceChangeRequestLine.approver1__c = (String)recordOwnerApprovalMap.get(eachPriceChangeRequestLine.Owner.Name).get(Schema.LATAM_Pricing_Approval_Hierarchy__mdt.Approver1__c);
	
	}
}

 
This was selected as the best answer
Susannah PSusannah P
Thank you Debanjan! This was incredibly helpful. I've got the code working and there is only one issue that I'm still facing. My field Shared_Approver_1__c on Price_Change_Request_Line_Item__c is a lookup to the user record but right now my code is inserting a string value (LATAM_Pricing_Approval_Hierarchy__mdt.Approver_1__c) instead of an ID.
 
eachPriceChangeRequestLine.Shared_Approver_1__c = 
            (String)recordOwnerApprovalMap.get(eachPriceChangeRequestLine.Shared_Owner_Name__c)
            .get(Schema.LATAM_Pricing_Approval_Hierarchy__mdt.Approver_1__c);
I had hoped to use my custom metadata definition to store the user name that I could use to lookup the ID of that user (I was trying to avoid hard coding IDs). Any help you could provide in helping me get this last step would be much appreciated!!

Here's the full code I have that is working, it's just inserting a String into my lookup field instead of an ID
public class PriceChangeRequestLineItemTriggerHandler {

    //Before they are inserted,put all new record in a set named newPCRLIs
    public void OnBeforeInsert(Price_Change_Request_Line_Item__c[] newPCRLIs){
    system.debug('This is the price change request I just inserted' +newPCRLIs);
      
    //Query for custom metadata definition named approval Hierarchies
    LATAM_Pricing_Approval_Hierarchy__mdt [] approvalHierarchies = [SELECT MasterLabel, QualifiedApiName,Record_Owner__c,
                                                                 Approver_1__c,Approver_2__c,Approver_3__c
                                                                 FROM LATAM_Pricing_Approval_Hierarchy__mdt];
        
Map<String,LATAM_Pricing_Approval_Hierarchy__mdt> recordOwnerApprovalMap = new Map<String,LATAM_Pricing_Approval_Hierarchy__mdt>();

for (LATAM_Pricing_Approval_Hierarchy__mdt approvalHierarchy : approvalHierarchies){
      
	  String owner = (String)approvalHierarchy.get(Schema.LATAM_Pricing_Approval_Hierarchy__mdt.Record_Owner__c);
      recordOwnerApprovalMap.put(owner,approvalHierarchy);
}

// Now this map can be used to assign approval in individual records

system.debug('This is my original set'+newPCRLIs);
for(Price_Change_Request_Line_Item__c temp : newPCRLIs)
    system.debug('This is my set with PCRLIs with Owner Name' +temp.Shared_Owner_Name__c);
        
for(Price_Change_Request_Line_Item__c eachPriceChangeRequestLine: newPCRLIs){
	system.debug('This is the owner name of the records' +eachPriceChangeRequestLine.Shared_Owner_Name__c);
    system.debug('Here is the recordOwnerApprovalMap' +recordOwnerApprovalMap);
    
	if(recordOwnerApprovalMap.containsKey(eachPriceChangeRequestLine.Shared_Owner_Name__c)){
		
		//Assign approvers to this record 
		//Find the approver using the key of map recordOwnerApprovalMap
		eachPriceChangeRequestLine.Shared_Approver_1__c = 
            (String)recordOwnerApprovalMap.get(eachPriceChangeRequestLine.Shared_Owner_Name__c)
            .get(Schema.LATAM_Pricing_Approval_Hierarchy__mdt.Approver_1__c);
        
       
	
	}
}}}
Debanjan SharmaDebanjan Sharma
Hi Susanna,

I would suggest to store username instead of name in custom metadata. Because there can be user with same name in CRM but username will be always unique.

Now to get the user id we have to query the user. So let's take the usenames in a list and query user object at once.
 
Map<String,Id> userIdMap = new Map<String,Id>();
List<String> userNameList = new List<String>();

for (LATAM_Pricing_Approval_Hierarchy__mdt approvalHierarchy : approvalHierarchies){
      
	  String owner = (String)approvalHierarchy.get(Schema.LATAM_Pricing_Approval_Hierarchy__mdt.Record_Owner__c);
      recordOwnerApprovalMap.put(owner,approvalHierarchy);
      userNameList.add(owner);
}

List<User> userList = [select id,name,Username from User where Username in :(userNameList)];

for(User u:userList ){

	userIdMap.put(u.Username,u.Id); // This map can be used to get userid by name
}

I have added this in your code & it should be something like this-
public class PriceChangeRequestLineItemTriggerHandler {

    //Before they are inserted,put all new record in a set named newPCRLIs
    public void OnBeforeInsert(Price_Change_Request_Line_Item__c[] newPCRLIs){
    system.debug('This is the price change request I just inserted' +newPCRLIs);
      
    //Query for custom metadata definition named approval Hierarchies
    LATAM_Pricing_Approval_Hierarchy__mdt [] approvalHierarchies = [SELECT MasterLabel, QualifiedApiName,Record_Owner__c,
                                                                 Approver_1__c,Approver_2__c,Approver_3__c
                                                                 FROM LATAM_Pricing_Approval_Hierarchy__mdt];
        
Map<String,LATAM_Pricing_Approval_Hierarchy__mdt> recordOwnerApprovalMap = new Map<String,LATAM_Pricing_Approval_Hierarchy__mdt>();
Map<String,Id> userIdMap = new Map<String,Id>();
List<String> userNameList = new List<String>();

for (LATAM_Pricing_Approval_Hierarchy__mdt approvalHierarchy : approvalHierarchies){
      
	  String owner = (String)approvalHierarchy.get(Schema.LATAM_Pricing_Approval_Hierarchy__mdt.Record_Owner__c);
      recordOwnerApprovalMap.put(owner,approvalHierarchy);
      userNameList.add(owner);
}

List<User> userList = [select id,name,Username from User where Username in :(userNameList)];

for(User u:userList ){

	userIdMap.put(u.Username,u.Id);
}

// Now this map can be used to assign approval in individual records

system.debug('This is my original set'+newPCRLIs);
for(Price_Change_Request_Line_Item__c temp : newPCRLIs)
    system.debug('This is my set with PCRLIs with Owner Name' +temp.Shared_Owner_Name__c);
        
for(Price_Change_Request_Line_Item__c eachPriceChangeRequestLine: newPCRLIs){
	system.debug('This is the owner name of the records' +eachPriceChangeRequestLine.Shared_Owner_Name__c);
    system.debug('Here is the recordOwnerApprovalMap' +recordOwnerApprovalMap);
    
	if(recordOwnerApprovalMap.containsKey(eachPriceChangeRequestLine.Shared_Owner_Name__c)){
		
		//Assign approvers to this record 
		//Find the approver using the key of map recordOwnerApprovalMap
		
            String ownerName= (String)recordOwnerApprovalMap.get(eachPriceChangeRequestLine.Shared_Owner_Name__c)
            .get(Schema.LATAM_Pricing_Approval_Hierarchy__mdt.Approver_1__c);
	   eachPriceChangeRequestLine.Shared_Approver_1__c = userIdMap.get(ownerName);
        
       
	
	}
}}}

Regards,
Debanjan​