+ Start a Discussion
Rich.ax131Rich.ax131 

sControl capabilities question

My company has a potential sControl need. I have poked around these boards and the sControl documentation to see if what I need is possible but can't quite piece it all together. I was hoping someone here might be able to tell me if this is even possible, and if so point me in the right direction for accomplishing implementation.

We have a custom table containing cross-reference information for the zip code entered for a lead. For example, if the zip code entered is 'XXXXX,' this table would be referenced to obtain the associated city, state, country, county, and sales manager (or lead owner) for that zip code. Ideally, the following process would take place in Sales Force:

1. A user enters or edits the zip code for a lead.
2. An event fires on exit of the zip code form field which triggers the sControl to retrieve information from the custom zip code table.
3. The retrieved information is placed in the appropriate lead form fields.
4. If no cross-referencing data is found for the entered zip code, a JavaScript alert is fired to notify the user.

I can accomplish this fairly easily by building a completely custom HTML form and AJAX, but I was hoping (and users as well) that it could all be done in Sales Force.

Thoughts?

Thanks in advance.

Rich
adamgadamg
Note that the following is with regards to auto populating the address info from the zip code (or whatever logic); the assignment of the lead to a rep should be done via workflow, and doesn't requiring any coding or scontrol.

The basic flow for this would be:

1. User enters zip code, and saves the record.
2. User clicks on a web link which opens an s-control, written in Javascript using the AJAX toolkit, that does the appropriate lookups and writes back to the originating lead, handles the error (through the UI - you can't send an email via the scontrol), and returns the user back to the lead page.

So yes, you'd need to write some Javascript to do this.. there are other ways to do this of course, but they involve code as well.


Adam
The_FoxThe_Fox
Hi Adam,

hrough the UI - you can't send an email via the scontrol
this is not rue as per se. In fact I have succeeded in posting a XMLHttpRequest to the salesforce jsp handling emails OK that is not supported but it works like a charm

REgards
Rich.ax131Rich.ax131
Thank you for the response. I mentioned the lead assignment role possibility and was told that with 42,000 zip codes to cross reference, maintaining such assignment rules would be impossible in this scenario.

Any chance you could point me to a working example or sample code that does what you describe in some fashion? All of the examples I've seen in the AJAX toolkit utilize custom HTML pages - not quite what I'm looking for.

Thanks again.
Rich.ax131Rich.ax131
Ok. I think I've done as you suggested. I have it working outside of Sales Force as expected, but when I attempt to implement it as an sControl I get errors (e.g. "Permission Denied"). Any ideas? I'm sure I'm not implementing something correctly in the sControl but I haven't been able to figure it out yet.

Thanks.

**********

Message Edited by DevAngel on 01-23-2006 04:48 PM

Rich.ax131Rich.ax131
??? What does one need to to post code???
DevAngelDevAngel
To post code, switch to Edit As HTML mode at the bottom of the message body are to the right of Submit Post button.

While in the html editor create a textarea tag like [textarea rows=20 cols=60][/textarea]. Switch back and paste your code into the text area.

Left and right open and close tag delimeters above where replaced with square brackers.

Message Edited by DevAngel on 01-23-2006 02:15 PM

Rich.ax131Rich.ax131
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title></title> <scr + ipt src="https://www.sforce.com/ajax/beta1/sforceclient.js" type="text/javascript"></scr + ipt> <scr + ipt language="javascript"> <!-- function init() { var leadId; leadId = "{!Lead_ID}"; //leadId = "00Q00000004LFbOEAW"; var errors = ""; var msg = "____________________________________\n\n" msg += "The form was not submitted because of the following error(s).\n"; msg += "Please correct these error(s) and re-submit.\n"; msg += "____________________________________\n\n" //1. Log in logIn(); //2. Retrieve PostalCode for lead sforceClient.setBatchSize(1); var sql = "Select PostalCode From Lead where Id = '" + leadId + "'" var qrLead = sforceClient.Query(sql); if (qrLead.getClassName() == "QueryResult") { if (qrLead.size > 0) { var lead = qrLead.records[0]; var zip = lead.get("PostalCode"); //3. Retrieve zip__c values for the PostalCode sforceClient.setBatchSize(1); sql = "Select Zip__c, City__c, State__c, County__c, FIPS__c, OwnerId From Zip__c where Zip__c = '" + zip + "'" var qrZip = sforceClient.Query(sql); if (qrZip.getClassName() == "QueryResult") { if (qrZip.size > 0) { var zipRecord = qrZip.records[0]; var city = zipRecord.get("City__c"); var state = zipRecord.get("State__c"); var county = zipRecord.get("County__c"); var FIPS = zipRecord.get("FIPS__c"); //var rsm = zipRecord.get("RSM__c"); var rsmId = zipRecord.get("OwnerId"); } else { errors += "No zip table information found for entered postal code."; } } //4. Update lead with zip_c values lead.set("Id", leadId); lead.set("City", city); lead.set("State", state); lead.set("County__c", county); //lead.set("FIPS__c", FIPS); lead.set("OwnerId", rsmId); var saveResult = sforceClient.Update([lead])[0]; alert(saveResult.toString()); } else { errors += "No postal code exists for selected lead."; } } //5. Report any errors, refresh parent, and close if (errors != "") { msg += errors; alert(msg); return; } window.opener.location.reload(); window.close(); } function logIn() { //Including the two merge fields below will enable this sforce control when used in your account. sforceClient.init("{!API_Session_ID}", "{!API_Partner_Server_URL_60}"); window.setTimeout(";", 1000); sforceClient.Login([username], [pwd]); } //--> </scr + ipt> </head> <body onload="init();"> </body> </html>

Message Edited by Rich on 01-23-2006 02:40 PM

Ron HessRon Hess
only thing i can see is that you are calling :
sforceClient.init()
AND
sforceClient.Login()

if you are inside the app, running from a customlink, you don't need the "Login()" as the init already has the SID it needs to open communication.

if this is not helping, what line number does the permission problem occur?
Rich.ax131Rich.ax131
I considered that, but I'm still getting an error. When I remove the call to the custom login function I now get the following:

Line: 283
Char: 3
Error: Invalid procedure call or argument
Code: 0
URL: https://ssl.salesforce.com/servlet.Integration?xxxxx

Once again, this code works fine outside of Sales Force, so there must be something I'm doing incorrectly in the sControl implementation. I'm not sure how to debug an error that is apparently occurring inside the servlet though.

Thanks for your help.
Rich.ax131Rich.ax131
I've stripped my code down and the error appears to be occurring here:

var qrLead = sforceClient.Query(sql);

I've taken the value for "sql" out (Select PostalCode From Lead where Id = '00Q00000004LFbO') and run it throught the sForce Explorer thinking maybe there was something wrong with the sql, but it ran fine there.
DevAngelDevAngel

Hi Rich,

I checked your code and made a couple of changes. First, the code is now referencing the most recent version of the toolkit. This is more stable and represents the interface that will continue to be provided.

Second, I changed the endpoints to the 7.0 soap endpoint which is the most recent release of the API.

Third, I broke your init function into 2 functions, init and processLead. In the init we set an init callback function specifying that after initialization, the code should run the processLead function. I also removed the login function and moved the init call up to the top of the init function. After the init is called the precessLead will execute. The first thing the processLead does is check to see if the merge field for sessionId was replaced with a session id. If it wasn't then the login call is made and the loginResult checked for success. If the login did not succeed, then and alert is shown and the function is terminated. Otherwise, the code will run as you wrote it to.

Fourth, since the newer version uses className property instead of GetClassName() method, I replaced those parts.

This should run as expected.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title></title> <script src="https://www.salesforce.com/services/lib/ajax/beta3.3/sforceclient.js" type="text/javascript"></script> <script language="javascript"> <!-- var leadId; leadId = "{!Lead_ID}"; //leadId = "00Q00000004LFbOEAW"; var errors = ""; var msg = "____________________________________\n\n" msg += "The form was not submitted because of the following error(s).\n"; msg += "Please correct these error(s) and re-submit.\n"; msg += "____________________________________\n\n" function init() { //1. Log in sforceClient.registerInitCallback(processLead); sforceClient.init("{!API_Session_ID}", "{!API_Partner_Server_URL_70}", false); } function processLead() { if (sforceClient.sessionId.indexOf("API_Session_ID") != -1) { var lr = sforceClient.login([username], [password]); if (lr.className.toLowerCase() != "loginresult) { alert("Invalid login: " + lr.toString()); return; } } //2. Retrieve PostalCode for lead sforceClient.setBatchSize(1); var sql = "Select PostalCode From Lead where Id = '" + leadId + "'" var qrLead = sforceClient.Query(sql); if (qrLead.className.toLowerCase() == "queryresult") { if (qrLead.size > 0) { var lead = qrLead.records[0]; var zip = lead.get("PostalCode"); //3. Retrieve zip__c values for the PostalCode sforceClient.setBatchSize(1); sql = "Select Zip__c, City__c, State__c, County__c, FIPS__c, OwnerId From Zip__c where Zip__c = '" + zip + "'" var qrZip = sforceClient.Query(sql); if (qrZip.className.toLowerCase() == "queryresult") { if (qrZip.size > 0) { var zipRecord = qrZip.records[0]; var city = zipRecord.get("City__c"); var state = zipRecord.get("State__c"); var county = zipRecord.get("County__c"); var FIPS = zipRecord.get("FIPS__c"); //var rsm = zipRecord.get("RSM__c"); var rsmId = zipRecord.get("OwnerId"); } else { errors += "No zip table information found for entered postal code."; } } //4. Update lead with zip_c values //lead.set("Id", leadId); lead.set("City", city); lead.set("State", state); lead.set("County__c", county); //lead.set("FIPS__c", FIPS); lead.set("OwnerId", rsmId); var saveResult = sforceClient.Update([lead])[0]; alert(saveResult.toString()); } else { errors += "No postal code exists for selected lead."; } } //5. Report any errors, refresh parent, and close if (errors != "") { msg += errors; alert(msg); return; } window.opener.location.reload(); window.close(); } //--> </script> </head> <body onload="init();"> </body> </html>

As an aside, you should not deploy your scontrol with a username and password in the javascript.  For development and testing purposes the new version of the toolkit contains an automatic login dialog when the init runs and the merge fields in the init call where not replaced.  This allows you to run the scontrol outside of salesforce and not hardcode username and password.  You can also make use of cookies for the dialog so that after you successfully login using the dialog, the username and password will pre-populate for you on subsequent refreshes.

To enable this feature add ?browser=true to the script tag src for the toolkit (/sforceclient.js?browser=true).  Next to enable cookies add this line above the registerInitCallback  sforceClient.useCookies = true; .  Change the third parameter on the init call from false to true. Remove the first 7 lines of the processLead function.

The next post contains the login dialog version.  One note about the login dialog.  In firefox, for some reason the username and password input boxes don't recieve focus when you click the box.  You can give these boxes the focus if you right-click the boxes.  Not sure why this is so, so I don't have a fix for it yet.

 

DevAngelDevAngel

This is the login dialog version:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title></title> <script src="https://www.salesforce.com/services/lib/ajax/beta3.3/sforceclient.js?browser=true" type="text/javascript"></script> <script language="javascript"> <!-- var leadId; leadId = "{!Lead_ID}"; //leadId = "00Q00000004LFbOEAW"; var errors = ""; var msg = "____________________________________\n\n" msg += "The form was not submitted because of the following error(s).\n"; msg += "Please correct these error(s) and re-submit.\n"; msg += "____________________________________\n\n" function init() { //1. Log in sforceClient.useCookies = true; sforceClient.registerInitCallback(processLead); sforceClient.init("{!API_Session_ID}", "{!API_Partner_Server_URL_70}", true); } function processLead() { //2. Retrieve PostalCode for lead sforceClient.setBatchSize(1); var sql = "Select PostalCode From Lead where Id = '" + leadId + "'" var qrLead = sforceClient.Query(sql); if (qrLead.className.toLowerCase() == "queryresult") { if (qrLead.size > 0) { var lead = qrLead.records[0]; var zip = lead.get("PostalCode"); //3. Retrieve zip__c values for the PostalCode sforceClient.setBatchSize(1); sql = "Select Zip__c, City__c, State__c, County__c, FIPS__c, OwnerId From Zip__c where Zip__c = '" + zip + "'" var qrZip = sforceClient.Query(sql); if (qrZip.className.toLowerCase() == "queryresult") { if (qrZip.size > 0) { var zipRecord = qrZip.records[0]; var city = zipRecord.get("City__c"); var state = zipRecord.get("State__c"); var county = zipRecord.get("County__c"); var FIPS = zipRecord.get("FIPS__c"); //var rsm = zipRecord.get("RSM__c"); var rsmId = zipRecord.get("OwnerId"); } else { errors += "No zip table information found for entered postal code."; } } //4. Update lead with zip_c values //lead.set("Id", leadId); lead.set("City", city); lead.set("State", state); lead.set("County__c", county); //lead.set("FIPS__c", FIPS); lead.set("OwnerId", rsmId); var saveResult = sforceClient.Update([lead])[0]; alert(saveResult.toString()); } else { errors += "No postal code exists for selected lead."; } } //5. Report any errors, refresh parent, and close if (errors != "") { msg += errors; alert(msg); return; } window.opener.location.reload(); window.close(); } //--> </script> </head> <body onload="init();"> </body> </html>
Rich.ax131Rich.ax131
Looks and works great, Dave. My only remaining confusion is that I noticed you had the code "lead.set("Id", leadId);" commented out in your reply. The only way I could get this to work was to allow that code to execute.

I definitely understand why you would not suggest exposing your username and password in JavaScript, but I hadn't dug into alternatives yet.

Thanks again for your help!

Rich
DevAngelDevAngel
Sorry, I thought you were requesting the Id field when you did the lead query. If you include the id in your select statement, then you wouldn't need to set it later.

Select Id, PostalCode From Lead where Id = '" + leadId + "'

For that matter, you should always use the retrieve call if your only criteria is the id of the object (id = ''). That call is optimized for id queries. Check out the doc on the retrieve call.

Cheers