4

I need to write a trigger in which if an account that has related contacts and the user tries to delete that account it throws you an error..

trigger DoNotDeleteAccountHavingRelatedContact on Account (before insert, before update)  
{  
    List<Account> accList = new List<Account>();  
    Set<id> accIdSet = new Set<id>();  
    for(Account acc : Trigger.new)  
    {  
        accIdSet.add(acc.id);  
    }  

Map<Id,Contact> mapContacts = new Map<Id,Contact>([Select lastname,id,accountid 
                                        From Contact Where Accountid 
                                        IN : accIdSet]);

for(Account acc : Trigger.new)
{
    if(mapContacts.get(acc.id).contacts.size()>0)
    {
        acc.adderror('Account cannot be deleted');
    }
}                                       

}
10

Your trigger is a Before Insert/Update. Try:

trigger DoNotDeleteAccountHavingRelatedContact on Account (before delete)

And do replace Trigger.new with Trigger.old

** UPDATE **

Another commenter raised the issue that there was also a code problem. Please find an updated sample below

trigger DoNotDeleteAccountHavingRelatedContact on Account (before delete)  
{  
    List<Account> accList = new List<Account>();  
    Set<id> accIdSet = new Set<id>();  
    for(Account acc : Trigger.old)  
    {  
        accIdSet.add(acc.id);  
    }  

    Map<Id, Account> accts = new Map<Id, Account>([Select Id, (Select Id from contacts) from Account where id in :accIdSet]);

    for(Account acc : Trigger.old)
    {
        if(accts.get(acc.id).contacts.size()>0)
        {
            acc.adderror('Account cannot be deleted');
            }
        }                                       

}
  • 1
    Beat me to it. +1 – Adrian Larson Feb 19 '16 at 21:41
  • Awesome! Mark it as accepted it if worked so others can see the solution and benefit. – Sebastian Kessel Feb 20 '16 at 8:33
4

Unless I am wrong, the query will fill your map with the Contact.id => Contact not with the AccountId. So the get call on the map will return null.

Here is what I would do:

trigger DoNotDeleteAccountsWithContacts on Account(before delete) {
Set<Id> accountsWithContacts = new Set<Id>();
for(Contact c : [SELECT Id, AccountId FROM Contact WHERE AccountId in :trigger.oldMap.keySet()]) {
    accountsWithContacts.add(c.AccountId);
}
for(Id id : accountsWithContacts) {
    trigger.oldMap.get(id).addError('Account cannot be deleted while there are related contacts');
}

}

  • I like your solution, and I've adapted mine to use the concept you mention. The reason why I adapted from yours (Instead of pointing to it) is that you are iterating over every contact, and there is no need to do that. – Sebastian Kessel Feb 20 '16 at 0:28
  • I like your solution by including the contacts in the query itself. I think you can skip looping through the accounts to put them in a set by just calling Trigger.oldMap.keySet() in your query. I'd comment on your answer but I'm new to the community and still can't comment on other people's answers. – trankz Feb 20 '16 at 15:44
4

You could also query for accounts that have contact records and prevent those from being deleted like:

trigger DoNotDeleteAccountHavingRelatedContact on Account (before delete)  
{  
    for(Account acc : [SELECT Id FROM Account WHERE Id IN (SELECT AccountId FROM Contact) AND Id IN :Trigger.oldMap.KeySet()]){
        Trigger.oldMap.get(acc.Id).adderror('Account cannot be deleted');
    }
}
  • @anzar have you tried this solution ? – Jarvis Feb 20 '16 at 13:32
  • @Bennie yeah its working fine.. – Anzar Feb 20 '16 at 20:36

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.