- Go to Setup->App Setup->Create->Report Types.
- Make a new Custom Report Type. Select the primary object as Account.
- On the next screen set the "B" object to Cases -- I use "with or without cases" so you can see accounts of yours that have no cases onthem.
- Save it. Now go to the reports tab and make a report of this type. When you get to the filter part you'll see that you can now filter by "My Account." You can also add regular criteria to case fields like Case.IsClosed so that you only see the open cases in the report, for example.
A blog reviving some of my most popular posts ever from the Salesforce.com blog world, and some brand new stuff too! Tips, tricks and sample code for Salesforce.com.
Monday, June 24, 2013
Reporting On "Cases Filed By My Accounts"
The other day a poster on the Best Practices board asked whether there was a way to filter a report on Cases by "My Accounts." By default, Case reports are filterable by the case owner, but not by account. Fortunately, there is a way to do this, it's just a little roundabout: you have to create a case report which is driven off of Account using Custom Report Types. Here's how.
Monday, June 17, 2013
Workflow From Case Comments
Workflow From Case Comments gives you the ability to create a workflow rule on the Case Comments object. From that rule, you can create a field update that takes effect on either the comment itself or on the parent case.
For example, let's say I have a process whereby I set my case to a status of "Awaiting Customer Response" when I'm waiting for the customer to get back to me. Now my customer logs into the Customer Portal and adds a comment to the case. That constitutes a response, so the system should automatically set my case back to a "Working" status.
All I have to do is write a workflow rule on Case Comment with the requisite criteria (and the criteria can refer to items from the Case as well). Once that's done, I can make a field update that updates the status field on the case.
As people begin creating workflows from Case Comments, they inevitably notice some restrictions about these workflow rules. They ask, what if I want to send an email to the case owner? Why can't the email alert find that field?
As with workflow from Email Messages, Workflow From Case Comments is a "chaining" workflow -- it can trigger other workflow rules. Certain operations on Case Comment are limited because of what the workflow action is "looking at" -- an Email Alert, for example, is "looking at" the Case Comment and so cannot see the Case Owner, for example. However, you can put an email alert on a workflow on the parent case, and that workflow will get triggered and send out the email (and the email will be associated to the parent case, as you might expect).
So, although you can't send an email directly from a Workflow From Case Comments, you can put an email alert on the parent case. So, for example, you might make a Workflow From Case Comments that updates a "Last Comment" field on the parent case with the text of the most recent comment, and then make a workflow on Case which emails out that last comment to the Case Owner, or to certain members of the Case Team.
For example, let's say I have a process whereby I set my case to a status of "Awaiting Customer Response" when I'm waiting for the customer to get back to me. Now my customer logs into the Customer Portal and adds a comment to the case. That constitutes a response, so the system should automatically set my case back to a "Working" status.
All I have to do is write a workflow rule on Case Comment with the requisite criteria (and the criteria can refer to items from the Case as well). Once that's done, I can make a field update that updates the status field on the case.
As people begin creating workflows from Case Comments, they inevitably notice some restrictions about these workflow rules. They ask, what if I want to send an email to the case owner? Why can't the email alert find that field?
As with workflow from Email Messages, Workflow From Case Comments is a "chaining" workflow -- it can trigger other workflow rules. Certain operations on Case Comment are limited because of what the workflow action is "looking at" -- an Email Alert, for example, is "looking at" the Case Comment and so cannot see the Case Owner, for example. However, you can put an email alert on a workflow on the parent case, and that workflow will get triggered and send out the email (and the email will be associated to the parent case, as you might expect).
So, although you can't send an email directly from a Workflow From Case Comments, you can put an email alert on the parent case. So, for example, you might make a Workflow From Case Comments that updates a "Last Comment" field on the parent case with the text of the most recent comment, and then make a workflow on Case which emails out that last comment to the Case Owner, or to certain members of the Case Team.
Monday, June 10, 2013
Using Visualforce Components Defined in a Managed Package
As part of our KXEN Predictive Offers package, we define a couple of Visualforce components. This has two purposes. First, it fosters code reuse: we reuse these components on pages within our package that apply to Contacts, Leads and PersonAccounts, so we don't have to duplicate a bunch of Visualforce code. Then, our customers may want to embed the capability to show an offer into a larger Visualforce page, so they can use these components themselves in their own pages.
In testing the latter capability today, I ran into a buzzsaw of incomplete and hard-to-find documentation on the Salesforce.com side, so I am going to address it here so that folks googling this topic in the future might find this.
The first issue was that, in attempting to use our component in a target org, it was not found. I was specifying it just as we do in our own pages, like this:
<c:ShowOfferConsole userId="{!Contact.Id}"/>
This was buzzsaw #1: within our package, we can refer to the component using the standard c: notation. The component was global, so I should be able to use it, right? I also tried c:Offers__ShowOfferConsole, thinking maybe the kind of namespacing you do in Apex would work, but no dice there. Finally I figured it out: outside our package I had to refer to it via its package namespace (which in this case is "Offers"), like this:
<Offers:ShowOfferConsole userId="{!Contact.Id}"/>
Great! That only took me about an hour to figure out! But it still didn't work, now for a different reason. Now I get this error:
Error: Cannot use attribute userid (in component offers:showofferconsole) without global access in a component/page that is not in the same namespace as the component in my_visualforce_page at line 117 column 61
This took a while to track down. The component is global, yes, so I should be able to use it; but in components, like in Apex classes, you also have to make the individual attributes global in order to access them from outside the package. Fortunately this is our own package so we can modify the code, and here we needed to modify the component to make the userId attribute global. Now, finally, I can use the component outside the package!
In testing the latter capability today, I ran into a buzzsaw of incomplete and hard-to-find documentation on the Salesforce.com side, so I am going to address it here so that folks googling this topic in the future might find this.
The first issue was that, in attempting to use our component in a target org, it was not found. I was specifying it just as we do in our own pages, like this:
<c:ShowOfferConsole userId="{!Contact.Id}"/>
This was buzzsaw #1: within our package, we can refer to the component using the standard c: notation. The component was global, so I should be able to use it, right? I also tried c:Offers__ShowOfferConsole, thinking maybe the kind of namespacing you do in Apex would work, but no dice there. Finally I figured it out: outside our package I had to refer to it via its package namespace (which in this case is "Offers"), like this:
<Offers:ShowOfferConsole userId="{!Contact.Id}"/>
Great! That only took me about an hour to figure out! But it still didn't work, now for a different reason. Now I get this error:
Error: Cannot use attribute userid (in component offers:showofferconsole) without global access in a component/page that is not in the same namespace as the component in my_visualforce_page at line 117 column 61
This took a while to track down. The component is global, yes, so I should be able to use it; but in components, like in Apex classes, you also have to make the individual attributes global in order to access them from outside the package. Fortunately this is our own package so we can modify the code, and here we needed to modify the component to make the userId attribute global. Now, finally, I can use the component outside the package!
Monday, June 3, 2013
Assigning Cases According To The Email Address From Which They Originated
Someone asked me an interesting question recently, which was:
I have multiple email addresses that correspond to different divisions of my company. How do I assign cases to these various divisions according to which email address the original email arrived at?
This seemed at first to be a bit of a head-scratcher, since the email address itself is not stored anywhere on the case. However, there is a simple solution: use Case Origin.
Case has a field called Case Origin which can be set on a per-routing-address basis. Our first step, then, will be to set up our Case Origin field to contain the necessary items pertaining to each division. Go to Setup->Customize->Cases->Fields and click the Case Origin link. At the bottom of the page you'll find the Picklist Values. Press the New button to add some entries to this list, one for each division (note that you can add more than one at a time by separating them with a linefeed).
Now go over to Setup->Customize->Cases->Email-To-Case. Click on the Edit link for your Support routing address for each division. At the bottom of the ensuing page, you can set the Case Origin for this routing address. After saving this, you now have a field on Case which records which email address it was created from! You can now use that in your assignment rules. And that's all there is to it.
Oh, and one more thing: if your process requires that you use record types on cases, you can do the exact same trick with the Case Record Type field instead.
I have multiple email addresses that correspond to different divisions of my company. How do I assign cases to these various divisions according to which email address the original email arrived at?
This seemed at first to be a bit of a head-scratcher, since the email address itself is not stored anywhere on the case. However, there is a simple solution: use Case Origin.
Case has a field called Case Origin which can be set on a per-routing-address basis. Our first step, then, will be to set up our Case Origin field to contain the necessary items pertaining to each division. Go to Setup->Customize->Cases->Fields and click the Case Origin link. At the bottom of the page you'll find the Picklist Values. Press the New button to add some entries to this list, one for each division (note that you can add more than one at a time by separating them with a linefeed).
Now go over to Setup->Customize->Cases->Email-To-Case. Click on the Edit link for your Support routing address for each division. At the bottom of the ensuing page, you can set the Case Origin for this routing address. After saving this, you now have a field on Case which records which email address it was created from! You can now use that in your assignment rules. And that's all there is to it.
Oh, and one more thing: if your process requires that you use record types on cases, you can do the exact same trick with the Case Record Type field instead.
Monday, May 27, 2013
The Mass Case Close Button
From time to time, people on the Salesforce.com forums ask how they can make a Mass Case Close button that skips the Case Close screen and just closes the cases directly. This is just a twist on the Quick Case Close button that I have written about previously on this blog. The code is quite simple:
{!REQUIRESCRIPT("/soap/ajax/13.0/connection.js")}
var records = {!GETRECORDIDS($ObjectType.Case)};
if (records[0] == null) {
alert("Please select at least one case to close.")
} else {
//Get more info on the cases that were selected and generate a query out of it
var updateRecords = [];
//Iterate through the returned results
for (var recordIndex=0;recordIndex<records.length;recordIndex++) {
var caseUpdate = new sforce.SObject("Case");
caseUpdate.Id = records[recordIndex];
caseUpdate.Status = 'Closed';
updateRecords.push(caseUpdate);
}
var result = sforce.connection.update(updateRecords);
//handle errors here
if (result.error) {
alert('There was an error processing one or more cases');
}
//Reload the list view to show what he now owns
parent.window.location.reload();
}
To add this code, go to Setup->Cases->Buttons and Links and make a new custom button called Mass Close. Its Display Type should be set to List Button, its Behavior to Execute JavaScript, and its Content Source to OnClick JavaScript. Paste the above code into the OnClick JavaScript field -- but be sure to replace the caseUpdate.Status = 'Closed'; line with a status that is present in your org.
Now you'll have to add this button to the Case list view. To do this, go to Setup->Cases->Search Layouts. Click Edit next to the Cases List View entry, and add your new button from the Available Buttons section to the Selected Buttons section. As with the Contention-Proof Accept Button, the trick here is that GETRECORDIDS call -- it gets us the list of Case IDs that you selected from the list. The rest here is simple, just put all those Case IDs into an array and set the case status fields to Closed, and call update. Easy! Just imagine what other sorts of mass actions you could do with this method. It's hard to fathom the creativity of the readers of this blog.
{!REQUIRESCRIPT("/soap/ajax/13.0/connection.js")}
var records = {!GETRECORDIDS($ObjectType.Case)};
if (records[0] == null) {
alert("Please select at least one case to close.")
} else {
//Get more info on the cases that were selected and generate a query out of it
var updateRecords = [];
//Iterate through the returned results
for (var recordIndex=0;recordIndex<records.length;recordIndex++) {
var caseUpdate = new sforce.SObject("Case");
caseUpdate.Id = records[recordIndex];
caseUpdate.Status = 'Closed';
updateRecords.push(caseUpdate);
}
var result = sforce.connection.update(updateRecords);
//handle errors here
if (result.error) {
alert('There was an error processing one or more cases');
}
//Reload the list view to show what he now owns
parent.window.location.reload();
}
To add this code, go to Setup->Cases->Buttons and Links and make a new custom button called Mass Close. Its Display Type should be set to List Button, its Behavior to Execute JavaScript, and its Content Source to OnClick JavaScript. Paste the above code into the OnClick JavaScript field -- but be sure to replace the caseUpdate.Status = 'Closed'; line with a status that is present in your org.
Now you'll have to add this button to the Case list view. To do this, go to Setup->Cases->Search Layouts. Click Edit next to the Cases List View entry, and add your new button from the Available Buttons section to the Selected Buttons section. As with the Contention-Proof Accept Button, the trick here is that GETRECORDIDS call -- it gets us the list of Case IDs that you selected from the list. The rest here is simple, just put all those Case IDs into an array and set the case status fields to Closed, and call update. Easy! Just imagine what other sorts of mass actions you could do with this method. It's hard to fathom the creativity of the readers of this blog.
Thursday, May 23, 2013
The Quick Case Close Button
People often ask me how they can get around the Close Case page. One option to do this is to replace the standard Close Case button with a custom button of your own. It's remarkably easy to do! Here's how.
First, go to Setup->Cases->Buttons and Links and make a new custom button called Close Case. Its Display Type should be set to Detail Page Button, its Behavior to Execute JavaScript, and its Content Source to OnClick JavaScript.
Now you need only paste the following JavaScript in there:
{!REQUIRESCRIPT("/soap/ajax/13.0/connection.js")}
var caseObj = new sforce.SObject("Case");
caseObj.Id = '{!Case.Id}';
caseObj.Status = 'Closed';
var result = sforce.connection.update([caseObj]);
if (result[0].success=='false') {
alert(result[0].errors.message);
} else {
location.reload(true);
}
This is assuming, of course, that you actually have a status called "Closed" -- but if you don't, don't despair -- just change the caseObj.Status = 'Closed'; line to a closed status that actually exists in your case status list.
Now edit your Case page layout. Click on the Detail Page Buttons box and it will be highlighted, then click the Edit Properties button. Here you'll be able to hide the standard Close Case button and show your new custom Close Case button. Finally test your new button by making a test case and closing it. Voila! The button sets the case to a closed status and reloads the page to give you feedback that in fact it was closed!
Please note that because this trick uses the API, it will only work for Enterprise Edition and up, or for Professional Edition with the API add-on.
First, go to Setup->Cases->Buttons and Links and make a new custom button called Close Case. Its Display Type should be set to Detail Page Button, its Behavior to Execute JavaScript, and its Content Source to OnClick JavaScript.
Now you need only paste the following JavaScript in there:
{!REQUIRESCRIPT("/soap/ajax/13.0/connection.js")}
var caseObj = new sforce.SObject("Case");
caseObj.Id = '{!Case.Id}';
caseObj.Status = 'Closed';
var result = sforce.connection.update([caseObj]);
if (result[0].success=='false') {
alert(result[0].errors.message);
} else {
location.reload(true);
}
This is assuming, of course, that you actually have a status called "Closed" -- but if you don't, don't despair -- just change the caseObj.Status = 'Closed'; line to a closed status that actually exists in your case status list.
Now edit your Case page layout. Click on the Detail Page Buttons box and it will be highlighted, then click the Edit Properties button. Here you'll be able to hide the standard Close Case button and show your new custom Close Case button. Finally test your new button by making a test case and closing it. Voila! The button sets the case to a closed status and reloads the page to give you feedback that in fact it was closed!
Please note that because this trick uses the API, it will only work for Enterprise Edition and up, or for Professional Edition with the API add-on.
Monday, May 20, 2013
The Quick Email Button Revisited: Sending One-And-Done Emails with Workflow
In my popular post The Quick Email Button I reference a means of making a button that just sends the email immediately with no edit window. I then mention that it's been deprecated for orgs that have been created since 2010.
Salesforce.com deprecated this URL parameter for a good reason: the save=1 parameter is not particularly secure, and a clever attacker could make spoofed links to Salesforce.com to save random data to your org. I will say this about URL hacks in general: they are hacks, and that makes them inherently unreliable. Sometimes they will stop working. So despite my tacit encouragement in my original post, try not to use them if you can avoid them.
The question remains, then:
How can you make a button that sends a one-and-done email?
This simple but roundabout method uses Workflow email alerts and a Javascript custom button. Note that this method uses the Salesforce.com API, so it will only work with orgs that have the API (generally Enterprise Edition and above, or Professional Edition with the API add-on). Here's how to do it:
1. Make a custom checkbox field on your object called "Send Email." Don't show it on any page layouts -- it should only be used as a proxy for the workflow we'll define below.
2. Make a new workflow rule on this object and set it to run when a record is "created, and any time it’s edited to subsequently meet criteria." Change the Rule Criteria to run if the "formula evaluates to true," and in the formula box, enter ISCHANGED(Send_Email__c).
3. Press Next and add an Email Alert that selects the proper template and sends to the person you want to send to (generally the email address of the Lead or Contact you're putting the button on). Save the email alert. Don't forget to activate your workflow rule!
4. Now go to your object and create a custom button on it. Set this custom button to Execute Javascript, and put code in that looks like this (the below example is for the Lead object, you'll need to modify it slightly for any other object type):
{!REQUIRESCRIPT("/soap/ajax/16.0/connection.js")}
var leadObj= new sforce.SObject("Lead");
leadObj.Id='{!Lead.Id}';
//Update that checkbox to true, which will trigger the workflow
leadObj.Send_Email__c = true;
var result=sforce.connection.update([leadObj]); /*updating the object*/
if (result[0].success=='false') {
alert(result[0].errors.message);
} else {
location.reload(true);
}
5. Add this custom button to your page layouts.
And voila! You now have a custom button that immediately sends out an email without any further user intervention.
There's another way to do this with just a custom button alone and no workflow, but it's a bit more involved on the code side. I'll cover that in a future post on this topic.
Happy emailing!
Salesforce.com deprecated this URL parameter for a good reason: the save=1 parameter is not particularly secure, and a clever attacker could make spoofed links to Salesforce.com to save random data to your org. I will say this about URL hacks in general: they are hacks, and that makes them inherently unreliable. Sometimes they will stop working. So despite my tacit encouragement in my original post, try not to use them if you can avoid them.
The question remains, then:
How can you make a button that sends a one-and-done email?
This simple but roundabout method uses Workflow email alerts and a Javascript custom button. Note that this method uses the Salesforce.com API, so it will only work with orgs that have the API (generally Enterprise Edition and above, or Professional Edition with the API add-on). Here's how to do it:
1. Make a custom checkbox field on your object called "Send Email." Don't show it on any page layouts -- it should only be used as a proxy for the workflow we'll define below.
2. Make a new workflow rule on this object and set it to run when a record is "created, and any time it’s edited to subsequently meet criteria." Change the Rule Criteria to run if the "formula evaluates to true," and in the formula box, enter ISCHANGED(Send_Email__c).
3. Press Next and add an Email Alert that selects the proper template and sends to the person you want to send to (generally the email address of the Lead or Contact you're putting the button on). Save the email alert. Don't forget to activate your workflow rule!
4. Now go to your object and create a custom button on it. Set this custom button to Execute Javascript, and put code in that looks like this (the below example is for the Lead object, you'll need to modify it slightly for any other object type):
{!REQUIRESCRIPT("/soap/ajax/16.0/connection.js")}
var leadObj= new sforce.SObject("Lead");
leadObj.Id='{!Lead.Id}';
//Update that checkbox to true, which will trigger the workflow
leadObj.Send_Email__c = true;
var result=sforce.connection.update([leadObj]); /*updating the object*/
if (result[0].success=='false') {
alert(result[0].errors.message);
} else {
location.reload(true);
}
5. Add this custom button to your page layouts.
And voila! You now have a custom button that immediately sends out an email without any further user intervention.
There's another way to do this with just a custom button alone and no workflow, but it's a bit more involved on the code side. I'll cover that in a future post on this topic.
Happy emailing!
Subscribe to:
Posts (Atom)