1

I have a child object having Master-Detail relationship with contact object. There is a checkbox Primary__c on both of the object. I need to see if that checkbox is checked for more than one record and if it is I need make another checkbox = true on every record.

For ex. Contact A have the primary__c checkbox = true (checked) and the child object address__c also have the checkbox = true, when this is the scenario I need to update another checkbox popup__c on all the records that are related to the contact and also the contact itself. I tried to write after insert, update and delete trigger and was not able to achieve it. Relationship name is addresses__r. Please help me as in how this can be done.

trigger AlternateAddressPopupAlert on Alternate_Address__c (after insert, after update,after delete){
map<Id,Alternate_address__c> mapOfAllFamily = new map<Id,Alternate_address__c>();
set<Id> setOfparentconact = new set<Id>();

if(trigger.isInsert || trigger.isUpdate){
    for(Alternate_Address__c altObj : trigger.new){
        if((trigger.isInsert || trigger.isUpdate) && altObj.checkbox__c!=trigger.oldmap.get(altObj.Id).checkbox__c){
            if(altObj.contact__c != null){
                setOfparentconact.add(altObj.contact__c); 
            }else{

            }           
        }
        system.debug('Set of primary contact----'+setOfparentconact);
    }
}else if(trigger.isDelete){
    for(Alternate_Address__c altObj : trigger.old){
        if(altObj.contact__c != null){
            setOfparentconact.add(altObj.contact__c); 
        }   
    }
}
if(!setOfparentconact.isEmpty()){
    for(Contact cntObj : [SELECT id,checkbox__c,(SELECT id,checkbox__c from Contacts__r) from Contact WHERE id in : setOfParentContacts]){
        set<Id> setOfOwners = new set<Id>();
        if(cntObj.Contacts__r != null && cntObj.Contacts__r.Size() > 0 ){
            for(Contact ChildCntObj : cntObj.Contacts__r){
                setOfOwners.add(ChildCntObj.OwnerId);
            }
        }
        setOfOwners.add(cntObj.OwnerId);
        mapOfAllFamily.put(cntObj.Id,setOfOwners);     
    }}

I haven't got very far as I am unable to decide how to proceed with this.

3
  • Can you show your code.and i didn't understand on all the records that are related to the contact @apple123
    – Pavan tej
    Jun 17, 2016 at 15:13
  • I added the code Pavan. I havent got much far as I couldnt figure out how get child records and once I get all the child records I have compare them with parent object's checkbox field, If there are more than 1 checkbox field checked then for all of the addresses and contact needs to have a field updated. On all records as in, Contact A (child addresses : add1, add2) If the checkbox is true on parent contact and add1 then I have to update another field on contact A, add1 and add2 as well. Jun 17, 2016 at 15:17
  • This should be doable with RSF on Contact and Process Builder (which can apply a single field update to all children)
    – cropredy
    Jun 20, 2016 at 16:47

1 Answer 1

0

I'm not entirely certain I understand the relationships, but let me see if I can point you in the right direction. I'm going to make the assumption that you want to do this afterinsert and afterupdate and before Delete since an after Delete makes no sense. I'm also understanding that the checkbox field is named primary__c on both the objects Contact and it's child Alternate_Address__c. There's a third Object named Address__c that's also a child of Contact with a checkbox field named popup__c.

You mention "needing to see if that checkbox is checked for more than one record, and if it is, needing to make another checkbox = true on every record." Its unclear if this refers to it being checked on more than one related record causing you to need to check it all on other records or something else. If so, you'll need to clarify that requirement as that can be a lot of work to make happen. You might say, that's a big ask and beyond the scope of what I intend to answer.

trigger AlternateAddressPopupAlert on Alternate_Address__c (after insert, after update, before delete){

map<Id,Alternate_address__c> mapOfAllFamily = new map<Id,Alternate_address__c>();
set<Id> setOfparentconact = new set<Id>();
map<Id,Id>ctc2altadd = new map<Id,Id>();

if(trigger isBefore)
{
    if(trigger.isDelete)
    {
        // Note, if deleting, not certain what you really want to do here other than clear any addresses that might match in Contact Object, so logic should be different
        for(Alternate_Address__c altObj : trigger.old){
        if(altObj.contact__c != null){
            ctc2altadd.put(altObj.contact__c,altObj.Id);
            system.debug('altobjcontact__c = `+ altObj.contact__c);
            system.debug('setOfparentconact size = `+ctc2altadd.keyset().size());
        }   
    }
}

if(trigger isAfter) 
{
    if(trigger triggerIsInsert || trigger.IsUpdate)
    {
        for(Alternate_Address__c altObj : trigger.new)
        {
            // As I understand it, the field to test is primary__c, it needs to be = true & you only want to do something when it's changed
            if(altObj.primary__c!=trigger.oldmap.get(altObj.Id).primary__c && alt.primary__c == true && altObj.contact__c != null). 
            // last test condition seems superfluous since since in a M-D relationship, you'd need to have the reference to the parent
            {
                ctc2altadd.put(altObj.contact__c,altObj.Id);
                system.debug('altobjcontact__c = `+ altObj.contact__c);
                system.debug('setOfparentconact size = `+ctc2altadd.keyset().size());
            }
        }
    }
    system.debug('Set of primary contacts size = '+ctc2altadd.keyset().size());
}


set<id>ctcIds = new set<id>();
// test to see if Contact also  
if(!setOfparentconact.isEmpty())
{
    // add any other fields to this query (like address fields) that you may need to update
    for(Contact cntObj : [SELECT id,Primary__c from Contact WHERE id in : setOfParentContacts])
    {
        // test to see if Contact checkbox = true
        if (cntObj.Primary__c = true;)
        {
           ctcIds.add(cntObj.Id);
           system.debug('contactId = '+cntObj.Id);
         }        
     }        
}

// time to query for address__c records
if(!ctcIds.isEmpty())
{
    // add any other fields to this query (like address fields) that you may need to update
    for( address__c addr : [SELECT Id, popup__c, contact__c (M-D child ID) FROM Address__c where contact__c in :ctcIds]}
    {
        if(addr.popup__c = true)
        {
           // add your logic here as it's not clear what you want to do
        }else{


        }           
    }       
}

// Update all the objects that you need to at the end of the trigger here. Be certain to add recursion protection using Booleans applied at the entry points of your trigger

}// end of trigger

Hopefully this shows you the kind of approach using MAPS that you'll want to take. Get your fields sorted out along with your queries and use the Maps to determine which records are a match between your object for updating or manipulation. Since I don't know your schema, the exact fields to use, or precisely what you're trying to do, I can't really help you any further but this should point you in the right direction to follow.

Edit

Regardless of the relationship names, you'll need to follow the kind of pattern I've outlined above. What you'll need to do in addition is once you have a list of all children, for each parent record, you'll need to iterate through the list of child records and count the number of children to see how many have the checkbox = true. If the number is more than one (you can break if you want to), you add that list to a map for updating.

To help you with that, instead of keeping a map<ParentId,ChildId> (or vice-versa), you'll want to keep either a map> or map> plus a map<ChildId,ChildsObject>. so you can pull everything out that needs to be updated when it's needed.

Based on your comments, it sounds as though your entry criteria would need to be altered to something like below for the afterUpdate part of your trigger. Note that an AfterInsert trigger doesn't have a trigger.old, so best to do these in separate blocks :

    if(trigger.IsUpdate)
    {
        for(Alternate_Address__c altObj : trigger.new)
        {
            if(altObj.primary__c!=trigger.oldmap.get(altObj.Id).primary__c && alt.primary__c == true && altObj.contact__c != null). 
            // last test condition seems superfluous since since in a M-D relationship, you'd need to have the reference to the parent
            {
                ctc2altadd.put(altObj.contact__c,altObj.Id);
                system.debug('altobjcontact__c = `+ altObj.contact__c);
                system.debug('setOfparentconact size = `+ctc2altadd.keyset().size());
            }
        }
    }
    system.debug('Set of primary contacts size = '+ctc2altadd.keyset().size());
}
// you have your list of changed records and now need to compare with ALL related     
// Alternate_Address__c records that are children of the same Contact record

list<Alternate_Address__c>altObj2 = [SELECT Id, primary__c, contact__c FROM Alternate_Address__c WHERE contact__c IN: ctc2altadd.keyset() ];

// Sort results into map of contact__c and list<Id> or list<Alternate_Address__c> (your choice)
 map<contact__c, list<Alternate_Address__c>>ctcId2AAC = new map<contact__c, list<Alternate_Address__c>>();
for(Alternate_Address__c aa:altObj2)
{
    for(contact__c c:ctc2altadd.keyset())
    {
         list<Alternate_Address__c>aac=new list<Alternate_Address__c>();
         if(aa.contact__c = c)
         {
             aac.add(aa);
             ctcId2AAC.put(c,aac);
         }
         //clear list for next contact__c
         aac.clear();
    }
}

// now check to see which lists of aac had more than one checkbox = true
map<contact__c, list<Alternate_Address__c>>ctcId2AACSort = new mapmap<contact__c, list<Alternate_Address__c>>();
for{contact__c c:ctcId2AAC.keyset())
{
     for(Alternate_Address__c a:ctcId2AAC.get(c))
     {
         integer i=0;
         if(a.primary__c = true) i++;
         if(i>=2)
         {
             ctcId2AACSort.put(c, ctcId2AAC.get(c));
         }
     }
}

That should give you a sorted map of all the child records that have more than 1 checkbox checked. If I've used the wrong field name, you'll be able to correct that. At least you can see the pattern now and apply it to all the other parts of your trigger.

5
  • Thank you so much for taking time. I really appreciate your help and also sorry for poor explanation. Let me put it this way. One object Contact and child object alternate_Address having master detail relation ship. A checkbox that is on both of the objects. There can be more than 1 children. If that checkbox is checked on both parent and child or checked on 2 children, I have to make popup__c checkbox checked on all of the records related to that contact. Ex. contact A has alternate 1, alternate 2 and multiple checkbox are checked on them then I have to make popup__c true on all 3 of them. Jun 20, 2016 at 13:46
  • realtionship name is addresses__c. Jun 20, 2016 at 13:46
  • See my edited answer. This will give you the patterns you need for your sorting.
    – crmprogdev
    Jun 20, 2016 at 14:52
  • Thank you so much. I will implement this and will get back to you. Just to make my self clear, The code in the EDIT part is the correct one right? Should I use that one or merge the logic of both? Jun 21, 2016 at 1:08
  • Hi, I have asked this question. can you please provide your feedback? salesforce.stackexchange.com/questions/128391/… Jun 24, 2016 at 12:28

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.