1

I have created a trigger which should create a task on opportunities only when opportunity's owner is active.Here is my trigger and helper class:

Trigger

trigger AutoTaskCreation on Opportunity (before insert, before update, after update) {
    if (Trigger.isAfter) {
        if (Trigger.isUpdate) { 
           TaskServices.createTaskforOpp(Trigger.new);
        }
    }

}

Helper Class

public with sharing class TaskServices {

public static void createTaskforOpp(List<Opportunity> oppList) {

    List<Task> taskList = new List<Task>();
    For(Opportunity opp : oppList) {
      if(opp.Owner.isActive == false) {
      Task newTask = new Task(
           WhatId = opp.Id,
           OwnerId = opp.OwnerId,
           ActivityDate = Date.today(),
          Subject = 'Test Subject',
           Description = 'This a Test'
       );
        taskList.add(newTask);

    }
        }
        insert taskList;
    }
}

The above code is creating task for both active and inactive opportunity owners. Why if(opp.Owner.isActive == false) is not working?

3
  • 2
    This is a pretty common problem, and we regularly get questions like this. The problem is that relationships are not automatically populated in Trigger.new, so you have to query for them.
    – sfdcfox
    Commented Jan 23, 2017 at 15:40
  • N.B. You can't do this in before insert as opp.Id will be null
    – cropredy
    Commented Jan 23, 2017 at 18:04
  • You don't need opp.Id at all, just query the owners directly. But it should be an after trigger anyway if you are doing cross-object updates.
    – Adrian Larson
    Commented Jan 23, 2017 at 19:18

2 Answers 2

1

The trigger context variables (Trigger.new, Trigger.oldMap, etc...) do not contain data on related objects, they only contain data for the object the trigger is on.

So, in your helper class, when we get to this line:

if(opp.Owner.isActive == false) {

opp.Owner.isActive is null, null is not equal to false, so your tasks get created.

Technically, opp.Owner is null as well, but Salesforce appears to do some magic in the background to prevent this from throwing a Null Pointer Exception.

To have your helper class behave as expected when called from a trigger, you'll need to query the Opportunities you want to pass to your helper class (and explicitly query for Owner.isActive)

trigger AutoTaskCreation on Opportunity (after insert, after update) {
    if (Trigger.isAfter) {
        TaskServices.createTaskforOpp([SELECT Id, OwnerId, Owner.isActive FROM Opportunity WHERE Id IN :Trigger.new);
    }
}
1
  • 1
    As an aside, you'll also probably want to add a check to see if you've previously generated tasks for a given opportunity. If you don't, you'll have a new task generated every time an Opportunity is updated. Since you will need to query Opportunity, and since you aren't modifying any fields on Opportunity, you should be running this code after insert and after update.
    – Derek F
    Commented Jan 23, 2017 at 15:44
0

Trigger context records do not contain cross object fields in memory. You have to query for them.

Set<Id> allOwnerIds = new Set<Id>();
for (Opportunity record : newRecords)
    allOwnerIds.add(record.OwnerId);
Set<Id> inactiveOwnerIds = new Map<Id, User>([
    SELECT Id FROM User
    WHERE Id IN :allOwnerIds
    AND IsActive = true
]);

for (Opportunity record : newRecords)
{
    if (inactiveOwnerIds.contains(record. OwnerId)
    {
        // do stuff
    }
}

You must log in to answer this question.

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