function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Steve HuseSteve Huse 

Custom button to create case from won opportunity

Hi all,

 

I've struggled with this for a while and welcome any advice.

 

I want to place a custom button in opportunities (detail page) that, providing the opp stage is 'Closed Won' creates a case, copying a number of opp fields across into the case fields as it does so.

 

I currently have two custom buttons on the page that I'm testing ... both using Onclick Javascript.

 

HERE'S THE CODE BEHIND THE FIRST ONE:

if ("{!Opportunity.StageName}" == 'Closed Won')

{location.href = "/500/e?retURL=%2F500%2Fo

&cas4={!Account.Name}

&cas3={!Opportunity.Opportunity_Contact__c}

&cas5={!Opportunity.Type}

&cas11={!'Converted Opportunity'}

&cas14={!Opportunity.Name}

&cas15={!Opportunity.Requirement__c}

&retURL=/{!Opportunity.Id}&saveURL=/{!Opportunity.Id}";}

else

{alert('Opportunity must be won before a case can be created.'); }

 

What works:

  • The 'new case' page is launched and the fields are populated.

What doesn't work:

  • It doesn't always copy the full content of each field across ... i.e. an opportunity account name of 'ABC Construction Ltd' only populates as 'ABC' in the account name field on the case screen.
  • It requires the user to click the Save button after the fields have been populated.

 

HERE'S THE CODE BEHIND THE SECOND ONE:

{!REQUIRESCRIPT("/soap/ajax/25.0/connection.js")}
var status = "{!Opportunity.StageName}";
var newRecords = [];

if (status == "Closed Won")
{
var c = new sforce.SObject("Case");
c.AccountId = "{!Opportunity.AccountId}";
c.Contact = "{!Opportunity.Opportunity_Contact__c}";   <-------- Problem arises when other fields are included.
//add any other related fields you like

newRecords.push(c);

result = sforce.connection.create(newRecords);
}
else
{
alert ('Opportunity must be won before a case can be created.');
}

 

What works:

  • Providing the line in red is left out, the button works fine.

What doesn't work:

  • As soon as I try to include any additional fields to carry across from the opp to the case, the button no longer works ... no case is created at all.

 

Can anyone tell me which code is best, or provide some guidance as to how to tweak either of the existing codes so that they work in the way I'd like them to?

 

Sorry for the long post!

 

Regards


Steve

 

SteveBowerSteveBower

Hi, for approach one, think about the mechanism of action that you're using.  You're building a URL where your browser will be redirected to.   If you typed in a URL and you left a space in it somewhere, well, that's the end of the URL.  Space is a terminiator.   So, the rest of the field that has a space in it won't be passed, neither will the other fields.   It's even worse if, for example, one of your fields had data that contained ampersands because then you'd be declaring new parameters.

 

Look into {!URLENCODE()).

 

 

Approach two's only flaw that I can see is that the "c" object doesn't have a field called Contact.  "c.Contact" doesn't exist, but "c.ContactId", does exist. 

 

 

I'd go with approach one by the way.  Best, Steve.

Steve HuseSteve Huse

Thanks Steve - some solid advice there.

 

I have a couple of questions please.

 

1.  Given the issue of the first URL method failing to pass words after a space in a field whereas the second method doesn't suffer this problem, why is the first method your preference?

 

2.  I've tweaked the 'second method' code which now passes all relevant Opp fields into a new case, EXCEPT the case contact field.  In Opps I have a custom field called Opportunity_Contact__c which looksup to Contacts to allow the user to select the contact associated with the opportunity.  I want the contact's name in this custom field to be sent into the 'Contact' field in the case, which in itself is a lookup field to Contacts.

 

I'm inserting this line: c.Contact = "{!Opportunity.Opportunity_Contact__c}";    ... but no-go.  You mentioned that the case contact field is called ContactId, but that doesn't seem to be the case (well I'm not seeing this field name in the Case fields list anyway).  The standard field in Cases is labelled 'Contact Name' but the field name is just listed as 'Contact'.

 

Any chance of shedding some light?

 

BW

 

Steve

Alex.AcostaAlex.Acosta

As far as your question in regards to ContactId, these fields can be seen with anything useing the API / Metadata from Salesforce. You can either use Eclipse or Workbench to see these fields. But Steve is correct on the field ceing called ContactId.

 

For more information on what standard fields exist on Cases please refer to the docs. http://www.salesforce.com/us/developer/docs/api/Content/sforce_api_objects_case.htm

 

Just so you have some knowledge on how lookups / master detail relationships works. In the backend for any database, these relationships are stored by related record Id. There are many reasons for this, one major one would be for having a unique index / field which can bring back the correct record since the 'Name' field is not unquie in most cases for records. To make things easier on an end user, Salesforce will automatically show you the related field's name rather than the Id, though it's still on the page through the use of a hidden field.

Steve HuseSteve Huse

Thanks Alex,

 

I'm not sure what I've got wrong ... here's my button code:

 

{!REQUIRESCRIPT("/soap/ajax/25.0/connection.js")}
var status = "{!Opportunity.StageName}";
var newRecords = [];

if (status == "Closed Won")
{
   var c = new sforce.SObject("Case");
   c.AccountId = "{!Opportunity.AccountId}";
   c.Type = "{!Opportunity.Type}";
   c.Subject = "{!Opportunity.Name}";
   c.Origin = "{!'Converted Opportunity'}";
   c.Description = "{!Opportunity.Requirement__c}";
   c.ContactId= "{!Opportunity.Opportunity_Contact__c}";

 

   newRecords.push(c);

   result = sforce.connection.create(newRecords);
   alert ('Case has been created.')}
else
{
   alert ('Opportunity must be won before a case can be created.');
}

 

... it works fine until I put the red line above in, and then it fails to create a new case at all.

 

Are you able to see what's wrong?

 

Many thanks

 

Steve

SteveBowerSteveBower

Hi, well, the reason I'd go with the first, button, method is because it's simpler and uses less resources to execute.  It's also easier coding and the problems are far easier to find and debug.  To debug it, just use the browser's tools to look at the HTML that's been generated for your button.

 

However, based on your code below, I first think that this:

 

c.Origin = "{!'Converted Opportunity'}";

 

Should be:

 

c.Origin = "Converted Opportunity";  

 

 

 

For this line,    

c.ContactId= "{!Opportunity.Opportunity_Contact__c}";

 

I don't know why this would fail unless the Opportunity_Contact__c field isn't an ID type field (e.g. a Lookup), but instead contains a text string or something with the contact's name.

 

So, check to see what the definition for the Opportunity_Contact__c field is.  

 

I know there is the temptation to think that Case.Contact should be the text string of the Contact.Name field.   But, it should instead be the Contact's ID and then Salesforce will automatically do the job, when displaying the Case, of looking up the Contact based on the ID, pulling out the Name field and displaying it for you.   I'm wondering if this temptation led you to defining Opportunity_Contact__c as a text field instead of an Id.

 

Best, Steve.

Steve HuseSteve Huse

Thanks Steve,

 

I've corrected the c.Origin line, which still populates fine in the case.

 

The custom Opportunity_Contact field is a lookup (see field information below)

 

Field Information:
Field LabelOpportunity ContactObject NameOpportunity
Field NameOpportunity_ContactData TypeLookup
API NameOpportunity_Contact__c  
Description 
Help Text 
Created BySteve Huse, 16/07/2012 11:58Modified BySteve Huse, 16/07/2012 11:58
Lookup Options:
Related ToContactChild Relationship NameOpportunities
Related List LabelOpportunities
RequiredNot Checked
What to do if the lookup record is deleted?Clear the value of this field.

 

I really appreciate your help ... I'm a bit further forward.  If you wake up in the middle of the night realising what my problem is, be sure to let me know!

 

Thanks again.

 

Steve

SteveBowerSteveBower

 

Sorry, I wasn't thinking.   Watch what happens if, for this particular Opportunity, the Contact field is null.

 

c.ContactId= "";

 

Perhaps that's what's happening?   Try:

 

c.ContactId = "{!NULLVALUE(Opportunity.Opportunity_Contact__c, null)}";

 

or some such thing... Best, Steve.

Steve HuseSteve Huse

Hi Steve,

 

Yes, if I delete the contact name from the Opportunity_Contact field on my test opportunity, the case then creates ok (minus a case contact name obviously).  If I re-populate this field and hit my 'Create case' button, no case is created.

 

I've tried replacing the original c.ContactId = "{!Opportunity.Opportunity_Contact__c}"; line with the new line you've suggested: c.ContactId = "{!NULLVALUE(Opportunity.Opportunity_Contact__c, null)}"; but the same problem exists ... no case is created if the Opportunity_Contact field is populated, but it does if left blank.

 

BW

 

Steve

SteveBowerSteveBower

Well, I suppose it's more debugging time.   You could always throw in an    alert("Case is: " + c); and see what the Javascript object contains.

 

If you use Chrome then in the console you can look at the various Javascript scripts that are being generated and see what's going on.

 

Best, Steve.

Alex.AcostaAlex.Acosta

Best thing you can do for populating these types of fields which are relationships are just IF conditions.

Steve HuseSteve Huse

Hi Alex,

 

Can you give me an example of what you mean please?  Where do I use the IF condition?

 

Regards


Steve

Alex.AcostaAlex.Acosta

if your code looks like so, just add what i have in red.

 

{!REQUIRESCRIPT("/soap/ajax/25.0/connection.js")}
var status = "{!Opportunity.StageName}";
var newRecords = [];
if (status == "Closed Won")
{
   var c = new sforce.SObject("Case");
   c.AccountId = "{!Opportunity.AccountId}";
   c.Type = "{!Opportunity.Type}";
   c.Subject = "{!Opportunity.Name}";
   c.Origin = "{!'Converted Opportunity'}";
   c.Description = "{!Opportunity.Requirement__c}";
   if(null != {!Opportunity.Opportunity_Contact__c}){
      c.ContactId= "{!Opportunity.Opportunity_Contact__c}";
   }
   newRecords.push(c);
   result = sforce.connection.create(newRecords);
   alert ('Case has been created.')}
else
{
   alert ('Opportunity must be won before a case can be created.');
}

 

Steve HuseSteve Huse

Steve / Alex,


Thank you both ... I'm finally there.

 

The line that was preventing the case being created was as follows:

 

c.Contact = "{!Opportunity.Opportunity_Contact__c}";

 

Knowing the name of my opportunity fields, I hand typed the button code, but using the 'Insert field' tool I've just noticed that I am able to insert this field: {!Opportunity.Opportunity_ContactId__c}.

 

I never created this field ... it's a variant of my Opportunity_Contact custom field that appears to have been automatically created by Salesforce.

 

Using this field the code now works fine ... a case is created and all fields populate correctly.

 

Thanks to you both for your time.

 

BW


Steve