By default, the Task Due Date is based on the current date. So if the value is 2, the due date is two (working) days after the Tasks prerequisites (if any) have been completed.
This feature allows to calculate backwards.
Examples are a Release or a Meeting preparations to meet a target date.
With a negative relative date, the Due Date is calculated based on the Target Date.
Setup
In the Checklist Item, use a negative value for the Date Offset Days.
You can mix positive (based on the current date) and negative values in the checklist.
Optionally, you can default the Target Date from the record. In the Checklist, set the Dynamic Target Date - a reference to the date field (use the api name like MyDate__c)
- example: Use the Clise Date in the Opportunity as the Target Date
Use
When creating the Tasks from the Checklist, enter the target date.
When you change the Target Date, the Due Dates are updated based on the Date Offset.
The target date is stored in the Checklist Instance, and you can update it there, if required.
Update of the Target Date
You can manually update the Target date in the checklist instance or update the Target date from the (changed) record date. Example: the Opportunity Close Date changed and you want to update the checklist tasks.
Manual Target Date Update when Record changed
- In the Tab Checklist, select any List (other than Recently Viewed) and click "Instance Maintenance" - or
- In the Tab Checklist, select any checklist record and select "Instance Maintenance"
In the Form,
- select e.g. -all- checklists -- by default the instances of this checklist are updated
- click on Update Target Date
This updates the Checklist Instance if the target date of the record was changed and also updates the Activity Date of the Tasks.
Automatic Target Update (Scheduled)
In Setup > Apex Classes
click on "Schedule Apex"
- Select the Apex Class: CheckListTargetUpdate
- Enter Name, Frequency, and Start/End date
(note that Salesforce does not notify you when the job expires)
Automatic Target Update (Immediate)
For the immediate update of the Task due date from the record target date, you can use a trigger.
You just need to find the Checklist Instance for the record and update the target date.
There is an example of updating based on the Opportunity Close Date:
(note that for readability the namespace acheck__ is omitted)
/** * Automatic Update of Tasks when Target Date changes * Example: Opportunity.DueDate */ trigger ExampleOpportunityTargetDate on Opportunity (after update) { // get the opportunities with changed target date Map<Id, Date> opportunityMap = new Map<Id, Date>(); for (Opportunity opp : Trigger.new) { Opportunity oldOpp = Trigger.oldMap.get(opp.Id); if (opp.CloseDate != oldOpp.CloseDate) { opportunityMap.put(opp.Id, opp.CloseDate); } } List<ChecklistInstance__c> instances = [ SELECT Id, Name, RelatedId__c, TargetDate__c FROM ChecklistInstance__c WHERE RelatedId__c IN :opportunityMap.keySet() AND TargetDate__c != NULL // should have a target date AND OpenCount__c > 0 // should not be completed ]; for (ChecklistInstance__c inst : instances) { Date theDate = opportunityMap.get(inst.RelatedId__c); if (theDate != null) { inst.TargetDate__c = theDate; } } update instances; } // ExampleOpportunityTargetDate
and the test case method
@IsTest static void testTargetDateExampleTrigger() { // Setup Date targetDate = System.today().addDays(10); Account acct = new Account( Name='test' ); insert acct; Opportunity opp = new Opportunity( Name = 'test-', AccountId = acct.Id, StageName = 'test', CloseDate = targetDate); insert opp; // Opportunity Checklist for one day before Target Date CheckList__c cl = new CheckList__c( Name = 'test', OnlyforObject__c = 'Opportunity', TargetDate_Dynamic__c = 'CloseDate' ); insert cl; CheckListItem__c cli = new CheckListItem__c( CheckList__c = cl.Id, Name = 'One day before', Subject__c = 'One day before', DateOffsetDays__c = -1, IsWorkdays__c = false ); insert cli; // Create Task from checklist List<Task> taskList = CheckListUtil.createTaskList(cl.Id, opp.Id); System.assertEquals(1, taskList.size()); // Save String errorMsg = CheckListUtil.saveTaskList(taskList); System.assertEquals(null, errorMsg); // Check Task taskList = [SELECT Id, Subject, ActivityDate FROM Task WHERE WhatId = :opp.Id ]; System.assertEquals(1, taskList.size()); System.assertEquals(targetDate.addDays(-1), taskList.get(0).ActivityDate); // Get Instance List<ChecklistInstance__c> instances = [SELECT Id, Name, TargetDate__c, RelatedId__c FROM ChecklistInstance__c WHERE RelatedId__c = :opp.Id ]; System.assertEquals(1, instances.size()); System.assertEquals(targetDate, instances.get(0).TargetDate__c); // System.debug('-- Change Instance Target Date --'); Date newTargetDate = targetDate.addDays(11); instances.get(0).TargetDate__c = newTargetDate; update instances; // check task changed taskList = [SELECT Id, Subject, ActivityDate FROM Task WHERE WhatId = :opp.Id]; System.assertEquals(1, taskList.size()); System.assertEquals(newTargetDate.addDays(-1), taskList.get(0).ActivityDate); System.debug('-- Change Record Target Date --'); newTargetDate = targetDate.addDays(11); opp.CloseDate = newTargetDate; update opp; // check checklist changed instances = [SELECT Id, Name, TargetDate__c, RelatedId__c FROM ChecklistInstance__c WHERE RelatedId__c = :opp.Id ]; System.assertEquals(1, instances.size()); System.assertEquals(newTargetDate, instances.get(0).TargetDate__c); // check task changed taskList = [SELECT Id, Subject, ActivityDate FROM Task WHERE WhatId = :opp.Id]; System.assertEquals(1, taskList.size()); System.assertEquals(newTargetDate.addDays(-1), taskList.get(0).ActivityDate); }