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
GRStevenBrookesGRStevenBrookes 

Task Apex Trigger Help!

Good Morning,

 

I was hoping (preying) that someone could help me with a problem I am having getting some pretty simple (IMO) fields completed.

 

In Leads - I have 4 custom fields:

 

Phone_Call_Attempts__c (Number(3, 0)

Successful_Phone_Calls__c (Number(3, 0)

Future_Dated_Task_Scheduled__c (Checkbox)

Overdue_Task_Flag__c (Checkbox)

 

When a Task is created (related to the lead) and has its Status' set to 'Completed', then I would like this to record as '1' in the Phone_Call_Attempts__c field on the related lead. Additional tasks of the same criteria would result in the number of Phone_Call_Attempts__c increasing. So if their had been 4 tasks with a status of completed, the Phone_Call_Attempts__c field would read '4'.

 

In addition, When a task (related to the lead) has its 'Status' set to 'Completed' and its 'Outcome' (Outcome__c (Picklist)) is 'Call Successful - Spoke with contact' I would like this to record as '1' in the 'Successful_Phone_Calls__c' field on the related Lead. Additional tasks of the same criteria would result in the number of 'Successful_Phone_Calls__c' increaseing. So if their had been 4 tasks with the outcome of 'Call Successful - Spoke with contact' then the Successful_Phone_Calls__c field would read '4'.

 

Where a task is raised against the lead that has a future date and has a 'Status' of 'Not Started' then this would result in the Future_Dated_Task_Scheduled__c checkbox being ticked. This should be unticked when/if the task is later completed.

 

Finally - where a task has a 'Status' of 'Not Started' and the 'ActivityDate' is in the past - the Overdue_Task_Flag__c should be ticked.

 

ANY help would be VERY VERY appreciated.

 

Steve

Best Answer chosen by Admin (Salesforce Developers) 
Ritesh AswaneyRitesh Aswaney

had to paste it into the ide to match on parenthesis :)

the for statement on leads had an extra left bracket

 

 

trigger TaskAfter on Task ( after insert, after update) {
 
Set<Id> leadsToUpdate = new Set<Id>{};
String leadPrefix = Lead.SObjectType.getDescribe().getKeyPrefix();
 
for(Task t : trigger.new)
if(t.WhoId != null && ((String)t.WhoId).startsWith(leadPrefix))  //if not null and whoId belongs to a Lead
leadsToUpdate.add(t.WhoId);
List<Lead> updateLeads = new List<Lead>{};
 
for (Lead currLead : [Select Id, Phone_Call_Attempts__c, Successful_Phone_Calls__c,  Future_Dated_Task_Scheduled__c, Overdue_Task_Flag__c, (Select Id, Status, ActivityDate, Outcome__c from Tasks ORDER BY CreatedDate DESC) from Lead where Id IN :leadsToUpdate ])
{
updateLeads.add(currLead);
currLead.Phone_Call_Attempts__c = 0;
currLead.Successful_Phone_Calls__c = 0;
currLead.Future_Dated_Task_Scheduled__c = false;
currLead.Overdue_Task_Flag__c = false;
 
for(Task t : currLead.Tasks )
{
 
if(t.Status == 'Completed')
{
currLead.Phone_Call_Attempts__c += 1;
 
if(t.Outcome__c == 'Call Successful - Spoke with contact')
currLead.Successful_Phone_Calls__c += 1;
}//end if
 
else if(t.ActivityDate > Date.Today() && t.Status == 'Not Started')
currLead.Future_Dated_Task_Scheduled__c = true;
 
else if (t.ActivityDate <= Date.Today() && t.Status == 'Not Started')
currLead.Overdue_Task_Flag__c = true;
 
}//end inner for
}//end outer for 
 
if (updateLeads != null && !updateLeads.isEmpty())
Database.update(updateLeads);
 
}

 

All Answers

Ritesh AswaneyRitesh Aswaney

For starters, I'd recommend you set a default value of 0 for the numerical fields on Lead. Here is a rather simplistic approach to thigns - i've assumed you want this only on Insert. Also, this would not cater to people deleting tasks after they've been added to the aggregate fields on Leads.

 

trigger TaskAfter on Task ( before insert) {

 

Set<Id> leadsToUpdate = new Set<Id>{};

String leadPrefix = Lead.SObjectType.getDescribe().getKeyPrefix();

 

for(Task t : trigger.new)

if(t.WhoId != null && ((String)t.WhoId).startsWith(leadPrefix)  //if not null and whoId belongs to a Lead

leadsToUpdate.add(t.WhoId);

 

Map<Id, Lead> leadMap = new Map<Id, Lead>([Select Id, Phone_Call_Attempts__c, Successful_Phone_Calls__c,  Future_Dated_Task_Scheduled__c, Overdue_Task_Flag__c from Lead where Id IN :leadsToUpdate ]);

 

for(Task t : trigger.new)

{

Lead currLead = leadMap.get(t.WhoId);

if (currLead != null)

{

if(t.Status == 'Completed')

{

currLead.Phone_Call_Attempts__c += 1;

 

if(t.Outcome__c == 'Call Successful - Spoke with contact')

currLead.Successful_Phone_Calls__c += 1;

}

 

else if(t.ActivityDate > Date.Today() && t.Status == 'Not Started')

currLead.Future_Dated_Task_Scheduled__c = true;

 

else if (t.ActivityDate <= Date.Today() && t.Status == 'Not Started')

currLead.Overdue_Task_Flag__c = true;

}

 

}

 

if (leadMap != null && !leadMap.values().isEmpty())

Database.update(leadMap.values());

 

}

b-Forceb-Force

 

public with sharing class LeadTaskController 
{
public static void UpdateLeadTaskComplete(List<Task> lstTask)
{
	
	List<Lead> lstToUpdate=new List<Lead>();	
	Set<Id> setLeads=new Set<Id>();	
	for(Task objTask :lstTask)
	{
		setLeads.add(objTask.WhoId);
	}	
	System.debug('---------task--------'+lstTask);
	System.debug('----------set-------'+setLeads);
	try
	{
		List<Lead> lstLeads=[Select l.Phone_Call_Attempts__c, l.Successful_Phone_Calls_c__c, l.Id, l.Future_Dated_Task_Scheduled_c__c, l.Four_Hour_Follow_Up_Time__c, l.FirstName From Lead l where l.Id in : setLeads];
		
		System.debug('-----------lstLead'+lstLeads);
		for(Lead objLead: lstLeads)
		{
			for(Task objTask : lstTask)
			{
				if(objLead.Id == objTask.WhoId	)
				{
					//Condition 1
					System.debug('----------------Task--------'+objLead +'-----------------Lead'+objTask);
					if(objTask.Status=='Completed')
					{
						if(objLead.Phone_Call_Attempts__c !=null)
						{
							objLead.Phone_Call_Attempts__c=objLead.Phone_Call_Attempts__c +1;
						}else
						{
							objLead.Phone_Call_Attempts__c=1;
						}
						//Condition 2
						
					}
					//Condition 2
					lstToUpdate.add(objLead);
					break;
				}			
			}
		}
System.debug('---------------'+lstToUpdate);
if(lstToUpdate.size() > 0)
update lstToUpdate;
	}catch(Exception ex)
	{
	lstTask[0].addError('Exception--'+ex.getMessage());
	System.debug('----------------'+ex);	
	}
}
}

 

Trigger Code

trigger UpdateLead on Task (before insert) 
{
	LeadTaskController.UpdateLeadTaskComplete(Trigger.New);
}

 

 

 

GRStevenBrookesGRStevenBrookes

Hi - thanks so much for reply!

am trying this in sandbox in task triggers but am gettnig the following error:

 

Error: Compile Error: No such column 'WhoId' on entity 'Lead'. If you are attempting to use a custom field, be sure to append the '__c' after the custom field name. Please reference your WSDL or the describe call for the appropriate names. at line 10 column 43

Ritesh AswaneyRitesh Aswaney

Oops, the perils of type in textpad

 

WhoId should not be in this SOQL Query

 

Map<Id, Lead> leadMap = new Map<Id, Lead>([Select Id, Phone_Call_Attempts__c, Successful_Phone_Calls__c,  Future_Dated_Task_Scheduled__c, Overdue_Task_Flag__c from Lead where Id IN :leadsToUpdate ]);

GRStevenBrookesGRStevenBrookes

This works perfectly thank you!

 

The only thing is when the 'Future Dated Task' is closed off as completed - it does not 'untick' the Future Dated Task Scheduled box.

 

Is their an easy way to do this?

Ritesh AswaneyRitesh Aswaney

sweet.

 

just add this couple of lines in the if block i'd written earlier

 

if(t.Status == 'Completed')

{

currLead.Phone_Call_Attempts__c += 1;

 

if(t.Outcome__c == 'Call Successful - Spoke with contact')

currLead.Successful_Phone_Calls__c += 1;

 

//NEW BLOCK OF CODE ADDED TO SET FUTURE TASK SCHEDULED TO FALSE IF COMPLETED

if (currLead.Future_Dated_Task_Scheduled__c)

currLead.Future_Dated_Task_Scheduled__c = false;

}

Ritesh AswaneyRitesh Aswaney

Well actually not quite, now that I think about it.

Because there may be other future dated tasks open? This depends on whether tasks are updated, or always created in a terminal state?

Coz then you'd have to maintain a counter of future dated tasks on lead, which is incremented as new tasks are created and decremented as tasks are closed. Then depending on the value of the counter, check or uncheck the future tasks scheduled.

 

Another alternative would be to wipe all the counters, and recalculate on every insert or update. the solution depends on the complexity / dynamic-ness of your business requirement.

GRStevenBrookesGRStevenBrookes

yes - was just about to say - dosnt seem to work - I agree with you, i think to wipe all the counters, and recalculate on every insert or update would be the better option.

 

Thanks so much for this by the way.

Ritesh AswaneyRitesh Aswaney

Here, lets try the wipe and recalculate approach - (caveat hopefully you wont have thousands of tasks on each Lead, else it could break some limits, over time)

 

trigger TaskAfter on Task ( after insert, after update) {

 

Set<Id> leadsToUpdate = new Set<Id>{};

String leadPrefix = Lead.SObjectType.getDescribe().getKeyPrefix();

 

for(Task t : trigger.new)

if(t.WhoId != null && ((String)t.WhoId).startsWith(leadPrefix)  //if not null and whoId belongs to a Lead

leadsToUpdate.add(t.WhoId);

 

for (Lead currLead : ([Select Id, Phone_Call_Attempts__c, Successful_Phone_Calls__c,  Future_Dated_Task_Scheduled__c, Overdue_Task_Flag__c, (Select Id, Status, ActivityDate, Outcome__c from Tasks ORDER BY CreatedDate DESC) from Lead where Id IN :leadsToUpdate ])

{

currLead.Phone_Call_Attempts__c = 0;

currLead.Successful_Phone_Calls__c = 0;

currLead.Future_Dated_Task_Scheduled__c = false;

currLead.Overdue_Task_Flag__c = false;

 

for(Task t : currLead.Tasks )

{

 

if(t.Status == 'Completed')

{

currLead.Phone_Call_Attempts__c += 1;

 

if(t.Outcome__c == 'Call Successful - Spoke with contact')

currLead.Successful_Phone_Calls__c += 1;

}

 

else if(t.ActivityDate > Date.Today() && t.Status == 'Not Started')

currLead.Future_Dated_Task_Scheduled__c = true;

 

else if (t.ActivityDate <= Date.Today() && t.Status == 'Not Started')

currLead.Overdue_Task_Flag__c = true;

 

}

}

 

if (leadMap != null && !leadMap.values().isEmpty())

Database.update(leadMap.values());

 

}

GRStevenBrookesGRStevenBrookes

ooooh getting error:

 

Compile Error: expecting a right parentheses, found 'leadsToUpdate.add' at line 8 column 0

Ritesh AswaneyRitesh Aswaney

doh ! then jsut add right paranthesis :) Looks like u added it last time to get it to compile :)

 

if(t.WhoId != null && ((String)t.WhoId).startsWith(leadPrefix))  //if not null and whoId belongs to a Lead

leadsToUpdate.add(t.WhoId);

GRStevenBrookesGRStevenBrookes

tried that but now get:

 

Compile Error: unexpected token: '{' at line 11 column 0 

when I delete that I get:

 

Compile Error: expecting a right parentheses, found 'currLead.Phone_Call_Attempts__c' at line 12 column 0

Ritesh AswaneyRitesh Aswaney

had to paste it into the ide to match on parenthesis :)

the for statement on leads had an extra left bracket

 

 

trigger TaskAfter on Task ( after insert, after update) {
 
Set<Id> leadsToUpdate = new Set<Id>{};
String leadPrefix = Lead.SObjectType.getDescribe().getKeyPrefix();
 
for(Task t : trigger.new)
if(t.WhoId != null && ((String)t.WhoId).startsWith(leadPrefix))  //if not null and whoId belongs to a Lead
leadsToUpdate.add(t.WhoId);
List<Lead> updateLeads = new List<Lead>{};
 
for (Lead currLead : [Select Id, Phone_Call_Attempts__c, Successful_Phone_Calls__c,  Future_Dated_Task_Scheduled__c, Overdue_Task_Flag__c, (Select Id, Status, ActivityDate, Outcome__c from Tasks ORDER BY CreatedDate DESC) from Lead where Id IN :leadsToUpdate ])
{
updateLeads.add(currLead);
currLead.Phone_Call_Attempts__c = 0;
currLead.Successful_Phone_Calls__c = 0;
currLead.Future_Dated_Task_Scheduled__c = false;
currLead.Overdue_Task_Flag__c = false;
 
for(Task t : currLead.Tasks )
{
 
if(t.Status == 'Completed')
{
currLead.Phone_Call_Attempts__c += 1;
 
if(t.Outcome__c == 'Call Successful - Spoke with contact')
currLead.Successful_Phone_Calls__c += 1;
}//end if
 
else if(t.ActivityDate > Date.Today() && t.Status == 'Not Started')
currLead.Future_Dated_Task_Scheduled__c = true;
 
else if (t.ActivityDate <= Date.Today() && t.Status == 'Not Started')
currLead.Overdue_Task_Flag__c = true;
 
}//end inner for
}//end outer for 
 
if (updateLeads != null && !updateLeads.isEmpty())
Database.update(updateLeads);
 
}

 

This was selected as the best answer
GRStevenBrookesGRStevenBrookes

OK - now I feel like a pain! :smileysad:

 

Compile Error: Variable does not exist: leadMap at line 37 column 5

Ritesh AswaneyRitesh Aswaney

I've update the corrections in my last post - apologies for the toing and froing !

GRStevenBrookesGRStevenBrookes

Working fantasticly! You are a live saver - thank you so very much!

 

My company offers call handling services - if you need some assistance with your call handling - get in touch and I shall look after you.

Ritesh AswaneyRitesh Aswaney

Sweet! :)

