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
SubC4i-dev1SubC4i-dev1 

Collections and SOQL - Need help cleaning up

I'm new to writing apex triggers and I need some help cleaning up the SOQL queries in my collections.  Not sure what is wrong, but it just looks like too much.  Also, I'm sure it's part of what is giving me issues when I try to write a test class.

 

Thanks in advance!

 

- Matt

 

Apex Trigger:

 

trigger LDRCreatedTask on Task (after insert, after update, before delete) {

//Insert or Update command
if(trigger.isInsert || trigger.isUpdate){

	List<Task> TargetTask = [SELECT Id, WhoId, CreatedById 
							 FROM Task 
							 WHERE Id IN: Trigger.newMap.keySet()];
	
	Task TargetTaskDetails = [SELECT Id, WhoId, CreatedById 
							  FROM Task 
							  WHERE Id IN: TargetTask];
	
	Map<Id,User> UserMap = new Map<Id,User>([SELECT Id, Name, Profile.Name 
											 FROM User 
											 WHERE Id = :TargetTaskDetails.CreatedById AND isActive = true]);

	Lead ParentLead = [SELECT Id, First_LDR_Task_User__c, First_LDR_Task_Date__c 
					   FROM Lead 
					   WHERE Id = :TargetTaskDetails.WhoId];


	List<Task>LDRRelatedTasks = [SELECT Id, WhoId, CreatedBy.Profile.Name 
								 FROM Task 
								 WHERE WhoId = :ParentLead.Id AND CreatedBy.Profile.Name LIKE'%LDR%'];
							 
	List<Task> FirstTask = [SELECT Id, CreatedBy.Name, CreatedDate
							FROM Task
							WHERE Id IN: LDRRelatedTasks
							ORDER BY LastModifiedDate ASC LIMIT 1];

		Task FirstTaskDetails = [SELECT Id, CreatedBy.Name, CreatedDate
							 	FROM Task
							 	WHERE Id IN: FirstTask];	

	Map<Id,Lead> LeadstoUpdate = new Map<Id,Lead>();

for (Task t: TargetTask){

	//Update 'Most Recent' fields after each insert and everytime an existing task is modified
	if(UserMap.get(t.CreatedById).ProfileId != null 
		&& UserMap.get(t.CreatedById).Profile.Name.contains('LDR') 
		&& t.WhoId != null 
		&& (((String)t.WhoId).startswith('00Q'))){
			Lead l = new Lead(Id = t.WhoId, Most_Recent_LDR_Task_User__c = UserMap.get(t.CreatedById).Name, Most_Recent_LDR_Task_Date__c = System.now() ); 
			LeadstoUpdate.put(l.Id, l);		
			
			//Run if 1 or more LDR tasks
			if(FirstTask.size() > 0){
				if(ParentLead.First_LDR_Task_User__c == null && ParentLead.First_LDR_Task_Date__c == null){
					l.First_LDR_Task_User__c = FirstTaskDetails.CreatedBy.Name;
					l.First_LDR_Task_Date__c = FirstTaskDetails.CreatedDate;
					LeadstoUpdate.put(l.Id, l);
				}
			}
			
			//Run if 0 LDR tasks
			if(FirstTask.size() == 0){
				if(ParentLead.First_LDR_Task_User__c == null && ParentLead.First_LDR_Task_Date__c == null){
					l.First_LDR_Task_User__c = UserMap.get(t.CreatedById).Name;
					l.First_LDR_Task_Date__c = System.now();
					LeadstoUpdate.put(l.Id, l);
				}
			}
	}
	
}

update LeadstoUpdate.values();

}


if(trigger.isBefore && trigger.isDelete){

	List<Task> TargetTask = [SELECT Id, WhoId, CreatedById 
							 FROM Task 
							 WHERE Id IN: Trigger.oldMap.keySet()];
	
	Task TargetTaskDetails = [SELECT Id, WhoId, CreatedById 
							  FROM Task 
							  WHERE Id IN: TargetTask];
	
	Map<Id,User> UserMap = new Map<Id,User>([SELECT Id, Name, Profile.Name 
											 FROM User 
											 WHERE Id = :TargetTaskDetails.CreatedById AND isActive = true]);

	Lead ParentLead = [SELECT Id, First_LDR_Task_User__c, First_LDR_Task_Date__c 
					   FROM Lead 
					   WHERE Id = :TargetTaskDetails.WhoId];


	List<Task>LDRRelatedTasks = [SELECT Id, WhoId, CreatedBy.Profile.Name 
								 FROM Task 
								 WHERE WhoId = :ParentLead.Id AND CreatedBy.Profile.Name LIKE'%LDR%'];
							 
	List<Task> FirstTask = [SELECT Id, CreatedBy.Name, CreatedDate
							FROM Task
							WHERE Id IN: LDRRelatedTasks AND Id NOT IN: TargetTask
							ORDER BY LastModifiedDate ASC LIMIT 1];

	List<Task> MostRecentTask = [SELECT Id, CreatedBy.Name 
									 FROM Task 
									 WHERE Id IN: LDRRelatedTasks AND Id NOT IN: TargetTask
									 ORDER BY LastModifiedDate DESC LIMIT 1];

	Map<Id,Lead> LeadstoUpdateFirst = new Map<Id,Lead>();
	Map<Id,Lead> LeadstoUpdateMostRecent = new Map<Id,Lead>();	

for(Task t: TargetTask){
		
	//Run when all LDR tasks have been deleted
	if(LDRRelatedTasks.size() < 2){
		if(UserMap.get(t.CreatedById).ProfileId != null 
		&& UserMap.get(t.CreatedById).Profile.Name.contains('LDR') 
		&& t.WhoId != null
		&& (((String)t.WhoId).startswith('00Q'))){
			//Reset 'Most Recent' fields on lead
			Lead l = new Lead (Id = t.WhoId, Most_Recent_LDR_Task_User__c = null, Most_Recent_LDR_Task_Date__c = null);
			LeadstoUpdateMostRecent.put(l.Id, l);
		}
	}
	

	//Run when there are 1 or more LDR tasks
	if(LDRRelatedTasks.size() > 1) {
		Task MostRecentTaskDetails = [SELECT Id, CreatedBy.Name, LastModifiedDate
									  FROM Task 
									  WHERE Id IN: MostRecentTask];
		if(UserMap.get(t.CreatedById).Profile.Name.contains('LDR') && (((String)t.WhoId).startswith('00Q'))){
			//Update 'Most Recent' fields on lead			
			Lead l = new Lead (Id = t.WhoId, Most_Recent_LDR_Task_User__c = MostRecentTaskDetails.CreatedBy.Name, Most_Recent_LDR_Task_Date__c = MostRecentTaskDetails.LastModifiedDate);
			LeadstoUpdateMostRecent.put(l.Id, l);
		}	
	}
		
	//Run when there is no first LDR task - no LDR tasks on the lead record (all deleted)
	if(FirstTask.size() < 2){ 
			//Reset 'First' fields on lead			
			Lead l = new Lead(Id = t.WhoId, First_LDR_Task_User__c = null, First_LDR_Task_Date__c = null);
			LeadstoUpdateFirst.put(l.Id, l);
	}
	
	//Run when there is a first(oldest) LDR task on the lead record
	if(FirstTask.size() > 0){
		Task FirstTaskDetails = [SELECT Id, CreatedBy.Name, CreatedDate
								 FROM Task
							 	 WHERE Id IN: FirstTask];			
			//Update 'First' fields on lead		
			Lead l = new Lead(Id = t.WhoId, First_LDR_Task_User__c = FirstTaskDetails.CreatedBy.Name, First_LDR_Task_Date__c = FirstTaskDetails.CreatedDate);
			LeadstoUpdateFirst.put(l.Id, l);
	}
}

update LeadstoUpdateFirst.values();
update LeadstoUpdateMostRecent.values();

}

}

 

