function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
NarcissuNarcissu 

How to show most recent due date of a task using Trigger

Hi,

 

As we know, we can have multiple open tasks with different due dates at the same time.

 

Now I want to create a field in Account object, and this field will pick up the most recent due date of the multiple tasks. For example, there are two open tasks. One's due date is 1/1/2013, the other's is 2/1/2013. Since 1/1/2013 is the first task I create, it will automatically be populated into the field using the trigger below:

 

trigger UpcomingActivity on Task(after update, after insert)
{
Task b = new Task();
Set<id> AccountIDs = new set<id>();
list<Account> AcctList = new list<Account>();
for(Task c : Trigger.new)
{
for(Account at:[Select id,Upcoming_Due__c From Account where id =: c.accountid])
{
at.Upcoming_Due__c = date.valueof(c.ActivityDate);
AcctList.add(at);
}
}
update AcctList;
}

 

However, if I create another task, the new due date will override 1/1/2013. There are two issues.

 

1. If the new task due date is after the due date of the second task - 2/1/2013, the second one will be ignored.

2. If the new task due date is prior to the two existing ones, the code cannot pick the existing ones anymore. E.g. the new one is 5/1/2012, even 1/1/2013 and 2/1/2013 are in the future and never happen, they are out of the date pending flow.

 

Please give me some ideas how to make the field always show the most recent upcoming due date no matter how many open tasks I have. *Task and Opportunity are two different objects.

sfdcfoxsfdcfox
trigger updateAccountRecent on Task (after insert, after update, after delete, after undelete) {
    map<id,account> accounts = new map<id,account>();
    if(trigger.new!=null)
        for(task t:trigger.new)
            accounts.put(t.accountid,null);
    if(trigger.old!=null)
        for(task t:trigger.old)
            accounts.put(t.accountid,null);
    accounts.putall([select id,(select id,activitydate from tasks where isclosed = false and activitydate != null order by activitydate asc limit 1) from account where id in :accounts.keyset()]);
    for(account a:accounts.values())
        if(a.tasks.isempty())
            a.upcoming_due__c = null;
        else
            a.upcoming_due__c = a.tasks[0].activitydate;
    update accounts.values();
}

Step 1. Gather all accounts that will be affected.

Step 2. Query for the next upcoming task for each account.

Step 3. Update your custom field.

Step 4. Commit this value to the database.

 

You might need to tweak this a bit, but this is a fairly standard "aggregate-query-update" pattern. You often use this sort of pattern when you need to process records in bulk, no matter what you're doing.

NarcissuNarcissu

Thanks so much for the reply. Can you please also give me some ideas to write the test code for this?

sfdcfoxsfdcfox

My apologies for the delayed response. A suitable test method would be something like the following:

 

Insert an account.

Insert at least two tasks, either all at once, or staggered.

Make sure that the latest date is in the account (requires query).

Move one task's date ahead of the other, and check changes.

Close the one you moved ahead, check date.

Delete the remaining task, make sure field is now null.

 

Basically, you just want to run through all "reasonable" scenarios you would expect, and make sure that the code works. If there's a bug, you can write a test method for it. I normally write a number of test methods that setup a specific scenario I'd like to test.