+ Start a Discussion
Cloud AtlasCloud Atlas 

Trigger to prevent delete

Hi ,

Can some one help me to write a trigger to prevent delete of all Account records and its supporting test class.
Doesn't matter who the user is (Sys Admin/Custom Profile/Read Only...etc), the user should not be able to delete the account record.
There cannot be any exception.

Any help is appreciate.
Thanks!
A
Best Answer chosen by Cloud Atlas
Mohan_ShanmugamMohan_Shanmugam
Hi Ashish,

Here is the trigger which will prevent deletion of Account record.
trigger preventAccountDeletion on Account (before delete) {

    for(Account acc : trigger.old){
        acc.adderror('Account Cannot be deleted');
    }

}

TestClass for the above trigger would be
@isTest
private class testPreventAccountDeletion {
	
    static testmethod void testPreventAccDel(){
        Account accRecord = new Account(name='testAccount');
        insert accRecord;
        
        try{
            delete accRecord;
        }catch(DMLexception e){
            system.assert(e.getMessage().contains('Account Cannot be deleted'),'Account Cannot be deleted');                       
        }
    }
}

i did not get this - "There cannot be any exceptions"

with the above no user cannot delete a Account record, if attempted to do then a validation will thrown on a different page informing that account cannot de deleted. Below is the screensshot of error message.

User-added image
If you want the error to be in a differnt fashion then override the delete button with VF page as you like.

Hope this helps!

Thanks,
Mohan Shanmugam
 

All Answers

Cloud AtlasCloud Atlas
One update...I cannot remove the "DELETE" permission from profiles...Users have to have "MODIFY ALL" permission.
Amit Chaudhary 8Amit Chaudhary 8
Try to add below link in trigger

addError();

That will help u
Mohan_ShanmugamMohan_Shanmugam
Hi Ashish,

Here is the trigger which will prevent deletion of Account record.
trigger preventAccountDeletion on Account (before delete) {

    for(Account acc : trigger.old){
        acc.adderror('Account Cannot be deleted');
    }

}

TestClass for the above trigger would be
@isTest
private class testPreventAccountDeletion {
	
    static testmethod void testPreventAccDel(){
        Account accRecord = new Account(name='testAccount');
        insert accRecord;
        
        try{
            delete accRecord;
        }catch(DMLexception e){
            system.assert(e.getMessage().contains('Account Cannot be deleted'),'Account Cannot be deleted');                       
        }
    }
}

i did not get this - "There cannot be any exceptions"

with the above no user cannot delete a Account record, if attempted to do then a validation will thrown on a different page informing that account cannot de deleted. Below is the screensshot of error message.

User-added image
If you want the error to be in a differnt fashion then override the delete button with VF page as you like.

Hope this helps!

Thanks,
Mohan Shanmugam
 
This was selected as the best answer
Cloud AtlasCloud Atlas
Okay guys...

 I tried to write on my own and landed with this..

trigger AcctDeletePrevent on Account (before delete) {
    
    for(Account acct: trigger.old){
        if(Trigger.isBefore){

            if(Trigger.isDelete){

                acct.adderror('You cannot delete the record'); 

        }

    }
    }

}

Apex Class...

@isTest

private class PreventAcctDel{

    private static testMethod void testDeleteFail(){

           Account acc=new Account(Name='Test Account');
           insert acc;
           try{

              delete acc;
              System.assert(false);

           }

         catch (DMLException e){
 
           }

        }

}

Seems to work if I try with individual records...
What I would like to know if this trigger will prevent the records from getting "Mass Deleted".
Cloud AtlasCloud Atlas
@Amit...Thanks.. I did the same...(after some research)

@Mohan.... Thank you. I checked your code and mine looks similar to your's...Ofcourse your is much more compact.

Will this trigger work in case someone launches "Mass Delete"??? I tried to delete via Mass delete in developer edition and records are still in .
But I want to be sure that trigger will hold and won't delete when millions or records in Unlimited edition are in play.
Mohan_ShanmugamMohan_Shanmugam
It will work perfectly for mass deletion as well.

Thanks,
Mohan
Arundhati DebArundhati Deb
Well I have the same issue and i have implemented the same but when i go for deployment its giving the error as 0% code coverage and in sandbox its 100% covered. please suggest.
 
Cloud AtlasCloud Atlas
Is it giving error or just showing 0%.
They are 2 different things.... Upon deployment most classes and triggers show 0%. You have to run test execution again to see the coverage numbers.
If it giving error, what does the error say??
Priyanshu guptaPriyanshu gupta

Trigger to prevent Delete Content document Link  from Account Object:-

Trigger:-

trigger ContentDocumentLinkTrigger on ContentDocumentLink (before delete,before insert) {
    
    if(Trigger.isBefore ){ 
        
        if(Trigger.isdelete ){ 
            ContentDocumentLinkTriggerFunction.restrictDeleteFiles(Trigger.oldMap);
        }
    }
}

Trigger Handler:-

