0

I'm new to coding and my developer friend and I have this APEX trigger to update a custom field on opportunities, based on recently created tasks.

However, we can't create a task on the account level, I keep getting an error. I can create the task on all other objects like Lead, Opportunity, and Contact, but not the Account.

Can you help me find out why?

trigger ActivityCreationLogger on Task (after insert, after update) {
for (Task task : Trigger.new) {
    if (task.WhatId != null) {
        Opportunity correspondingOpp = [SELECT Id, Last_Activity_Subject__c, CreatedDate FROM Opportunity WHERE Id =:task.WhatId];
        if (correspondingOpp != null){
            Task nextDueTask = [SELECT ActivityDate, Subject FROM Task WHERE WhatId =:correspondingOpp.Id AND Status != 'Completed' ORDER BY ActivityDate ASC LIMIT 1];
            if (nextDueTask != null) {
                correspondingOpp.Last_Activity_Subject__c = nextDueTask.Subject  + ': ' + nextDueTask.ActivityDate.format();
            } else {
                correspondingOpp.Last_Activity_Subject__c = null;
            }
            update correspondingOpp;
        }
    }
}

}

1
  • 2
    could you add the actual code you tried on Account? And also the error you are getting? Commented Oct 16, 2014 at 18:58

1 Answer 1

3

This line:

Opportunity correspondingOpp = [SELECT Id, Last_Activity_Subject__c, CreatedDate
        FROM Opportunity WHERE Id =:task.WhatId];

will produce the error "QueryException: List has no rows for assignment to SObject" if the task.WhatId relates to some other object rather than resulting in a null correspondingOpp.

One way to fix it is this (and the same sort of approach is needed for the Task query too):

Opportunity[] correspondingOpps = [SELECT Id, Last_Activity_Subject__c, CreatedDate
        FROM Opportunity WHERE Id =:task.WhatId];
if (correspondingOpps.size() > 0) {
    Opportunity correspondingOpp = correspondingOpps[0];
    ...
}

or another way (just for the Opportunity query) is:

if (task.WhatId != null && task.WhatId.getSObjectType() == Opportunity.SObjectType) {
    Opportunity correspondingOpp = [SELECT Id, Last_Activity_Subject__c, CreatedDate
            FROM Opportunity WHERE Id =:task.WhatId];
    // No null check needed

I suggest you start by making these changes and re-test with Tasks on various objects.

PS

A (untested) bulkified (see e.g. General trigger bulkification - best practices) version of what you appear to be doing is:

trigger ActivityCreationLogger on Task (after insert, after update) {
    Set<Id> oppIds = new Set<Id>();
    for (Task task : Trigger.new) {
        if (task.WhatId != null
                    && task.WhatId.getSObjectType() == Opportunity.SObjectType) {
            oppIds.add(task.WhatId);
        }
    }
    if (oppIds.size() > 0) {
        Map<Id, Task> tasks = new Map<Id, Task>();
        for (Task t : [
                SELECT ActivityDate, Subject, WhatId
                FROM Task
                WHERE WhatId in :oppIds
                AND Status != 'Completed'
                ORDER BY ActivityDate ASC
                ]) {
            // Using first only
            if (tasks.get(t.WhatId) == null) {
                tasks.put(t.WhatId, t);
            }
        }
        // No need to query before updating
        Opportunity[] opps = new Opportunity[] {};
        for (Opportunity oppId : oppIds) {
            Task t = tasks.get(oppId);
            opps.add(new Opportunity(
                    Id = oppId,
                    Last_Activity_Subject__c = t != null
                            ? t.Subject  + ': ' + t.ActivityDate.format()
                            : null
                    ));
        }
        update opps;
    }
}

You must log in to answer this question.

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