Another satisfied 'customer' ;) 

DestinyLomasDestinyLomas

I am trying to fix my apex class testing code except I do not understand a way around what it is telling me to do. It tells me that in line 17, its expecting a right parenthesis, but only found a ;...however when I attempt to put a right parenthesis in it begins telling me all manor of things. It tells me that it does not expect token 'product' in the next line, that it is now expecting a close right curly bracket in line 17, etc. Please help!

 

This is my code, you will probably recognize it from the force.com workbook spring 13 release. I followed their instructions exactly:

 

@isTest

private

class TestHandleProductPriceChange {

 

   

statictestMethodvoid testPriceChange () {

   

Invoice_Statement__c Invoice = newInvoice_Statement__c(Status__c = 'Negotiating');

   

insert Invoice;

   

   

Merchandise__c[] products = new merchandise__c[]{

   

newMerchandise__c(Name = 'item 1', Description__c =

   

'test product 1', Price__c = 10,Total_Inventory__c = 10),

   

newMerchandise__c(Name = 'item 2', Description__c =

   

'test product 2', Price__c = 11,Total_Inventory__c = 10)

    };

    Insert products;

   

Line_Items__c[] LineItems = newLine_Items__c[] {

   

newLine_Items__c(Invoice_Statement__c = invoice.id,

   

Merchandise__c = products[0].price__c = 20; //raise price

    prodcts[1].price__c = 5;

//lower price

    Test.startTest();

   

update products;

    Test,stopTest();

   

    lineItems =

    [

SELECT id, unit_price__c FROM Line_items__c WHERE id IN :lineItems];

    System.assert(lineItems[0].unit_price__c ==10);

//unchanged

    System.assert(lineItems[1].unit_price__c == 5);

//changed!!

    };

   

insert lineItems;

   

    products[0].price__c = 20;

    Test.startTest();

   

update products;

    Test.stopTest ();

   

    lineItems = [

SELECT id, unit_Price__c FROMLine_Items__cWHERE id IN :lineItems];

   

   

system.assert(lineItems[0].unit_Price__c == 10);

    }

    }