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
Brooks Johnson 6Brooks Johnson 6 

Trigger to count Tasks with unique subject line.

Hello Friends. 

I am hoping someone can help me with this method. I have been working on it all afternoon with no luck.  My requirement is to get to a  count of tasks that are related to contacts and place a value on a custom object. The custom object relationship_owner__C is the parent in a  look up a relationship with the Contact object. 

When a relationship_owner__C is updated then look for all contacts owned by the relationship owner with tasks that begin with the phrase "Pardot List" Evaluate the text that comes after Pardot list to determine how many unique subject lines there are. 

If the relationship owner  Test Owner has 5 contacts and Each Contact has Two Tasks with the Subject Line Pardot List 1 and Pardot List 2. The relationship owner would be updated with a  total unique value of 2.  When I test in the UI I get a value of 1 no matter how many tasks I create. And my test class for a single email fails its assertions and says 0 emails.

Here is my method.  It is called from a trigger handler on before update. 
public static void uniqueRelationshipOwnerEmails(List<relationship_owner__c> roList){
        //count the unique emails  that have been sent by a relationship owner
        // add all contacts associated with relationship owner to map.         
        Map<id, Contact> contactMap = new Map<Id, Contact>([SELECT Id,
                                                            New_Relationship_Owner1__c
                                                            FROM Contact
                                                            WHERE New_Relationship_owner1__c IN : roList]);
        system.debug('Number of relationship owners in trigger = ' + roList.size());
        system.debug('Contacts found = ' + contactMap.size());
        //put tasks where whoId is in the contact map into a new map
        List<Task> taskList = [SELECT Id, WhoId,Subject
                               FROM Task 
                               WHERE WhoId IN :contactMap.keySet()
                               AND Subject LIKE '%Pardot List %'];
        system.debug('Tasks Found  and added to map = ' + taskList.size());
        
        //use set to dedupe the list
        Map<Id, Set<String>> subjectLineMap = new Map<Id, Set<String>>();
        
        for(task t : taskList){
            Id ownerId = contactMap.get(t.WhoId).New_Relationship_Owner1__c;            
            if(!subjectLineMap.containsKey(ownerId)){
                subjectLineMap.put(ownerId, new Set<String>());
                system.debug('Subect Line found ' + t.Subject);
               
                
            }

 
Best Answer chosen by Brooks Johnson 6
Steven NsubugaSteven Nsubuga
Here is my take 
public static void uniqueRelationshipOwnerEmails(List<relationship_owner__c> roList){
        //count the unique emails  that have been sent by a relationship owner
        // add all contacts associated with relationship owner to map.  

		Set<Id> relationshipOwnerIds = new Set<Id>();
		for(relationship_owner__c relationshipOwner : roList){
			relationshipOwnerIds.add(relationshipOwner.Id);
		}
        Map<id, Contact> contactMap = new Map<Id, Contact>([SELECT Id,
                                                            New_Relationship_Owner1__c
                                                            FROM Contact
                                                            WHERE New_Relationship_owner1__c IN :relationshipOwnerIds]);
															
        system.debug('Number of relationship owners in trigger = ' + roList.size());
        system.debug('Contacts found = ' + contactMap.size());
        //put tasks where whoId is in the contact map into a new map
        List<Task> taskList = [SELECT Id, WhoId,Subject
                               FROM Task 
                               WHERE WhoId IN :contactMap.keySet()
                               AND Subject LIKE '%Pardot List %'];
        system.debug('Tasks Found  and added to map = ' + taskList.size());
        
        //use set to dedupe the list
        Map<Id, Set<String>> subjectLineMap = new Map<Id, Set<String>>();
        
        for(task t : taskList){
            Id ownerId = contactMap.get(t.WhoId).New_Relationship_Owner1__c;            
            if(!subjectLineMap.containsKey(ownerId)){
                subjectLineMap.put(ownerId, new Set<String>());
                system.debug('Subect Line found ' + t.Subject);       
            }
			Set<String> subjects = subjectLineMap.get(ownerId);
			subjects.add(t.Subject);
			subjectLineMap.put(ownerId, subjects);
		}
	}

 

All Answers

Steven NsubugaSteven Nsubuga
Here is my take 
public static void uniqueRelationshipOwnerEmails(List<relationship_owner__c> roList){
        //count the unique emails  that have been sent by a relationship owner
        // add all contacts associated with relationship owner to map.  

		Set<Id> relationshipOwnerIds = new Set<Id>();
		for(relationship_owner__c relationshipOwner : roList){
			relationshipOwnerIds.add(relationshipOwner.Id);
		}
        Map<id, Contact> contactMap = new Map<Id, Contact>([SELECT Id,
                                                            New_Relationship_Owner1__c
                                                            FROM Contact
                                                            WHERE New_Relationship_owner1__c IN :relationshipOwnerIds]);
															
        system.debug('Number of relationship owners in trigger = ' + roList.size());
        system.debug('Contacts found = ' + contactMap.size());
        //put tasks where whoId is in the contact map into a new map
        List<Task> taskList = [SELECT Id, WhoId,Subject
                               FROM Task 
                               WHERE WhoId IN :contactMap.keySet()
                               AND Subject LIKE '%Pardot List %'];
        system.debug('Tasks Found  and added to map = ' + taskList.size());
        
        //use set to dedupe the list
        Map<Id, Set<String>> subjectLineMap = new Map<Id, Set<String>>();
        
        for(task t : taskList){
            Id ownerId = contactMap.get(t.WhoId).New_Relationship_Owner1__c;            
            if(!subjectLineMap.containsKey(ownerId)){
                subjectLineMap.put(ownerId, new Set<String>());
                system.debug('Subect Line found ' + t.Subject);       
            }
			Set<String> subjects = subjectLineMap.get(ownerId);
			subjects.add(t.Subject);
			subjectLineMap.put(ownerId, subjects);
		}
	}

 
This was selected as the best answer
Brooks Johnson 6Brooks Johnson 6
Hi, Steven that was a big help. I am still struggling with how to get the number of values and assign it to the relationship owner.  Calling .size gives the number of key-value pairs. I don't seem to be able to get an integer value by calling.values()I appreciate the help. I am just starting on the journey from Admin to Dev. 
for(relationship_owner__c r : roList){
            if(subjectLineMap.containsKey(r.Id)){
           r.Unique_Emails_Sent__c = subjectLineMap.size();
Steven NsubugaSteven Nsubuga
Hi Brooks, see the for loop at the end of the class
public static void uniqueRelationshipOwnerEmails(List<relationship_owner__c> roList){
        //count the unique emails  that have been sent by a relationship owner
        // add all contacts associated with relationship owner to map.  

		Set<Id> relationshipOwnerIds = new Set<Id>();
		for(relationship_owner__c relationshipOwner : roList){
			relationshipOwnerIds.add(relationshipOwner.Id);
		}
        Map<id, Contact> contactMap = new Map<Id, Contact>([SELECT Id,
                                                            New_Relationship_Owner1__c
                                                            FROM Contact
                                                            WHERE New_Relationship_owner1__c IN :relationshipOwnerIds]);
															
        system.debug('Number of relationship owners in trigger = ' + roList.size());
        system.debug('Contacts found = ' + contactMap.size());
        //put tasks where whoId is in the contact map into a new map
        List<Task> taskList = [SELECT Id, WhoId,Subject
                               FROM Task 
                               WHERE WhoId IN :contactMap.keySet()
                               AND Subject LIKE '%Pardot List %'];
        system.debug('Tasks Found  and added to map = ' + taskList.size());
        
        //use set to dedupe the list
        Map<Id, Set<String>> subjectLineMap = new Map<Id, Set<String>>();
        
        for(task t : taskList){
            Id ownerId = contactMap.get(t.WhoId).New_Relationship_Owner1__c;            
            if(!subjectLineMap.containsKey(ownerId)){
                subjectLineMap.put(ownerId, new Set<String>());
                system.debug('Subect Line found ' + t.Subject);       
            }
			Set<String> subjects = subjectLineMap.get(ownerId);
			subjects.add(t.Subject);
			subjectLineMap.put(ownerId, subjects);
		}
		
		for(relationship_owner__c relationshipOwner : roList){
			relationshipOwner.Unique_Emails_Sent__c = subjectLineMap.get(relationshipOwner.Id).size();
		}
		
	}

 
Brooks Johnson 6Brooks Johnson 6
Hi Steven, Thank you so much. This is working great in the UI. Now for the test classes. 

I wanted to ask you a question about maps. I seem to still be struggling with using them. In the case of this map. Is the value being determined by the number of times the key (owner Id) appears? Or the number of values in the set matched to the key? Because we are calling .size() on the Id it makes me think we are counting the number of times the ID appears. But I feel like that is incorrect. 
Steven NsubugaSteven Nsubuga
Hi Brooks,
the Map has the ID of the New_Relationship_Owner1__c as its key, and has a set of strings Set for each ID.
What we are doing in relationshipOwner.Unique_Emails_Sent__c = subjectLineMap.get(relationshipOwner.Id).size();
s combining 2 separate operations.

Operation 1 would be to retrieve the Set for each ID in the map
Set strings = subjectLineMap.get(relationshipOwner.Id);

Operation 2 s to set the size of this retrieved set to the field on the New_Relationship_Owner1__c object
relationshipOwner.Unique_Emails_Sent__c = strings.size();

What I did was combine those 2 operations into 1 line.
relationshipOwner.Unique_Emails_Sent__c = subjectLineMap.get(relationshipOwner.Id).size();
It is confusing to see when one has just started writing code but eventually you get the hang of it, it is just a matter of time.