Best Answer chosen by Admin (Salesforce Developers) 
sfdcfoxsfdcfox

Try this out:

 

trigger LDRCreatedTask on Task (after insert, after update, after delete) {
    Map<Id,Lead> leads = new Map<Id,Lead>();
    if(Trigger.old!=null)
        for(Task record:Trigger.old)
            if(record.whoid!=null&&record.whoid.getsobjecttype()==lead.sobjecttype)
                leads.put(record.whoid,new lead(id=record.whoid,first_ldr_task_user__c=null,first_ldr_task_date__c=null,most_recent_ldr_user__c=null,most_recent_ldr_date__c=null));
    if(Trigger.new!=null)
        for(Task record:Trigger.new)
            if(record.whoid!=null&&record.whoid.getsobjecttype()==lead.sobjecttype)
                leads.put(record.whoid,new lead(id=record.whoid,first_ldr_task_user__c=null,first_ldr_task_date__c=null,most_recent_ldr_user__c=null,most_recent_ldr_date__c=null));
    Map<Id,AggregateResult> taskRanges = new Map<Id,AggregateResult>(
        [SELECT WhoId Id,MIN(CreatedDate) FirstDate,MAX(LastModifiedDate) LastDate FROM Task WHERE WhoId IN :leads.keySet() and CreatedBy.Profile.Name LIKE '%LDR%' GROUP BY WhoId]
    );
    Set<DateTime> firstTimes = new Set<DateTime>(), lastTimes = new Set<DateTime>();
    for(AggregateResult summary:taskRanges.values()) {
        firstTimes.add((DateTime)summary.get('FirstDate'));
        lastTimes.add((DateTime)summary.get('LastDate'));
    }
    for(Task record:[SELECT Id,WhoId,CreatedBy.Name,createddate,lastmodifieddate FROM Task WHERE WhoId IN :leads.keySet() AND (CreatedDate IN :firstTimes OR LastModifiedDate IN :lastTimes)]) {
        if(firstTimes.contains(record.CreatedDate)) {
            leads.get(record.whoid).first_ldr_task_date__c=record.createddate;
            leads.get(record.whoid).first_ldr_task_user__c=record.createdby.name;
        }
        if(lastTimes.contains(record.LastModifiedDate)) {
            leads.get(record.whoid).most_recent_ldr_date__c=record.lastmodifieddate;
            leads.get(record.whoid).most_recent_ldr_user__c=record.createdby.name;
        }
    }
    update leads.values();
}

 

