Oh my god. It's full of code!

Salesforce, google maps, and jQuery fun

Another Cloudspokes challenge entry submission. This one was for the challenge http://www.cloudspokes.com/challenges/1345. Basically the idea is get Sales data from Salesforce, plot it on a google map using geocoding without creating duplicate map points and allow a user to click one of the points to see all the sales data for it. The tricky part here is that the data comes from different objects based on what country you are filtering on (oh yeah, it has to support multiple countries). So data for the united states comes from a custom object called Sales Orders, while data for Japan and Germany come from opportunities. It had to allow to be easily expanded for more countries in the future as well with an easy way to set the data source. It was recommended to use address tools (an application from the app exchange that has prepopulated lists of countries and their states, along with some other data) for country and state data, but then there was some confusion because address tools is a for pay app with a 14 day trial. What is a developer to do?

I decided to try and make the best of both worlds. Using a flag in the javascript you can tell the controlling class whether to try and pull country and state data from address tools, or return a hard coded set of data (which was said to be an acceptable alternative in the comments of the challenge). The bummer here is that the org does at least have to have the address tools objects otherwise the class won’t compile. Nice thing is my installable package does include the objects and fields, so while it doesn’t have all the data that a full functionally addressTools would have it should at least install and not error. If you do have a functional addressTools install then no need to worry at all. The application will just work, because it defaults to attempting to pull it’s data from there.

To solve the issue of pulling data from different objects with different field names, I decided to create a wrapper object. A simple class that contains only the data needed to plot the address on the map. So whether the data be originally coming from Sales Orders or opportunities, they both end up returning a list of salesData objects (which is what I ended up calling my wrapper class). I created two separate methods (though they probably could have been consolidated into one, but it would have been a bit messy) for getting data from either object. The correct method was called by another which gets invoked by the user interface. Something like

User picks country
Javascript uses apex remoting to call getSales(string formData);
deserialize the form data from a url query string into a map of string to string (key to value)
find useOpp key in the deserialized data (this got set by the javascript in the application before the request was sent)
call the buildQueryFilter method and pass the form data. This method evaluates the data passed in the form and creates a SOQL where condition that will filter the records as the user has requested.
If useOpp is true call the getOpportunitySales() method. If not, call the getSalesOrderSales() method.
Both methods return a map of address (string) to salesData objects, using the filter created above.
Return the map of addresses to salesData objects to the javascript to be plotted on the map.

Those few parts where really the trickiest part of this challenge. I feel creating the wrapper object was probably the slickest solution, and even allows for other potential data sources in the future, and easily expand-ability to return more data to the front end if desired. I’ll be honest and stay a little bit of my code is redundant because of a feature I added at the very last moment, so I end up deserializing the form data twice, which I should really only need to do once, but it’s a short string of data so it’s not a big deal. I also not 100% sure the application is safe from SOQL injection. You could probably get the application to error by passing junk data with firebug or something, but I doubt you could make it do anything besides just error. I mean SOQL is select only anyway, and the filters it runs through and the way the query string gets built is pretty solid. So I am pretty sure at worst an attack could just get the application to toss some errors for their instance of it. Nothing that should be able to bring the app down, especially with governor limits in place.

As usual, I can’t release the source code myself until I have lost, or Cloudspokes gives me the okay. They generally host all code on their github anyway so in that case I’ll updated this post with the link to it.

Anyway you can see the video here: http://www.screencast.com/t/cLUc7dqpHEkC
Or play with the Demo App!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s