+ Start a Discussion
Baguiar2Baguiar2 

Trigger to update Parent role ID in Opportunity

HI there,

 

working on a trigger too get the parent role of the opportunity Owner user, as I beleive I can;t do it using a formula in SF. If possible please let me know. But my issue is that the trigger bellow will not let me update the field "Manager_role__C" as the error says that  "Can't execute the After Update" as record is read only . Tried to change the trigger to "before update" and got another error as it says " execution of BeforeUpdate caused by: System.SObjectException: DML statment cannot operate on trigger.new or trigger.old: Trigger.AboveRole: line 20, column 1"

 

Pretty sure it is a simple thing in my code but driving me crazy as usual.. Not sure also if this is becasue I have other triggers in the Oppt object , all 'After update" but they will change values in other objects than the Oppt itself. Here is the code:

 

trigger AboveRole on Opportunity (before insert, before update) {
  Set<Id> recordIds = new Set<Id>();
  Set<Id> acctIds = new Set<Id>();
  Set<Id> userIds = new Set<Id>();
  Set<Id> roleIds = new Set<Id>();
 

  for(opportunity S:Trigger.new)
    if(S.type == 'Renewal'){
     recordIds.add(S.id);
      acctIds.add(S.accountid);
    userIds.add(S.ownerid);
 
        
    List<User> RoleUSer = [Select userroleID from USER where id in :userids];
    roleIds.add(RoleUser[0].userroleID);
    List<Userrole> roleparent =[Select parentroleid from userrole where id in:roleIds];
       IF (roleparent.size() > 0){
       S.manager_role__C = roleparent[0].parentroleid;
       update s;      
       }
    }

}

 


Best Answer chosen by Admin (Salesforce Developers) 
Aar3538Aar3538

Hello,

 

With a before trigger, you do not need to call an update for Trigger.new since the dataset hasn't been written yet.  So to take your code for example:

 

IF (roleparent.size() > 0){
       S.manager_role__C = roleparent[0].parentroleid;
}

 

This is all you would need since S is an opportunity record from Trigger.new and the manager_role__c field has been updated with the roleParent[0].parentroleid before the insert or update.

 

If for whatever reason, you DID want the trigger to occur on an after update, you could always do the following:

 

List<Opportunity> oppsToUpdate = [Select Id From Opportunity where Id in: Trigger.new];

And then update the oppsToUpdate list.

 

Also as an FYI, please be careful about your triggers not being bulkified.  I notice you have an update s; inside a for loop.  While this wont be a problem if you remove the update s, in the future you would want to add the changed records (in this case Opportunity S) to a list and then at the end update the list.

 

Hope this helps!

All Answers

Aar3538Aar3538

Hello,

 

With a before trigger, you do not need to call an update for Trigger.new since the dataset hasn't been written yet.  So to take your code for example:

 

IF (roleparent.size() > 0){
       S.manager_role__C = roleparent[0].parentroleid;
}

 

This is all you would need since S is an opportunity record from Trigger.new and the manager_role__c field has been updated with the roleParent[0].parentroleid before the insert or update.

 

If for whatever reason, you DID want the trigger to occur on an after update, you could always do the following:

 

List<Opportunity> oppsToUpdate = [Select Id From Opportunity where Id in: Trigger.new];

And then update the oppsToUpdate list.

 

Also as an FYI, please be careful about your triggers not being bulkified.  I notice you have an update s; inside a for loop.  While this wont be a problem if you remove the update s, in the future you would want to add the changed records (in this case Opportunity S) to a list and then at the end update the list.

 

Hope this helps!

This was selected as the best answer
Baguiar2Baguiar2

Thanks a lot and really, thatks for the heads up on the bukifying ! that solved my problem.