Hello and thank you for your time.

I have created a trigger on an opportunity that 'should' only run my methods if the stageName = 'PO IN(100%) and a contract is not already created.. as well if certain fields are not null. I get I should do my error checking on the if(trigger.isbefore) and then run my actual methods on the if(trigger.isafter) I am just confused on how I can :

  1. Disregard any updated opportunity that doesn't meet the criteria of 'PO In 100%'
  2. Make sure the trigger.old isnt already 'PO In 100%'
  3. If there are errors (fields are null or a child contract exists) do an addError() but allow the other triggers to run.

So far, I know how to get the opportunities and add them to a list (and put a child quote id if it exists)

 List<Id> oppIds = new List<Id>();
 List<ServiceContract> SContract = new List<ServiceContract>(); // List that will contain all the new Service Contracts that need to be added
 for(Opportunity opp:Trigger.new){
   if(Trigger.oldMap.get(opp.id).StageName != 'PO In (100%)' && opp.StageName == 'PO In (100%)') //This should take care of my first & second Step      
List<Opportunity> oppsFromDb =  [SELECT
                                Id, StageName, name, Accountid, owner__c, end_user_contact__c, RecordTypeId, OwnerId,
                                                (SELECT Id FROM Service_Contracts__r), (SELECT Id From Quotes)
                                Id IN:oppIds

Now I imagine is the time to use the before Update

  for(Opportunity verifyOpps: oppsFromDb){
    if(verifyOpps.Service_Contracts__r.size() != 0) { //A contract child exists
      verifyOpps.addError('A contract already exists, cannot create a new contract.');
    //.... other error checking code
   verifyOpps.save() // I have no idea how to save the record.. 
else if(Trigger.isAfter){
  for(Opportunity GoodOpps: oppsFromDb){
    // create a contract using the opp variables and other calculations
insert SContract;

If a contract does exist it should run the opp.addError. Does this mean i need to do an else and put the ones without errors in a new list, so only they go into the isafter trigger?

And by just doing opp.addError, does it automatically give the error or do i have to do something else for it to go back into the db? (Sorry if this is confusing).

Does this code make sense at all? Or am I doing this very wrong :)

Thanks again for your time.

1 Answer 1


This should work properly. Take a look at the Salesforce Order of Execution. Every time a record is saved, that record will run through this entire process. You will notice that the before trigger will run before a save (not a commit) happens to the server. When it goes to run that save, it will see that an error has been added and that record failed. It will fail out of the process and not run any of the after triggers.

So, essentially, you have it working fine. That trigger will actually get run multiple times during a single save.

  • Thanks Jesse for the quick response! So I dont need to make a new list with only the 'good' opportunities? I can just run a for loop in the if(trigger.isbefore){ for(Opportunity checkerrors: opp){...} and then if(trigger.isafter){ for(Opportinty addgood: opp{...} ? This will make my life very easy
    – jnoel10
    Commented Feb 20, 2013 at 15:53
  • Exactly. There is no filtering required because your Trigger.isAfter is statement will only run the second time the trigger is called (after the record Save). If you addError before your Save, that Save will never occur and it will error out of the entire process. Commented Feb 20, 2013 at 15:56
  • I am confused with the record save you are mentioning.. I will add it to code above in a moment.
    – jnoel10
    Commented Feb 20, 2013 at 16:09
  • added.. I did some research on the saving record but I am not finding anything..
    – jnoel10
    Commented Feb 20, 2013 at 16:24
  • Take a look at the order of execution I linked to earlier - salesforce.com/us/developer/docs/apexcode/Content/…. This trigger is only running when you Save a record (either Insert or Update). Specifically, step 5. Notice how it saves the record (but does not commit). If the record has an error on it (which it would from the addError), that will fail and the rest of the Order of Execution will stop. Commented Feb 20, 2013 at 16:30

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .