+ Start a Discussion
brozinickrbrozinickr 

Stopping Automatic Transfer of Open Activity Ownership (Related to the Account)

Hello,

 

I am wrote this really simple trigger to stop the changing of the ownership of open activities.  Whenever account owner changes in SF, it changes all of the open activitiy owners of tasks to the new owner of the account.   We don't want that to happen.  Here's my code:

 

 

trigger StopTaskOwnerChange on Task (before update) {

    List<Task> updateTask = new List<Task>();
    
        for(Task t : trigger.new){
            if(t.ownerId != t.CreatedById)
                updateTask.add(t);
        }
        
        for(Task t : updateTask){
        t.ownerId = t.CreatedById;
        }

 


I am thinking this problem with this is probably has to do with timing of the execution of the trigger.  I know salesforce automatically changes all of the activity ownership automatically, and I am wondering if I'm firing my trigger before salesforce automatically changes the Owners so it looks the owner is not changing.

 

 

 

MoUsmanMoUsman

Hi ,

 

Please try in After update like

list<Task> getAllTask = [SELECT id,CreatedById,ownerId FROM Task WHERE id IN:trigger.oldMap.keyset() ];

 and update task as you want.

 

If your are not clear for this solution please let me know.

--

Regards

Usman

brozinickrbrozinickr

I think so, this is what I have now with your changes:

 

trigger StopTaskOwnerChange on Task (after update) {

   list<Task> updateTask = [SELECT id,CreatedById,ownerId FROM Task WHERE id IN:trigger.oldMap.keyset()];
    
        for(Task t : trigger.new){
            if(t.ownerId != t.CreatedById)
                updateTask.add(t);
        }
        
        for(Task t : updateTask){
        t.ownerId = t.CreatedById;
        }
}

 

I did some manual testing and it still changes the task if the Account Owner owns the task.  For example, I own XYZ Account and have one open activity.  Another rep, Jane, has an open activity too on this account.  Let's say I change the ownership of this XYZ Account to John.  When I tested it, Jane's task stayed with her, which is correct, but my open task assigned to me switched over to John's ownership.  Is there a way that I can stop that from happening too?

 

Chitral ChaddaChitral Chadda
@brozinickr
check this and let me know if it works


trigger preventTaskOwnerChange on Account ( after update)
{  

   list<task> updatetask = new list<task>();
    for(account a :trigger.new)
     {
             string oldownerid  = trigger.oldmap.get(a.id).OwnerId;
             string newownerid  = a.ownerid;
             if(oldownerid != newownerid)
                {
        
                     for( account acc : [ select OwnerId, ( select OwnerId from tasks  ) from account])
                     {      
                            for( task tsk :acc.tasks)
                             {
                                                    
                              tsk.ownerId = oldownerid;
                               updatetask.add(tsk);
                               
                              
                             }  
                           
                      }
                       update updatetask;
                     
                }
      } 
}
Tony White (BNE)Tony White (BNE)
This is how I solved this issue for a client as I found that the Task Trigger was not being fired when the change owner process was being used.

Add a new custom field on Task (Activities): Last_Assigned_Owner__c (lookup to user or text(18))
Add in a Trigger for before insert and before update to keep this new field updated:
// Store the current owner so we can detect it changing.
    for (Task t : Trigger.new) {
        t.Last_Assigned_Owner__c  = t.OwnerId;
    }



Add in Trigger for Case after update to detect owner change and restore all open tasks:
// Identify all Cases that have a changed Owner
for (Integer idx = 0; idx < trigger.new.size(); idx++) {
        if (Trigger.new[idx].OwnerId <> Trigger.old[idx].OwnerId) {
            changedOwnerCases.put(Trigger.new[idx].id, Trigger.new[idx]);
        }
    }
    List<Task> restoreTaskOwner = new List<Task>();
    System.debug('changedOwnerCases:' + changedOwnerCases);
    // Find all the tasks (repeat for Events if required) that are not closed for these cases and revert them
    for(Task t : [SELECT Id, WhatId, OwnerId, Last_Assigned_Owner__c 
                  FROM Task
                  Where WhatId in : changedOwnerCases.keySet() AND IsClosed <> TRUE AND Last_Assigned_Owner__c <> null]) {
        system.debug('t.OwnerId:' + t.OwnerId);
        system.debug('t.Last_Assigned_Owner__c:' + t.Last_Assigned_Owner__c);
        if (t.OwnerId <> t.Last_Assigned_Owner__c) {
            t.OwnerId = t.Last_Assigned_Owner__c;
            restoreTaskOwner.add(t);
        }
    }
    System.debug('restoreTaskOwner:' + restoreTaskOwner);
    if (!restoreTaskOwner.isEmpty()) {
        update restoreTaskOwner;
    }

I hope this helps
Lin ThawLin Thaw
Hi Tony,

Thanks for your source.

please could you show me the way,
how to add this source to what class?

I am adding [Last_Assigned_Owner] field to New Task (Activity) Page and want to assign owner from that specific Last_Assigned_Owner after saving or updating task.

best regards,
Lin Thaw.
Tony White (BNE)Tony White (BNE)
Ok breaking it down to basics you need to go into the setup and search for trigger
select "Task Triggers" then click the new button and paste in this code
trigger Task on Task (before update, before insert) {
    // Store the current owner so we can detect it changing.
    for (Task t : Trigger.new) {
        t.Last_Assigned_Owner__c  = t.OwnerId;
    }
}

That will ensure that anytime the task is updated or created the current owner is saved away, changing the owner on a parent of the task (case or account etc does not fire this code it would seem).
Click Save.

Next from the quick search find the "Case Triggers", click the New button and paste in this code
trigger caseOwnerUpdate on Case (after update) {
    Map<Id,Case> changedOwnerCases = new Map<Id,Case>();
    
    for (Integer idx = 0; idx < trigger.new.size(); idx++) {
        if (Trigger.new[idx].OwnerId <> Trigger.old[idx].OwnerId) {
            changedOwnerCases.put(Trigger.new[idx].id, Trigger.new[idx]);
        }
    }
    List<Task> restoreTaskOwner = new List<Task>();
    System.debug('changedOwnerCases:' + changedOwnerCases);
    // Find all the tasks for these cases and the new owner that are not closed and revert them
    for(Task t : [SELECT Id, WhatId, OwnerId, Last_Assigned_Owner__c 
                  FROM Task
                  Where WhatId in : changedOwnerCases.keySet() AND IsClosed <> TRUE AND Last_Assigned_Owner__c <> null]) {
        system.debug('t.OwnerId:' + t.OwnerId);
        system.debug('t.Last_Assigned_Owner__c:' + t.Last_Assigned_Owner__c);
        if (t.OwnerId <> t.Last_Assigned_Owner__c) {
            t.OwnerId = t.Last_Assigned_Owner__c;
            restoreTaskOwner.add(t);
        }
    }
    System.debug('restoreTaskOwner:' + restoreTaskOwner);
    if (!restoreTaskOwner.isEmpty()) {
        update restoreTaskOwner;
    }
}

Click the Save button and you are pretty much done apart from test classes to cover this, naturally if you had triggers for Task or Case already you would try to add them to those...
 
Lin ThawLin Thaw
Thank you Tony!!
Lin ThawLin Thaw
Hi Tony,

Thanks for previous answer.
I have another related question.

When a user creating new task (from Open Activities), is it possible to create only one task (not copies) that can be edited and closed by all users (but not more than 100 users) who are from one specific role.
Can I do that by using Trigger and Case?
Could you please share if you have some solution about it.

Currently, [Assigned To] [Multiple Users] (Lookup) function is creating individual copy tasks for each user. So I want to use above logic.

best regards,
Lin Thaw
Jake BackuesJake Backues
I'd like to offer this helper class based on the previous post by Tony White (BNE). This will work for Accounts or Cases with related tasks whose Owners are changing. This requires adding the field Last_Assigned_Owner__c on the Activity(Task) object. and setting up an Account/Case Trigger that calls this classes method on After Update and After Insert (see original post by Tony).
 
public class TaskOwnerHelper {
    
    /*
     * This will work for tasks under Accounts or Cases, just pass in those types of records
     */
    public static void syncTaskOwner( Map<Id, SObject> oldParents, Map<Id, SObject> newParents ){
        Set<Id> changedOwnerIds = new Set<Id>();
        
        // Identify all Parents that have a changed Owner
        for( SObject parent : newParents.values() ){
            SObject oldParent = oldParents.get((Id)parent.get('Id'));
            
            if( parent.get('OwnerId') <> oldParent.get('OwnerId') ){
                changedOwnerIds.add((Id)parent.get('Id'));
            }
        }
        
        // Find all the tasks (repeat for Events if required) that are not closed for the parent records that had new Owners
        Task[] restoreTaskOwner = new Task[0];
        
        // revert the owner on the found tasks
        for(Task tsk : [
            SELECT Id, OwnerId, Last_Assigned_Owner__c 
            FROM Task
            Where WhatId IN :changedOwnerIds AND IsClosed = FALSE AND Last_Assigned_Owner__c <> null
        ]){
            if (tsk.OwnerId <> tsk.Last_Assigned_Owner__c) {
                tsk.OwnerId = tsk.Last_Assigned_Owner__c;
                restoreTaskOwner.add(tsk);
            }
        }
        
        update restoreTaskOwner;
    }
}

And also want to offer this test class:
@IsTest
public class TaskOwnerHelperTest {
	
    @TestSetup
    static void setup(){
        Account newAcct = new Account(
        	Name = 'Test'
        );
        insert newAcct;
        
        Task newTsk = new Task(
        	WhatId = newAcct.Id
            , Subject = 'Test'
        );
        insert newTsk;
    }
    
    @IsTest
    static void happyPath(){
        Task[] existingTasks = [
            SELECT Id, OwnerId, Last_Assigned_Owner__c, WhatId
            FROM Task
            Where IsClosed = FALSE AND Last_Assigned_Owner__c <> null
        ];
        System.assert( existingTasks.size() == 1, existingTasks );
        System.assertEquals( existingTasks[0].Last_Assigned_Owner__c, UserInfo.getUserId() );
        System.assertEquals( existingTasks[0].Last_Assigned_Owner__c, existingTasks[0].OwnerId );
        
        User[] usr = [SELECT Id FROM User WHERE IsActive = true AND Id != :UserInfo.getUserId() LIMIT 1];
        
        Test.startTest();
        update new Account(
            Id = existingTasks[0].WhatId
            , OwnerId = usr[0].Id
        );
        Test.stopTest();
        
        existingTasks = [
            SELECT Id, OwnerId, Last_Assigned_Owner__c, WhatId
            FROM Task
        ];
        Account acct = [SELECT Id, OwnerId FROM Account LIMIT 1];
        system.assertEquals( usr[0].Id, acct.OwnerId );
        System.assert( existingTasks.size() == 1, existingTasks );
        System.assertEquals( existingTasks[0].Last_Assigned_Owner__c, UserInfo.getUserId() );
        System.assertEquals( existingTasks[0].Last_Assigned_Owner__c, existingTasks[0].OwnerId );
    }
}

 
Jeevana Priyanka BJeevana Priyanka B
Hello Jake,

Thank you for the Code, Apex class works fine but the Test class is not working can you please confirm.

Regards,
Jeevana.
Jake BackuesJake Backues
Hey Jeevana,

I was just confirming in my dev org that this test still runs and passes, your org may be different and it may need to be modified. What error are you getting in the test class in your org?
Jeevana Priyanka BJeevana Priyanka B
Not just the error it is not even covering the single line in the code, Not sure why.
 
Jake BackuesJake Backues
Did you also write the trigger on the parent record, either account or Case? See the code above from Tony White (BNE) .
Jeevana Priyanka BJeevana Priyanka B
Yes I did on Case.
Jake BackuesJake Backues
The test I wrote is starting from the Account, So you'll have to update it to run off the Case record and change the Case owner.
Jake BackuesJake Backues
The Case Version would look something like this, but I haven't tested this version.
@IsTest
public class TaskOwnerHelperTest {
	
    @TestSetup
    static void setup(){
        Account newAcct = new Account(
        	Name = 'Test'
        );
        insert newAcct;
        
        Case newCase = new Case(
        	Subject = 'test'
            , Status = 'new'
        );
        insert newCase;
        
        Task newTsk = new Task(
        	//WhatId = newAcct.Id
        	WhatId = newCase.Id
            , Subject = 'Test'
        );
        insert newTsk;
    }
    
    @IsTest
    static void happyPath(){
        Task[] existingTasks = [
            SELECT Id, OwnerId, Last_Assigned_Owner__c, WhatId
            FROM Task
            Where IsClosed = FALSE AND Last_Assigned_Owner__c <> null
        ];
        System.assert( existingTasks.size() == 1, existingTasks );
        System.assertEquals( existingTasks[0].Last_Assigned_Owner__c, UserInfo.getUserId() );
        System.assertEquals( existingTasks[0].Last_Assigned_Owner__c, existingTasks[0].OwnerId );
        
        User[] usr = [SELECT Id FROM User WHERE IsActive = true AND Id != :UserInfo.getUserId() LIMIT 1];
        
        Test.startTest();
        update new Case(
            Id = existingTasks[0].WhatId
            , OwnerId = usr[0].Id
        );
        Test.stopTest();
        
        existingTasks = [
            SELECT Id, OwnerId, Last_Assigned_Owner__c, WhatId
            FROM Task
        ];
        Account acct = [SELECT Id, OwnerId FROM Account LIMIT 1];
        system.assertEquals( usr[0].Id, acct.OwnerId );
        System.assert( existingTasks.size() == 1, existingTasks );
        System.assertEquals( existingTasks[0].Last_Assigned_Owner__c, UserInfo.getUserId() );
        System.assertEquals( existingTasks[0].Last_Assigned_Owner__c, existingTasks[0].OwnerId );
    }
}

 
Jeevana Priyanka BJeevana Priyanka B
I have already done that it still didnt work...No worries. I will find another way.
Thank You!
Ken Koellner 7Ken Koellner 7
Does anyone know if this will work with Event?  When I update the owner of a Lead, the Owner open Events for that Lead get updated.  But, no trigger on Event fires.  I'm curious why the technique above works for Task but I don't think it would work for Event.