Prohibit the deletion of a Task ? - Answers - Salesforce Trailblazer Community
Trailblazer Community
Ask Search:
Simeon TzanevSimeon Tzanev 

Prohibit the deletion of a Task ?

Hi guys,

certain Profiles should only be able to create Tasks but not delete them. Is this possible ? 

Many thanks
Simeon
Best Answer chosen by Simeon Tzanev
RAJKUMAR MUTHUSAMYRAJKUMAR MUTHUSAMY
Simeon,

Currently it's not available by standard - Ability to prevent deletion of Activity History (https://success.salesforce.com/ideaview?id=08730000000BrENAA0)

Create a apex trigger to prevent to delete tasks for certain profiles.

trigger NoDeleteonTask on Task (before delete)
{
   String ProfileId = UserInfo.getProfileId();  
   List<Profile> profiles=[select id from Profile where name='Profile 1' or name='Profile 2'];

   if (2!=profiles.size())
   {
      // unable to get the profiles - handle error
   }
   else
   {
       for (Task a : Trigger.old)      
       {            
          if ( (profileId==profiles[0].id) || (profileId==profiles[1].id) )
          {
             a.addError('You can't delete this record');
          }
       }            
   }
}

Source- Thanks to Bob buzzard - https://developer.salesforce.com/forums/ForumsMain?id=906F000000092ojIAA

All Answers

Emanuel SeewaldEmanuel Seewald
Under the Profile --> General User Permissions --> Edit Task:
User-added image

this should permit from editing and deleting I assume
RAJKUMAR MUTHUSAMYRAJKUMAR MUTHUSAMY
Simeon,

Currently it's not available by standard - Ability to prevent deletion of Activity History (https://success.salesforce.com/ideaview?id=08730000000BrENAA0)

Create a apex trigger to prevent to delete tasks for certain profiles.

trigger NoDeleteonTask on Task (before delete)
{
   String ProfileId = UserInfo.getProfileId();  
   List<Profile> profiles=[select id from Profile where name='Profile 1' or name='Profile 2'];

   if (2!=profiles.size())
   {
      // unable to get the profiles - handle error
   }
   else
   {
       for (Task a : Trigger.old)      
       {            
          if ( (profileId==profiles[0].id) || (profileId==profiles[1].id) )
          {
             a.addError('You can't delete this record');
          }
       }            
   }
}

Source- Thanks to Bob buzzard - https://developer.salesforce.com/forums/ForumsMain?id=906F000000092ojIAA
This was selected as the best answer
Deepak AnandDeepak Anand
+1 Raj K.

Another without writing a Trigger will be to override the Delete button on the Task object. So the advantage of this method is that it should work irrespective of the Sales Cloud edition and anyone can customize it since it's just a matter of writing a formula!

So here are the steps:
  1. Create a Visualforce Page(Setup | Develop | Pages) like as below[You can name it - PreventTaskDelete]:
    <apex:page 
        standardController = "Task"
        action = "
          {!
            IF(
                $Profile.Name <> "System Administrator",
                NULL,
                URLFOR(
                    $Action.Task.Delete,
                    Task.Id,
                    [retURL='/007'],
                    TRUE
                )
            )
          }">
        <apex:pageMessage 
            severity = "ERROR" 
            strength = "3" 
            title = "Task Delete" 
            summary = "You are not allowed to Delete Task records.">
        </apex:pageMessage>
    </apex:page>
  2. Save it.
Now, let us override the Delete button. Here you go:
  1. Setup | Customize | Activities | Task Buttons, Links & Actions
  2. Click Edit next to the Delete
  3. Select Override with: Visualforce Page
  4. Select the Visualforce PagePreventTaskDelete
  5. Save it.

You can notice in the VF that we are using a formula kinda thing:
IF(
    $Profile.Name <> "System Administrator",
    NULL,
    URLFOR(
        $Action.Task.Delete,
        Task.Id,
        [retURL='/007'],
        TRUE
    )
)
So this means if the Profile is not a System Administrator, don't do anything(NULL) and stay on the same Visualforce Page and show the Error Message otherwise go to the Delete Page right away!
Simeon TzanevSimeon Tzanev
Hi Deepak,

I just tried your solution: It works marvelous, just the Error Message can't fire. Instead of it, this message is displayed:

"Insufficient Privileges. You do not have the level of access necessary to perform the operation you requested. Please contact the owner of the record or your administrator if access is necessary."

Where could be the problem ?

Many Thanks
Simeon
Deepak AnandDeepak Anand
When did the Error Message come ? Did you try it out by Loging as another User ? Also make sure that you have given Permissions to this Visualforce Page for all the Users.
Simeon TzanevSimeon Tzanev
You were right with the Security issue. I had to assign the VF Page to the needed Profile.

Now I get this message when I try to delete a Task while logged in as a different user

"Formula Expression is required on the action attributes"


Deepak AnandDeepak Anand
Did you make any changes in the Visualforce ? Can you post a screenshot of the Error and the VF ?
RAJKUMAR MUTHUSAMYRAJKUMAR MUTHUSAMY
Nice Job @Deepak.

@Simeon - It seems error with formula expression. It may work for you by changing the below line. From '<>' to '!='

Visualforce may not supported
'<>' operator.

$Profile.Name != "System Administrator"
I tried myself it's working fine for me.

Try and let me know, if it helps.
Jan FialaJan Fiala
I am going to go the trigger route RajKumaR suggests. It's a better solution since it will not only prevent end users from deleting records through a browser but also through 3rd party tools that use the API. In addition, I may look into javascript solutions to conditionally remove the Delete button from as many places as I can. Thanks RajKumaR!
RAJKUMAR MUTHUSAMYRAJKUMAR MUTHUSAMY
Jan - Glad to know, it helped.
Saravana KumarSaravana Kumar
Hi, im getting the same ERROR as Simeon Tzanev mentioned above "Formula Expression is required on the action attributes." But i changed the condition like this 

IF( $Profile.Name == "System Administrator",
NULL,
URLFOR
( $Action.Task.Delete, $CurrentPage.Parameters.id, [retURL="/00T"], TRUE ) )

Profile.Name == "System Administrator" This condition is because of testing, moreover can we check Record Type of the Before Deletion Action??
 
RAJKUMAR MUTHUSAMYRAJKUMAR MUTHUSAMY

Saravana Kumar,

Please try something like this,

<apex:page standardController="Task"
    action="{!
        IF(
            ( $Profile.Name == 'System Administrator' &&  
              Task.RecordType.Name == 'YourRecordTypeName'
            ),
           NULL,
           URLFOR(
                $Action.Task.Delete,
                Task.Id,
                [retURL='/007'],
                TRUE
                 )
                 )}" >
             
    <apex:pageMessage severity="ERROR" 
        strength="3" 
        title="Task Delete" 
        summary="You are not allowed to Delete Task records.">
    </apex:pageMessage>

</apex:page>

-RajKumaR
Sanjay GuptaSanjay Gupta
Hi Raj, 

I tried the above solution, on click on delete button,  I am directed to a list screen, for 'My deleted activities', and it's blank. 

User-added image

Any help is much appreciated. 

Thanks
Erik EitelErik Eitel
@Deepak I used your VF example above and am running into the same error as Simeon above.

User-added image

This is what my code looks like. I had to change your code slightly as I only want the error to fire for our Customer Care profile.

User-added image
All my profiles have access to the VF page as well.

Thanks for your help!
Ruchika PatilRuchika Patil
@erik - you seem to have put the below code
$Profile.Name = "Customer Care",
which has a single equal to sign which is not used for checking but for assigning the value. 
It should be as below:
($Profile.Name == 'Customer Care'),
and somehow adding brackets around profile name helped me to get rid of the error.

Thanks,
Ruchika

 
Kelly ChiltonKelly Chilton
Hi
Can i apply the same code for events ?
Erik EitelErik Eitel
@Kelly Yes you can. Just make sure you change the controller to the standard Event controller. :)
Kelly ChiltonKelly Chilton
Thanks i did it and it worked, it doesn’t allow another user to edit it either so even better :o)
Larissa JohnsonLarissa Johnson
Hi Deepak, I am implementing your solution to override the delete button with a visualforce page. The delete capability is being prevented but it is preventing delete of any task record type and my error message is not displaying and instead I am receiving the following: "SObject row was retrieved via SOQL without querying the requested field: Task.RecordType". I seem to have an error in validating the record type.

