+ Start a Discussion
KitagawaSan1337KitagawaSan1337 

Read only error....

Trying to write a trigger to help out with our reporting on lead sources... 

 

The idea is to have upon creation of opportunity, if lead source is not defined, look into the contact. If the contact lead source is null, look at the custom Account_Source__c field. 

 

I have the following written, but am getting an error 

Apex trigger SetOpSource caused an unexpected exception, contact your administrator: SetOpSource: execution of AfterInsert caused by: System.FinalException: Record is read-only: Trigger.SetOpSource: line 6, column 1

 

trigger SetOpSource on Opportunity (after insert,after update) {

//If Opportunity LeadSource = Null and Primary Contact != null then go to Contact Lead Source
for(Opportunity o2:Trigger.new){
if(o2.LeadSource == null && o2.Primary_Contact__r.LeadSource != null){
  o2.LeadSource=o2.Primary_Contact__r.LeadSource;

}else{

//If Opportunity LeadSource = Null and Account.Account_Source__c != null then go to Contact Lead Source
if(o2.LeadSource == null && o2.Account.Account_Source__c != null){
  o2.LeadSource=o2.Account.Account_Source__c;
}
} 
}
}

 

On a side note, I also cant get the trigger to fire based on if statement... can you not use == null on a picklist value?

 

Thanks!

 

Best Answer chosen by Admin (Salesforce Developers) 
Starz26Starz26

I believe that the field is not available for comparison using the trigger.new object (maybe it is I have not tested in trigger. Anon block works when using the object itself). You may have to build a list of related records using soql that have an id in the trigger.new and then use that as the comparison....

 

I.e.

 

Set<ID> oppID = New Set<ID>();

 

for (yourobject o : trigger.new)

    oppID.add(o.Opportunity)

 

Map<ID, Opportunity> opp = [Select Field From Opportunity Where ID IN :oppID];

 

Then loop

 

for (yourObject o : trigger.new){

 if(opp.containsKey(o.Opportunity){

     if(opp.FIELD) == Null{

          do stuff

     }else{

          do stuff

     }

  

}

}

 

 

or something like that

All Answers

Starz26Starz26

You cannot edit a record that is in AFTER UPDATE

 

You should be able to accomplish this in a Before update trigger

trigger SetOpSource on Opportunity (before insert,before update) {

//If Opportunity LeadSource = Null and Primary Contact != null then go to Contact Lead Source
for(Opportunity o2:Trigger.new){
if(o2.LeadSource == null && o2.Primary_Contact__r.LeadSource != null){
  o2.LeadSource=o2.Primary_Contact__r.LeadSource;

}else{

//If Opportunity LeadSource = Null and Account.Account_Source__c != null then go to Contact Lead Source
if(o2.LeadSource == null && o2.Account.Account_Source__c != null){
  o2.LeadSource=o2.Account.Account_Source__c;
}
} 
}
}

 As for the picklist, == null should work, throw some misc debug statements like:

 

if(o2.LeadSource == null)

    system.debug('LeadSource IS NULL');

else

   system.debug('LeadSource IS NOT NULL and Equals: ' + o2.leadsource);

 

to see what is going on. A picklist value that has not been set is NULL so == Null works...

KitagawaSan1337KitagawaSan1337

I think the problem might actually be referencing data from the Primay_Contact__r relationship... 

 

Even if I set the trigger to if(true) I still cant set the opportunity Lead Source with any data from the Primary Contact (using Primary_Contact__r). 

 

If i change to set just text it works... 

Starz26Starz26

I believe that the field is not available for comparison using the trigger.new object (maybe it is I have not tested in trigger. Anon block works when using the object itself). You may have to build a list of related records using soql that have an id in the trigger.new and then use that as the comparison....

 

I.e.

 

Set<ID> oppID = New Set<ID>();

 

for (yourobject o : trigger.new)

    oppID.add(o.Opportunity)

 

Map<ID, Opportunity> opp = [Select Field From Opportunity Where ID IN :oppID];

 

Then loop

 

for (yourObject o : trigger.new){

 if(opp.containsKey(o.Opportunity){

     if(opp.FIELD) == Null{

          do stuff

     }else{

          do stuff

     }

  

}

}

 

 

or something like that

This was selected as the best answer
KitagawaSan1337KitagawaSan1337

Thanks! 

 

Finished Product: 

trigger SetOpSource on Opportunity (before insert,before update) {

//Get and set variables 
Set<ID> ContactIDs = new Set<ID>();
for(Opportunity o:Trigger.new){ContactIDs.add(o.Primary_contact__c);}
Map<ID,Contact> pContactMap = new Map<ID,Contact>([select id,LeadSource from Contact where id=:ContactIDs]);

for(Opportunity o:Trigger.new){

//If Opportunity LeadSource = Null and Primary Contact != null then go to Contact Lead Source
if(o.LeadSource == null && pContactMap.get(o.Primary_contact__c).LeadSource != null){


  o.LeadSource=pContactMap.get(o.Primary_contact__c).LeadSource;


//ELSE
}else{


Set<ID> AccountIDs = new Set<ID>();
for(Opportunity o2:Trigger.new){AccountIDs.add(o2.AccountId);}
Map<ID,Account> AcctMap = new Map<ID,Account>([Select id,Account_Source__c from Account where id=:AccountIDs]);

for(Opportunity o2:Trigger.new){
//If Opportunity LeadSource = Null and Primary_Contact__c.LeadSource = null and  Account.Account_Source__c != null then go to Contact Lead Source
if(o2.LeadSource == null && AcctMap.get(o2.AccountId).Account_Source__c != null){


  o2.LeadSource=AcctMap.get(o2.AccountId).Account_Source__c;
}
} 
}}}