0

This is linked to this other Salesforce Stack Exchange question and answer: Trigger to get fields from Object linked with the 'Related To' field in an Event

I have a custom object called Customer_Statement__c. When I associate a task to a record of this sObject, a custom lookup (account) field on the task called 'Account_Name__c' should be populated with the Account__c value on the Customer_Statement__c field.

There is no compile error but when I create a task and have the task.type as 'Customer_Statement__c', the following error message is returned:

'execution of BeforeInsert caused by: System.NullPointerException: Attempt to de-reference a null object: Trigger.AccountFromCustomerStatementOnTask: line 9, column 1'

I am confused about this error because the trigger puts the what.id in the Map as per line 7.

Any help would be much appreciated.

Many thanks,

trigger AccountFromCustomerStatementOnTask on Task (after insert, after update, before insert, before update) { 

    Map<Id, List<Task>> taskWhatIds = new Map<Id, List<Task>>{};

        for (Task t : trigger.new) {
            if (t.What.Type == 'Customer_Statement__c') {
                taskWhatIds.put(t.whatId, new List<Task>()); 
            }
                taskWhatIds.get(t.WhatId).add(t);
    }


    for (Customer_Statement__c cs: [Select Id, Account__c FROM Customer_Statement__c WHERE Id IN :taskWhatIds.keySet()]){
        for (task t : taskWhatIds.get(cs.id)){
            t.Account_Name__c = cs.Account__c;
        }
    }
}

TL;DR Objects in triggers can only get values from fields which are on the actual object itself. So I replaced t.what.type == 'abc' with String.valueOf(t.WhatId).startsWith('a00')) { //. This string method checks if the first 3 chars of the record Id correspond to the custom object id. More info here: What are Salesforce ID's composed of?

2 Answers 2

2

A common pattern for doing what I think you want is this:

        if (t.What.Type == 'Customer_Statement__c') {
            List<Task> tasks = taskWhatIds.get(t.WhatId);
            if (tasks == null) {
                tasks = new List<Task>();
                taskWhatIds.put(t.WhatId, tasks);
            }
            tasks.add(t); 
        }

where if there is already a list present in the map it is used else a list is added to the map. Then the object is added to the list. All of this has to be inside the if block.

PS But see Fernando's important point.

2

First of all: whenever you create a task where What type is different from Customer_Statement__c it'll fail in the same way.

Objects in a trigger only contain the values on the object fields. For values on related objects (i.e. What.Type), you'll have to query using either a SELECT statement ou a database.query.

p.s.: don't forget to bulkify your code to avoid unnecessary queries.

1
  • Ah - very helpful. In the end I went with for (Task t : trigger.new) { if (String.valueOf(t.WhatId).startsWith('a00')) { // logic. Is there any better way you could think on how to achieve this, since as per this link - salesforce.stackexchange.com/questions/1653/… - not all unique ids (the first three characters in an id) are actually unique. Thanks! Commented Nov 18, 2015 at 15:44

You must log in to answer this question.

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