All Answers

sfdcfoxsfdcfox

Try this out:

 

trigger LDRCreatedTask on Task (after insert, after update, after delete) {
    Map<Id,Lead> leads = new Map<Id,Lead>();
    if(Trigger.old!=null)
        for(Task record:Trigger.old)
            if(record.whoid!=null&&record.whoid.getsobjecttype()==lead.sobjecttype)
                leads.put(record.whoid,new lead(id=record.whoid,first_ldr_task_user__c=null,first_ldr_task_date__c=null,most_recent_ldr_user__c=null,most_recent_ldr_date__c=null));
    if(Trigger.new!=null)
        for(Task record:Trigger.new)
            if(record.whoid!=null&&record.whoid.getsobjecttype()==lead.sobjecttype)
                leads.put(record.whoid,new lead(id=record.whoid,first_ldr_task_user__c=null,first_ldr_task_date__c=null,most_recent_ldr_user__c=null,most_recent_ldr_date__c=null));
    Map<Id,AggregateResult> taskRanges = new Map<Id,AggregateResult>(
        [SELECT WhoId Id,MIN(CreatedDate) FirstDate,MAX(LastModifiedDate) LastDate FROM Task WHERE WhoId IN :leads.keySet() and CreatedBy.Profile.Name LIKE '%LDR%' GROUP BY WhoId]
    );
    Set<DateTime> firstTimes = new Set<DateTime>(), lastTimes = new Set<DateTime>();
    for(AggregateResult summary:taskRanges.values()) {
        firstTimes.add((DateTime)summary.get('FirstDate'));
        lastTimes.add((DateTime)summary.get('LastDate'));
    }
    for(Task record:[SELECT Id,WhoId,CreatedBy.Name,createddate,lastmodifieddate FROM Task WHERE WhoId IN :leads.keySet() AND (CreatedDate IN :firstTimes OR LastModifiedDate IN :lastTimes)]) {
        if(firstTimes.contains(record.CreatedDate)) {
            leads.get(record.whoid).first_ldr_task_date__c=record.createddate;
            leads.get(record.whoid).first_ldr_task_user__c=record.createdby.name;
        }
        if(lastTimes.contains(record.LastModifiedDate)) {
            leads.get(record.whoid).most_recent_ldr_date__c=record.lastmodifieddate;
            leads.get(record.whoid).most_recent_ldr_user__c=record.createdby.name;
        }
    }
    update leads.values();
}

 