Do you have any suggestion as to why this may be occuring? Here is what my visualforce page looks like:

User-added image

Thanks in advance. This string has been very helpful thus far!
 
Cody CusicCody Cusic
Hi Larissa,

That is because you are trying to access Task.RecordType.Name, and that would require a SOQL query (example in JS (https://developer.salesforce.com/forums/?id=906F0000000988PIAQ) or can query in a Custom Controller) in order to retrieve the name as you can only access the Task attributes and not the related record attributes (RecordType.Name).

Alternatively you could use Task.RecordTypeId == '<SFDC Record Type ID>' but you would be hardcoding an ID (against best practices).  The workaround would be to store it in a Hierarchy Custom Setting to make it easier to change the ID in the future.  

Thanks,
Cody Cusic
Abby RinzelAbby Rinzel
Thanks Deepak. The formula worked out perfectly. Do you know how I can do the same thing but for preventing the deletion of notes instead of tasks?
Jason ThurgoodJason Thurgood
Revised Visualforce code that I found worked: 

<apex:page standardController="Task"
    action="{!
        IF(
            ( $Profile.Name != 'System Administrator'),
           NULL,
           URLFOR(
                $Action.Task.Delete,
                Task.Id,
                [retURL='/007'],
                TRUE
                 )
                 )}" >
             
    <apex:pageMessage severity="ERROR" 
        strength="3" 
        title="Task Delete" 
        summary="You are not allowed to Delete Task records.">
    </apex:pageMessage>

</apex:page>
Simon LaytonSimon Layton
Thanks Jason - this worked for me!
Todd ThompsonTodd Thompson
Thanks Jason, this worked for me as well!  
 
Harold CarlsonHarold Carlson
Thanks to everyone for this.  This is a great workaround since Salesforce does not have an option to prevent deletion of tasks/events.
Sonia GenesseSonia Genesse
 Hi everyone,

The way I coded this seems to disallow all Profiles for Event deletion. I'm trying to allow more than one profile to delete an Event.

Ideas?

<apex:page standardController="Event">
    action = "
      {!
        IF(
            $Profile.Name != "SGSYSADMIN" || $Profile.Name != "System Administrator" || $Profile.Name != "IPG TS" || $Profile.Name != "IPG TS-FSE" || $Profile.Name != "IPG SM",
            NULL,
            URLFOR(
                $Action.Event.Delete,
                Event.Id,
                [retURL='/007'],
                TRUE
            )
        )
      }">
    <apex:pageMessage severity="ERROR"
        strength="3"
        title="Event Delete"
        summary="You are not allowed to Delete Event records.">
    </apex:pageMessage>
</apex:page>

Thanks!
Sonia
Ruchi KagdaRuchi Kagda

Hi All,

I am facing same issue as @sanjay Gupta.

I used the same revised fomula posted by @Jason thurgood. It not only took me to the same page as mentioned by Sanjay, but it also deleted the task. Can anyone help here.

Thanks,

Ruchi  

Jackie StampJackie Stamp
I've added a VF page using Jason's code exactly as above & it's working to prevent the deletion of tasks as it should, including showing the correct error message. Problem is, from the system administrator side, deleting a task ends up redirecting out of lightning to the screen below. Task gets deleted successfully... Just opens up this window.
 User-added image
Any ideas? Thanks for the help!
Jackie
Tad AalgaardTad Aalgaard
For anyone who is trying Deepak's solution and runs into the following error.
 
Formula Expression is required on the action attributes

You need to remove the extra line after action = from
 
<apex:page 
    standardController = "Task"
    action = "
      {!
        IF(
            $Profile.Name <> "System Administrator",
            NULL,
            URLFOR(
                $Action.Task.Delete,
                Task.Id,
                [retURL='/007'],
                TRUE
            )
        )
      }">
    <apex:pageMessage 
        severity = "ERROR" 
        strength = "3" 
        title = "Task Delete" 
        summary = "You are not allowed to Delete Task records.">
    </apex:pageMessage>
</apex:page>

to
 
<apex:page 
    standardController = "Task"
    action = "{!
        IF(
            $Profile.Name <> "System Administrator",
            NULL,
            URLFOR(
                $Action.Task.Delete,
                Task.Id,
                [retURL='/007'],
                TRUE
            )
        )
      }">
    <apex:pageMessage 
        severity = "ERROR" 
        strength = "3" 
        title = "Task Delete" 
        summary = "You are not allowed to Delete Task records.">
    </apex:pageMessage>
