Wednesday 11 September 2013

Email Case Team Members on Case Comment

14:40

This is going to be a short blog for a requirement I came across, But didn't find any blogs out there addressing this. So lets get right to it, I need to notify all the case team members when a case comment is logged, be it contact, users etc.


Here's what we'll need


  • Trigger on Case Comment 
  • A Helper Class (To keep the trigger clean)
  • Test Class ( Don't forget to test your code)
To make things look clean we'll keep most of the code to the helper class,


Trigger : 

You could put in additional filters, checks etc in the trigger to suit your needs
trigger CommentEmail on CaseComment (after insert,after update) {
   CaseCommentEmailHelper Obj = new CaseCommentEmailHelper();
   Obj.SendCaseCommentEmail(Trigger.new);
   }

Helper Class:

This Class helps to send the email out to all the case team members when ever a Case Comment is created/Edited Trigger Associated: CommentEmail Scenario: 1)Case has contacts and/or Users as Case Team Members 2)Send Email only if Case Comment is Public Sorry for the long Block of code, But this is a tested working piece of code to cover possible scenarios,There are a couple of Helper Methods at the bottom
public class CaseCommentEmailHelper {
    
    public  void SendCaseCommentEmail(List<CaseComment> newTrigger)
    {
     system.debug('Entered Case Comment');
        Set<id> parentCaseIds = new Set<id>();
        Set<id> CommentedUsers = new Set<id>(); // To set the reply-to Address
        set<id> ContactMembers = new Set<id>();
        Set<id> UserMembers = new set<id>();
       
        List<CaseComment> isValidComment = new List<CaseComment>();
        
        for(CaseComment CC :newTrigger)
        {
         if(CC.IsPublished==true)//Only if comment is public, send out emails 
         {
          isValidComment.add(CC);
          parentCaseIds.add(CC.ParentId);
          CommentedUsers.add(CC.LastModifiedById);
         }
        }
        
        if(isValidComment.size()>0)
        {
         Map<id,Case> CaseObjs = new Map<id,Case>([select Id,Description,
                   Owner.Email,CaseNumber,Subject 
                   from Case where id in:parentCaseIds]);// Query all case related Data
         Map<id,List<id>> CaseToUserCaseTeamMembersMap = new Map<id,List<id>>();// Query Case Team Members
         Map<id,List<id>> CaseToContactCaseTeamMembersMap = new Map<id,List<id>>();
         
  // We Maintain 2 maps, Case => User Case Members and 
         // Case => Contact Case Members Map to reduce further loops ahead
          
         for(CaseTeamMember CTMember: [SELECT Id,MemberId,ParentId FROM 
                                              CaseTeamMember WHERE ParentId in:parentCaseIds])
         {
         
          if(!isContactID(CTMember.MemberID))
          {
           if(CaseToUserCaseTeamMembersMap.get(CTMember.ParentID)!=null)
            CaseToUserCaseTeamMembersMap.get(CTMember.ParentID).add(CTMember.MemberID); //Add to the list of User Members
           else
            CaseToUserCaseTeamMembersMap.put(CTMember.ParentID,new id[]{CTMember.MemberID}); 
                          //Create a new List for the case and add the memeber to it
            
            UserMembers.add(CTMember.MemberID);
          }
          else if(isContactID(CTMember.MemberID))
          {
           if(CaseToContactCaseTeamMembersMap.get(CTMember.ParentID)!=null)
            CaseToContactCaseTeamMembersMap.get(CTMember.ParentID).add(CTMember.MemberID); 
                           //Add to the list of Contact Members
           else
            CaseToContactCaseTeamMembersMap.put(CTMember.ParentID,new id[]{CTMember.MemberID}); 
                       //Create a new List for the case and add the memeber to it
            
            ContactMembers.add(CTMember.MemberID);
          }
         }
         
         /* Now we have the required Data to map and send emails out, 
            There are 2 scenarios, The Case team can consist of Users and Contacts, 
            We send out Emails to Contacts only if their Email is not Blank 
         */
            
         Map<id,User> UserObjs;
         Map<id,Contact> ContactObjs;
         
         if((CommentedUsers.size() > 0) || (!CaseToUserCaseTeamMembersMap.isEmpty()))
          UserObjs = new Map<id,User>([select id,Email from 
                                                   User where ID in: CommentedUsers OR ID in:UserMembers]);
                                                   //Query all User Required Data 
          
         if(!CaseToContactCaseTeamMembersMap.isEmpty()) 
      ContactObjs = new Map<id,Contact>([select id,Email from Contact 
                                                        where ID in: ContactMembers AND Email!=NULL AND Email!='']);
          
          for(CaseComment CC :newTrigger)
          {
            List<String> toAddresses = new List<String>();
          
              // Add Users in case Team to email list    
              if((!CaseToUserCaseTeamMembersMap.isEmpty())&&CaseToUserCaseTeamMembersMap.get(CC.ParentId).size()>0)
             toAddresses.addall(getUserEmailList(UserObjs,CaseToUserCaseTeamMembersMap.get(CC.ParentId)));
             //Add Contacts in Case Team to Email List
             if((!CaseToContactCaseTeamMembersMap.isEmpty())&&
                                     CaseToContactCaseTeamMembersMap.get(CC.ParentId).size()>0)
             toAddresses.addall(getContactEmailList(ContactObjs,CaseToContactCaseTeamMembersMap.get(CC.ParentId)));
             
            if(toAddresses.size()>0) 
            SendCommentEmail(toAddresses,UserObjs.get(CC.LastModifiedById).Email,CaseObjs.get(CC.parentId),CC.CommentBody);
          }   
        }   
      
    }
    
