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
KitaSanKitaSan 

Trigger to update Lookup

In our evironment, users can relate opportunities to another opportunity (add on sales) or to a 'vision' (custom object). There are two lookup fields on the opportunity to track this. 

 

Source_Vision__c and Source_Opportunity__c 

 

It is possible that an opportunity is created from another opportunity that was created from a vision. What I would like to do is create a trigger that will populate this relationship so that the newly created opportunity has both the relationship to the original vision, and the source opportunity. 

 

trigger OpportunityTrigger on Opportunity (after insert) {
	for(Opportunity o:Trigger.new){
//Check if Source_Vision__c is null if(o.Source_Opportunity__r.Source_Vision__c.name != null ){

//If not, set Source_Vision__c on new record to Source_Vision of relaated record. o.Source_Vision__c = o.Source_Opportunity__r.Source_Vision__c;} } }

 I am getting an invalid key relationship error (Opportunity.Source_Vision__c)


Am I missing something? 

 

Thanks@

 

BPrakash1BPrakash1

I think you need to get the list and need to update the opp

That should work!

KitaSanKitaSan

Thanks, 

 

I was able to modify the trigger to get it to validate, but am still having trouble getting the data. 

trigger OpportunityTrigger on Opportunity (before insert,before update) {
    for(Opportunity o:Trigger.new){
        if(o.Source_Opportunity__r.Source_Vision__c.id != null){
            o.Source_Vision__c = o.Source_Opportunity__r.Source_Vision__r.id;}
        }
}

 The trigger is firing, but I can't seem to get to any data from the vision. 

I did some testing and I am unable to use the customobject__r.customobject2__r.field structure. Is there another way to accomplish this?

BPrakash1BPrakash1

Take that in a list and update the list.

Trigger will fire but you need to get the id and get the oopportunity in a List and update the List,intstead of directly assigning the value.

 

 

KitaSanKitaSan

Thanks, however I am not trying to update the parent in a parent-child relationship. 

 

I simply want to take the ID from a lookup on Opportunity 1 to Opportunity 2 (which is also related to Opportunity 1). 

 

Example:

I have a Vision, VisionONE which leads to an opportunity. Opportunity 1 has Source_Vision__c = VIsionONE. Opportunity 1 leads to Opportunity 2. Opportunity 2 has Source_Opportunity __c = Opportunity 1, but Source_Vision__c = blank.

 

I would like to set Opportunity2.Vision_Source__c to Opportunity2.Source_Opportunity__r.Source_Vision__c. 

 

Would I have to query Opportunity 1 in the list? [Select Id, Source_Vision__c From Oppotunity where Id = o.Source_Opportunity__r.id ? 

 

Thanks, and apologies if I am not understanding this correctly. 

BPrakash1BPrakash1

yes,

GET THE LIST and assign the values.

trigger test(before insert,before update){

   Set<Id> oppId = new SEt<Id>();

  for(Opportunity opp : trigger.new){

    if(opp.Source_Opportunity__c != null){

      oppId.add(opp.Source_Opportunity__c);

    }

 

}

 

Map<Id,Opportunity> oppMap = new Map<Id,Opportunity>([Select Id,Name,Source_Vision__c from Opportunity where Id in: oppId]);

 

for(opportunity opp1 : trigger.new){

         if(oppMap.get(opp1.Id) != null){

             opp1.Source_Vision__c =oppMap.get(opp1.Id).Source_Vision__c;

 

}

 

}

 

update oppMap.Values();

 

 

 

}

 

this will work

i guess

KitaSanKitaSan

Thanks for your help, but this still does not appear to be working. 

 

trigger test(before insert,before update){
   Set<Id> oppId = new SEt<Id>();
  for(Opportunity opp : trigger.new){
    if(opp.Source_Opportunity__c != null){
      oppId.add(opp.Source_Opportunity__c);
    }
}
 
Map<Id,Opportunity> oppMap = new Map<Id,Opportunity>([Select Id,Name,Source_Vision__c from Opportunity where Id in: oppId]);
 
for(opportunity opp1 : trigger.new){
         if(oppMap.get(opp1.Id) != null){
             opp1.Source_Vision__c =oppMap.get(opp1.Id).Source_Vision__c;
}
}
update oppMap.Values();
}


It looks like it is not adding the opportunity to the map as it is failing the  if(oppMatp.get(opp1.Id) != null) comparison

Rahul SharmaRahul Sharma
 
Best way to check if the value is present in map is with use of map.containsKey.
 
Change this code
    if(oppMap.get(opp1.Id) != null){
to
   if(oppMap.containsKey(opp1.Id)){
 
Check out this salesforce documentation for details.
KitaSanKitaSan

Thanks, I tried rewriting the trigger with your suggestion, but I still cannot get it to work. 

 

trigger OpportunityTrigger on Opportunity (before insert,before update) {
              
     Map<Id,Opportunity> OppMap = new Map<Id,Opportunity>();
     
     //Add SourceOpportunity ID to the map
     Set<id> Ids = new Set<id>();
         for (Opportunity  Opp : Trigger.new) 
         {
         	if(opp.Source_Opportunity__c != null){
         		Ids.add(opp.Source_Opportunity__c);
         	}
         }
     
     //Query the Source Opportunity to get the Vision_Source__c
     Map<id,Opportunity> OppMap2 = new Map<id,Opportunity>([Select Id, Source_Vision__c from Opportunity Where Id in :Ids]);  
     
     
		//Assign the Source Vision of the new Opportunity to the Source Vision of the source opportunity     
         for (Opportunity Opp2 : Trigger.new) 
         	if(oppMap.containsKey(opp2.Id))
         {
             Opp2.Source_Vision__c = OppMap2.get(Opp2.id).Source_Vision__c;
         }
         
         //Update Values
         if(!OppMap.isEmpty())
         {
             update OppMap.values();
         }
}

 

I think the steps would be something like this: 

 

Check to see if new opportunity (oppNew) OppNew.SourceOpportunity__c is blank. 

If not blank, add the SourceOpportunity__c to a map. 

Query to find the source opportunity oppSrc and pull in oppSrc.Source_Vision__c

Set oppNew.Source_Vision__c to oppSrc.Source_Vision

Update

 

but I just cant seem to get it to work. I have read the suggested posts but still have no luck. Any help would be very much appreciated. 

KitaSanKitaSan

Got it to work. 

 

trigger OpportunityTrigger on Opportunity (before insert,before update) {
//Set the ID
Set<ID> srcOpptyID = new Set<ID>();
for(Opportunity o:Trigger.new){srcOpptyID.add(o.Source_Opportunity__c);}

//Map of source opportunities
Map<ID,Opportunity> srcOpptyMap = new Map<ID,Opportunity>([select id,Source_Vision__c from Opportunity where id=:srcOpptyID]);

for(Opportunity o2:Trigger.new){
	//Check to see if the map is empty to avoid a null pointer
	if(!srcOpptyMap.isEmpty()){
		o2.Source_Vision__c = srcOpptyMap.get(o2.Source_Opportunity__c).Source_Vision__c;
	}
}
}

 

 

However, my test class is failing.. I have it deployed in sandbox and it is working fine, but fails in the test class.

@isTest 
private class OpportunityControllerTestClass {
static testMethod void myUnitTest() {

	//Create an account
    Account a = new Account (name='Test Account');
    insert a;

    //Create a vision
    Vision__c v = new Vision__c (name='Test Vision');
    v.Account__c = a.id;
    
    insert v;
     	
    //Create a source opporunity with the vision as Vision_Source__c
    Opportunity o = new Opportunity (name='Test Opportunity');
    o.StageName = 'Targeted Account';
    o.CloseDate = system.today();
    o.Source_Vision__c = v.id;
    insert o;
     	
		//Test if Opportunity Vision link is there
     	System.assertEquals(v.id, o.Source_Vision__c);

	//Create another opporunity with the o as the Source_Opportunity__c
	Opportunity o2 = new Opportunity (name='Test Opportunity2');
	o2.StageName = 'Targeted Account';
	o2.CloseDate = system.today();
	o2.Source_Opportunity__c = o.id;
	insert o2;

		//Test if Opportunity to Opportunity link is there
     	System.assertEquals(o.id, o2.Source_Opportunity__c);
			
		//Test if Opportunity Vision link is there
     	System.assertEquals(o.Source_Vision__c, o2.Source_Vision__c);

}
}