</apex:page>
The action attribute needs to see the {! on the same line.​
Jackie StampJackie Stamp
Thanks - I copied exactly as you described above for the required change and am still running into the issue depicted in my previous screenshot. No worries though as the function works from a user end. Thanks for your assistance everyone!
karen brownkaren brown
Jason thanks so much just implemented this and works perfectly.
Zeeshan KamalZeeshan Kamal
trigger TaskDelProhibited on Task (before delete)
{
   String profileName=[Select Id,Name from Profile where Id=: UserInfo.getProfileId()].Name; 
       for (Task a : Trigger.old)      
       {  
              if ( ProfileName ='Profilename1' || ProfileName ='Profilename2')
              {
                 a.addError('You cant delete this record');
              } 
      }   
}
karen brownkaren brown
@ZeeshanKamal Sorry what is this for, some explaination would be good since the code above already works.

Thanks
Rana RoyRana Roy
Hi Deepak,
This solution works fine for Classic, but we are in Lightning Experience. In Lightning, the Delete button disappears for the System Administrator Users which we dont want.

Can you please help?
Sam JorgensonSam Jorgenson
Hi @Deepak, 

I'm a system admin and it looks like I have lost the ability to delete a task.  See my link below.  
https://cl.ly/3Y0V0V2A2Y2A
Patricia CapshawPatricia Capshaw
I created a Visualforce Page with the below formula. I then Enabled Visualforce Page Access on a number of Profiles, and they no longer can delete tasks.  I want to allow a few other profiles besides System Administrator to be able to delete tasks.  One of the profiles is CS Supervisor.  How would I add that to the formula below?  And then do I need to enable the Visualforce Page on the CS Supervisor Profile?

Also, truly I would only like to stop Profiles from deleting tasks if the Type field on the task includes the word Responsibility.  Is that possible?  Meaning profiles can delete any task unless the Type has Responsibility in it. 

<apex:page standardController="Task"
action="{!
IF( ( $Profile.Name != 'System Administrator'),
NULL,
URLFOR(
$Action.Task.Delete,
Task.Id,
[retURL='/007'],
TRUE
)
)}" >
<apex:pageMessage severity="ERROR"
strength="3"
title="Task Delete"
summary="You are not allowed to Delete Task records.">
</apex:pageMessage> </apex:page>
 
