Uncategorized

The next generation…

Friday, November 21st, 2008

will see the world differently.

smart president

Visual Force Email Templates 2

Friday, November 14th, 2008

Using custom components makes lots of stuff possible. Here’s an example of a year-end giving thank you email:

screenshot

This shows all gifts for 2008 and attaches a PDF of the giving history as well. Note that this is done just by connecting to the Contact, so this would work in the Salesforce.com mass mail interface.

Update: You cannot use vf templates in mass email or in the apex outboundemail method in Winter ‘09. Maybe next release…

Also note that it’s an ugly HTML email just because I’m not a designer. You can make this as professional as you’re willing to make it.

Here’s the relevant code:

The VisualForce Email Template

<messaging:emailTemplate subject="Thank you for your Support!" recipientType="Contact" >
    <messaging:htmlEmailBody >
        <html>
        <body>
            <p>Hello {!recipient.Household_Greeting__c}--</p>
            <p>Thank you so much for you giving this year. Every gift helps us make a difference in our envrionment...</p>
            <c:thisYearGivingTable ContactId="{!recipient.Id}"/>
            <br/><br/>
            We look forward to seeing you in 2009!
            <br/><br/>
            Best,
            Steve

            </body>
        </html>
    </messaging:htmlEmailBody>
    <messaging:attachment renderas="pdf" filename="{!recipient.Household_Greeting__c}_2008_Giving.pdf">
<html>
<body>
<h3>2008 Giving History for {!recipient.Household_Greeting__c}</h3>
<c:thisYearGivingTable ContactId="{!recipient.Id}"/>

</body>
</html>
</messaging:attachment>
</messaging:emailTemplate>

The VisualForce Component that is included in the Email Template:

<apex:component controller="thisYearGivingTableController" access="global">
	<apex:attribute name="ContactId" description="This is the Contact Id." type="Id" assignTo="{!thisContactId}"/>
	<table border="1">
		<tr>
		    <td><apex:outputText value="Date"/></td>
		    <td><apex:outputText value="Amount"/></td>
		    <td><apex:outputText value="Check Number"/></td>
		    <td><apex:outputText value="Check Date"/></td>
		</tr>
 	<apex:repeat value="{!thisYearOpps}" var="opp" id="theRepeat">
		<tr>
		    <td><apex:outputField value="{!opp.CloseDate}"/></td>
		    <td><apex:outputField value="{!opp.Amount}"/></td>
		    <td><apex:outputField value="{!opp.Check_Number__c}"/></td>
		    <td><apex:outputField value="{!opp.Check_Date__c}"/></td>

		</tr>
	</apex:repeat>
	</table>
</apex:component>

The Apex Controller that powers the logic for the VisualForce Component:

public class thisYearGivingTableController {
	//capture the contact id
	public Id thisContactId {get;set;}
	//a list to hold this year's gifts
	public List<Opportunity> thisYearOpps = new List<Opportunity>();
	//get the gifts into the list
	public List<Opportunity> getThisYearOpps() {
		//criteria for opps
		thisYearOpps = [SELECT Id, Amount,CloseDate, Check_Date__c, Check_Number__c FROM Opportunity
			WHERE IsWon=true AND Year__c=:String.valueOf(system.Today().Year()) AND Id IN
			(SELECT OpportunityId FROM OpportunityContactRole WHERE ContactId = :thisContactId AND Role='Individual Donor')
			ORDER BY CloseDate];
		return thisYearOpps;
	}
}

Kudos to Andrew and the team for making the email template functionality so robust! This is killer stuff!

VisualForce Email Templates

Friday, November 14th, 2008

When I saw that Winter ‘09 was going to include VisualForce email templates, I got really excited. I thought about all the cool things I could do with pages running custom controllers and getting whatever data I wanted.

And then I saw that VF email templates weren’t going to be able to use custom controllers and I wrote them off.

Well, I’ve dug back into them and turns out they are going to be amazingly useful. And when we get custom controllers on them, they will be seriously butt-kicking.

Here’s a VF email template:

<messaging:emailTemplate subject="Thank you for your Support!" recipientType="Contact" >
    <messaging:htmlEmailBody >
        <html>
        <body>
            <p>Hello {!recipient.Household_Greeting__c}--</p>
            <p>Thank you so much for you giving this year. Every gift helps us make a difference in our envrionment...</p>
            <apex:outputPanel rendered="{!recipient.Total_Gifts_YTD__c>0}">
                <apex:outputText rendered="{!recipient.Total_Gifts_YTD__c>0}">
                    <table>
                        <tr>
                            <td>Gift Date</td>
                            <td>Check Number</td>
                            <td>Check Date</td>
                            <td>Amount</td>
                        </tr>
                </apex:outputText>
                <apex:repeat value="{!recipient.OpportunityContactRoles}" var="opps" id="theRepeat">
                    <apex:outputText rendered="{!opps.Role=='Individual Donor'&&opps.Opportunity.IsWon&&opps.Opportunity.Year__c=='2008'}">
                        <tr>
                    </apex:outputText>
                    <apex:outputText rendered="{!opps.Role=='Individual Donor'&&opps.Opportunity.IsWon&&opps.Opportunity.Year__c=='2008'}">
                        <td><apex:outputField value="{!opps.Opportunity.CloseDate}"/></td>
                        <td><apex:outputField value="{!opps.Opportunity.Check_Number__c}"/></td>
                        <td><apex:outputField value="{!opps.Opportunity.Check_Date__c}"/></td>
                        <td><apex:outputField value="{!opps.Opportunity.Amount}"/></td>
                    </apex:outputText>
                    <apex:outputText rendered="{!opps.Role=='Individual Donor'&&opps.Opportunity.IsWon&&opps.Opportunity.Year__c=='2008'}">
                        </tr>
                    </apex:outputText>

                </apex:repeat>
                <apex:outputText rendered="{!recipient.Total_Gifts_YTD__c>0}">
                    </table>
                </apex:outputText>

            </apex:outputPanel>
            </br></br>
            We look forward to seeing you in 2009!

            Best,
            Steve

            </body>
        </html>
    </messaging:htmlEmailBody>
</messaging:emailTemplate>

In line 1 I connect this template to the Contact record as RecipientType. Then when I send to a Contact, I can merge fields. So in line 5 I’m pulling a custom field on Contact called Household_Greeting__c. So far so good.

On line 7 I start building an HTML table, and I only want to show it if this Contact has given money this year, so I render only if their Total_Gifts_YTD__c>0. Slick. No custom controller, but I can still put some logic in there.

On line 17 I create a repeat that will loop through all OpportunityContactRoles this Contact has. Whoa! I suddenly have access to all their donations!

On 18 I want to create a table row, but only when the opp we’re dealing with is won, was in this year, and this contact was the individual donor role on it. We have to repeat the same rendering logic on each field as well.

I’m looping through OpportunityContactRoles, but I want Opportunity information. That’s really easy. On line 22 I get {!opps.Opportunity.CloseDate}–the close date off the Opportunity on this contact role. Simple!

So with no controller, I can get any related list off the Contact and iterate through it. And I can traverse across multiple relationships. Only getting the records I care about requires some rendering hacks, but it works. Also, I don’t think I can sort the items at all.

I’m impressed with what VisualForce email templates can do with no controller. Check them out, they’re easy to use! And when they give us the ability to use Custom Controllers, we’ll be able to do crazy things.

Update: In the comments Andrew sets me straight on a key feature–you can put custom VisualForce components in VisualForce email templates. Wow. We can now do just about anything we want. Seriously, there are very few limitations to what can be done now. Thanks Andrew for pointing out that killer feature!

Real-time Dreamforce updates

Sunday, November 2nd, 2008

Come back to this post over the next 4 days because it’s a real-time feed of everything Dreamforce. Sonny Cloward set it up over at FriendFeed. Thanks Sonny!

Obamakin

Friday, October 31st, 2008

School Hallway

Friday, October 31st, 2008

salmon bay hallway

Salmon Bay school in Seattle.

Seattle Nonprofit Salesforce User Group

Monday, October 27th, 2008

The folks over at NPower Seattle have created a Salesforce User Group for nonprofits. Go to the first meeting on November 19th. I’ll be there, and you should be, too. Come to share, learn, and network!

Wednesday, November 19, 8:00am - 9:00am


View Larger Map

Serious logistical expertise

Sunday, October 19th, 2008

I’m about to head to Dreamforce, Salesforce’s annual user conference. Last year it was 5,000 people. This year could be as many as 10,000. It’s a big conference with tons of logistics.

But check out what the Obama campaign pulled off yesterday. They had an event in St. Louis with at least 100,000 people. And then followed it up with a 75,000 person rally in Kansas City.

These rallies require amazing logistics around parking, security, crowd control, secret service for Obama, PA, lighting, media, the list goes on and on. Check out this great post from Al Giordano about what it takes to do a 20,000 person rally.

And then realize that the Obama campaign did this twice in one day. Whatever you think about Obama’s policies, the man has pulled together an army for this campaign. On every level he’s out-organizing John McCain. That’s not a subjective feeling–it’s a clear fact. No doubt about it. Very impressive.