Saturday, April 12, 2014

Building an email recipient list from pre-selected users

This is the first post in the series of 5 post that revolve around sending an Opportunity Report as an email attachment to members of the Opportunity Team on a weekly basis.  


Problem Definition


Sales Managers need to send an opportunity report every week to members of the opportunity team. A custom button on the opportunity page layout is used for this. Selected email addresses should be remembered so that they can be pre-selected the following week.

Solution


Build a Visualforce table which will enable selecting and deselecting of opportunity team members from a list. Use a custom field on opportunity to hold a String of comma separated values. These will be parsed in Apex and used to pre-select entries in the table when it is displayed.

Your end result could look like this







Apex


You need 4 things in this order;
- a wrapper class which holds your table entries
- a property to bind your wrapper class list to the page
- a list of opportunity team members, thier emails, names etc.
- a list of previously selected recipients

Wrapper Class


A wrapper class is a class that "wraps" or "encapsulates" the functionality of another or component with the intention of adding a layer of indirection and abstraction. 

 public class TeamMembers{  
      public OpportunityTeamMember teamMember { get; set; }  
      public Boolean sendEmail { get; set;}  
      public TeamMembers(OpportunityTeamMember member, Boolean selected){  
           teamMember = member;  
           sendEmail = selected;  
      }  
 }  

Our Wrapper class is very simple and straight forward. It wraps the opportunity team member and adds a binary value which determines if the team member is selected to receive the email or not.

Property


 public List<TeamMembers> OpportunityTeam { get; set; }  

Opportunity Team


 List<OpportunityTeamMember> members = new List<OpportunityTeamMember>([SELECT id, User.Email, User.Name, TeamMemberRole, OpportunityAccessLevel FROM OpportunityTeamMember WHERE OpportunityId =: this.opportunity.id]);  

this.opportunity is opportunity whose opportunity report we want to send out. Could be set in the Constructor using the Standard Opportunity Controller as follows;

 this.opportunity = (Opportunity)stdController.getRecord();  

Previously Selected Recipients


 List<String> emailAddress = new List<String>(this.opportunity.Email_Recipients__c.split(','));  

This will give you a list of all team members who received the mail the previous week

Since you will not need to use "Email_Recipients__c" on the page, you need to tell the Standard Controller to fetch it along with the other fields by adding the following to the constructor;

 stdController.addFields(new List<String>{'Email_Recipients__c'});  

Apex Summary


To summarize, here is what an Apex function which merges all the above parts together could look like

 public void buildListOfEmailRecipients(){  
      this.OpportunityTeam = new List<TeamMembers>();  
      List<String> emailAddress = new List<String>();  
      if(this.opportunity.Email_Recipients__c != null){  
           emailAddress = new List<String>(this.opportunity.Email_Recipients__c.split(','));  
      }  
      Map<String, String> teamMemberMap = new Map<String, String>();  
      for(String mailadd : emailAddress){  
           teamMemberMap.put(mailadd, mailadd);  
      }  
      List<OpportunityTeamMember> members = new List<OpportunityTeamMember>([SELECT id, User.Email, User.Name, TeamMemberRole, OpportunityAccessLevel FROM OpportunityTeamMember WHERE OpportunityId =: this.opportunity.id]);  
      for(OpportunityTeamMember otm : members){  
           if(teamMemberMap.containsKey(otm.User.Email)){  
                this.OpportunityTeam.add(new TeamMembers(otm, true));  
           } else {  
                this.OpportunityTeam.add(new TeamMembers(otm, false));  
           }  
      }  
 }  

Visualforce


Most of the work has been done by the Controller, so displaying the table on Visualforce is a peaice of cake. Begin be sending the Standing Controller and Extension. Could look something like this;

 <apex:page StandardController="Opportunity" extensions="OpportunityEmailOnClosedCtr" sidebar="false" title="Send Email to \'{!Opportunity.Name} \' opportuinty team">  

Then Build the actual table which will could look like this;

 <apex:pageBlockSection title="Select Recipients from Opportunity Team and specify additional Recipients">  
      <apex:pageBlockSectionItem >  
           <apex:outputLabel value="Select Recipients from Opportunity Team" />  
      </apex:pageBlockSectionItem>  
      <apex:pageBlockSectionItem >  
           <apex:outputPanel ></apex:outputPanel>  
      </apex:pageBlockSectionItem>  
      <apex:PageBlockSectionItem rendered="{!OpportunityTeam.size > 0}">  
           <apex:pageBlockTable value="{!OpportunityTeam}" var="record" styleClass="sameWidth">  
                <apex:column headerValue="Slected">  
                     <apex:inputCheckbox value="{!record['sendEmail']}" />  
                </apex:column>  
                <apex:column headerValue="User Name">  
                     <apex:outputText value="{!record['teamMember'].User.Name}" />  
                </apex:column>  
                <apex:column headerValue="Email">  
                     <apex:outputText value="{!record['teamMember'].User.Email}" />  
                </apex:column>  
                <apex:column headerValue="Team Member Role">  
                     <apex:outputText value="{!record['teamMember'].TeamMemberRole}" />  
                </apex:column>  
           </apex:pageBlockTable>  
      </apex:PageBlockSectionItem>  
 </apex:pageBlockSection>  

The key to letting users select and deselect recipients is the inputCheckbox Component which uses the binary "sendMail" property of the wrapper class to keep track of which recipients are currently selected.


Finally in the Controller Extension, build a list or email recipients like this;
 List<String> emailAddresses = new List<String>();  
 for(TeamMembers tm : this.OpportunityTeam){  
      if(tm.sendEmail) {  
           emailAddresses.add(tm.teamMember.User.Email);  
      }  
 }  

Conlcusion


I hope this post was helpful to you. Watch out for related post which will handle topics such as dynamically adding and removing email recipients, sending emails with Visualforce PDF attachments, email validation and proper error handling etc.
Finally, please challenge the contents of this post, add value to it in the comments if you can, so that it can help others viewing it in the future. God bless

1 comment:

  1. JMT casino and sportsbook opening in Maryland
    The state is set to 광명 출장안마 begin offering live betting and sports betting on 경주 출장안마 Monday, 세종특별자치 출장안마 Sept. 18, 대구광역 출장마사지 according to 안성 출장안마 Mohegan Gaming. It's not yet clear when the

    ReplyDelete