Tad AalgaardTad Aalgaard
Just add || between entries

$Profile.Name != 'System Administrator' || $Profile.Name != 'CS Supervisor.'
Patricia CapshawPatricia Capshaw
I did that & the user using that profile still received an error when trying to delete a task.  Do I need to remove the PreventTaskDelete from their profile?
Patricia CapshawPatricia Capshaw
This is what i changed the formula to.  (went with a different Profile)

<apex:page standardController="Task"
action="{!
IF(
( $Profile.Name != 'System Administrator'|| $Profile.Name != 'Debit/Credit User' ),
NULL,
URLFOR(
$Action.Task.Delete, Task.Id,
[retURL='/007'],
TRUE
)
)}" >
<apex:pageMessage severity="ERROR"
strength="3"
title="Task Delete"
summary="You are not allowed to Delete Task records.">
</apex:pageMessage>
</apex:page>
Cody CusicCody Cusic
@Patricia, if you want any profile except for Sys Admin, that looks correct ($Profile.Name != 'Sys Admin'). You may need to use <> instead of != if that doesn't work, and if you don't want it to be other Admin profiles, you can do ($Profile.Name != 'Sys Admin'  && $Profile.Name != 'Other Admin' && ...). Can similarly use AND(x, y, z) vs the &&.
If you only want certain profiles, use ($Profile.Name = 'CS Supervisor' || $Profile.Name = 'Other Profile' || ...). You can alternatively use OR($Profile.Name = 'CS Supervisor', $Profile.Name = 'Other Profile', ...).

@Tad, that would always result in true. Suppose I were a Sys Admin, my $Profile.Name != 'CS Supervisor' => true; similarly if I were a 'CS Supervisor', my Profile != 'Sys Admin'. For negations, you have to use AND (&&), not OR (||), due to De Morgans Laws (https://en.wikipedia.org/wiki/De_Morgan's_laws).
Tad AalgaardTad Aalgaard
Well.... if you want real working code.  Here is what I implemented a while back.

<apex:page extensions="TaskDelOverrideController" standardController="Task"
    action="{!
        IF(
            $Profile.Name == "ProfileA" ||
            $Profile.Name == "ProfileB" ||
            $Profile.Name == "ProfileC"
            ,
            NULL,
            URLFOR(
                $Action.Task.Delete,
                t.Id,
                [retURL=retURLId],
                TRUE
            )
        )
      }">
    <apex:pageMessage severity="ERROR" 
        strength="3" 
        title="Task Delete" 
        summary="You are not allowed to Delete Task records.">
    </apex:pageMessage>
    <form action="/{!$CurrentPage.parameters.id}" style="margin-left:20px;">
        <input type="submit" value="Ok" />
    </form>
