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
VioletViolet 

Auto-populate lookup field from Custom object on Standard Object

Trying to auto-populate Custom_Object on Asset from Opportunity before insert. Getting errors, any help would be appreciated
Asset has lookup to Opportunity
Asset has lookup to Custom_Object
Custom_Objet has lookup to Opportunity

User-added imageUser-added image
trigger AutoPopulate on Asset (before insert) {
    
    Map <Id, Opportunity> mapidopp= new map<id,Opportunity> ([select Id,(select Id,Name from Custom_Object__r 
                                    where Is_Primary__c=true ),(select Id,Name from Assets__r 
                                        where Id IN: Trigger.new)from Opportunity where 
                                    (Id IN (SELECT Opportunity_Name__c from Custom_Object__c))]);
    List <Asset> listasst=new List <Asset> ();
    for(Id i: mapidopp.keyset()){

    for (Custom_Object__c obj:mapidopp.get(i).Custom_Object__r){
          for (Asset asst:mapidopp.get(i).Assets__r ){
                System.debug('test7' + obj.Id);
              //getting error here that Custom_Object_r.Id was not retrieved in SOQL
              //but when I add it to SOQL get Attempt to de-refernece a null point
           		asst.Custom_Object__r.Id=obj.Id;
                listasst.add(asst);
           		System.debug('test4' + asst.Custom_Object__r.Id); 
           		
        }  
        }
        
    }

insert listasst;
}

 
Best Answer chosen by Violet
Neetu_BansalNeetu_Bansal
Hi Violet,


I have updated the code, and I am populating the value in before insert. Try this code:
trigger AssetTrg on Asset( before insert )
{
	Set<Id> opportunityIds = new Set<Id>();
	for( Asset a : trigger.new )
	{
		if( a.Opportunity__c != null )
		{
			opportunityIds.add( a.Opportunity__c );
		}
	}
	
	Map<Id, Custom_Object__c> oppToCustomObject = new Map<Id, Custom_Object__c>();
	for( Custom_Object__c c : [ Select Opportunity_Name__c, Id, Name from Custom_Object__c where Is_Primary__c = true AND Opportunity_Name__c IN: opportunityIds ])
	{
		oppToCustomObject.put( c.Opportunity_Name__c, c );
	}
	
	for( Asset a : trigger.new )
	{
		if( a.Opportunity__c != null && oppToCustomObject.containsKey( a.Opportunity__c ))
		{
			a.A__c = oppToCustomObject.get( a.Opportunity__c ).Id;
		}
	}
}
Let me know, if you need any other help.

Thanks,
Neetu

All Answers

Chris Gary CloudPerformerChris Gary CloudPerformer
I'll take aswing at this.  You are selecting the Assets as a Subselect in the Opportunity Map,  but your assets are not written yet because this is in a before insert.  So I think you are attempting to work with records that aren't written.  What you may want to do is instead of attempting to loop through the opportunities and work with child Custom Objects and child Assets,  loop through the Assets being inserted , and based on the Opportunity they are related to, get the related Custom Object and write it that way.  Good luck!
ManojjenaManojjena
Hi Violet,

As your trigger  with before insert so record is not in data base so ID is not generated  that is the reason you got first error .
BAsically in apex you should not write loop inside loop inside loop which have max chance to hit the LIMIT .
Can you explain your requirment So that we can help you .
VioletViolet
Thank you for replying. I am trying to auto-populate a look up field on Asset . When the user creates an Asset from Opportunity the lookup field on Asset needs to populate the Custom_Object with Is_Primary flag that exists on Opportunity. 
  • Asset has lookup relationship to Opportunity (You can create Assets from Opportunity)
  • Asset has lookup relationship to  A (Custom_Object)
  • A(Custom_Objet_c) has lookup relationship to Opportunity: A has Is_Primary flag  
I even tried a simpler approach but getting: System.StringException: Invalid id when trying to assign the Lookup field to a text value
trigger PopulateGVQuotev2 on Asset (after insert) {
    
   //get the opportunitu ID of the Asset in this trigger
   //get the primry Custom_Object on the Opportunity
   //populate primary Custom_Object on the Asset
   
 
    List <Asset> listasset=[select Id, Opportunity__c,Opportunity__r.Primary_A__c from Asset where Id IN:Trigger.new];

        for (Asset asst: listasset){
            system.debug('test'+ asst.Opportunity__r.Primary_A__c);
            asst.A__c=asst.Opportunity__r.Primary_A__c;
                
            }    
           
    }

 
Neetu_BansalNeetu_Bansal
Hi Violet,


I have updated the code, and I am populating the value in before insert. Try this code:
trigger AssetTrg on Asset( before insert )
{
	Set<Id> opportunityIds = new Set<Id>();
	for( Asset a : trigger.new )
	{
		if( a.Opportunity__c != null )
		{
			opportunityIds.add( a.Opportunity__c );
		}
	}
	
	Map<Id, Custom_Object__c> oppToCustomObject = new Map<Id, Custom_Object__c>();
	for( Custom_Object__c c : [ Select Opportunity_Name__c, Id, Name from Custom_Object__c where Is_Primary__c = true AND Opportunity_Name__c IN: opportunityIds ])
	{
		oppToCustomObject.put( c.Opportunity_Name__c, c );
	}
	
	for( Asset a : trigger.new )
	{
		if( a.Opportunity__c != null && oppToCustomObject.containsKey( a.Opportunity__c ))
		{
			a.A__c = oppToCustomObject.get( a.Opportunity__c ).Id;
		}
	}
}
Let me know, if you need any other help.

Thanks,
Neetu
This was selected as the best answer
VioletViolet
Thank you all for your help! Much appreciated!
@Neetu-It worked! It is amazing! Thank you so much! I see you used Sets in your code if there are any good resources to understand Maps and Sets for this type of triggers I would appreciate it if you could send me the links.