0

I created a trigger that queries and deletes all related tasks once a user in deactivated.

and I am getting this frustrating error.

"MIXED_DML_OPERATION, DML operation on setup object is not permitted after you have updated a non-setup object (or vice versa): Task, original object: User: []: Trigger.AutoDeleteTasks4InactiveUsers: line 25, column 1"

here is my trigger:

trigger AutoDeleteTasks4InactiveUsers on User (after update) 
{

        Set<Id> UserIds = new Set<Id>();

        for (User u: trigger.new)
        {
            if(u.IsActive == false)
            {
                UserIds.add(u.id);
            }

        }    


        List<Task> Task2Close = [SELECT Id from Task 
                                  where IsClosed = false 
                                    and OwnerId = :UserIds];

        for(Task tsk : Task2Close)
        {
            tsk.Status = 'Closed - User Deactivated';
        }

        if(!Task2Close.isEmpty())
        {
            update Task2Close;
        }
}

can a good samaritan lend a helping hand.

I already tried using a class but still the same result.

1 Answer 1

4

Reason for Mix DML error

sObjects That Cannot Be Used Together in DML Operations DML

operations on certain sObjects sometimes referred to as setup objects, can’t be mixed with DML on other sObjects in the same transaction. This restriction exists because some sObjects affect the user’s access to records in the org. You must insert or update these types of sObjects in a different transaction to prevent operations from happening with incorrect access-level permissions. For example, you can’t update an account and a user role in a single transaction. However, deleting a DML operation has no restrictions.

Solution - Use Future method

you need to use future method for updating the task records. That will solve your mix DML error

if(!Task2Close.isEmpty())
{
     // call a future method. SInce we can pass list in future method thats why
    // pass the json string 
    futureClassForUpdate.updateTak(json.serialize(Task2Close));
}

Future Method

public class futureClassForUpdate
{
    @future
    public static void updateTak(String strJSON)
    {
        // deserialize your string into list of task and update that list in future method to avoid mix dml error 
        List<Task > lstTask = (List<Task>) json.deserialize(strJSON, List<Task >.class);
        update lstTask;
    }
}

Updates - Handler Recurrence Task Update

INVALID_FIELD_FOR_INSERT_UPDATE, You cannot update the Status of a recurring task.: [Status]"

I got this answer How to get around this - “Error: You cannot reassign a recurring task occurrence.”?

From Apex, have a read of Task - Recurring Tasks. If the IsRecurrence field is true on the current Task you can use the RecurrenceActivityId to get the ID of the main record that created the current recurrence. You can then modify this parent record.

From the UI, first use the edit series link in the recurrence to get to the parent record and modify that.

To handle this error, you need to update recurrence task's parent task record

trigger AutoDeleteTasks4InactiveUsers on User (after update) 
{

        Set<Id> UserIds = new Set<Id>();

        for (User u: trigger.new)
        {
            if(u.IsActive == false)
            {
                UserIds.add(u.id);
            }
        }    
        List<Task> Task2Close = [SELECT Id, IsRecurrence, RecurrenceActivityId 
                                   FROM Task 
                                  where IsClosed = false 
                                    and OwnerId = :UserIds];
        // use new list of task to update the record 
        List<Task> lstTask = new List<Task>();
        for(Task tsk : Task2Close)
        {
            // if task is recurrence type then get the parent task Id using RecurrenceActivityId and update parent task status
            lstTask.add(new Task(Status = 'Closed - User Deactivated', 
                                Id = tsk.IsRecurrence ? tsk.RecurrenceActivityId : tsk.Id ));
        }

        if(!lstTask.isEmpty())
        {
            // call a future method. Since we can't pass list in future method thats why
            // pass the json string 
            futureClassForUpdate.updateTak(json.serialize(lstTask));
        }
}
10
  • I am gonna give it a try right away sir. really appreciate the help.
    – JOE
    Commented Aug 22, 2016 at 5:53
  • apologies sir but I aint good with future methods but is this future method supposed to update the task status? sorry for the dumb question
    – JOE
    Commented Aug 22, 2016 at 6:04
  • @JOE yes it will update task status. This way take 1-2 second more. also check debug logs if you got any exception or not
    – Ratan Paul
    Commented Aug 22, 2016 at 6:06
  • oh thanks a lot @ratan. let me check the logs and one more, if I may, will this close recurring tasks too?
    – JOE
    Commented Aug 22, 2016 at 6:08
  • I guess the debug log answered the question. " INVALID_FIELD_FOR_INSERT_UPDATE, You cannot update the Status of a recurring task.: [Status]" I guess I am dead?
    – JOE
    Commented Aug 22, 2016 at 6:09

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .