function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
S_BatmanS_Batman 

Create a Checkbox field based on two fields on Related list

I want to create a check box field (let's call it  TestABC), which will be on true based on the below criteria;

I have two checkbox fields on the Contact object - Primary Contact & Do Not email (these fields also show up on the Contact Related List on the Account object)

TestABC = True if (Primary Contact is true and Do Not Email is false)

I want this TestABC field on the Account level, and look through all the contacts associated with the account to validate the formula.

Is this possible with a trigger?  Could someone help me write such Trigger?

 
Best Answer chosen by S_Batman
Mahesh DMahesh D
Hi Sutha,

Please find the latest code based on your new logic:
 
trigger ContactTrigger on Contact (after insert, after delete, after undelete, after update) {
    set<Id> accIdSet = new set<Id>();
    if(trigger.isinsert || trigger.isUpdate || trigger.isUndelete){
        for(Contact con: Trigger.new){            
            if(con.AccountId != null && 
                (Trigger.isInsert || Trigger.isUndelete || 
                    (con.AccountId != Trigger.oldMap.get(con.Id).AccountId || 
                        con.Primary_Contact__c != Trigger.oldMap.get(con.Id).Primary_Contact__c ||
                            con.Do_Not_Email__c != Trigger.oldMap.get(con.Id).Do_Not_Email__c))) {
                accIdSet.add(con.AccountId);
            }
        }
    }
    
    if(trigger.isUpdate || trigger.isDelete) {
        for(Contact con: Trigger.old){            
            if(con.AccountId != null && 
                (Trigger.isDelete || 
                    (con.AccountId != Trigger.newMap.get(con.Id).AccountId ||
                        con.Primary_Contact__c != Trigger.newMap.get(con.Id).Primary_Contact__c ||
                            con.Do_Not_Email__c != Trigger.newMap.get(con.Id).Do_Not_Email__c))) {
                accIdSet.add(con.AccountId);
            }
        }
    }

    if(!accIdSet.isEmpty()) {
        List<Account> accList = [Select Id, TestABC__c, (Select Id, AccountId, Primary_Contact__c, Do_Not_Email__c from Contacts) from Account Where ID IN: accIdSet];      
        
        for(Account acc: accList) {
            acc.TestABC__c = false;
            for(Contact con : acc.Contacts) {
                if(con.Primary_Contact__c == true && con.Do_Not_Email__c == false){
                    acc.TestABC__c = true;
                    break;
                }
            }
        }

        if(!accList.isEmpty())
            update accList;
    }
}

Please do let me know if it helps you.

Regards,
Mahesh

All Answers

Mahesh DMahesh D
Hi,

Yes we can do it.

If you can clarify onething here 

Account --> TestABC field should be true only if

Cont 1 --> PC is True and DNE is False
Cont 2 --> PC is True and DNE is False
Cont 2 --> PC is True and DNE is False​


Account --> TestABC field should be False only if

Cont 1 --> PC is True and DNE is False
Cont 2 --> PC is False and DNE is False
Cont 2 --> PC is True and DNE is True​


By Considering the scenario one, below is the code:

 
trigger ContactTrigger on Contact (after insert, after delete, after undelete, after update) {
    set<Id> accIdSet new set<Id>();
    if(trigger.isinsert || trigger.isUpdate || trigger.isUndelete){
		for(Contact con: Trigger.new){
			if(con.AccountId != null) {
				accIdSet.add(con.AccountId);
			}
        }
    }
    
    if(trigger.isUpdate || trigger.isDelete) {
        for(Contact con: Trigger.old){
			if(con.AccountId != null) {
				accIdSet.add(con.AccountId);
			}
        }
    }

	if(accIdSet.isEmpty()) {
    
		List<Account> accList = [Select Id, TestABC__c, (Select Id, AccountId, Primary_Contact__c, Do_Not_Email__c from Contacts) from Account Where ID IN: accIdSet];		
		
		for(Account acc: accList) {
			acc.TestABC__c = true;
			for(Contact con : acc.Contacts) {
				if(con.Primary_Contact__c, Do_Not_Email__c == false || Do_Not_Email__c == true) {
					acc.TestABC__c = false;
					break;
				}
			}
		}
		
		if(!accList.isEmpty())
			update accList;
	}
}

Please do let me know if it helps you.

Regards,
Mahesh
S_BatmanS_Batman
That is the correct logic, however I am getting an error - Error: Compile Error: unexpected token: 'new' at line 2 column 21
Mahesh DMahesh D
Please check the modified code:
 
trigger ContactTrigger on Contact (after insert, after delete, after undelete, after update) {
    set<Id> accIdSet = new set<Id>();
    if(trigger.isinsert || trigger.isUpdate || trigger.isUndelete){
		for(Contact con: Trigger.new){
			if(con.AccountId != null) {
				accIdSet.add(con.AccountId);
			}
        }
    }
    
    if(trigger.isUpdate || trigger.isDelete) {
        for(Contact con: Trigger.old){
			if(con.AccountId != null) {
				accIdSet.add(con.AccountId);
			}
        }
    }

	if(accIdSet.isEmpty()) {
    
		List<Account> accList = [Select Id, TestABC__c, (Select Id, AccountId, Primary_Contact__c, Do_Not_Email__c from Contacts) from Account Where ID IN: accIdSet];		
		
		for(Account acc: accList) {
			acc.TestABC__c = true;
			for(Contact con : acc.Contacts) {
				if(con.Primary_Contact__c, Do_Not_Email__c == false || Do_Not_Email__c == true) {
					acc.TestABC__c = false;
					break;
				}
			}
		}
		
		if(!accList.isEmpty())
			update accList;
	}
}

Typo mistake.

Regards,
Mahesh
S_BatmanS_Batman
Now I am getting;

Compile Error: expecting a right parentheses, found ',' at line 26 column 45

I checked to see all the parentheses line up
Mahesh DMahesh D
Please check the latest code:
 
trigger ContactTrigger on Contact (after insert, after delete, after undelete, after update) {
    set<Id> accIdSet = new set<Id>();
    if(trigger.isinsert || trigger.isUpdate || trigger.isUndelete){
		for(Contact con: Trigger.new){
			if(con.AccountId != null) {
				accIdSet.add(con.AccountId);
			}
        }
    }
    
    if(trigger.isUpdate || trigger.isDelete) {
        for(Contact con: Trigger.old){
			if(con.AccountId != null) {
				accIdSet.add(con.AccountId);
			}
        }
    }

	if(accIdSet.isEmpty()) {
    
		List<Account> accList = [Select Id, TestABC__c, (Select Id, AccountId, Primary_Contact__c, Do_Not_Email__c from Contacts) from Account Where ID IN: accIdSet];		
		
		for(Account acc: accList) {
			acc.TestABC__c = true;
			for(Contact con : acc.Contacts) {
				if((con.Primary_Contact__c == true && Do_Not_Email__c == true ) ||
				   (con.Primary_Contact__c == false && Do_Not_Email__c == true ) ||
				   (con.Primary_Contact__c == false && Do_Not_Email__c == false )){
					acc.TestABC__c = false;
					break;
				}
			}
		}
		
		if(!accList.isEmpty())
			update accList;
	}
}

Regards,
Mahesh
S_BatmanS_Batman
Lol now I am getting 
Variable does not exist: Do_not_email__c at line 26 column 59

I copied the API name into the code you wrote above.  My API name is the same as the one you used in the code
Mahesh DMahesh D
Finally what I did, I made full setup into my DE and saved the trigger:

Pleae take the final code:
 
trigger ContactTrigger on Contact (after insert, after delete, after undelete, after update) {
    set<Id> accIdSet = new set<Id>();
    if(trigger.isinsert || trigger.isUpdate || trigger.isUndelete){
        for(Contact con: Trigger.new){
            if(con.AccountId != null) {
                accIdSet.add(con.AccountId);
            }
        }
    }
    
    if(trigger.isUpdate || trigger.isDelete) {
        for(Contact con: Trigger.old){
            if(con.AccountId != null) {
                accIdSet.add(con.AccountId);
            }
        }
    }

    if(accIdSet.isEmpty()) {
    
        List<Account> accList = [Select Id, TestABC__c, (Select Id, AccountId, Primary_Contact__c, Do_Not_Email__c from Contacts) from Account Where ID IN: accIdSet];      
        
        for(Account acc: accList) {
            acc.TestABC__c = true;
            for(Contact con : acc.Contacts) {
                if((con.Primary_Contact__c == true && con.Do_Not_Email__c == true ) ||
                   (con.Primary_Contact__c == false && con.Do_Not_Email__c == true ) ||
                   (con.Primary_Contact__c == false && con.Do_Not_Email__c == false )){
                    acc.TestABC__c = false;
                    break;
                }
            }
        }
        
        if(!accList.isEmpty())
            update accList;
    }
}

Regards,
Mahesh
S_BatmanS_Batman
Thank you!

I created this trigger in the Contact Object;

I have 3 contacts where Primary Contact = true for all 3, and Do not email = is false for 3; in this case TestABC = True, but it's not checked off.

PS:  where can I learn how to write code like this? I know there's salesforce Trailhead, any other resources you would recommend? 
S_BatmanS_Batman
Yes, I updated the Account as well as the Contacts.  

The checkbox field did not update.  
Mahesh DMahesh D
Can you paste the data here take a printscreen and post it here.

Regards,
Mahesh
S_BatmanS_Batman
User-added image

User-added image

This is created in Sandbox, I have not deployed it yet in production yet.  
Mahesh DMahesh D
Can you just update any of the 3 Contacts,

Just click on update and save and see the results.

Also make sure that the fields you used correct.

Regards,
Mahesh
S_BatmanS_Batman
I've tried updating the contacts. I build this on the sandbox, would deploying it and trying it in production make a difference? The fields are correct as well.
Mahesh DMahesh D
Hi

One more change

Replace below line in your code:

if(accIdSet.isEmpty()) {

with

if(!accIdSet.isEmpty()) {


Thats it everything is good to go.

I tested it and it is working the functionality also.

Please do let me know if it works.

Regards,
Mahesh
S_BatmanS_Batman
So I made the change

and now whenever I update contact and try to save I get this:

Error:Apex trigger ContactTrigger caused an unexpected exception, contact your administrator: ContactTrigger: execution of AfterUpdate caused by: System.DmlException: Update failed. First exception on row 0 with id 00156000005ZGoxAAG; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, updatemytest: maximum trigger depth exceeded Contact trigger event AfterUpdate for [00356000006luQD] Account trigger event AfterUpdate for [00156000005ZGox] Contact trigger event AfterUpdate for [00356000006luLD, 00356000006luLI, 00356000006luQD] Account trigger event AfterUpdate for [00156000005ZGox] Contact trigger event AfterUpdate for [00356000006luLD, 00356000006luLI, 00356000006luQD] Account trigger event AfterUpdate for [00156000005ZGox] Contact trigger event AfterUpdate for [00356000006luLD, 00356000006luLI, 00356000006luQD] Account trigger event AfterUpdate for [00156000005ZGox] Contact trigger event AfterUpdate for [00356000006luLD, 00356000006luLI, 00356000006luQD] Account trigger event AfterUpdate for [00156000005ZGox] Contact trigger event AfterUpdate for [00356000006luLD, 00356000006luLI, 00356000006luQD] Account trigger event AfterUpdate for [00156000005ZGox] Contact trigger event AfterUpdate for [00356000006luLD, 00356000006luLI, 00356000006luQD] Account trigger event AfterUpdate for [00156000005ZGox] Contact trigger event AfterUpdate for [00356000006luLD, 00356000006luLI, 00356000006luQD] Account trigger event AfterUpdate for [00156000005ZGox]: []: ()
Mahesh DMahesh D
Can you paste the trigger on Account.

You have one trigger on the Account which is updating the contact and this contact trigger is updating the contact.

Please paste you Account trigger here.
S_BatmanS_Batman
There's this trigger  on the Account, this was there from the previous admin

trigger updatemytest on Account (after update)
{
list<contact>cm1=[select id,accountid  from contact where accountid IN : trigger.newMap.KeySet()];
List<contact> cm2= new List<contact>();
for(contact cm4 : cm1)
  {  Account acct = Trigger.NewMap.get(cm4.accountid);
      if(acct.Account_Type__c=='Top X' )
      {
       cm4.TOP_X__c= true;
       cm4.Customer__c=false;
       cm4.KHA__c=false;
       cm2.add(cm4);  
      }
  
      else if((acct.Account_Type__c=='Customer - GB') || (acct.Account_Type__c=='Customer' ))    
      {
        cm4.Customer__c= true;
        cm4.TOP_X__c= false;
        cm2.add(cm4);  
      }
       
      else if (acct.Partner__c=='Kaufman Hall')    
      {        
        cm4.KHA__c= true;   
        cm2.add(cm4);  
      } 
  
       else { 
       cm4.KHA__c=false;   
       cm2.add(cm4);  
     } 
 
     }
     
     List<Database.SaveResult> srList = Database.update(cm2);
     for (Database.SaveResult sr : srList) 
     {
     if (sr.isSuccess())  {
        // Operation was successful, so get the ID of the record that was processed in Debug Logs
     System.debug('Successfully inserted account. Account ID: ' + sr.getId());
                          }
     else   {
        // Operation failed, so get all errors                
            for(Database.Error err : sr.getErrors()) 
            {
            Trigger.newMap.get(sr.getId()).addError(err.getMessage());                
            }     
             }  


      }
}
Mahesh DMahesh D
I modified the Contact Trigger and please take this code:
 
trigger ContactTrigger on Contact (after insert, after delete, after undelete, after update) {
    set<Id> accIdSet = new set<Id>();
    if(trigger.isinsert || trigger.isUpdate || trigger.isUndelete){
        for(Contact con: Trigger.new){            
            if(con.AccountId != null && 
                (Trigger.isInsert || Trigger.isUndelete || 
                    (con.AccountId != Trigger.oldMap.get(con.Id).AccountId || 
                        con.Primary_Contact__c != Trigger.oldMap.get(con.Id).Primary_Contact__c ||
                            con.Do_Not_Email__c != Trigger.oldMap.get(con.Id).Do_Not_Email__c))) {
                accIdSet.add(con.AccountId);
            }
        }
    }
    
    if(trigger.isUpdate || trigger.isDelete) {
        for(Contact con: Trigger.old){            
            if(con.AccountId != null && 
                (Trigger.isDelete || 
                    (con.AccountId != Trigger.newMap.get(con.Id).AccountId ||
                        con.Primary_Contact__c != Trigger.newMap.get(con.Id).Primary_Contact__c ||
                            con.Do_Not_Email__c != Trigger.newMap.get(con.Id).Do_Not_Email__c))) {
                accIdSet.add(con.AccountId);
            }
        }
    }

    if(!accIdSet.isEmpty()) {
        List<Account> accList = [Select Id, TestABC__c, (Select Id, AccountId, Primary_Contact__c, Do_Not_Email__c from Contacts) from Account Where ID IN: accIdSet];      
        
        for(Account acc: accList) {
            acc.TestABC__c = true;
            for(Contact con : acc.Contacts) {
                if((con.Primary_Contact__c == true && con.Do_Not_Email__c == true ) ||
                   (con.Primary_Contact__c == false && con.Do_Not_Email__c == true ) ||
                   (con.Primary_Contact__c == false && con.Do_Not_Email__c == false )){
                    acc.TestABC__c = false;
                    break;
                }
            }
        }

        if(!accList.isEmpty())
            update accList;
    }
}

While testing the functionality,

Make sure that, you are modifying any of the below fields

Account
Primary Contact
Do Not Email

Any of these field changes then only it will perform the calculation.

Regards,
Mahesh
S_BatmanS_Batman
so I deactivated the trigger on the account and it works, but would it be possible to alter it to what is below:

Cont 1 - PC = True DNE = False
Cont 2 - PC = False DNE = False
Cont 3 - PC = False DNE = False 

TestABC = True

so pretty much if an account has at least Contact who is Primary Contact and DNE = False I want the TestABC = true 

if the account only has contacts that are primary contact but all the primary contact are DNE = true then TestABC = False.

Also, this trigger will work on any number of contacts within the account, correct?
Mahesh DMahesh D
Hi Sutha,

Please find the latest code based on your new logic:
 
trigger ContactTrigger on Contact (after insert, after delete, after undelete, after update) {
    set<Id> accIdSet = new set<Id>();
    if(trigger.isinsert || trigger.isUpdate || trigger.isUndelete){
        for(Contact con: Trigger.new){            
            if(con.AccountId != null && 
                (Trigger.isInsert || Trigger.isUndelete || 
                    (con.AccountId != Trigger.oldMap.get(con.Id).AccountId || 
                        con.Primary_Contact__c != Trigger.oldMap.get(con.Id).Primary_Contact__c ||
                            con.Do_Not_Email__c != Trigger.oldMap.get(con.Id).Do_Not_Email__c))) {
                accIdSet.add(con.AccountId);
            }
        }
    }
    
    if(trigger.isUpdate || trigger.isDelete) {
        for(Contact con: Trigger.old){            
            if(con.AccountId != null && 
                (Trigger.isDelete || 
                    (con.AccountId != Trigger.newMap.get(con.Id).AccountId ||
                        con.Primary_Contact__c != Trigger.newMap.get(con.Id).Primary_Contact__c ||
                            con.Do_Not_Email__c != Trigger.newMap.get(con.Id).Do_Not_Email__c))) {
                accIdSet.add(con.AccountId);
            }
        }
    }

    if(!accIdSet.isEmpty()) {
        List<Account> accList = [Select Id, TestABC__c, (Select Id, AccountId, Primary_Contact__c, Do_Not_Email__c from Contacts) from Account Where ID IN: accIdSet];      
        
        for(Account acc: accList) {
            acc.TestABC__c = false;
            for(Contact con : acc.Contacts) {
                if(con.Primary_Contact__c == true && con.Do_Not_Email__c == false){
                    acc.TestABC__c = true;
                    break;
                }
            }
        }

        if(!accList.isEmpty())
            update accList;
    }
}

Please do let me know if it helps you.

Regards,
Mahesh
This was selected as the best answer
uHaveOptionsuHaveOptions
Did anyone have the right answer? i'm interested in knowing
Mahesh DMahesh D
Hi Jon,

Please follow my last reply which I tested it in my DE environment and everything is working properly.

Waiting for Sutha to confirm on it.

Regards,
Mahesh
uHaveOptionsuHaveOptions
Thanks Mahesh...  I will try that.  

In the meantime, you think you can help me answer my question?
https://developer.salesforce.com/forums/ForumsMain?id=906F0000000DBvSIAW
 
S_BatmanS_Batman
Works like a charm!

Thanks again Mahesh :)