nainika
nainika

Reputation: 31

Prevent last contact from delete using trigger in salesforce

I am a newbie to salesforce and i have a requirement to which i need suggestions how to approach this requirement

I have 4 contacts related to one account and when someone deletes contacts, he should not be able to delete the last contact related to the account.For example: in account A1 i have 4 contacts and someone deletes the 3 contacts from that account then it should be deleted, after that there will be only 1 contact related to that account and den someone tries to delete the last contact than it should not be deleted.

How can i achieve this using trigger?

Upvotes: 1

Views: 1645

Answers (2)

Egor
Egor

Reputation: 1660

In your trigger, run a query for all contacts related to the account. If you are trying to delete all of them in this trigger, don't allow it. I don't know how you want to deal with people deleting multiple contacts at the same time, but let's say you will simply disallow the entire delete and the user has to retry with fewer contacts. If you want to come up with some logic that deletes all but 1 of the contacts, that's up to you. Something like:

Trigger OnContactDelete on Contact (before delete) {
   Set<ID> accountIds = new Set<ID>(); //all accounts that contacts are being deleted from
   for (Contact contact : Trigger.old) {
       accountIds.add(contact.AccountId);
   }

   List<Contact> contacts = [SELECT Id, AccountId FROM Contact WHERE AccountId IN :accountIds]; //get all of the contacts for all of the affected accounts

   Map<ID, Set<ID>> deleteMap = new Map<ID, Set<ID>>(); //map an account ID to a set of contact IDs being deleted
   Map<ID, Set<ID>> foundMap = new Map<ID, Set<ID>>(); //map an account ID to a set of contact IDs that were found by the query

   for (Contact deleteContact : Trigger.old) {
     Set<ID> idSet = deleteMap.get(deleteContact.AccountId);
     if (idSet == null) {
       idSet = new Set<ID>();
     }

     idSet.add(deleteContact.Id);
     deleteMap.put(deleteContact.AccountId, idSet);
   }

   for (Contact foundContact : contacts) {
     Set<ID> idSet = foundMap.get(foundContact.AccountId);
     if (idSet == null) {
       idSet = new Set<ID>();
     }

     idSet.add(foundContact.Id);
     foundMap.put(foundContact.AccountId, idSet);
   }

   for (ID accountId : accountIds) { //go through each affected account
     Set<ID> deleteIds = deleteMap.get(accountId);
     Set<ID> foundIds = foundMap.get(accountId);

     if (deleteIds != null && foundIds != null && deleteIds.containsAll(foundIds)) {
       for (Contact contact : Trigger.old) {
         if (deleteIds.contains(contact.Id)) { //this is one of the contacts being deleted
           contact.addError('This contact is potentially the last contact for its account and cannot be deleted');
         }
       }
     }
   }
 }

Note, I just typed this up in SO and haven't actually tested the code at all, even for syntax errors like missing semicolons or braces. It should work in theory, but there may be better ways of doing it.

Upvotes: 1

Hleb
Hleb

Reputation: 7371

You can solve this without triggers. You can create a Roll-Up Summary field on Account that counts the Contact records (ContactCount__c) and evaluate this count in a validation Rule on Account like this:

ContactCount__c = 0 &&  PRIORVALUE(ContactCount__c) > 0

Upvotes: 0

Related Questions