+ Start a Discussion

after update trigger - cannot insert update activate entity

I have several triggers on the opportunity object...before insert, before update and before insert, before update.  I need to add a new trigger that fires after the opportunity is updated:


trigger OpportuntityAfterUpdate on Opportunity (after update) { List<Opportunity> opps = [Select Id, Transaction_ID__c, Name, StageName, Product_Line_ProDev_Category__c, Opportunity.Account.BillingStreet, Opportunity.Account.BillingCity, Opportunity.Account.BillingState, Opportunity.Account.BillingPostalCode From Opportunity WHERE Id in :Trigger.new]; Set<Id> oppyIds = new Set<Id>(); for (Opportunity o : opps) { oppyIds.add(o.Id); } OpportunityLineItem oli = [Select Site__c From OpportunityLineItem WHERE OpportunityId in : oppyIds LIMIT 1]; if (oli.Site__c <> null) { Account acct = [Select a.Name, a.Id From Account a WHERE a.Id = : oli.Site__c]; for (Opportunity oppy: opps) { if (oppy.StageName == 'Closed Won' && oppy.Product_Line_ProDev_Category__c > 0) { // Create a new single email message object // that will send out a single email to the addresses in the To, CC & BCC list. Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage(); // Strings to hold the email addresses to which you are sending the email. String[] toAddresses = new String[] {'test@test.com'}; String[] ccAddresses = new String[] {'test@test.com.com',}; // Assign the addresses for the To and CC lists to the mail object. mail.setToAddresses(toAddresses); mail.setCcAddresses(ccAddresses); // Specify the address used when the recipients reply to the email. mail.setReplyTo('test@test.com'); // Specify the name used as the display name. mail.setSenderDisplayName('Salesforce Support'); // Specify the subject line for your email address. mail.setSubject('A new Professional Development order has been placed!'); // Set to True if you want to BCC yourself on the email. mail.setBccSender(false); // Optionally append the salesforce.com email signature to the email. // The email address of the user executing the Apex Code will be used. mail.setUseSignature(false); // Specify the text content of the email. mail.setPlainTextBody('Opportunity Name: ' + oppy.Name + '/n' + 'Transaction ID: ' + oppy.Transaction_ID__c + '/n' + 'Account Name: ' + acct.Name + '/n' + 'Billing Address: ' + oppy.Account.BillingStreet + '/n' + 'Billing City: ' + oppy.Account.BillingCity + '/n' + 'Billing State: ' + oppy.Account.BillingState + '/n' + 'Billing Zip: ' + oppy.Account.BillingPostalCode + '/n'); mail.setHtmlBody('<p>Opportunity Name: ' + oppy.Name + '</p>' + '<p>Transaction ID: ' + oppy.Transaction_ID__c + '</p>' + '<p>Account Name: <a href=https://cs2.salesforce.com/' + acct.Id + '>' + acct.Name + '</a></p>' + '<p><hr /></p>' + '<p>Billing Address: ' + oppy.Account.BillingStreet + '</p>' + '<p>Billing State: ' + oppy.Account.BillingState + '</p>' + '<p>Billing Zip: ' + oppy.Account.BillingPostalCode + '</p>'); // Send the email you have created. Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail }); } } } }


The above trigger works by itself, but it is conflicting with the other triggers on the opportunity object.  It is causing the error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY error when a new opportunity is created. 


Here are the three existing triggers on the opportunity that are conflicting with the after update trigger:


trigger OpportunityBeforeInsert on Opportunity (before insert) { // calculate the "active *" fields on this opportunity's accounts for (Opportunity oppy : Trigger.new) { AccountActivityCalculator.updateAccount(oppy.AccountId); } } trigger OpportunityBeforeInsertBeforeUpdate on Opportunity (before insert, before update) { // grab owner's ID and push it into Commission_Salesperson__c (since Owner fields are not available in formula lookups) for (Opportunity opp : Trigger.new) { if(opp.Commission_Salesperson__c == null) { opp.Commission_Salesperson__c = opp.OwnerId; } } } trigger OpportunityAfterInsert on Opportunity (after insert) { List<Opportunity> opps = [select Id, Invoice_Preference__c, Account.Invoice_Preference_Value__c, Account.Sales_Area__c, Account.FOB_Destination__c, Account.District_Active_Sites__c, Account.District_Active_Subscriptions__c from Opportunity where Id in :Trigger.new]; for (Opportunity oppy: opps) { // copy over fields from account that should be historically accurate (i.e. can't be done via formulas) oppy.Invoice_Preference__c = oppy.Account.Invoice_Preference_Value__c; if (oppy.Payment_Terms__c == '') { // user is a salesperson, did not enter it; copy from Account oppy.Payment_Terms__c = oppy.Account.Payment_Terms__c; } oppy.FOB_Destination__c = oppy.Account.FOB_Destination__c; oppy.Sales_Area__c = oppy.Account.Sales_Area__c; oppy.Active_Sites__c = oppy.Account.District_Active_Sites__c; oppy.Active_Subscriptions__c = oppy.Account.District_Active_Subscriptions__c; } update opps; }


How can I get around this conflict and fire the after update trigger successfully?
Message Edited by Dman100 on 04-21-2009 09:51 AM


As far as I know, you can't update the record that fired the trigger in an after update/after insert trigger.


 Move the code from your trigger:

trigger OpportunityAfterInsert on Opportunity (after insert) 



to a before insert trigger



Obseservation , for best practice , separate your code from Trigger. Create a one Class for treatment this events.
Ex. OpportunityTriggerHandler(ParameterTrigger)
Or Make Ifs() to separate your code. only one trick