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
AK123AK123 

Trigger After Account Update

Hello, I am writing a trigger that displays information from the most recently created opportunity on the account page. The fields are dynamic, meaning anytime theres an account update or insert, it looks for the most recently created opportunity, and grabs the necessary info. The trigger works fine, except when you move an opportunity. When moving an opporuntiy,  the information displayed on the account page is from the newly moved opportunity (which is incorrect). It does trigger an account update, but it still shows the old/incorrect data. My thought was to write a second after update trigger. Below is the error message i receive when attempting to update any field on the account page. Seems to be an iterative loop problem. 

 

Error:Apex trigger DynamicOppDataOnAcctPageafter caused an unexpected exception, contact your administrator: DynamicOppDataOnAcctPageafter: execution of AfterUpdate caused by: System.DmlException: Update failed. First exception on row 0 with id 001g0000006lRjZAAU; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, DynamicOppDataOnAcctPageafter: maximum trigger depth exceeded Account trigger event AfterUpdate for [001g0000006lRjZ] Account trigger event AfterUpdate for [001g0000006lRjZ] Account trigger event AfterUpdate for [001g0000006lRjZ] Account trigger event AfterUpdate for [001g0000006lRjZ] Account trigger event AfterUpdate for [001g0000006lRjZ] Account trigger event AfterUpdate for [001g0000006lRjZ] Account trigger event AfterUpdate for [001g0000006lRjZ] Account trigger event AfterUpdate for [001g0000006lRjZ] Account trigger event AfterUpdate for [001g0000006lRjZ] Account trigger event AfterUpdate for [001g0000006lRjZ] Account trigger event AfterUpdate for [001g0000006lRjZ] Account trigger event AfterUpdate for [001g0000006lRjZ] Account trigger event AfterUpdate for [001g0000006lRjZ] Account trigger event AfterUpdate for [001g0000006lRjZ] Account trigger event AfterUpdate for [001g0000006lRjZ] Account trigger event AfterUpdate for [001g0000006lRjZ]: []: Trigger.DynamicOppDataOnAcctPageafter: line 17, column 1

 

I have included both the before and after triggers below, any help/advice would be greatly appreciated

 

Before Trigger

 

trigger DynamicOppDataOnAcctPageBefore on Account (before insert, before update) {
 
Account acct = Trigger.new[0];
String accountid = acct.id;
String OpQ = null;
String OpA = null;
 
for (Opportunity opp: [SELECT id, security_question__c, security_answer__c
                                        FROM opportunity
                                        WHERE (AccountID = :accountid) AND (recordtypeid = '01230000000000K'  OR recordtypeid = '012600000009I8D'
                                        OR recordtypeid = '012600000009FS0' OR recordtypeid = '01230000000000L')
                                        ORDER BY user_created_date__c ASC
                                        ]){
                                       
              acct.Security_question_opp__c  =  opp.security_question__c ;
              acct.Security_answer_opp__c  =  opp.security_answer__c   ;                    
              } 
}

 

After Trigger

 

 

