1

Question
When a Billing Address is modified, get the new Postal Code. Then check which Contacts on the Account are outside that Postal Code. If 1 or more Contacts are outside of the Postal Code, mark Out_of_Zip as TRUE.

I want to update Out_of_Zip__c field on the Account when ever the above conditions are met but the problem is if after trigger is used then the trigger will goes to infinite loop and if before trigger is used is will show an DML exception.

Trigger code

trigger Update_Postal_Code on Account (after update) {
    List<Account> lst_acc = [select id,Out_of_Zip__c,Billingpostalcode from Account where id in :Trigger.new];
    for(Account a : lst_acc)
    {
        Out_of_Zip_Contact.Out_of_Zip(a);
    }
}

Class code

public class Out_of_Zip_Contact {

    Public static void Out_of_Zip(Account lst_acc){
        list<Contact> lst_con = [select id,Mailingpostalcode from contact where Accountid  =:lst_acc.id];   
        for(Contact c : lst_con)
        {
            if(c.MailingPostalCode == lst_acc.BillingPostalCode) {
                continue;
            }
            else
            {
                lst_acc.Out_of_Zip__c = True ; 
                update lst_acc;
                break;
            }
        }
    }
}

This how I am trying to do but it shows me an error so please help to solve this issue.

1

You should move your trigger to a before trigger, as you are just updating a field and you do not need to do any super fancy logic, you also do not need to run any DML Statements on a before trigger.

Also ensure you have 1 Trigger per sObject, as you cannot define the order of execution for triggers, so you should have 1 trigger that references classes to run your logic.

Your trigger will look like this:

trigger AccountTrigger on Account (before update) {
    if(Trigger.isBefore){
        if(Trigger.isUpdate){
            OutOfZipContact.doCheck();
        }
    }
}

And your class will look like this:

public class OutOfZipContact {
    public static void doCheck(){
        // Instantiate a List of Account Ids
        List<Id> accountIds = new List<Id>();

        // Query Contacts and iterate over the returned list, using the Id Set from Trigger.newMap
        for(Contact c : [SELECT Id, AccountId, MailingPostalCode FROM Contact WHERE AccountId IN :Trigger.newMap.keySet()]){
            // If the current iterations MailingPostalCode does not equal the Accounts MailingPostalCode (retrieveing it from Trigger.newMap), then store the AccountId
            if(c.MailingPostalCode != ((Account)Trigger.newMap.get(c.AccountId)).MailingPostalCode)
                accountIds.add(c.AccountId);
        }

        // Iterate over Tirgger.new
        for(Account a : (List<Account>)Trigger.new){
            // Set Out of Zip to a boolean value, which is determined by whether the accountIds list contains the current Iterations Id
            a.Out_of_Zip__c = accountIds.contains(a.Id)
        }
    }
}

Nice and simple code - I hope this helps!

0

First thing:

In after trigger update will be running infinitely.

Because:

When an update in Account, the trigger is run.

In trigger itself you are making an update to account, so it again calls trigger.

It goes infinite.

Second thing: Out_of_Zip() method is being called in the loop. THIS IS FORBIDDEN.

You should never call a method in a loop which have DML statements.

This will hit your DML limit of 150 if you have more than 150 objects to update.

Third thing: SOQL being called in a method which is being call in loop:

list<Contact> lst_con = [select id,Mailingpostalcode from contact where Accountid  =:lst_acc.id];

Again a forbidden thing in apex developement.

Solution:

Trigger:

    trigger Update_Postal_Code on Account (after update) {
    System.debug( 'Update_Postal_Code called' );
    Out_of_Zip_Contact.Out_of_Zip( Trigger.new );
}

Class:

    public class Out_of_Zip_Contact {
    static boolean isFirstCall = true;//We are using isFirstCall flag to break the infinity run
    public static void Out_of_Zip( List<Account> updatedAccountList){
        Account accountToUpdate;
        List<Account> accountToUpdateList;//List to contain accounts to update so don't need to call update in loop

        System.debug( 'updatedAccountList[0].Name=' + updatedAccountList[0].Name );
        System.debug( 'updatedAccountList[0].Billingpostalcode=' + updatedAccountList[0].Billingpostalcode );
        List<Account> lst_acc = [SELECT id
                                    , Out_of_Zip__c
                                    , Billingpostalcode
                                    ,(SELECT id
                                        ,Mailingpostalcode 
                                        FROM Contacts)
                                    FROM Account WHERE id IN :updatedAccountList];//Should sub query Contacts with Account So don't need to query contacts in the loop

        System.debug( 'Out_of_Zip() called' );
        accountToUpdateList= new List<Account>();
        if( isFirstCall == true ){
            System.debug( 'isFirstCall is true');
            for(Account a : lst_acc)
            {
                System.debug('Iterating over accounts');
                for(Contact c : a.Contacts)
                {
                    System.debug('Iterating over contacts');
                    System.debug( 'c.MailingPostalCode=' + c.MailingPostalCode );
                    System.debug( 'a.BillingPostalCode=' + a.BillingPostalCode );
                    if(c.MailingPostalCode == a.BillingPostalCode) {
                        continue;
                    }
                    else
                    {
                        System.debug('Adding accountToUpdate in accountToUpdateList');
                        accountToUpdate = new Account(Id= a.Id, Out_of_Zip__c=true);
                        accountToUpdateList.add( accountToUpdate );
                    }
                }
            }
        }
        if( accountToUpdateList.size()>0)
        {
            isFirstCall = false;//We are marking isFirstCall false so it is not called again
            update accountToUpdateList;
        }
    }

}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.