</apex:page>


/*
*    Controller for TestDelOverride page
*    Used to retrieve the WhoId an WhatId in order ot create the correct retURL for the page
*
*    @author Tad Aalgaard
*    @date    10/25/2017
*/

public with sharing class TaskDelOverrideController {

    public Task t {get; set;}

    public Id retURLId {get; set;}

    public TaskDelOverrideController(ApexPages.StandardController stdController) {
        Id taskId = ((Task)stdController.getRecord()).Id;
        t = [select Id, WhoId, Whatid from Task where id = : taskId];
        if (t.WhoId != null) {
            retURLId = t.WhoId;
        } else if (t.WhatId != null) {
            retURLId = t.WhatId;
        }
    }
}
 
Neil MartinNeil Martin
I get the below error message when using the Visual Force Page code, when previewing this page:

Visualforce Error
Help for this Page
Invalid parameter for function URLFOR
Error is in expression ' {!IF( $Profile.Name != "System Administrator", NULL, URLFOR( $Action.Task.Delete, Task.Id, [retURL="/007"], TRUE ) )}' in component <apex:page> in page donotdeletetask

Any suggestions?
Sourav DuttaSourav Dutta
Login as some user NOT having System Administrator Profile & check.
Colin LammersColin Lammers

So I'm trying to adjust the code to check if the user id is the same as the task owner id:

 

<apex:page standardController="Task"
    action="{!
        IF(
            ( $User.Id != Task.OwnerId),
           NULL,
           URLFOR(
                $Action.Task.Delete,
                Task.Id,
                [retURL='/007'],
                TRUE
                 )
                 )}" >
             
    <apex:pageMessage severity="ERROR" 
        strength="3" 
        title="Task Delete" 
        summary="You are not allowed to Delete Task records.">
    </apex:pageMessage>

</apex:page>

I'm getting this error though: SObject row was retrieved via SOQL without querying the requested field: Task.OwnerId 

 

Any help?

Tad AalgaardTad Aalgaard
@Colin Lammers

Fields that you are going to reference need to be rendered on the page (just the way it works).
Add the following to your page.
 
<apex:outputText value="{!Task.OwnerId}" rendered="false"/>
Colin LammersColin Lammers

@Tad Aalgaard

 

Thank you!

Patricia CapshawPatricia Capshaw
I’m not certain. Your formula looks so similar to mine except mine is checking the profile of the user. But I’d love to know the answer. Tricia
Shanna TuckerShanna Tucker
I think I found a very simple solution without formulas or code. You cannot delete the user's permissions... but you can remove the delete button from the task layout (in the page layout section of the user profile).

User-added image

 
Peter BenderPeter Bender
If we could just create validation rules for delete events (requested for 10 years and counting: https://success.salesforce.com/ideaView?id=08730000000BrGiAAK), this wouldn't be an issue.
Olivia Salvatore-KingOlivia Salvatore-King
Hi all, @RAJKUMAR MUTHUSAMY
I am writing a trigger for my org to prevent users from deleting tasks with a specific type value and have the below code. I know that the "&& Task.type=='Review"  is wrong and it gives me the error: Compile Error: Comparison arguments must be compatible types: Schema.SObjectField, String at line 6 column 20

I am not very good at code and this thread has been super helpful thus far. Just not sure how to handly the type value of the current task being triggered.


trigger TaskDelProhibited on Task (before delete)
{
   String profileName=[Select Id,Name from Profile where Id=: UserInfo.getProfileId()].Name; 
       for (Task a : Trigger.old)      
       {  
              if ( ProfileName !='System Administrator' || ProfileName !='Corporate Admin' && Task.Type=='Review')
              {
                 a.addError('You cant delete this record');
              } 
      }   
}
Venkatesh GundaVenkatesh Gunda
@olivia

Instead of Task.Type replace it with a.Type == 'Review' 

And ProfileName !=''  replace  it with profileName !=