This was selected as the best answer
SubC4i-dev1SubC4i-dev1

Very nice!  I'm going to need to wrap my head around this before I can test it out.  But I will certainly post again soon.

SubC4i-dev1SubC4i-dev1

That worked!  Thanks for your help.  I will still need to stare at your code to figure it out, but it's always great to have a "proper" example.  Btw, I've also learned a bunch from other posts you've made.

sfdcfoxsfdcfox

Thanks for the compliment. Glad I could help. Here's a summary of the code's logic:

 

1) Look for all the Lead ID values in Trigger.old and Trigger.new.

 

2) Query for the first task created date and last task modified date by lead.

 

3) Place all of the first created and last modified dates into sets (unique combinations of date/times).

 

4) Query for each task that belongs to the lead that happens to be the first created or last modified.

 

5) Set the correct fields based on if it's the lead's first or last modified task.

 

After thinking about this, there's a possibility that two tasks on two separate leads, with the created date and last modified date coincidentally overlapping for some reason might cause incorrect updates.

 

Based on that, I decided I should post an update to the code. This change makes sure that the created date and/or last modified date matches the value previously queried for that lead. This avoids any ambiguity. Here's the updated  code:

 

trigger LDRCreatedTask on Task (after insert, after update, after delete) {
    Map<Id,Lead> leads = new Map<Id,Lead>();
    if(Trigger.old!=null)
        for(Task record:Trigger.old)
            if(record.whoid!=null&&record.whoid.getsobjecttype()==lead.sobjecttype)
                leads.put(record.whoid,new lead(id=record.whoid,first_ldr_task_user__c=null,first_ldr_task_date__c=null,most_recent_ldr_user__c=null,most_recent_ldr_date__c=null));
    if(Trigger.new!=null)
        for(Task record:Trigger.new)
            if(record.whoid!=null&&record.whoid.getsobjecttype()==lead.sobjecttype)
                leads.put(record.whoid,new lead(id=record.whoid,first_ldr_task_user__c=null,first_ldr_task_date__c=null,most_recent_ldr_user__c=null,most_recent_ldr_date__c=null));
    Map<Id,AggregateResult> taskRanges = new Map<Id,AggregateResult>(
        [SELECT WhoId Id,MIN(CreatedDate) FirstDate,MAX(LastModifiedDate) LastDate FROM Task WHERE WhoId IN :leads.keySet() and CreatedBy.Profile.Name LIKE '%LDR%' GROUP BY Id]
    );
    Set<DateTime> firstTimes = new Set<DateTime>(), lastTimes = new Set<DateTime>();
    for(AggregateResult summary:taskRanges.values()) {
        firstTimes.add((DateTime)summary.get('FirstDate'));
        lastTimes.add((DateTime)summary.get('LastDate'));
    }
    for(Task record:[SELECT Id,WhoId,CreatedBy.Name,CreatedDate.lastmodifieddate FROM Task WHERE WhoId IN :leads.keySet() AND (CreateDate IN :firstTimes OR LastModifiedDate IN :lastTimes)]) {
        if(((DateTime)taskRanges.get(record.WhoId).get('FirstDate'))==record.createddate) {
            leads.get(record.whoid).first_ldr_task_date__c=record.createddate;
            leads.get(record.whoid).first_ldr_task_user__c=record.createdby.name;
        }
        if(((DateTime)taskRanges.get(record.WhoId).get('LastDate'))==record.lastmodifieddate) {
            leads.get(record.whoid).last_ldr_task_date__c=record.lastmodifieddate;
            leads.get(record.whoid).last_ldr_task_user__c=record.createdby.name;
        }
    }
    update leads.values();
}

 

SubC4i-dev1SubC4i-dev1

Awesome!  Thanks again.  Really appreciate the summary and updating the code again.  Combined with my staring at the code last night to reverse engineer the syntax, I'm on my way.