0

I have to delete all the tasks (both single and recurring) when a case is cancelled. I have tried a trigger which is showing the error that the Apex task trigger can't handle recurring tasks. What would be a possible workaround ?

Below is what I have tried.

public static void onAfterUpdate(List<Case> newCases){
     set<id> caseIdSet = new set<id>();
    list<task> toUpdateTaskLst = new list<task> ();
     for(case c : newcases)
    {
        caseIdSet.add(c.id);   
        system.debug('caseIdSet  '+caseIdSet);
    }
    for(case c: [select Id , (select id, whatid, status from tasks) from Case where id in :caseIdSet and status = 'cancelled' ] )
    {
        if(!c.tasks.isEmpty() && c.tasks != null )
        {
            for(task t: c.tasks)
            {
                system.debug('t.status'+t.status);
                t.status = 'Completed';
                toUpdateTaskLst.add(t);
            }
        }
    }
    update toUpdateTaskLst;

 }
4
  • frame your question properly... cancelled is cancelled means?? – Avijit Das May 5 '17 at 19:39
  • 1
    did you try this: carvingintheclouds.blogspot.com/2014/08/… – Santanu Boral May 5 '17 at 20:06
  • You can also right Apex Batch that will run daily and delete the task of the cancelled cases. – Abhi Tripathi May 5 '17 at 20:24
  • @Sandhya - if either of the below answers helped you please mark one as your preferred answer to encourage others helping out in the community. Thanks – glls May 8 '17 at 2:00
0

You could also do something like this:

Trigger to pass Task Id of related Cases that are on Status='Cancelled':

trigger DeleteCaseTaskOnCancelledStatus on Case (after insert, after update) {

  Set<Id> listTaskToDelete = new Set<Id>();
  Set<Id> listCases = new Set<Id>(); 

  for(List<Case> cases : [SELECT Id, Status FROM Case WHERE Status='Cancelled' AND Id IN: trigger.new])
  {
   if(!cases.isEmpty() && cases.size()>0)
  {
   for(Case c: cases)
    {
      listCases.add(c.Id);
    }

  }
}

for(List<Task> taskList : [SELECT Id, WhatId FROM Task WHERE WhatId IN: listCases])
{
    if(!taskList.isEmpty() && taskList.size()>0)
    {
      for(Task t: taskList)
      {
        listTaskToDelete.add(t.Id); 
      }
    }
}

if(!listTaskToDelete.isEmpty() && listTaskToDelete.size()>0)

    TaskFutureDeletionClass.sendToDelete(listTaskToDelete); 


}

Then you pass their ids to a class with a @future method, like this:

global class TaskFutureDeletionClass{

  @future
  public static void sendToDelete(Set<Id> tasksList)
  {   

   List<Task> tasksToDelete = [SELECT Id FROM Task WHERE Id IN: tasksList]; 

    try{
        delete tasksToDelete;   

        }catch(Exception e)
         {
          for(Task t: tasksToDelete)
          {
           t.addError('There was a problem deleting this task ' + e);
        }
      }
   }
 }

Salesforce will take care of deletion when resources are available.

UPDATE:

Added the WhatId and changed the name of the trigger to point the Case object rather than the Task object.

UPDATE: (One trigger to handle all trigger context variables)

I think it would be better to have a trigger that handles all trigger contexts variables for Case.

trigger DeleteCaseTaskOnCancelledStatus on Case (before insert, before update, after insert, after update, after delete, after undelete)
{


    if((trigger.isAfter && trigger.isInsert) || (trigger.isAfter && trigger.isUpdate))
    {
      DeletionProcessForCancelledCases.startDeletionProcess();
    }

}

Then we call our helper class:

 public with sharing class DeletionProcessForCancelledCases {

  public static void startDeletionProcess()
  {
   Set<Id> listTaskToDelete = new Set<Id>();
   Set<Id> listCases = new Set<Id>(); 


    for(Case c:(List<Case>) trigger.new)
    {
        if(c.Status =='Cancelled')
         listCases.add(c.Id);
    }


for(List<Task> taskList : [SELECT Id, WhatId FROM Task WHERE WhatId IN: listCases])
{
  if(!taskList.isEmpty() && taskList.size()>0)
  {
   for(Task t: taskList)
   {
     listTaskToDelete.add(t.Id); 
   }
  } 
}  

 if(!listTaskToDelete.isEmpty() && listTaskToDelete.size()>0)

    TaskFutureDeletionClass.sendToDelete(listTaskToDelete); 
 }
}

Then our TaskFutureDeletionClass.sendToDelete(listTaskToDelete); is executed and the @future method will take care of the rest of the operation.

2
  • Hi Carlos, The trigger should be on Case object and I need to delete the tasks when case status is cancelled. – KSR May 5 '17 at 21:32
  • You can try the new with a new trigger. Actually, it will be also better to move the logic out of the trigger to a helper class. – Carlos Naranjo May 5 '17 at 21:56
1

The error means exactly what it says. You'll need to process these asynchronously. Consider using Queueable or future methods. You'll need to set up a class to handle any processing you need.

Task[] syncTasks = [SELECT Id FROM Task WHERE IsClosed = FALSE AND IsRecurring = FALSE AND WhatId = (SELECT Id FROM Case WHERE Id = :Trigger.new AND Status = 'Cancelled'];
Task[] asyncTasks = [SELECT Id FROM Task WHERE IsClosed = FALSE AND IsRecurring = TRUE AND WhatId = (SELECT Id FROM Case WHERE Id = :Trigger.new AND Status = 'Cancelled'];
delete syncTasks;
if(asyncTasks.size() > 0) {
  CaseTriggerHelper.completeTasksAsync(asyncTasks);
}

CaseTriggerHelper.completeTasksAsync could lead to a future method, or a queueable that can process the tasks, or a batchable class, whichever way you'd like to process those tasks.

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.