public static void restrictDeleteFiles(Map<id,ContentDocumentLink> mapContentDocument) {

    Set<Id> oldIdContentDoc = new Set<Id>();
    oldIdContentDoc = mapContentDocument.keySet();
    List<Id> linkIds = new List<Id>();    
        //get doc links by trigger records on ContentDocment.
        List<ContentDocumentLink> doclinks = [SELECT LinkedEntityId, ContentDocumentId FROM ContentDocumentLink 
                                              WHERE Id IN: oldIdContentDoc ];
        for(ContentDocumentLink doclink : doclinks){
            linkIds.add(doclink.LinkedEntityId); 
        }
        //get Candidate Records which are linked to ContentDocumentLink via LinkedEntityId with Age > 18.
        Map<Id, Account> candidates = new  Map<Id, Account>([SELECT Name FROM Account  
                                                                        WHERE Id IN :linkIds AND Active__c='Yes']);
        //Collect ContentDocumentIds which link to Candidate > 18. 
        for(ContentDocumentLink doclink : doclinks){
            if(candidates.get(doclink.LinkedEntityId) != null){
                //idDoc.add(doclink.ContentDocumentId);
                
                //doclink.LinkedEntityId.addError('Cannot delete a Note from an Escalated Issue that has been closed already'); 
                
                SObject  actualRecord = mapContentDocument.get(doclink.Id);
                actualRecord.addError('Cannot delete a Note from an Escalated Issue that has been closed already'); 
            }
        }
    }

Hope this will also help. :)
Mike  KMike K
@Mohan,

I tried your code, but code coverage is only 60%. The for loop in the Trigger is not covered. Do you have any suggestions on how to cover this last bit of code to get this solution to work?

TaskDeleteStop Trigger
  • The code in bold below is not covered by the test class below.
trigger TaskDeleteStop on Task (before delete) {

    Id userProfileId = userinfo.getProfileId();
    String userProfileName = [SELECT ID, Name from Profile Where Id = : userProfileId].Name;
     
    if( userProfileName == 'Sales'){
    	
        for(Task tsk : trigger.old){
            tsk.adderror('Task cannot be deleted');
            }
        }
}

TaskDeleteStop_Test Class
@isTest
private class TaskDeleteStop_Test {
static testmethod void TaskDeleteStop_Test(){
    	
    	Test.startTest();
    
    	Task tskRecord = new Task(Subject='testTask');        
  		insert tskRecord;
        
    	Test.stopTest();
    	try{
            delete tskRecord;
        }catch(DMLexception e){
            system.assert(e.getMessage().contains('Task cannot be deleted'),'Task cannot be deleted');
        }
    }
}

 
Cloud AtlasCloud Atlas
@Michael ...
You are running the trigger for users under a specific profile.. Sales in your case... and don't want Sales users to delete tasks.
So you need to ensure to test your code under a user account/profile for the trigger to accept the record for consideration.
For this a mock user needs to be created.

I have changed your trigger very slightly and re-written your test class.. 
This should cover like 80% code.

TaskDeleteStop Trigger
trigger TaskDeleteStop on Task (before delete) {
    
    Id userProfileId = userinfo.getProfileId();
    String userProfileName = [SELECT ID, Name from Profile Where Id = : userProfileId].Name;
    
    for(Task tsk : trigger.old){		
        if( userProfileName == 'Sales'){	
             tsk.adderror('Task cannot be deleted');
            
        }
    }
}

TaskDeleteStop_Test Class
Your code needs to create a user and test will be run for that user/profile.
I am purposely testing with a system admin user because Sales user is just the exception.
Profiles other than Sales will cover most of the code and sys admin profiles are default in all Salesforce orgs
@isTest
private class TaskDeleteStop_Test {
    
    static testmethod void Deletion_Success_Test(){
        Task tskRecord = new Task(Subject='testTask');        
        insert tskRecord;
 
        Test.startTest();       
		// Create a unique UserName
        String uniqueUserName = 'salesuser' + DateTime.now().getTime() + '@testorg.com';
        // This code runs as the system user
        Profile p = [SELECT Id FROM Profile WHERE Name='System Administrator'];
        
        User usr = new User(Alias = 'suser', Email='adminuser@testorg.com',
                            EmailEncodingKey='UTF-8', LastName='SalesTesting', LanguageLocaleKey='en_US',
                            LocaleSidKey='en_US', ProfileId = p.Id,
                            TimeZoneSidKey='America/New_York',
                            UserName=uniqueUserName);
        
        
        System.runAs(usr){
            try{
        	    delete tskRecord;
            }catch(Exception ex){
                system.debug('Exception');
            }    
        }
        Test.stopTest();
        
        List<Task> upTask = [Select Id, IsDeleted From Task Where Subject ='testTask'];
        system.assertEquals(upTask.size(), 0);
    }

}
You can further work on this toimprove code coverage if you wish.
Hope this helps your cause.



 
Mike  KMike K
Thank you, worked beautifully 😊
Kevin WinnKevin Winn
Thanks Mohan,

Not only did you help with the delete prevention but your sample test also helped me solve how to test all of the catch blocks I have in my methods.  Much appreciated!