trigger DynamicOppDataOnAcctPageAfter on Account (after update) {

Account acct = Trigger.new[0];
String accountid = acct.id;


   Map<Id, Account> accountMap = new Map<Id, Account>();
   for (Opportunity opp: [SELECT id, accountid, security_question__c, security_answer__c FROM opportunity
      WHERE (AccountID = :accountid) AND (recordtypeid = '01230000000000K'  OR recordtypeid = '012600000009I8D'
      OR recordtypeid = '012600000009FS0' OR recordtypeid = '01230000000000L')
      ORDER BY user_created_date__c ASC]){

      Account acct1 = new Account(Id=opp.AccountId, Security_Question_opp__c = opp.security_question__c, security_Answer__c = opp.Security_Answer__c);
      AccountMap.put(acct1.Id, acct1);
   } 
   if(accountMap.size()>0) {
       update accountMap.values();
   }

  Thanks Again!

 

crop1645crop1645

You are having the common problem of recursive triggers

 

Solution is here: http://developer.force.com/cookbook/recipe/controlling-recursive-triggers

 

The after update trigger is updating Accounts that in turn cause the before/after triggers to fire again...and again...

souvik9086souvik9086

The problem is due to that your trigger is calling recursively. To prevent that you have to create a class where you can keep a static variable and then in the trigger make that variable as true, so that recursive call will be prevented.

 

Controller

 

public class FutureTriggerController{

public static boolean isFutureUpdate = false;

}

 

Trigger

 

trigger DynamicOppDataOnAcctPageAfter on Account (after update) {
if(FutureTriggerController.isFutureUpdate != true){
FutureTriggerController.isFutureUpdate =true;
Account acct = Trigger.new[0];
String accountid = acct.id;


Map<Id, Account> accountMap = new Map<Id, Account>();
for (Opportunity opp: [SELECT id, accountid, security_question__c, security_answer__c FROM opportunity
WHERE (AccountID = :accountid) AND (recordtypeid = '01230000000000K' OR recordtypeid = '012600000009I8D'
OR recordtypeid = '012600000009FS0' OR recordtypeid = '01230000000000L')
ORDER BY user_created_date__c ASC]){

Account acct1 = new Account(Id=opp.AccountId, Security_Question_opp__c = opp.security_question__c, security_Answer__c = opp.Security_Answer__c);
AccountMap.put(acct1.Id, acct1);
}
if(accountMap.size()>0) {
update accountMap.values();
}
}
}

 

If this post is helpful please throw Kudos.If this post solves your problem kindly mark it as solution.

Thanks

AK123AK123

Thanks all, this is running error-free, but not working as expected. The after update trigger doesn't seem to be updating the account pages. I replaced the bolded/underlined code below with a static Account ID, and it worked correcrly. Therefore, I believe theres an issue with the way this map is getting and updating the account pages.  Please advice, thanks!

 

trigger DynamicOppDataOnAcctPageAfter on Account (after insert, after update, after delete) {

if(FutureTriggerController.isFutureUpdate != true){
FutureTriggerController.isFutureUpdate =true;

Account acct = Trigger.new[0];
String accountid = acct.id;


Map<Id, Account> accountMap = new Map<Id, Account>();
for (Opportunity opp: [SELECT id, accountid, security_question__c, security_answer__c FROM opportunity
WHERE (AccountID = :accountid) AND (recordtypeid = '01230000000000K' OR recordtypeid = '012600000009I8D'
OR recordtypeid = '012600000009FS0' OR recordtypeid = '01230000000000L')
ORDER BY user_created_date__c ASC]){
Account acct1 = new Account(Id=opp.AccountId, Security_Question_opp__c = opp.security_question__c, security_Answer__c = opp.Security_Answer__c);
AccountMap.put(acct1.id, acct1);
}
if(accountMap.size()>0) {
update accountMap.values();
}
}
}

 

crop1645crop1645

AK123

 

Your problem statement said you wanted to take the most recently created Oppo and update the Account with data from that Oppo whenver the account is updated

 

trigger DynamicOppDataOnAcctPageAfter on Account (after update) {  // only need after update as there can't be any oppos on account insert and you don't care on after delete

if(FutureTriggerController.isFutureUpdate != true){
   FutureTriggerController.isFutureUpdate =true;

   // Bulkify the trigger by building map of all updated accounts : latest user created oppo
   Map<ID,Opportunity> aIdToOppoMap = new Map<ID,Opportunity> ();
   for (Opportunity o : [select id, accountid, security_question__c, security_answer__c from Opportunity
                          where accountId IN : Trigger.new and 
                                recordTypeId IN : new List<ID> {'01230000000000K', '012600000009I8D','012600000009FS0','01230000000000L'}
                          order by user_created_date__c asc])
       if (!aIdToOppoMap.containsKey(o.accountId)) aIdToOppoMap.put(o.accountId,o);      // map is empty, put the oppo in
       else 
       if (aIdToOppoMap.get(o.accountId).user_created_date__c < o.user_created_date__c)  // repl in map with the latest user-created Oppo
           aIdToOppoMap.put(o.accountId,o);  

   List<Account> aUpdList = new List<Account> ();   // bulk list to update
   for (Account a: Trigger.new) {
      a.Security_Question_opp__c = aIdToOppoMap.get(a.id).Security_Question_opp__c;
      a.security_Answer__c = aIdToOppoMap.get(a.id).security_Answer__c ;
      aUpdList.add(a);
   }
   if (aUpdList.size() > 0) 
      try {update aUpdList;}
      catch(DmlException e) {// do something useful here }
}
}

 I rewrote your trigger to be bulk aware; I removed the after insert and after delete as they are not relevant here. I'm assuming that you don't have other after update triggers on Account that don't undo this trigger's work as trigger execution order is not deterministic.

 

I also tried to be clearer in variable names

 

Also best practice advice is not to use recordtypeIds in code. If you create the recordtypes first in a sandbox, those ids wont be the same when you deploy to PROD. Always use the developerName field instead to locate recordtypeIds before you need to use them - much better documentation for your code

 

e.g

 

where recordType.DeveloperName IN ('name1', 'name2', ... )