    //=============== Private Methods ===================
     private  List<String> getUserEmailList(Map<id,User> UserObjs,List<ID>UserIds)
       {
        List<String> UserEmailList = new List<String>();
        if(UserIds!=null && UserObjs!=null)
        {
         for(Id userId :UserIDs)
          {
           if(UserObjs.get(userId)!=null)
              UserEmailList.add(UserObjs.get(userId).Email);
          }
        }
        return UserEmailList;
       }
       
     private  List<String> getContactEmailList(Map<id,Contact> ContactObjs,List<ID>ContactIds)
       {
        List<String> ContactEmailList = new List<String>();
        if(ContactIds!=null && ContactObjs!=null)
        {
         for(Id ContactId :ContactIds)
          {
           if(ContactObjs.get(ContactId)!=null)
              ContactEmailList.add(ContactObjs.get(ContactId).Email);
          }
        }
        return ContactEmailList;
       }
       
       private void SendCommentEmail(List<String> toAddresses,string replyTo,Case CurrentCase,string CommentBody)
  {
   
      String CaseLink =System.URL.getSalesforceBaseUrl().toExternalForm().remove('-api' )+'/'+CurrentCase.Id;
      string TXTEmailBody =(String.isNotBlank(CurrentCase.Description)?'Description: '+CurrentCase.Description:'')
           +'\n\nCase Comment: '+CommentBody
           +'\n\n Case Link: '+CaseLink
           +'\n\n Thank You!';
           
      string Subject ='Case #'+CurrentCase.CaseNumber+': '
          + (String.isNotBlank(CurrentCase.Subject)?CurrentCase.Subject:'')
          +' has been updated.';
      
      // Send Email
      Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
      mail.setToAddresses(toAddresses);
      mail.setReplyTo(replyTo);
      mail.setSubject(Subject);
      mail.setUseSignature(false);
      mail.setPlainTextBody(TXTEmailBody);
      Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });   
     
     }
    
   private boolean isContactID(id IdInQuestion)
 {
  return (IdInQuestion.getSObjectType()== Contact.sObjectType);
 }
}

Well that was a lot of code to go through, But hopefully it helped you. Remember, The test class is still pending Check it out here.. Let me know if any clarifications are required. Happy Coding !