<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>gokubi.com &#187; CRM</title>
	<atom:link href="http://gokubi.com/archives/category/technology/crm/feed" rel="self" type="application/rss+xml" />
	<link>http://gokubi.com</link>
	<description></description>
	<lastBuildDate>Fri, 16 Sep 2011 14:54:38 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Advocacy in the Cloud slides and recording</title>
		<link>http://gokubi.com/archives/advocacy-in-the-cloud</link>
		<comments>http://gokubi.com/archives/advocacy-in-the-cloud#comments</comments>
		<pubDate>Fri, 16 Sep 2011 14:54:38 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[Change]]></category>
		<category><![CDATA[CRM]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://gokubi.com/?p=1347</guid>
		<description><![CDATA[I recently had the pleasure of facilitating a Dreamforce session where two amazing people talked about how their organizations have gone all-in with engagement. The DC Project and Idaho Conservation League are each betting their futures on engagement, and in very different ways. Sara Arkle talked about how Idaho Conservation League is turning the organizational [...]]]></description>
			<content:encoded><![CDATA[<p>I recently had the pleasure of facilitating a Dreamforce session where two amazing people talked about how their organizations have gone all-in with engagement. <a href="http://weatherizedc.org">The DC Project</a> and <a href="http://idahoconservation.org">Idaho Conservation League</a> are each betting their futures on engagement, and in very different ways. Sara Arkle talked about how Idaho Conservation League is turning the organizational ship to find a new generation of supporters. Matthew Dunn told the compelling story of how the DC Project was birthed with technology and engagement at it’s heart. Very different stories, well told and I think helpful for folks looking to engage supporters more deeply than they are today. Below is the recorded presentation, as well as the slide deck we presented.</p>
<p><iframe width="600" height="450" src="http://www.youtube.com/embed/N-1m0BVtciY?fs=1&#038;wmode=transparent" frameborder="0" allowfullscreen></iframe></p>
<div style="width:425px" id="__ss_9284445"><strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/salesforcefoundation/advocacy-in-the-cloud" title="Advocacy in the Cloud">Advocacy in the Cloud</a></strong><object id="__sse9284445" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=df11017andersen-110916092009-phpapp02&#038;stripped_title=advocacy-in-the-cloud&#038;userName=salesforcefoundation" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed name="__sse9284445" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=df11017andersen-110916092009-phpapp02&#038;stripped_title=advocacy-in-the-cloud&#038;userName=salesforcefoundation" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object></div>
]]></content:encoded>
			<wfw:commentRss>http://gokubi.com/archives/advocacy-in-the-cloud/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Chrome Extension: Salesforce.com Id Clipper</title>
		<link>http://gokubi.com/archives/chrome-extension-salesforce-com-id-clipper</link>
		<comments>http://gokubi.com/archives/chrome-extension-salesforce-com-id-clipper#comments</comments>
		<pubDate>Mon, 06 Jun 2011 13:51:25 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[CRM]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://gokubi.com/?p=1320</guid>
		<description><![CDATA[I had a great idea for a Chrome Extension that was pretty complicated, so I decided to come up with a simpler project to learn the ropes. This weekend I built the Salesforce.com Id Clipper, a Chrome Extension that helps you get Salesforce.com Ids from records more easily than copying. It&#8217;s a small problem I&#8217;m [...]]]></description>
			<content:encoded><![CDATA[<p>I had a great idea for a Chrome Extension that was pretty complicated, so I decided to come up with a simpler project to learn the ropes. This weekend I built <a href="https://chrome.google.com/webstore/detail/hfiffenhnefppjhloglpebefjlbhoeai">the Salesforce.com Id Clipper</a>, a Chrome Extension that helps you get Salesforce.com Ids from records more easily than copying. It&#8217;s a small problem I&#8217;m attempting to solve, but I think this extension does it pretty well. Here&#8217;s a rundown:</p>
<p><iframe width="600" height="363" src="http://www.youtube.com/embed/gPd_duxHXnA?fs=1&#038;wmode=transparent" frameborder="0" allowfullscreen></iframe></p>
<p><a href="https://chrome.google.com/webstore/detail/hfiffenhnefppjhloglpebefjlbhoeai">Go get it</a> in the Chrome Web Store and please rate it if you try it out! <a href="https://github.com/gokubi/Salesforce-Id-Clipper-Chrome-Extension">The source is also out on Github</a> free to use.</p>
]]></content:encoded>
			<wfw:commentRss>http://gokubi.com/archives/chrome-extension-salesforce-com-id-clipper/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Nonprofit Starter Pack and Money</title>
		<link>http://gokubi.com/archives/nonprofit-starter-pack-and-money</link>
		<comments>http://gokubi.com/archives/nonprofit-starter-pack-and-money#comments</comments>
		<pubDate>Mon, 09 May 2011 16:43:47 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[CRM]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://gokubi.com/?p=1301</guid>
		<description><![CDATA[At a recent gathering of nonprofit-focused Salesforce developers, we got into a deep discussion about how to best track money in Salesforce. Everyone agreed that the Opportunity object was key, but there were differing opinions about what else needed to be done and how. I realized that this group of people, who had years and [...]]]></description>
			<content:encoded><![CDATA[<p>At a recent gathering of nonprofit-focused Salesforce developers, we got into a deep discussion about how to best track money in Salesforce. Everyone agreed that the Opportunity object was key, but there were differing opinions about what else needed to be done and how. I realized that this group of people, who had years and years of consulting experience with nonprofits, did not have a shared understanding of the best practices of how nonprofits should track money. I include myself in this group&#8211;I’ve had nonprofit accounting explained to me countless times, and it’s been a little different each time.</p>
<p>This article is meant to lay out what I’ve learned about this subject from all the great finance people I’ve worked with over my career. But more importantly it will examine how it all relates to Salesforce.com and some changes <a href="http://twitter.com/#!/kevinbromer">Kevin Bromer</a> is making to the <a href="http://www.salesforcefoundation.org/products/nonprofit_starter_pack">Nonprofit Starter Pack</a>.</p>
<p>First I’ll talk a bit about how the Nonprofit Starter Pack works today. Next I’ll get into the accounting of it all, with the full disclaimer that I am not an accountant. And then I’ll get into the new way we’re going to do things, and talk about why that’s better, all with the goal of us better understanding the business processes we support.</p>
<p>Salesforce.com isn’t an accounting system, but thousands of organizations use it to track money. Many organizations directly integrate with their accounting systems. Modeling money well in Salesforce.com makes that kind of integration easier. And even if you don’t integrate, the changes we’re making provide much better support for key nonprofit work like pledged gifts, and gifts with multiple payments. </p>
<p> I got a lot of help in writing this article from <a href="http://www.linkedin.com/pub/debbi-lewang/27/382/397">Debbi Lewang</a>, <a href="http://www.linkedin.com/in/shalineethakur">Shalinee Thakur</a>, <a href="http://nickhbailey.com/">Nick Bailey</a>, <a href="http://samdorman.com/">Sam Dorman</a> and of course Kevin Bromer&#8211;any insights should be attributed to them, any errors in logic or accounting are most definitely mine. </p>
<h2>How the nonprofit starter pack works today</h2>
<p>The Nonprofit Starter Pack is used by thousands of organizations on Salesforce.com to manage their organizations and their missions. These organizations are incredibly diverse, engaging in everything from class-room education to lobbying congress to providing health care to the homeless. But no matter what they do, they must track their organizational revenue stream, and many do in the form of gifts, grants, ticket sales, etc. </p>
<p><img src="http://gokubi.com/wp-content/uploads/2011/05/opp_payment.png" alt="" title="opp_payment" width="109" height="170" class="alignleft size-full wp-image-1305" />Salesforce.com has a database object called Opportunity that represents revenue and potential future revenue. It was created by the company to handle sales deals when Salesforce.com was limited to Sales and Marketing. Now that the platform is so much more flexible, the Opportunity object serves well as any kind of revenue&#8211;gifts, grants, memberships, ticket sales, etc.</p>
<p>The Nonprofit Starter Pack uses Opportunity to track revenue, and it works pretty well. We also have a Recurring Donations package that can be used to track gifts that are paid with more than one payment. It has a simple object and wizard for creating a schedule of Opportunities spaced out at intervals you select. It is a simple way to create multiple Opportunities that are related.</p>
<p>There are some limitations with the way the Nonprofit Starter Pack supports money today. The main problems have to do with a lack of support for cash in addition to revenue. In the next section I’ll talk about the accounting realities that we are planning to support.</p>
<h2>Revenue and Cash: Nonprofit accounting</h2>
<p>Revenue tracking and forecasting is critical to all nonprofits. Annual revenue must be reported to the IRS, and any business that doesn’t know its revenue picture can’t effectively plan for the future. This is easily done by reporting on Opportunities, and most nonprofits using Salesforce.com have already figured that out.</p>
<p>Nonprofit accounting (and accounting in general) is more complex than simply recording revenue, though. We need to support cash tracking in addition to revenue. This is because nonprofits can report revenue without receiving any money. When that happens from a donor or a grant maker, we often call it a pledge. The donor commits to giving to the organization, and may identify a payment schedule at that time. Let’s look at an example case to get into the specifics.</p>
<p>The nonprofit Friends of Tiny Creek (FOTC) wins a $1 million grant from a foundation. At the time of the award, they are promised a check for $250,000 and are told to expect 3 additional payments of $250,000 over the next 3 years. How should this be recorded on the financial statements?</p>
<p>FOTC records $1 million in revenue from the foundation. This is revenue in the fiscal year in which the grant was received. Because the cash isn’t received at the time the revenue is recorded, it can’t be spent yet. While the funder can put other restrictions on the gift, we will assume that this one hasn’t, and the money will be available when the cash payments are received. </p>
<p>So this $1 million commitment is recorded as a credit (increase) to revenue on the income statement and a debit to assets on the balance sheet.</p>
<p>One week later the $250,000 check comes in as promised. $250,000 is now cash that can be spent. On the balance sheet, cash is debited by $250,000 and assets receivable is credited by the same amount. The effect of this seemingly backwards transaction (there is a reason I’m not an accountant) is that $250,000 of the grant funds are now available for use and $750,000 is still to be received. [<a href="#1">1</a>]</p>
<p>The initial pledge and the resulting cash are related, but come in at very different times. And in this case you can see how the date the revenue is recorded is very different from when FOTC can actually spend the money to support it’s mission efforts. If FOTC isn’t paying attention to it’s cash picture, they’re going to have a hard time planning and delivering.</p>
<p>As the yearly payments come in, they are recorded and revenue is released accordingly. When all payments are made, the receivable goes to zero and the funds are available.</p>
<p>In this case, though, the foundation in question rescinded the last payment of $250,000. In this case, FOTC must record that amount as a write off against the receivable. That balances the sheet, and the change in revenue can be reported in their annual numbers.</p>
<h3>The case of monthly giving</h3>
<p>On the face of it monthly giving looks a lot like a pledge of multiple payments similar to our grant example above. A monthly giver commits to $20/month and then makes payments on a schedule. However, the monthly giver’s commitment isn’t an official pledge unless they tell you the end point of their giving. In many cases the monthly gift is started with no set end date. If you don’t know the end date, you don’t know the total revenue, so you can’t record it as pledged revenue on your income statement.</p>
<p>Because of this, each monthly gift should be considered a separate revenue entry, with it’s own matching cash entry when it is paid.</p>
<h2>Better modeling cash in the Nonprofit Starter Pack</h2>
<p>As stated earlier, the Opportunity object is great for tracking revenue. But what about cash related to that revenue? There isn’t a good way to model cash in the Nonprofit Starter Pack, but lots of Salesforce.com users have already solved this for themselves&#8211;that’s the beauty of a flexible platform. We’ve looked at those solutions can come up with something that we think works pretty well. When we release this functionality, you&#8217;ll be able to turn it on, or continue to use the Nonprofit Starter Pack as you are today.</p>
<p>The Nonprofit Starter Pack will get a new child object to Opportunity called Payments. Payments will be where cash is recorded. The Payment object will represent all the cash received by an organization. It will be helpful in a number of ways:</p>
<ul>
<li>Payments will allow you to record received cash payments against promised revenue</li>
<li>Payments will allow you to record a payment schedule and make sure you don’t forget to collect them when they come due</li>
<li>Payments will allow you to write off rescinded payments</li>
<li>Tracking cash in Salesforce.com allows for much better analytics than most accounting systems</li>
</ul>
<p>The Payment object will have rollup summary fields to the Opportunity that show you the number of payments per Opportunity, the amount of payments that have been made, and the remaining balance. Having this information on Opportunity makes it very easy to see which Opportunities aren’t fully paid yet.</p>
<p>Ok, back to our scenario for some illumination.</p>
<p>FOTC is a very stable organization. If we look at a dashboard of their revenue (Opportunities), we see that it’s uniform. They get about the same amount of revenue each month.</p>
<p><img src="http://gokubi.com/wp-content/uploads/2011/05/revenue_history.png" alt="" title="revenue_history" width="409" height="308" class="aligncenter size-full wp-image-1307" /></p>
<p>Most of those Opportunities were one-time payments&#8211;the cash came in the same time the revenue did. But about a third of them were paid in multiple payments. If we take a look at a chart of the cash, you’ll see that it’s much more irregular than the revenue chart. Note that the scale is different in these charts.</p>
<p><img src="http://gokubi.com/wp-content/uploads/2011/05/cash_history.png" alt="" title="cash_history" width="410" height="308" class="aligncenter size-full wp-image-1308" /></p>
<p>The same is true with forecasting&#8211;revenue in the future is expected to be pretty stable.</p>
<p><img src="http://gokubi.com/wp-content/uploads/2011/05/revenue_forecast.png" alt="" title="revenue_forecast" width="406" height="308" class="aligncenter size-full wp-image-1309" /></p>
<p>If we look at a cash forecast, it’s very lumpy, with peaks and valleys.</p>
<p><img src="http://gokubi.com/wp-content/uploads/2011/05/cash_forecast.png" alt="" title="cash_forecast" width="407" height="309" class="aligncenter size-full wp-image-1310" /></p>
<p>FOTC needs to see its revenue picture and also it’s cash picture, and it’s not clear from one what the other will look like.</p>
<h3>Revenue where the cash is received immediately</h3>
<p>At most nonprofits, most gifts aren’t pledged, they are just given. A typical scenario is a $100 check coming in the mail. Recording that check requires recording the revenue and the cash at the same time. Data entry is a time consuming task as it is. Having to do double entry&#8211;revenue and cash&#8211;for all gifts is an unacceptable burden, so we built automatic cash recording right in.</p>
<p>In the case of a gift where revenue and cash are simultaneous, the new payments functionality creates one payment for every Opportunity. It keeps this payment in sync with the Opportunity, unless you choose to set up a payment schedule. This solves the case of multi-payment gifts without causing extra work for all those gifts that don’t have multiple payments.</p>
<p>By creating automatic cash payments for each opp, the cash picture isn’t limited just to pledges with payment schedules, but includes all cash for all revenue. This allows for better reporting, like the charts shown above.</p>
<h3>The case of monthly giving</h3>
<p><img src="http://gokubi.com/wp-content/uploads/2011/05/recurr_opp_payment.png" alt="" title="recurr_opp_payment" width="113" height="272" class="alignleft size-full wp-image-1312" />For monthly giving, each gift should be considered it’s own revenue event because they aren’t connected to a known pledged amount. Therefore each gift should be an Opportunity, rather than Payments under one Opportunity. Each gift will, of course, have a payment, because all revenue does when you&#8217;re tracking revenue and cash.</p>
<p>The Recurring Donations functionality in the Nonprofit Starter Pack will handle this case better with the next release. You will be able to create a Recurring Donation Profile, detailing the recurring gift. The wizard will then create Opportunities according to your schedule. At present moment we&#8217;re thinking that the Recurring Donation functionality doesn&#8217;t need to know about payments at all&#8211;it will just interact with Opportunities. This may change, but it&#8217;s what we&#8217;re thinking now.</p>
<p>Currently Recurring Donations has the word &#8220;Pledges&#8221; in the object name. If you&#8217;ve read this far, you understand now that this is incorrect. Kevin is planning major upgrades to Recurring donations, and we will likely be renaming things to make more sense. He&#8217;s also planning on supporting the automatic creation of Opportunities for open-ended giving, and keeping the Recurring Donation Profile in sync with the Opportunities. We’ll likely give you the ability to keep a rolling year of potential gifts in the system. If you don’t want all those open gifts out there, we’ll likely give you a way to keep just one open gift for each recurring donation.</p>
<h2>Conclusion</h2>
<p>While Salesforce.com isn’t an accounting system, better modeling of nonprofit accounting practices is great functionality and we expect it to be popular. The coming upgrades to the Nonprofit Starter Pack will allow for cash reporting, write-offs of revenue, and facilitate collections of promised payments. Upcoming improvements to Recurring Donations will make it easier to handle recurring donations that are open ended.</p>
<p>If you have questions or comments on our implementation, or have feature requests, please comment on this post.</p>
<p>&#8212;&#8212;&#8212;&#8212;-</p>
<p><a name="1">1</a>. Technically, multi-year grants are received as restricted assets. Each year the revenue is released from restricted net assets to operating net assets as it is needed (credit on the restricted side, debit on the unrestricted side). Another interesting point – multi-year pledges are worth less than cash received today.You have to discount to present value and adjust based on the outstanding amount of the pledge each year.  Again, this is something you’ll likely want to handle in your accounting system.</p>
]]></content:encoded>
			<wfw:commentRss>http://gokubi.com/archives/nonprofit-starter-pack-and-money/feed</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>Join our team</title>
		<link>http://gokubi.com/archives/join-our-team</link>
		<comments>http://gokubi.com/archives/join-our-team#comments</comments>
		<pubDate>Thu, 14 Apr 2011 15:11:06 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[Change]]></category>
		<category><![CDATA[CRM]]></category>

		<guid isPermaLink="false">http://gokubi.com/?p=1298</guid>
		<description><![CDATA[The Salesforce.com Foundation technology team received a compliment the other day when a co-worker said, &#8220;Wow, your technology team is atypical.&#8221; I&#8217;ve been on great teams before in my career, and our team right now is up there as one of the best. I&#8217;m looking for a Force.com Developer to join us in our work [...]]]></description>
			<content:encoded><![CDATA[<p>The Salesforce.com Foundation technology team received a compliment the other day when a co-worker said, &#8220;Wow, your technology team is atypical.&#8221; I&#8217;ve been on great teams before in my career, and our team right now is up there as one of the best. <a href="http://www.salesforce.com/company/careers/locations/a0800000000AbXKAA0/a017000000PLVSI.jsp">I&#8217;m looking for a Force.com Developer</a> to join us in our work driving the vision of the Salesforce.com Foundation and helping thousands of nonprofits do the same for their visions. We are small, <a href="http://www.ted.com/talks/dan_pink_on_motivation.html">motivated</a>, we do great work, and we value each other.</p>
<p>If you want to make a difference working with the best tools and the best customers, on a great team, this may be the job for you.</p>
]]></content:encoded>
			<wfw:commentRss>http://gokubi.com/archives/join-our-team/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Segmenting Campaigns</title>
		<link>http://gokubi.com/archives/segmenting-campaigns</link>
		<comments>http://gokubi.com/archives/segmenting-campaigns#comments</comments>
		<pubDate>Fri, 15 Oct 2010 13:32:36 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[CRM]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://gokubi.com/?p=1270</guid>
		<description><![CDATA[In the run up to the amazing Web of Change conference this year, I was asked to write a think-piece. I ended up writing about being scientific in the design, implementation, and analysis of our work. I called it We Must Be Scientists for Change, and it seemed to resonate with a number of the [...]]]></description>
			<content:encoded><![CDATA[<p>In the run up to the amazing Web of Change conference this year, I was asked to write a think-piece. I ended up writing about being scientific in the design, implementation, and analysis of our work. I called it <a href="http://webofchange.com/We-Must-Be-Scientists-for-Change">We Must Be Scientists for Change</a>, and it seemed to resonate with a number of the attendees.</p>
<p>In that article I talked about doing some simple <a href="http://en.wikipedia.org/wiki/A/B_testing">A/B</a> testing. A/B testing is best described as doing some effort while changing one variable in the hopes of learning something about how to affect the outcome of effort. It&#8217;s been perfected by the direct mail industry&#8211;mailings are run as experiments and each mailing adds to the base of knowledge of how to increase response rats.</p>
<p>As I was writing the article I became dismayed that what I was proposing wasn&#8217;t actually very easy to do in Salesforce.com, the system I champion on a daily basis. We use Campaigns for outreach efforts, and while Campaigns are incredibly powerful and easy to work with, randomly breaking them into segments for A/B testing wasn&#8217;t easy.</p>
<p>I say &#8220;wasn&#8217;t&#8221; because I have released a tool for A/B testing that is free to users of Salesforce.com, which is listed on the Appexchange under the name <a href="https://sites.secure.force.com/appexchange/listingDetail?listingId=a0N30000003IQEIEA4">Campaign Segmentation Wizard</a>.</p>
<p>Build your list of people to whom you want to reach out, then use the wizard to randomly break them into segments of the exact size you desire. Those segments are Campaigns of their own, and can be used in any way you see fit&#8211;mass email, phone banking, etc.</p>
<p>Here&#8217;s a short video showing how it works.</p>
<p align="center"><object width="640" height="385"><param name="movie" value="http://www.youtube.com/v/vItvvB56pFw?fs=1&#038;ap=%2526fmt%3D22"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/vItvvB56pFw?fs=1&amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"></embed></object></p>
<p>If you install it and use it, please rate the app on the Appexchange so others will get a sense if it&#8217;s helpful or not.</p>
]]></content:encoded>
			<wfw:commentRss>http://gokubi.com/archives/segmenting-campaigns/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Textexpander snippets for Apex</title>
		<link>http://gokubi.com/archives/textexpander-snippets-for-apex</link>
		<comments>http://gokubi.com/archives/textexpander-snippets-for-apex#comments</comments>
		<pubDate>Sat, 14 Aug 2010 14:19:35 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[CRM]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://gokubi.com/?p=1261</guid>
		<description><![CDATA[I just upgraded my work computer to Snow Leopard and one of the benefits I was most excited about was being able to update Textexpander, the incredibly handy snippet tool. You create short codes and when you type them they are replaced with pre-recorded text. They&#8217;re much better at describing what it does. It&#8217;s really [...]]]></description>
			<content:encoded><![CDATA[<p>I just upgraded my work computer to Snow Leopard and one of the benefits I was most excited about was being able to update <a href="http://www.smileonmymac.com/TextExpander/">Textexpander</a>, the incredibly handy snippet tool. You create short codes and when you type them they are replaced with pre-recorded text. They&#8217;re much better at <a href="http://www.smileonmymac.com/TextExpander/screencast/index.html">describing what it does</a>. It&#8217;s really handy for email signatures, canned content for technical support&#8211;really anything you ever type more than once.</p>
<p>With the new features Textexpander got really interesting for use in coding on the Force.com platform. The Force.com IDE doesn&#8217;t have code completion like the in-line code editor does, and it&#8217;s something I look forward to Salesforce.com providing. But in the meantime Textexpander is a great solution for helping you with code you write over and over again.</p>
<p>Textexpander now allows you to put variables in your snippets and allows you to fill those variables as you are expanding the snippet. So, for example, when you&#8217;re declaring a List of Accounts, you don&#8217;t have to type List twice, and Account twice. It&#8217;s really slick.</p>
<p>I&#8217;ve created a <a href="http://gokubi.com/files/Apex%20Snippets.textexpander">Snippet Group for common Apex syntax</a>. To use the file, install Textexpander. Right click on the link to the Snippet Group and save to your computer. It&#8217;s an XML file, but you need to maintain the .textexpander extension on it. Then open up Textexpander and &#8216;Add Group from File.&#8217; The group will show up in Textexpander.</p>
<p>Right now this Snippet Group includes:</p>
<ul>
<li>declaration of lists, sets, and maps</li>
<li>declaration of an sObject</li>
<li>for loops, both kinds</li>
<li>if statements</li>
<li>select statements</li>
<li>test methods</li>
<li>try catch block</li>
<li>system.assert statements</li>
<li>describe result for an sObject</li>
<li>describe result for a field</li>
</ul>
<p>It&#8217;s just a start, but if you take it and like it, add to it. Let me know and we&#8217;ll expand this Snippet Group to be comprehensive. Clearly there should be a VisualForce Sinppet Group as well. If you create one, please let me know!</p>
]]></content:encoded>
			<wfw:commentRss>http://gokubi.com/archives/textexpander-snippets-for-apex/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Salesforce.com as free, bolt-on analytics engine for any database app</title>
		<link>http://gokubi.com/archives/salesforce-com-as-free-bolt-on-analytics-engine-for-any-database-app</link>
		<comments>http://gokubi.com/archives/salesforce-com-as-free-bolt-on-analytics-engine-for-any-database-app#comments</comments>
		<pubDate>Wed, 02 Jun 2010 21:47:26 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[CRM]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://gokubi.com/?p=1219</guid>
		<description><![CDATA[Over my career I&#8217;ve noticed that most applications have very limited reporting and charting features. I&#8217;ve tried to write some of my own and realized quickly why this is&#8211;analytics is hard! Visual query builders, dynamic charting, aggregation of data, it&#8217;s all really tough to do right. I also think most application teams start out with [...]]]></description>
			<content:encoded><![CDATA[<p>Over my career I&#8217;ve noticed that most applications have very limited reporting and charting features. I&#8217;ve tried to write some of my own and realized quickly why this is&#8211;analytics is hard! Visual query builders, dynamic charting, aggregation of data, it&#8217;s all really tough to do right. I also think most application teams start out with the feature list of business processes that need supporting&#8211;recording transactions, editing information, etc. I think they often punt on the analytics engine for these reasons&#8211;it&#8217;s hard and the value is limited if the app doesn&#8217;t even do what it needs to do yet. Because of this, most apps come later, if at all to the analytics game.</p>
<p>And because most of the apps we use have lousy analytics, we often don&#8217;t know what we&#8217;re missing. In my CRM consulting it was very common for people to under-value the analytics compared to the process streamlining aspects. Getting things done more quickly is important, but analytics can help tell you if you&#8217;re doing the right things.</p>
<p>Salesforce.com has a great analytics engine. It&#8217;s an amazing blend of efficiency and power. Easy things are in the reach of most users, and hard things are possible without coding.  Why are the analytics so good? Salesforce.com is a billion dollar company. They&#8217;ve spent amazing amounts of money building their platform, and as part of that, the killer analytics engine. They&#8217;ve made it a strategic priority, invested in it, and iterated over 10 years. It really shows.</p>
<p>Great, so Salesforce.com has good analytics. You might think that if you want to use those analytics tools, you need to ditch your app and rewrite the whole thing on Salesforce.com, right? Porting a functioning application is a big project, and while sometimes it might makes sense to do that, a lot of times it doesn&#8217;t. You may not have the money to do it. You may be on an open source platform and not want to go to a proprietary one.</p>
<p>But it turns out you don&#8217;t need to ditch your app to get Salesforce.com analytics for your data. Using free and open source tools you can bolt the Force.com Free Edition onto your application and very quickly get the power of Salesforce.com analytics for 100 users. For free. I did it myself last weekend. Here&#8217;s how it works:</p>
<ol>
<li>Get your app up and running</li>
<li>Get <a href="https://www.salesforce.com/form/signup/freeforce-platform.jsp">Force.com Free Edition</a>, or use your existing Salesforce.com organization</li>
<li>Create tables in Salesforce matching the key tables in your app</li>
<li>Create some simple triggers to get all your data relationships right</li>
<li>Set up an extract-transform-load (ETL) server like <a href="http://jitterbit.com">Jitterbit</a> to pull data from your app and push it to Salesforce.com.</li>
<li>Set up reports and dashboards on that data</li>
<li>Let your data inform the strategic direction of your organization</li>
</ol>
<p>If you do all this, you can pull data from your application directly into Salesforce.com, automatically updating it as changes are made in your app. Then your end users can get the analytics they can&#8217;t get in the app. And your key decision makers, who probably don&#8217;t use the app in the first place, can get the top level numbers and trends that help them manage the impact of your organization.</p>
<p><img class="aligncenter size-full wp-image-1226" title="jitterbit_architecture" src="http://gokubi.com/wp-content/uploads/2010/06/jitterbit_architecture2.png" alt="" width="481" height="232" /></p>
<p>I&#8217;ll now go into detail on each of the steps above to show you how it can be done.</p>
<p><strong>Step 1: Get your app up and running</strong></p>
<p>I chose to work with <a href="http://mifos.org">Mifos</a>, an open source application that helps microfinance institutions track their loans and borrowers. Microfinance is a global effort to get working capital in the hands of the poorest people. It&#8217;s amazing work being done by organizations all over the world. Mifos happens to be built on Tomcat with a MySQL database.  But which app I use really isn&#8217;t important. All that matters is that is has extensive functionality for specific business cases, and it has a database we can directly access. If it does these things, it&#8217;s a candidate for Salesforce analytics.</p>
<p>I installed Mifos on an Amazon.com EC2 server, which saved me the trouble of trying to get it to run on my Mac. I love EC2!</p>
<p><strong>Step 2: Get Salesforce</strong></p>
<p>I got <a href="http://developer.force.com/">a free Developer account</a> for this test case, but you could get <a href="http://www.salesforcefoundation.org/products/donation">Salesforce.com donated to your nonprofit</a>, go with the Force.com Free Edition, or purchase Salesforce.com.</p>
<p><strong>Step 3: Create your schema</strong></p>
<p>Creating analogous tables to all the tables in your app is one of the more time-consuming parts of this process. I sped things up by using Model Metrics&#8217;s great <a href="http://sites.force.com/appexchange/listingDetail?listingId=a0N300000016cVIEAY">Cloud Converter tool</a>. I got the field names and one row of values for each table I cared about&#8211;you don&#8217;t need to get every table, just the ones that figure into your analytics. I created an Excel tab for each table, and pasted the header names and values into each. I then let the Cloud Converter loose on it, and the tables were created in just a few minutes! There might be some cleanup necessary with field types&#8211;Cloud Converter guesses what type the field should be, but sometimes it guesses incorrectly. You can do this by hand, or use the metadata API with Eclipse for the fastest action.</p>
<p>All the tables in your app probably have primary keys&#8211;some unique Id field that marks each row. In your Salesforce schema, you want to mark the analagous fields are External Ids. This will allow you to use Salesofrce&#8217;s Upsert web service method. Without External Ids, you need to know the Salesforce.com record Id in order to Update it. Upsert is incredibly amazing for this use case&#8211;it makes it all so easy. Just pass it the primary key from the app and it will find the right record in Salesforce.</p>
<p>The app you&#8217;re coming from has relationships between tables (using the primary key fields I just talked about), so you need to recreate those relationships in Salesforce. Cloud Converter might be able to do this for you, but I didn&#8217;t try that out. Create your lookup relationships between the objects and you&#8217;re good to go.</p>
<p><strong>Step 4: Create your triggers</strong></p>
<p>The ETL server will create your Salesforce records just fine, but it won&#8217;t make sure they&#8217;re related to the correct parent records for you. To do this you need simple triggers on each object to look at the foreign key from your app find the right Salesforce object, and relate the two. Here&#8217;s an example where the Account Payment object looks for the parent Account when it&#8217;s inserted or updated. If it finds it, the relationship gets recorded and the Account Payments show up under the Account:</p>
<pre class="brush: java">
trigger accountPaymentParentfinder on account_payment__c (before insert, before update) {

	Set&lt;Integer&gt; accountIds = new Set&lt;Integer&gt;();

	Map&lt;Integer,Id&gt; accountIdMap = new Map&lt;Integer,Id&gt;();

	//loop through the trigger set and build a set of all the Account Ids
	for(account_payment__c myAccountPayment : Trigger.new){
		if(myAccountPayment.account_ID__c!=null){
			accountIds.add(myAccountPayment.account_ID__c.intValue());
		}

	}

	//go query for those Account Ids and create a map connecting them with the Salesforce Ids
	for(account__c thisaccount : [select id,account_Id__c from account__c where account_Id__c IN :accountIds]){
		accountIdMap.put(thisaccount.account_Id__c.intValue(),thisaccount.id);
	}

	//put the right Salesforce Id in the lookup relationship
	for(account_payment__c myAccountPayment : Trigger.new){
		if(myAccountPayment.account_ID__c!=null){
			myAccountPayment.account__c = accountIdMap.get(myAccountPayment.account_ID__c.intValue());
		}
	}
}
</pre>
<p>You need to do this for each object. If an object has more than one lookup relationship, you&#8217;ll need to create the Set and Map structure for each. They all follow the same pattern. Easy peasy.</p>
<p><strong>Step 5: Set up your ETL server and transformations</strong></p>
<p>I chose <a href="http://jitterbit.com">Jitterbit</a> for my ETL server. They have a free Community edition but I used a 30 day trial of their Enterprise edition, only because there was a machine image on Amazon.com EC2 for the enterprise version. Installation was a 10 minute affair.</p>
<p>The Jitterbit client is where you create the operations that pull data from the source and get it where you want it to go. I created an operation to log in to Salesforce.com and store my session Id. Then you pretty much create one operation for each table in your app, grabbing the data and passing it to Salesforce.com&#8217;s Upsert web service method. This will try to update a record that exists with that External Id. If it can&#8217;t find the record, it will create one. Brilliant.</p>
<p>It&#8217;s a ton of drag-and-drop mapping&#8211;this app field maps to this field on the Salesforce object. But once you get the hang of it, you&#8217;ll crank through all your tables.</p>
<p>When your operations are set up you run them, starting with the login, until all your data comes over. These operations can be scheduled to run as often as makes sense to you. You can pull over only data modified since you last pulled. I created a very simple data flow&#8211;one way from my app to Salesforce.com. But you can really do just about anything. You can send data back to your app. You could pull from 25 different apps all to Salesforce. It&#8217;s up to you.</p>
<p><strong>Step 6: Set up your reports and dashboards</strong></p>
<p>Once your data is in Salesforce.com and related correctly, start creating your reports and dashboards. What I find is that when I create a dashboard the next one immediately comes to mind. Loan default rate over time. But does marital status have an impact on that? What about number of children the borrow has? And what are the patterns for defaults? Do loans tend to default more frequently during the dry season? In the months before harvest? Do non-agriculture loans behave differently? People who work at microfinance institutions ask themselves these questions. They see patterns and want the data to confirm or challenge their assumptions. Because Salesforce.com makes analytics easy, users can ask these questions and get immediate answers. Dashboards can even be sent to them via email every week.</p>
<p>Then step back and take a look at your analytics. Here are some I created with a sample data set in my app:</p>
<ul>
<li><a href="https://www.salesforce.com/secur/frontdoor.jsp?un=readonly@mfi.demo&amp;pw=grameen1&amp;startURL=/01Z30000000r9UQ">Customer Info</a></li>
<li><a href="https://www.salesforce.com/secur/frontdoor.jsp?un=readonly@mfi.demo&amp;pw=grameen1&amp;startURL=/01Z30000000r9jb">Default Info</a></li>
<li><a href="https://www.salesforce.com/secur/frontdoor.jsp?un=readonly@mfi.demo&amp;pw=grameen1&amp;startURL=/01Z30000000r9UG">Delinquency Info</a></li>
<li><a href="https://www.salesforce.com/secur/frontdoor.jsp?un=readonly@mfi.demo&amp;pw=grameen1&amp;startURL=/01Z30000000r9UV">Historic Delinquency Rates</a></li>
<li><a href="https://www.salesforce.com/secur/frontdoor.jsp?un=readonly@mfi.demo&amp;pw=grameen1&amp;startURL=/01Z30000000r9ui">Loan Demographics</a></li>
<li><a href="https://www.salesforce.com/secur/frontdoor.jsp?un=readonly@mfi.demo&amp;pw=grameen1&amp;startURL=/01Z30000000r9ns">Loan Info</a></li>
<li><a href="https://www.salesforce.com/secur/frontdoor.jsp?un=readonly@mfi.demo&amp;pw=grameen1&amp;startURL=/01Z30000000r9oQ">Loan Products</a></li>
</ul>
<p>I was very pleased with the story I am just starting to tell about the loan programs at this pretend microfinance institution. I think the take away is this: Salesforce.com can add value by helping you be creative in telling the story of your data. It&#8217;s a story that might be hard for you to tell right now. But with very little cost other than time and technical ability, you can add flexible, user-driven analytics to any database application by following this recipe.</p>
<p>You can add this power to your app. But the really amazing part is how easy it is to share this kind of setup. Once you create a schema that matches Mifos or OpenMRS or CiviCRM you can package that up in Salesforce and share it with anyone. Just a couple clicks and they can install all the objects, triggers, and dashboards for that app. Jitterbit operations can be shared as well. You export them as a &#8220;jitterpak&#8221; and anyone can use them with their setup. Just change the login information, point to your Salesforce.com web services and it should work without changes.</p>
<p>And perhaps the most important thing is that you&#8217;re not embedding Salesforce.com into your app. You&#8217;re not requiring that everyone using the app use Salesforce.com. I hop this example shows that Salesforce.com can be &#8220;bolted-on&#8221;, adding value along side your mission-critical application. The cost can be very low, the impact can be high, and you can do it without making big decisions about app architecture direction.</p>
]]></content:encoded>
			<wfw:commentRss>http://gokubi.com/archives/salesforce-com-as-free-bolt-on-analytics-engine-for-any-database-app/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Salesforce sending SMS through FrontlineSMS</title>
		<link>http://gokubi.com/archives/salesforce-sending-sms-through-frontlinesms</link>
		<comments>http://gokubi.com/archives/salesforce-sending-sms-through-frontlinesms#comments</comments>
		<pubDate>Thu, 27 May 2010 14:13:07 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[CRM]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://gokubi.com/?p=1208</guid>
		<description><![CDATA[FrontlineSMS is an open source application used primarily in the developing world for communicating with large numbers of cell phone users. It&#8217;s a locally installed application that pushes SMS messages out through your tethered cell phone. It&#8217;s a really cool app with all sorts of great real-world usage. My friend Dale Zak just built an [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://frontlinesms.com">FrontlineSMS</a> is an open source application used primarily in the developing world for communicating with large numbers of cell phone users. It&#8217;s a locally installed application that pushes SMS messages out through your tethered cell phone. It&#8217;s a really cool app with all sorts of great real-world usage. My friend Dale Zak just built an awesome <a href="http://www.frontlinesms.com/tag/frontlinesms-reminders/">reminders module</a> for it, and that got me looking at it again.</p>
<p>The newest version of FrontlineSMS (1.6) has a very simple API for sending SMS messages. I have been successful in getting Salesforce.com to use this API to send SMS messages to single Contacts and to Leads and Contacts who are members of a Campaign. Here&#8217;s a short video of it in action:</p>
<p style="text-align: center;"><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="640" height="385" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/au-iS2yD97w&amp;hl=en_US&amp;fs=1&amp;" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="640" height="385" src="http://www.youtube.com/v/au-iS2yD97w&amp;hl=en_US&amp;fs=1&amp;" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p style="text-align: left;">Here&#8217;s what&#8217;s going on in the one-off send:</p>
<ol>
<li>I&#8217;m using Visualforce to create UI that is called by the Send SMS buttons</li>
<li>The Visualforce page accepts the SMS text input</li>
<li>Clicking send shows an iFrame that calls the FrontlineSMS API correctly: http://localhost:&lt;port&gt;/sms_number/sms_message</li>
<li>A Task is related to the Contact with the data and content of the SMS message</li>
</ol>
<p>Why use the iFrame? Since FrontlineSMS is locally installed, we have to communicate with it from the browser. A more robust option would be to create Javascript that makes the localhost calls and listens for the success or failure and proceeds accordingly.</p>
<p>To all the members of a Campaign, we do the following:</p>
<ol>
<li>The Visualforce page accepts the SMS text input</li>
<li>Clicking Send exposes an Action Poller, which calls code every 5 seconds</li>
<li>When the Action Poller calls code, 10 Campaign Members of the correct Status are queried</li>
<li>10 iFrames are populated with the FrontlineSMS API URLs for the messages</li>
<li>The Campaign Member records have their Status changed so they won&#8217;t be queried again</li>
<li>Tasks are related to the Campaign and the Contact or Lead</li>
</ol>
<p>Here are the Salesforce code bits.</p>
<p>Visualforce page for one-off sends:</p>
<pre>
<pre class="brush: html">
&lt;apex:page standardController=&quot;Contact&quot; extensions=&quot;extSendSMS&quot; &gt;
	&lt;apex:form &gt;
		&lt;apex:sectionHeader title=&quot;FrontlineSMS&quot; subtitle=&quot;Send SMS via FrontlineSMS&quot;&gt;
			&lt;description&gt;
				Send an SMS using FrontlineSMS:
				&lt;ul&gt;
					&lt;li&gt;Install FrontlineSMS on your computer&lt;/li&gt;
					&lt;li&gt;Make sure FrontlineSMS is running&lt;/li&gt;
					&lt;li&gt;Make sure your phone is connected to FrontlineSMS&lt;/li&gt;
				&lt;/ul&gt;

			&lt;/description&gt;

		&lt;/apex:sectionHeader&gt;
		&lt;apex:pageMessages id=&quot;pageMessages&quot;/&gt;
		&lt;apex:pageBlock id=&quot;smsblock&quot; title=&quot;&quot;&gt;
			&lt;apex:pageBlockSection id=&quot;smssection&quot;&gt;
				&lt;apex:outputField value=&quot;{!contact.MobilePhone}&quot;/&gt;
				&lt;apex:inputField value=&quot;{!task.Description}&quot;/&gt;
			&lt;/apex:pageBlockSection&gt;
			&lt;apex:pageBlockButtons id=&quot;smsbuttons&quot;&gt;
				&lt;apex:commandButton value=&quot;Send SMS&quot; action=&quot;{!sendSMS}&quot; rerender=&quot;smsiframe&quot;/&gt; 

			&lt;/apex:pageBlockButtons&gt;
		&lt;/apex:pageBlock&gt;
		&lt;apex:pageBlock id=&quot;smsiframe&quot; title=&quot;&quot;&gt;
		&lt;apex:iframe id=&quot;frontlinesmsIframe&quot; src=&quot;{!endpoint}&quot; scrolling=&quot;no&quot;  rendered=&quot;{!showFrontlineSMSiframe}&quot;/&gt;
		&lt;/apex:pageBlock&gt;
	&lt;/apex:form&gt;
&lt;/apex:page&gt;
</pre>
<p>Apex controller for one-off sends:</p>
<pre>
<pre class="brush: java">
public with sharing class extSendSMS {
	public Task task {get;set;}
	public String endpoint {get;set;}
	public Boolean showFrontlineSMSiframe {get;set;}
	private Contact contact;
	private Lead lead;
	public extSendSMS(ApexPages.StandardController stdController) {
		this.contact = (Contact)stdController.getRecord();
		this.contact = [select id, MobilePhone from Contact where Id=:contact.id];
		this.task = new Task();
		this.task.WhoId = contact.Id;
		this.task.type = &#039;SMS&#039;;
		this.task.ActivityDate = Date.Today();

		this.task.status = &#039;Completed&#039;;
		showFrontlineSMSiframe = false;
    }
    public PageReference sendSMS(){
    	this.task.subject = &#039;SMS: &#039; + this.task.Description;
    	insert task;
    	String strippedMobilePhone = &#039;&#039;;
    	strippedMobilePhone = this.contact.mobilePhone;
    	strippedMobilePhone = strippedMobilePhone.replaceAll(&#039;[^0-9]&#039;, &#039;&#039;);

    	endpoint = &#039;http://localhost:8565/&#039;+ strippedMobilePhone +&#039;/&#039;+ this.task.Description;
    	showFrontlineSMSiframe = true;
    	return null;
    }
}
</pre>
<p>Visualforce page for Campaign sends:</p>
<pre>
<pre class="brush: html">
&lt;apex:page standardController=&quot;Campaign&quot; extensions=&quot;extSendSMSCampaign&quot; &gt;
&lt;apex:form &gt;
		&lt;apex:sectionHeader title=&quot;FrontlineSMS&quot; subtitle=&quot;Send SMS via FrontlineSMS&quot;&gt;
			&lt;description&gt;
				Send an SMS using FrontlineSMS:
				&lt;ul&gt;
					&lt;li&gt;Install FrontlineSMS on your computer&lt;/li&gt;
					&lt;li&gt;Make sure FrontlineSMS is running&lt;/li&gt;
					&lt;li&gt;Make sure your phone is connected to FrontlineSMS&lt;/li&gt;
				&lt;/ul&gt;

			&lt;/description&gt;

		&lt;/apex:sectionHeader&gt;
		&lt;apex:pageMessages id=&quot;pageMessages&quot;/&gt;
		&lt;apex:pageBlock id=&quot;smsblock&quot; title=&quot;&quot;&gt;
			&lt;apex:pageBlockSection id=&quot;headersection&quot; &gt;
				&lt;apex:outputLabel for=&quot;membercount&quot;&gt;Member Count&lt;/apex:outputLabel&gt;&lt;apex:outputText id=&quot;membercount&quot; value=&quot;{!memberCount}&quot;/&gt;
				&lt;apex:outputLabel for=&quot;numbersent&quot;&gt;Number Sent&lt;/apex:outputLabel&gt;&lt;apex:outputText id=&quot;numbersent&quot; value=&quot;{!numberSent}&quot;/&gt;
				&lt;apex:inputField value=&quot;{!dummyTask.Description}&quot;/&gt;

			&lt;/apex:pageBlockSection&gt;
			&lt;apex:pageBlockSection id=&quot;smssection&quot; rendered=&quot;{!showFrontlineSMSiframe}&quot;&gt;
				&lt;apex:outputLabel for=&quot;endpoint1&quot;&gt;SMS 1 (debug)&lt;/apex:outputLabel&gt;&lt;apex:outputText id=&quot;endpoint1&quot; value=&quot;{!endpoint1}&quot;/&gt;
				&lt;apex:outputLabel for=&quot;endpoint2&quot;&gt;SMS 2 (debug)&lt;/apex:outputLabel&gt;&lt;apex:outputText id=&quot;endpoint2&quot; value=&quot;{!endpoint2}&quot;/&gt;
				&lt;apex:outputLabel for=&quot;endpoint3&quot;&gt;SMS 3 (debug)&lt;/apex:outputLabel&gt;&lt;apex:outputText id=&quot;endpoint3&quot; value=&quot;{!endpoint3}&quot;/&gt;
				&lt;apex:outputLabel for=&quot;endpoint4&quot;&gt;SMS 4 (debug)&lt;/apex:outputLabel&gt;&lt;apex:outputText id=&quot;endpoint4&quot; value=&quot;{!endpoint4}&quot;/&gt;
				&lt;apex:outputLabel for=&quot;endpoint5&quot;&gt;SMS 5 (debug)&lt;/apex:outputLabel&gt;&lt;apex:outputText id=&quot;endpoint5&quot; value=&quot;{!endpoint5}&quot;/&gt;
				&lt;apex:outputLabel for=&quot;endpoint6&quot;&gt;SMS 6 (debug)&lt;/apex:outputLabel&gt;&lt;apex:outputText id=&quot;endpoint6&quot; value=&quot;{!endpoint6}&quot;/&gt;
				&lt;apex:outputLabel for=&quot;endpoint7&quot;&gt;SMS 7 (debug)&lt;/apex:outputLabel&gt;&lt;apex:outputText id=&quot;endpoint7&quot; value=&quot;{!endpoint7}&quot;/&gt;
				&lt;apex:outputLabel for=&quot;endpoint8&quot;&gt;SMS 8 (debug)&lt;/apex:outputLabel&gt;&lt;apex:outputText id=&quot;endpoint8&quot; value=&quot;{!endpoint8}&quot;/&gt;
				&lt;apex:outputLabel for=&quot;endpoint9&quot;&gt;SMS 9 (debug)&lt;/apex:outputLabel&gt;&lt;apex:outputText id=&quot;endpoint9&quot; value=&quot;{!endpoint9}&quot;/&gt;
				&lt;apex:outputLabel for=&quot;endpoint10&quot;&gt;SMS 10 (debug)&lt;/apex:outputLabel&gt;&lt;apex:outputText id=&quot;endpoint10&quot; value=&quot;{!endpoint10}&quot;/&gt;
			&lt;/apex:pageBlockSection&gt;
			&lt;apex:pageBlockButtons id=&quot;smsbuttons&quot;&gt;
				&lt;apex:commandButton value=&quot;Send SMS&quot; action=&quot;{!sendSMS}&quot; rerender=&quot;smsblock,smsiframe,actionblock&quot;/&gt;
			&lt;/apex:pageBlockButtons&gt;
		&lt;/apex:pageBlock&gt;
		&lt;apex:pageBlock id=&quot;actionblock&quot; title=&quot;&quot;&gt;
			&lt;apex:actionPoller action=&quot;{!sendSMSToMembers}&quot; rerender=&quot;smsblock,smsiframe,actionblock&quot; interval=&quot;5&quot; rendered=&quot;{!showActionBlock}&quot;/&gt;
		&lt;/apex:pageBlock&gt;
		&lt;apex:pageBlock id=&quot;smsiframe&quot; title=&quot;&quot; &gt;
			&lt;apex:pageBlockSection id=&quot;smsisection&quot; rendered=&quot;{!showFrontlineSMSiframe}&quot;&gt;
				SMS 1 (debug)
				&lt;apex:iframe id=&quot;frontlinesmsIframe1&quot; height=&quot;30&quot; src=&quot;{!endpoint1}&quot; scrolling=&quot;no&quot;  /&gt;
				SMS 2 (debug)
				&lt;apex:iframe id=&quot;frontlinesmsIframe2&quot; height=&quot;30&quot; src=&quot;{!endpoint2}&quot; scrolling=&quot;no&quot;  /&gt;
				SMS 3 (debug)
				&lt;apex:iframe id=&quot;frontlinesmsIframe3&quot; height=&quot;30&quot; src=&quot;{!endpoint3}&quot; scrolling=&quot;no&quot;  /&gt;
				SMS 4 (debug)
				&lt;apex:iframe id=&quot;frontlinesmsIframe4&quot; height=&quot;30&quot; src=&quot;{!endpoint4}&quot; scrolling=&quot;no&quot;  /&gt;
				SMS 5 (debug)
				&lt;apex:iframe id=&quot;frontlinesmsIframe5&quot; height=&quot;30&quot; src=&quot;{!endpoint5}&quot; scrolling=&quot;no&quot;  /&gt;
				SMS 6 (debug)
				&lt;apex:iframe id=&quot;frontlinesmsIframe6&quot; height=&quot;30&quot; src=&quot;{!endpoint6}&quot; scrolling=&quot;no&quot;  /&gt;
				SMS 7 (debug)
				&lt;apex:iframe id=&quot;frontlinesmsIframe7&quot; height=&quot;30&quot; src=&quot;{!endpoint7}&quot; scrolling=&quot;no&quot;  /&gt;
				SMS 8 (debug)
				&lt;apex:iframe id=&quot;frontlinesmsIframe8&quot; height=&quot;30&quot; src=&quot;{!endpoint8}&quot; scrolling=&quot;no&quot;  /&gt;
				SMS 9 (debug)
				&lt;apex:iframe id=&quot;frontlinesmsIframe9&quot; height=&quot;30&quot; src=&quot;{!endpoint9}&quot; scrolling=&quot;no&quot;  /&gt;
				SMS 10 (debug)
				&lt;apex:iframe id=&quot;frontlinesmsIframe10&quot; height=&quot;30&quot; src=&quot;{!endpoint10}&quot; scrolling=&quot;no&quot;  /&gt;
			&lt;/apex:pageBlockSection&gt;
		&lt;/apex:pageBlock&gt;
	&lt;/apex:form&gt;
&lt;/apex:page&gt;
</pre>
<p>Apex controller for campaign sends:</p>
<pre>
<pre class="brush: java">
public with sharing class extSendSMSCampaign {
	public Campaign campaign {get;set;}
	public Task dummyTask {get;set;}
	public String SMSmessage {get;set;}
	public String endpoint1 {get;set;}
	public String endpoint2 {get;set;}
	public String endpoint3 {get;set;}
	public String endpoint4 {get;set;}
	public String endpoint5 {get;set;}
	public String endpoint6 {get;set;}
	public String endpoint7 {get;set;}
	public String endpoint8 {get;set;}
	public String endpoint9 {get;set;}
	public String endpoint10 {get;set;}
	public Integer memberCount {get;set;}
	public Integer numberSent {get;set;}
	private List&lt;String&gt; endpoints = new List&lt;String&gt;();
	private List&lt;Task&gt; SMSTasks = new List&lt;Task&gt;();
	private Id whoId;
	public Boolean showActionBlock {get;set;}
	public Boolean showFrontlineSMSiframe {get;set;}
	private Contact contact;
	private Lead lead;
	private CampaignMember campaignMember;

	public extSendSMSCampaign(ApexPages.StandardController stdController) {
		this.campaign = (campaign)stdController.getRecord();
		memberCount = [select count() from CampaignMember where CampaignId=:this.campaign.id AND status=&#039;sent&#039; and (Contact.MobilePhone &lt;&gt; null OR Lead.MobilePhone &lt;&gt; null)];
		showFrontlineSMSiframe = false;
		showActionBlock=false;
		SMSmessage = &#039;test message&#039;;
		numberSent =0;
		dummyTask = new Task();
    }

    public PageReference sendSMS(){
    	showActionBlock = true;
    	showFrontlineSMSiframe = true;
    	return null;
    }

     public PageReference sendSMSToMembers(){
     	endpoints = new List&lt;String&gt;();
     	endpoint1 = &#039;&#039;;
		endpoint2 = &#039;&#039;;
		endpoint3 = &#039;&#039;;
		endpoint4 = &#039;&#039;;
		endpoint5 = &#039;&#039;;
		endpoint6 = &#039;&#039;;
		endpoint7 = &#039;&#039;;
		endpoint8 = &#039;&#039;;
		endpoint9 = &#039;&#039;;
		endpoint10 = &#039;&#039;;
		SMSTasks = new List&lt;Task&gt;();
    	List&lt;CampaignMember&gt; myCampaignMembers = new List&lt;CampaignMember&gt;();
    	myCampaignMembers = [select id, Contact.MobilePhone,Contact.Id,Lead.Id, Lead.MobilePhone, status from CampaignMember where CampaignId=:this.campaign.id AND status=&#039;sent&#039; and (Contact.MobilePhone &lt;&gt; null OR Lead.MobilePhone &lt;&gt; null) limit 10];
		if(myCampaignMembers.size()&gt;0){
	    	for(Integer i=0;i&lt;myCampaignMembers.size();i++){
	    		CampaignMember thisMember = myCampaignMembers[i];
		    	String strippedMobilePhone = &#039;&#039;;
		    	if(thisMember.Contact.MobilePhone!=null){
		    		strippedMobilePhone = thisMember.contact.mobilePhone;
		    		whoId = thisMember.Contact.Id;
		    	} else if(thisMember.Lead.MobilePhone!=null){
		    		strippedMobilePhone = thisMember.contact.mobilePhone;
		    		whoId = thisMember.Lead.Id;
		    	}
		    	strippedMobilePhone = strippedMobilePhone.replaceAll(&#039;[^0-9]&#039;, &#039;&#039;);

		    	endpoints.add(&#039;http://localhost:8565/&#039;+ strippedMobilePhone +&#039;/&#039;+ dummyTask.Description);
		    	SMSTasks.add(new Task(WhoId = whoId,WhatId=this.campaign.id,type = &#039;SMS&#039;,ActivityDate = Date.Today(),Description=dummyTask.Description,Status=&#039;Completed&#039;,Subject=&#039;SMS: &#039;+dummyTask.Description));
	    	}
	    	numberSent += myCampaignMembers.size();
	    	if(endpoints.size()&gt;0){
	    		While(endpoints.size()&lt;10){
	    			endpoints.add(&#039;&#039;);
	    		}

		    	endpoint1 = endpoints[0];
				endpoint2 = endpoints[1];
				endpoint3 = endpoints[2];
				endpoint4 = endpoints[3];
				endpoint5 = endpoints[4];
				endpoint6 = endpoints[5];
				endpoint7 = endpoints[6];
				endpoint8 = endpoints[7];
				endpoint9 = endpoints[8];
				endpoint10 = endpoints[9];
	    	}
	    	for(CampaignMember myMember : myCampaignMembers){
	    		myMember.status=&#039;Responded&#039;;
	    	}
	    	update myCampaignMembers;
	    	insert SMSTasks;
		} else {
			showActionBlock = false;
		}
		return null;
    }

}
</pre>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://gokubi.com/archives/salesforce-sending-sms-through-frontlinesms/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Strategic impact and making multi-level relationships look nice</title>
		<link>http://gokubi.com/archives/strategic-impact-and-making-multi-level-relationships-look-nice</link>
		<comments>http://gokubi.com/archives/strategic-impact-and-making-multi-level-relationships-look-nice#comments</comments>
		<pubDate>Wed, 05 May 2010 21:03:22 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[CRM]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://gokubi.com/?p=1138</guid>
		<description><![CDATA[I&#8217;ve been doing a little prototyping in Salesforce.com as a volunteer project for a nonprofit in town. They&#8217;ve got an interesting need to track their strategic plans in Salesforce. I&#8217;ve seen this kind of thing built many times and have built it myself for another org or two. For this org they&#8217;ve got 3 levels [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://gokubi.com/wp-content/uploads/2010/05/drivermetric.png" alt="" title="drivermetric" width="143" height="350" class="alignright size-full wp-image-1137" />I&#8217;ve been doing a little prototyping in Salesforce.com as a volunteer project for a nonprofit in town. They&#8217;ve got an interesting need to track their strategic plans in Salesforce. I&#8217;ve seen this kind of thing built many times and have built it myself for another org or two. For this org they&#8217;ve got 3 levels of custom objects to hold their data. Driver is their high-level strategic focus. Goal is the next level down&#8211;there can be many goals for each Driver. And Metrics our measurable things related to each Goal.</p>
<p>Salesforce lets you create these objects and relationships between them very easily. I created the schema in just a few minutes. I created three objects and related them together&#8211;in this case I made them master-detail relationships. You can see in the diagram what my schema ended up looking like.</p>
<p>Now tracking your strategic goals is great, and most nonprofits do that. But where I think it gets more interesting is when we can tie the actual work we do directly to the metrics we&#8217;re trying to deliver on. So you&#8217;ll see in the diagram that there is a 4th object called project. Project is used to track all the work efforts of the org that are worth recording. I created a lookup relationship from Project to Metric so every project this groups takes on can be explicitly related to a Metric we need to deliver on. Which is in turn related to a Goal, which is related to a Driver. So, why are you updating that website for the 100th time this year? Because the website Project is meant to deliver on the Metric of increasing engagement of our supporters 25%, which is part of a Goal to grow the direct impact our supporters have in the world, which in turn feeds our Driver which calls for us to lead the world with a model of catalytic impact.</p>
<p>Those strategic objectives are made up for this example, but you get the idea how daily work can roll up to why your organization exists. Seeing that direct relationship can be very powerful. So when you look at the Project record in Salesforce, what do you see? Because there is only a relationship to the Metric object, you only see the Metric on the page layout.</p>
<p><img src="http://gokubi.com/wp-content/uploads/2010/05/project_metrics.png" alt="" title="project_metrics" width="635" height="327" class="aligncenter size-full wp-image-1145" /></p>
<p>Because the Project isn&#8217;t directly related to Goal or Driver, we can&#8217;t have lookup fields to those objects. Lookups are only for direct relationships, from child to parent, not up to grandparent and beyond. So we need another solution, and it turns out to be formula fields. On the Project I can create a Goal field and a Driver field that are formula fields of type Text. Here&#8217;s the formula for each of them:</p>
<pre>
for Goal: HYPERLINK("/" + Metric__r.Goal__r.Id , Metric__r.Goal__r.Name,"_self" )
for Driver: HYPERLINK( "/" + Metric__r.Goal__r.Driver__r.Id , Metric__r.Goal__r.Driver__r.Name,"_self" )
</pre>
<p>We&#8217;re creating a hyperlink to fake a real lookup. The URL of the hyperlink is relative, so it starts with / rather than http://. It then has the Id of the object, which we get by traversing up the relationships in Salesforce. From project we follow the Metric__r relationship to the Metric object, then up the Goal__r relationship to the Goal where we can grab any fields we want. With Driver we do the same thing, just go up one more level. If you think this looks hard, don&#8217;t worry, the formula field editor is really easy to use and does all the hard work for you&#8211;you just click the relationship you want to traverse.</p>
<p>The text of the link is the Name of the object in question. And then we target the hyperlink to &#8220;_self&#8221; so that it will load the record in question into the current window&#8211;just like a regular lookup would.</p>
<p>After adding these formula fields to the page layout, the end result is this:</p>
<p><img src="http://gokubi.com/wp-content/uploads/2010/05/project_drivers.png" alt="" title="project_drivers" width="635" height="368" class="aligncenter size-full wp-image-1146" /></p>
<p>Now we&#8217;re telling the full story about this project with a little help from simple formula fields.</p>
]]></content:encoded>
			<wfw:commentRss>http://gokubi.com/archives/strategic-impact-and-making-multi-level-relationships-look-nice/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Medical Records for Gitwe</title>
		<link>http://gokubi.com/archives/medical-records-for-gitwe</link>
		<comments>http://gokubi.com/archives/medical-records-for-gitwe#comments</comments>
		<pubDate>Thu, 18 Mar 2010 20:37:30 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[Africa]]></category>
		<category><![CDATA[CRM]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://gokubi.com/?p=1120</guid>
		<description><![CDATA[My trip to Rwanda was amazing. This first post is going to be about the volunteer project I was a part of. I&#8217;ll write more later about Rwanda and the people. There is so much to say&#8230; First of all, our project team fully delivered on all we set out to do. While success was [...]]]></description>
			<content:encoded><![CDATA[<p>My trip to Rwanda was amazing. This first post is going to be about the volunteer project I was a part of. I&#8217;ll write more later about Rwanda and the people. There is so much to say&#8230;</p>
<p style="text-align: center;"><img class="centered aligncenter" title="Gitwe hills" src="http://farm3.static.flickr.com/2791/4415239372_3f883638bb.jpg" alt="Gitwe hills" width="500" height="333" /></p>
<p>First of all, our project team fully delivered on all we set out to do. While success was in doubt up until the last minute (why do I work in technology?) we pulled it out at the 11th hour. Literally&#8211;11pm the night before we left. I look at what we did and we really nailed every aspect. The hardware we brought is high-quality and well configured. We got all the server software running in the configuration required. The electrical infrastructure is sound and protects the hardware. And we documented the systems very well.</p>
<p>It was really interesting going to Rwanda, such an amazingly different place from where I live, and then spending a lot of time working with technology. Every day felt like two days. There was the experiential part&#8211;meeting people, taking in the bustle and beauty, and eating amazing food. And then there was the volunteer work. Every day we were focused on moving toward project success. It made for a trip that went by quickly, but at the same time seemed to be a month long.</p>
<p>And I wouldn&#8217;t do it differently. I highly recommend going to Rwanda and Kenya. And I really recommend going there with good work to do. Volunteer. Help out. Contribute to the country while you experience it. You&#8217;ll get more out of your time there. You will spend more time with Rwandans and Kenyans. You will connect deeper with the place and the people then you would as a tourist. When I go back to Rwanda, I will be going with some good work to do. Maybe technology related, maybe not. But this kind of travel really resonated with me.</p>
<p>Here&#8217;s a quick recap of the project and why I was there:</p>
<p style="text-align: center;"><img class="centered aligncenter" src="http://farm5.static.flickr.com/4049/4414451983_f3938e2733.jpg" alt="" width="500" height="333" /></p>
<p><a href="http://www.mmissions.org/">Medical Missions for Children</a> sends doctors to the hospital in a town called Gitwe a couple times a year. These doctors volunteer their time and perform surgeries on kids and adults. Things like repairing cleft pallets and resectioning goiters. Surgeries that are common and easy in more wealthy countries, but just don&#8217;t happen in poorer places. These cosmetic surgeries can be absolutely life changing&#8211;much like the <a href="http://dental.pacific.edu/News_and_Events/News_Archive/Dental_Hope_for_Homeless.html">impact of homeless people getting free dentures in San Francisco</a>. It turns out that these kinds of procedures can change people&#8217;s lives&#8211;giving them confidence they&#8217;ve lacked for years because of their limitations. The freedom to smile, and not feel self-conscious, re-connects people with society and their families in profound ways. These cosmetic procedures can be truly life-changing.</p>
<p>Lucky Gunasekara was the project lead and he assembled the team&#8211;me, Jordan Smock, and the incomparable Canadian, Dale Zak. I didn&#8217;t know any of these guys going into the trip, and I came away with real friends I know I&#8217;ll stay in touch with.</p>
<p style="text-align: center;"><img class="centered aligncenter" src="http://farm3.static.flickr.com/2737/4415121734_d80352c000.jpg" alt="" width="500" height="333" /></p>
<p>Our task on this trip was to install a computerized medical records system that could be used by Medical Missions for Children to record the patients they worked with. When you&#8217;re performing surgery, it&#8217;s really important to know the patient&#8217;s medical history so that you don&#8217;t inadvertently harm them with drugs they are alergic to, for example. Phase one of this project was to get the system in place and have MMFC use it after we left. Phase two is for Gitwe Hospital to use the medical records system more broadly&#8211;allowing for better care for the 300,000 people who turn to the hospital.</p>
<p style="text-align: center;"><img class="centered aligncenter" src="http://farm5.static.flickr.com/4059/4415193972_b9130b88a6.jpg" alt="" width="500" height="333" /></p>
<p>Gitwe Hospital is owned and operated by the wonderful Urayeneza Gerard. He was our gracious host during our time there. Everything we requested to get the project done&#8211;server room with a padlock, upgrade to the electrical system, curtains for the windows&#8211;was gotten on short order.</p>
<p style="text-align: center;"><img class="centered aligncenter" src="http://farm3.static.flickr.com/2777/4415191178_09d1a376b0.jpg" alt="" width="500" height="333" /></p>
<p>Because of limited prep time for the trip, we purchased the hardware in the US and carried it on the plane with us. 2 Netbooks, 2 small desktops, a server, a backup power supply (UPS) and a million cables, surge protectors and other miscellany. Surprisingly, everything made it to our destination safely, and worked when we unpacked it. We did the unpacking in Kigali, where we were more confident we would have reliable power and Internet access. One of our hotel rooms turned into a makeshift server room as we built up the hardware, the network, and the software.</p>
<p style="text-align: center;"><img class="centered aligncenter" src="http://farm3.static.flickr.com/2678/4414326585_00ec8c5219.jpg" alt="" width="500" height="333" /></p>
<p>The biggest issue we ran into while unpacking things was power. Rwandan power turned out to be reliable and clean, but it comes out of the wall at ~250V. The power supplies in all of our devices were rated to 240V, save the most important one, the UPS. Luckily that required an awesome day of walking around the commercial district searching for a solution. We found one with the amazing folks at Bricotech. They sold us a voltage regulator which would serve the dual purpose of stepping the voltage down to 110V and protecting our equipment against power fluctuations. They also put a British plug end on our UPS, solving our other issue.</p>
<p style="text-align: center;"><img class="centered aligncenter" src="http://farm3.static.flickr.com/2706/4415127582_1e460e6404.jpg" alt="" width="500" height="333" /></p>
<p>We were now ready to leave the big city for the rural outpost of Gitwe. We packed all our gear and made the 2+ hour drive south to the hospital, stopping along the way for a Mutzig in the van.</p>
<p style="text-align: center;"><img class="centered aligncenter" src="http://farm5.static.flickr.com/4058/4414409061_fe0b93f530.jpg" alt="" width="500" height="333" /></p>
<p>Gitwe is an amazing little spot. It&#8217;s not really a town, more of a collection of shops and homes. The main centers of activity are the Hospital and Esapac, a technical school with about 1000 students. So while it was a tiny little place, it bustled with activity of people coming and going.</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="480" height="385" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/kLDzOtsrGrU&amp;hl=en_US&amp;fs=1&amp;" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="480" height="385" src="http://www.youtube.com/v/kLDzOtsrGrU&amp;hl=en_US&amp;fs=1&amp;" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<p>Over the course of five days we took an empty room at the hospital and transformed it into the Gitwe Hospital server room. Here are the before and after pics:</p>
<p style="text-align: center;"><img class="centered aligncenter" src="http://farm3.static.flickr.com/2743/4414431679_582595fbd4.jpg" alt="" width="500" height="333" /></p>
<p style="text-align: center;"><img class="centered aligncenter" src="http://farm5.static.flickr.com/4030/4415324990_af9a0aa1d6.jpg" alt="" width="500" height="333" /></p>
<p>We worked side by side with the IT staff at the hospital&#8211;Innocent and Charles, setting up furniture, hardware and software. The technology we brought in is somewhat new to these folks. They haven&#8217;t used the medical records system before, and they need to come up to speed on Linux systems. We&#8217;re hoping to get them involved in an intensive nine-month training course offered by the Rwandan government to train folks to work with medical records systems. It&#8217;s a plumb placement, and a great opportunity if it comes through.</p>
<p style="text-align: center;"><img class="centered aligncenter" src="http://farm5.static.flickr.com/4058/4414439097_44d019ff92.jpg" alt="" width="500" height="333" /></p>
<p>OpenMRS was our steepest learning curve in this project. We ended up running up against a problem with a bad install file posted to their website. Things just weren&#8217;t working for the first 3 days of our stay. We tried every angle we could think of, and then used our cellphone modem Internet access to throw a hail mary out to Dave Thomas, who works at the other end of Rwanda for <a href="http://www.pih.org">Partners in Health</a>. He saved our bacon. Completely. With his help, we were able to get the system functioning on our last day, and then spent the rest of the day and night configuring it for the special needs of MMFC. At midnight we headed back to our rooms for a beer, a bit of whiskey and Coke, with a palpable sense of relief and accomplishment.</p>
<p>The next morning we had breakfast with Gerard and his wife Justine, like we did each day in Gitwe. After breakfast Gerard said a prayer for our travels and really got us choked up as we realized how important this contribution is to him. He&#8217;s doing amazing things for Gitwe with the school and the hospital. He is by far the largest employer in the area, with the hospital alone having 1,500 employees. And he has no plans to slow down&#8211;Gitwe will likely be the home of the second medical school in Rwanda. I can&#8217;t wait for that to happen!</p>
<p style="text-align: center;"><img class="centered aligncenter" src="http://farm5.static.flickr.com/4060/4414563569_3b7b7367e3.jpg" alt="" width="500" height="333" /></p>
<p>Now that our work was done, we could enjoy a little tourism. But, Lucky, Dale and I aren&#8217;t your average tourists. What we like to see are real people, and amazing good work. So, naturally, we headed up to Rwinkwavu to get a tour of the Partners in Health operation. It was the most amazing download of information I&#8217;ve had in a while. Hearing about the innovative things they are doing to ensure the health of the poor in northeastern Rwanda was nothing short of amazing and inspiring. <a href="http://www.pih.org">PIH</a> is my favorite nonprofit, and I highly recommend reading <a href="http://books.google.com/books?id=XifdzgU9ilsC&amp;source=gbs_navlinks_s">Mountains Beyond Mountain</a>s if you want to learn more about how comprehensive healthcare can be provided to people with no money. Thanks to our hosts Cheryl and Dave, we had plenty to think about on the long drive to Kigali.</p>
<p style="text-align: center;"><img class="centered aligncenter" src="http://farm5.static.flickr.com/4010/4414606971_a11cbf13a8.jpg" alt="" width="500" height="333" /></p>
<p>I can&#8217;t say enough about the experience of working side-by-side with great folks in an amazing setting. It&#8217;s a great feeling to visit a place and leave behind something of value that can be built on. I hope to go back and contribute some of that building. I&#8217;d love to have more time to focus on knowledge transfer and skill building with Charles and Innocent and whomever is interested. This trip felt like a first step into a longer relationship. I hope that&#8217;s the case and that Gitwe moves forward as fast as we all want. There are governmental plans to bring fiber optic Internet to all the district hospitals in the next year or so. Gitwe could be transformed in short order if that&#8217;s the case. I&#8217;d love to witness it first hand!</p>
]]></content:encoded>
			<wfw:commentRss>http://gokubi.com/archives/medical-records-for-gitwe/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>An Introduction to Exception Handling in Apex</title>
		<link>http://gokubi.com/archives/an-introduction-to-exception-handling-in-apex</link>
		<comments>http://gokubi.com/archives/an-introduction-to-exception-handling-in-apex#comments</comments>
		<pubDate>Tue, 12 Jan 2010 17:48:41 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[CRM]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://gokubi.com/?p=1095</guid>
		<description><![CDATA[I was privileged to get to write an article for DeveloperForce.com on exception handling in Apex. I wrote this article not from the perspective of an expert on the subject, but as someone who really wanted to learn more about my options for using exception handling in my Apex code. I&#8217;ve always had a nagging [...]]]></description>
			<content:encoded><![CDATA[<p>I was privileged to get to write an article for DeveloperForce.com on <a href="http://wiki.developerforce.com/index.php/An_Introduction_to_Exception_Handling">exception handling in Apex</a>. I wrote this article not from the perspective of an expert on the subject, but as someone who really wanted to learn more about my options for using exception handling in my Apex code.</p>
<blockquote><p>I&#8217;ve always had a nagging feeling that I wasn&#8217;t following best practices in my exception handling in Apex. In most cases I wasn&#8217;t doing any exception handling at all. I decided to write up what I have learned about error handling on the Force.com platform so that others could jump into it full-bore, and make their programs more robust and fault tolerant.</p></blockquote>
<p>I hope it&#8217;s helpful to Apex programmers out there. Let me know what you think!</p>
]]></content:encoded>
			<wfw:commentRss>http://gokubi.com/archives/an-introduction-to-exception-handling-in-apex/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>I&#8217;m going to Rwanda</title>
		<link>http://gokubi.com/archives/im-going-to-rwanda</link>
		<comments>http://gokubi.com/archives/im-going-to-rwanda#comments</comments>
		<pubDate>Wed, 30 Dec 2009 04:50:56 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[Africa]]></category>
		<category><![CDATA[CRM]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://gokubi.com/?p=1082</guid>
		<description><![CDATA[Today I got confirmation of some great news&#8211;in February I&#8217;ll be going to Rwanda for a week to help install an open source medical records system at a rural health clinic! I&#8217;ll be going with Lucky Gunasekara and meeting with Partners in Health. I&#8217;m really excited to work with Lucky! This project will be amazing, [...]]]></description>
			<content:encoded><![CDATA[<p>Today I got confirmation of some great news&#8211;in February I&#8217;ll be going to Rwanda for a week to help install an open source medical records system at a rural health clinic! I&#8217;ll be going with <a href="http://www.youtube.com/watch?v=Lm5Ep54IP9A">Lucky Gunasekara</a> and meeting with <a href="http://www.pih.org">Partners in Health</a>.</p>
<p>I&#8217;m really excited to work with Lucky! This project will be amazing, and Lucky has a longer-term vision. He wants to answer the question: does cloud computing have a role in health systems in rural Africa? He&#8217;s planning some really interesting efforts in Kenya later this year. In time, I think Salesforce.com can be a boon in rural Africa, and I&#8217;m really interested to start the work to figure out if that time is now, soon, or farther down the road. I see this trip as a great first step on that path.</p>
<p>When I started working with Salesforce.com five years ago, I felt part of my role was to go down the path of trying to deeply customize the platform for nonprofits, and then to report on that experience, warts and all. I really enjoyed that work, and I hope to do similar work and storytelling around Salesforce.com in parts of the world where people assume the cloud can&#8217;t work.</p>
<p>But most of all, I&#8217;m really excited to have all my assumptions and expectations blown out of the water! I can&#8217;t wait to walk the roads, meet folks, and most of all listen and learn. I will be arriving with no answers, and I don&#8217;t expect to leave with any. For me, it&#8217;s all about getting to the right questions. There will be so much to take in, to start orienting myself to this new set of challenges.</p>
<p>Only just a week ago a friend pointed me to this piece by David Brancaccio on Partners In Health&#8217;s work in Rwanda. I was floored by the outcomes they are getting, and the thoughtful design of the community health program. I recommend watching it&#8211;it&#8217;s amazing.</p>
<p align=center><embed src="http://www.pbs.org/now/media_player/flvplayer1.swf"; width="635" height="380" bgcolor="000000" allowfullscreen="true" allowscriptaccess="always" flashvars="file=http://www-tc.pbs.org/now/video/NOW-537-stream.mp4&#038;plugins=embed-1&#038;image=http://www-tc.pbs.org/now/shows/537/images/video-512.jpg"></embed></p>
<p>So many times people look to technology as a savior. That never works in my estimation&#8211;human systems are how problems are solved. Technology can augment and transform those solutions, but it isn&#8217;t the answer. I&#8217;m incredibly excited by what&#8217;s already working in Rwanda, and am fired up to start thinking about how technology can help extend that impact.</p>
<p>I watched this video and emailed the link to a friend of mine with the message, &#8220;this is the work I want to do with my life&#8211;helping people build community-based systems that really work.&#8221; Four days later I got an email from Lucky inviting me to Rwanda, to the very region where that video was filmed. Serendipity is a fabulous thing!</p>
<p>Ahh! I&#8217;m going to Rwanda! I still can&#8217;t really believe it. It all feels so fast and so amazingly exciting. Of course I&#8217;ll be writing about the experience, as well as taking tons of pictures and videos. So much to do to prepare!</p>
]]></content:encoded>
			<wfw:commentRss>http://gokubi.com/archives/im-going-to-rwanda/feed</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>A great job opportunity</title>
		<link>http://gokubi.com/archives/a-great-job-opportunity</link>
		<comments>http://gokubi.com/archives/a-great-job-opportunity#comments</comments>
		<pubDate>Fri, 11 Dec 2009 15:37:56 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[CRM]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://gokubi.com/?p=1061</guid>
		<description><![CDATA[Groundwire is an organization near and dear to my heart. I spent many wonderful years there back when it went by the name ONE/Northwest. My Salesforce-related career got it&#8217;s start there. Some of my most cherished relationships began there. And I was given the space and encouragement to grow exponentially as a person, technologist, and [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://groundwire.org">Groundwire</a> is an organization near and dear to my heart. I spent many wonderful years there back when it went by the name ONE/Northwest. My Salesforce-related career got it&#8217;s start there. Some of my most cherished relationships began there. And I was given the space and encouragement to grow exponentially as a person, technologist, and agent of change. I look back on those years very fondly&#8211;the work, the nonprofits we worked with, but most importantly the people.</p>
<p><a href="http://groundwire.org/about/jobs/CRM-Consultant">Groundwire is looking for a top-notch CRM Consultant</a>. Opportunities to join this amazing team are rare. If you are at all interested in using your Salesforce.com skills to make a difference in this world, you should follow up with Groundwire and make sure you don&#8217;t miss this chance.</p>
]]></content:encoded>
			<wfw:commentRss>http://gokubi.com/archives/a-great-job-opportunity/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Add a Donor Status Funnel to the Nonprofit Starter Pack</title>
		<link>http://gokubi.com/archives/add-a-donor-status-funnel-to-the-nonprofit-starter-pack</link>
		<comments>http://gokubi.com/archives/add-a-donor-status-funnel-to-the-nonprofit-starter-pack#comments</comments>
		<pubDate>Wed, 09 Dec 2009 16:18:42 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[CRM]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://gokubi.com/?p=1027</guid>
		<description><![CDATA[The vision of the Nonprofit Starter Pack has always been that it would be a starting place for nonprofits. It&#8217;s not a &#8220;application&#8221; so much as it&#8217;s a &#8220;platform.&#8221; We&#8217;ve tried to architect it in a way that gives some immediate benefit, while not precluding the change and extension that I feel is necessary for [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://gokubi.com/wp-content/uploads/2009/12/donorstatusfunnel.png" alt="donorstatusfunnel" title="donorstatusfunnel" width="400" height="300" class="alignright"/>The vision of the Nonprofit Starter Pack has always been that it would be a starting place for nonprofits. It&#8217;s not a &#8220;application&#8221; so much as it&#8217;s a &#8220;platform.&#8221; We&#8217;ve tried to architect it in a way that gives some immediate benefit, while not precluding the change and extension that I feel is necessary for successful use. In that spirit, I want to show how to add some donor segmentation you might find interesting if you&#8217;re using the One-to-one Account model.</p>
<p>The image on the right is from a Dashboard showing all Contacts in an instance with the Nonprofit Starter Pack installed. All Contacts have been categorized by something called &#8220;Donor Status.&#8221; We&#8217;re looking at their giving and putting them in one of four categories&#8211;never a donor, a donor previous to last year, a donor last year, or a donor this year. Here&#8217;s how I created it.</p>
<p>First, we need to have 2 rollup summary fields on Account that calculate the Opportunity values over this year and last year. You could also add a third rollup to get the value from two years back:</p>
<ul>
<li>Total Giving Year To Date &#8211; (Won EQUALS true) AND (Close Date GREATER THAN 12/31/2008) AND (Close Date LESS THAN 1/1/2010)</li>
<li>Total Giving Last Year &#8211; (Won EQUALS true) AND (Close Date GREATER THAN 12/31/2007) AND (Close Date LESS THAN 1/1/2009)</li>
<li>Total Giving 2 Years Previous &#8211; (Won EQUALS true) AND (Close Date GREATER THAN 12/31/2006) AND (Close Date LESS THAN 1/1/2008)</li>
</ul>
<p>These dates need to be hard-coded for the rollup summaries to work. On Jan 1, you&#8217;ll need to add a year to all the dates. Don&#8217;t worry, all the rollups will then recalculate for you.</p>
<p>Now you want to show these Account fields on the Contact. Create three formulas that just show the Account field value:</p>
<ul>
<li>YTD Giving Total &#8211; Account.Total_Giving_Year_To_Date__c</li>
<li>Last Year Giving Total &#8211; Account.Total_Giving_Last_Year__c</li>
<li>2 Years Previous Giving Total &#8211; Account.Total_Giving_2_Years_Previous__c</li>
</ul>
<p>Once you have these summary values, you can use them in another Formula, our Donor Status formula:</p>
<p><code>IF( npe01__Lifetime_Giving_History_Amount__c >0, IF( YTD_Giving_Total__c =0, IF( Previous_Year_Giving_Total__c =0, "2. SYBUNT" , "3. LYBUNT") , "4. Current Donor") , "1. Not Donor")</code></p>
<p>Note that the npe01__Lifetime_Giving_History_Amount__c field is included in the Nonprofit Starter Pack. The others are fields you just created, so make sure the names match.</p>
<p>Now that you&#8217;ve got the formula field built, create a Contact and Organizations report that takes all Contacts and groups by Donor Status. Variations on this report can easily be used to send a letter to everyone who gave in the past but not this year. Once you save this report, you can build a funnel dashboard based on it and you&#8217;re done! You&#8217;ve now segmented your donors based on when they last gave.</p>
]]></content:encoded>
			<wfw:commentRss>http://gokubi.com/archives/add-a-donor-status-funnel-to-the-nonprofit-starter-pack/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>My Nonprofit Starter Pack Session from Dreamforce 2009</title>
		<link>http://gokubi.com/archives/my-nonprofit-starter-pack-session-from-dreamforce-2009</link>
		<comments>http://gokubi.com/archives/my-nonprofit-starter-pack-session-from-dreamforce-2009#comments</comments>
		<pubDate>Sun, 29 Nov 2009 01:10:27 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
				<category><![CDATA[CRM]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://gokubi.com/?p=989</guid>
		<description><![CDATA[Getting the Most of of the Nonprofit Starter Pack. We cover 3 main things: Configuring the Starter Pack Importing Contacts via the wizard Upgrading a package Feel free to fast forward through the first 4 minutes, where we&#8217;re getting 110 people logged into their orgs&#8230;]]></description>
			<content:encoded><![CDATA[<p>Getting the Most of of the Nonprofit Starter Pack. We cover 3 main things:</p>
<ol>
<li>Configuring the Starter Pack</li>
<li>Importing Contacts via the wizard</li>
<li>Upgrading a package</li>
</ol>
<p>Feel free to fast forward through the first 4 minutes, where we&#8217;re getting 110 people logged into their orgs&#8230;</p>
<p align="center"><object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/nOY7IHp38WA&#038;rel=0&#038;color1=0xb1b1b1&#038;color2=0xcfcfcf&#038;hl=en_US&#038;feature=player_profilepage&#038;fs=1&#038;hd=1"></param><param name="allowFullScreen" value="true"></param><param name="allowScriptAccess" value="always"></param><embed src="http://www.youtube.com/v/nOY7IHp38WA&#038;rel=0&#038;color1=0xb1b1b1&#038;color2=0xcfcfcf&#038;hl=en_US&#038;feature=player_profilepage&#038;fs=1&#038;hd=1" type="application/x-shockwave-flash" allowfullscreen="true" allowScriptAccess="always" width="425" height="344"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://gokubi.com/archives/my-nonprofit-starter-pack-session-from-dreamforce-2009/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

