2

I have written a code to update all the sibling's and parent contact's field when one of the child records have been updated. The logic here is to make checkbox false on all the siblings and parent record if the checkbox has been checked on one of the child record. Below is the code, I am achieving the functionality but the code is not optimized and I want to achieve it through Maps if it is possible. Still trying to learn maps efficiently. Please help me optimizing the code.

    trigger Addressflag on Address__c (After update, After Insert) {
    if(Trigger.isUpdate || Trigger.isInsert){
    List<ID> ConIds = new List<ID>();
    Boolean needsUpdate = FALSE; 
    for (Address__c Adds: trigger.new)
    {
    ConIds.add(Adds.contact__c);
    }
    system.debug('parent con ids'+ConIds);
    contact con = [select id, checkbox__c, recordTypeId from contact where Id IN :conIds];
    List<Address__c> otherAlt = new List<Address__c>([select id, contact__c, checkbox__c, contact__r.recordTypeId from Address__c where contact__c in: conIDs]);
        for (Address__c adds: trigger.new)
        {
            for (integer i=0; i < otherAlt.size(); i++)
            {
                if ((otherAlt[i].contact__c==adds.contact__c) && (otherAlt[i].id != adds.id))
                {
                     otherAlt[i].checkbox__c = FALSE;
                     con.checkbox__c=FALSE;
                     needsUpdate = TRUE;
                }
            }
        }

        if(checkrecursive.runOnce())
        {
              if (needsUpdate)
              {
                  update otherAlt;
                  update con;
              }
        }
    }
 }

Please tell me how can I use a Map if it is applicable. Here contact is the parent and address is the child having master detail.

3
  • apple123 -- I heartily recommend you study the Apex Developer docs and look at the example apps that illustrate maps (for example: developer.salesforce.com/docs/atlas.en-us.apexcode.meta/…)
    – cropredy
    Jun 23 '16 at 4:38
  • Thank you for the advice I am doing that, but is there anyway you can help me optimizing it? That was my question initially. Jun 23 '16 at 12:57
  • @cropredy Can you help with MAP in above code? Jun 23 '16 at 21:05
3

As you've asked me to look at this, I've modified the first part of your solution to use maps (your query of List<Address__c> otherAlt was written to return a map) and completed your code to create a map of results for update.

I'm not certain that the map revisions to your existing code will be all that more efficient than what you'd already written, but it's at least easier to read. With that having been said, here's what you've asked for. The other mapping will clearly help you with what you were trying to do.

trigger Addressflag on Address__c (After update, After Insert) {
    if(Trigger.isUpdate || Trigger.isInsert){
        List<ID> ConIds = new List<ID>();
        for (Address__c Adds: trigger.new)
        {
            ConIds.add(Adds.contact__c);
        }
        system.debug('parent con ids'+ConIds);
        map<Id,contact>conMap = new map([select id, checkbox__c, recordTypeId from  contact where Id IN :conIds]);
        map<Id,Address__c>AddrssMap = new map<Id,Address__c>([select id, contact__c, checkbox__c, contact__r.recordTypeId from Address__c where contact__c in: conIDs]);


        Map<Id,map<Id,Contact>>ConsForUp = new map<Id,map<Id,Contact>>();    
        for (Address__c adds: trigger.new)
        {
            for(Id aId2: AddrssMap.keyset())
            {
                if ((AddrssMap.get(aId2).contact__c==adds.contact__c) && (aId2 != adds.Id))
                {
                    AddrssMap.get(aId2).checkbox__c = FALSE;
                    conMap.get(adds.contact__c).checkbox__c = FALSE
                    if(conMap.get(adds.contact__c).checkbox__c = FALSE){
                         ConsForUp.put(adds.contact__c,conMap);
                    }   
                }
            }
        }
        //*** Revised update method below *** 
        if(checkrecursive.runOnce())
        {
            list<Contact>toUpdate = new list<Contact>();

            for(Id cId : ConsForUp.keyset())
            {
                 toUpdate.addAll(ConsForUp.get(cId).values());
                 // above is a map of id to map, so first we extract the map, then the map's values()
                 // which results in a list of contacts for each map that we add together              
            }
            update toUpdate; 
        }
    }
}

Note: The above code has not been tested or debugged. Use at your own risk. ;)

Edit in resp to comments

The above trigger queries contacts then puts the results into a map. After you apply the results of your manipulations and perform the update on the results, any BeforeUpdate triggers you have on the Contact object would be expected to execute. They shouldn't execute until after your code in the above trigger has initiated the update (regardless of whether afterInsert or afterUpdate on Address__c).

Once that occurs, any BeforeUpdate triggers on Contact would indeed be expected to execute. See Triggers and Order of Execution in the Apex Developer Guide. Any updates caused by the above trigger must satisfy the requirements of your validation trigger on Contacts. If not, the entire transaction will be rolled back.

If you have multiple triggers on Contact, I recommend you combine them into a single trigger. Until you do, you won't be able to control the order of execution of those triggers. They will execute in a random order each time they're called. If there's any workflow on Contact, your Contact AfterUpdate triggers will be called one additional time.

10
  • Thank you so much sir for your help. I have one question here, I do see that we are updating parent contacts, but will it also update the sibling addresses? For example if I have 4 addresses related to a contact, If I update checkbox on one of the addresses trigger should update contact and other 3 addresses as well. Jun 24 '16 at 14:01
  • I simply followed your logic. If you want all of them to update if one matches, you'll need to change the logic. Add a nested NeedsUpdate into the if statement or something along those lines. or create a list until you've checked all of the related children to see if one needs an update before doing the put to the map.
    – crmprogdev
    Jun 24 '16 at 14:03
  • I am getting error in this line " conMap.get(adds.contact__c).checkbox__c = FALSE" as Initial term of field expression must be a concrete SObject: Id Jun 24 '16 at 14:24
  • I revised the code. The beginning of that for loop was declared as an Id not as for (Address__c adds: trigger.new). That should take care of the issue. Am surprised it even compiled.
    – crmprogdev
    Jun 24 '16 at 18:45
  • sir, thank you so much for your help. I am facing an issue, I have an apex before update trigger and several other triggers on contacts. While I am creating new contact it is triggering the before update trigger somehow. It is strange as the record still has not been inserted to the database. I have developed it to give a validation in before insert trigger and before update as well. But while creating record before update trigger is getting called and it gives error. What can I do? Jun 26 '16 at 16:13

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.