+ Start a Discussion
AK123AK123 

After Update Trigger

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 add an after update condition, but I get the below error:

 

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   ;                    

              } 

}

 

Error when adding the after update piece, the line bolded above is line 15:

 

Error:Apex trigger DynamicOppDataOnAcctPageBefore caused an unexpected exception, contact your administrator: DynamicOppDataOnAcctPageBefore: execution of AfterUpdate caused by: System.FinalException: Record is read-only: Trigger.DynamicOppDataOnAcctPageBefore: line 15, column 1

 

Any help would be greatly appreciated.

 

Thanks!

Best Answer chosen by Admin (Salesforce Developers) 
Tim BarsottiTim Barsotti

Change your where clause: 

WHERE (AccountID in : trigger.newMap.keySet())

 

All Answers

Avidev9Avidev9
For after trigger instead of doing
Account acct = Trigger.new[0];

do

Account acct = new Account(Id=Trigger.new[0].id);
Tim BarsottiTim Barsotti

This trigger will not hold up to bulk operations. Please review bulkifying principles.

 

See below for updated code.

 

trigger DynamicOppDataOnAcctPageBefore on Account (after insert, after update) {

String accountid = acct.id;
   List<Account> accountList = new List<Account>();
   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]){

Account acct = new Account(Id=opp.AccountId, Security_Question_opp__c = opp.security_question__c, security_Answer__c = opp.Security_Answer__c);
AccountList.add(acct); }
if(accountList.size()>0) {
update accountList;
} }

 

 

 

AK123AK123

Thanks all, I tried the bulkafied code, worked through some errors, but am stuck on this one.

 

Error:Apex trigger DynamicOppDataOnAcctPageBefore caused an unexpected exception, contact your administrator: DynamicOppDataOnAcctPageBefore: execution of AfterUpdate caused by: System.ListException: Duplicate id in list: 001g0000006lRjZAAU: Trigger.DynamicOppDataOnAcctPageBefore: line 17, column 1

 

Updated code:

 

trigger DynamicOppDataOnAcctPageBefore on Account (after insert, after update) {


Account acct = new Account(Id=Trigger.new[0].id);

String accountid = acct.id;
   List<Account> accountList = new List<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);
      AccountList.add(acct1);
   } 
   if(accountList.size()>0) {
       update accountList;
   }
}

 Please advise

 

 

Tim BarsottiTim Barsotti

Duplicate entries are permissible for lists, but not sets or maps. Switched the code to a map.

 

trigger DynamicOppDataOnAcctPageBefore on Account (after insert, after update) {

   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();
   }
}

 

AK123AK123

Thanks Tim, I now get the follow error. I think its running into an infinite loop:

 

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

 

Updated 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!

 

 

 

 

Tim BarsottiTim Barsotti

Setup an excution variable to prevent recursion. 

 

Public Class AccountController {
    Boolean triggerInProg = false;
}

 

trigger DynamicOppDataOnAcctPageafter on Account (after update) {

if(AccountController.triggerInProg = false) {
AccountController.triggerInProg = true;
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(); }
} }

 

AK123AK123

Thanks Tim, 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();
}
}
}

 

Tim BarsottiTim Barsotti

Change your where clause: 

WHERE (AccountID in : trigger.newMap.keySet())

 

This was selected as the best answer
AK123AK123

Thanks Tim, works like a charm