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
Stavros McGillicuddyStavros McGillicuddy 

Code to query and concatenate Opportunity Line items only works if more than one line item exists

At the click of a custom button on an Opportunity object, this is supposed to:
  1. Capture all Opportunity line items
  2. Concatenate all line items except ones that have DISCOUNT in the name into a Samples_Sent__c field
  3. Delete all Opportunity line items
It executes perfectly if the net count (opportunity line items that do not have DISCOUNT in the name) of the items being concatenated is two or more but does nothing (does not concatenate and no errors) if the net count is one.
 
{!REQUIRESCRIPT("/soap/ajax/32.0/connection.js")}
{!REQUIRESCRIPT("/soap/ajax/32.0/apex.js")}
var record = new sforce.SObject("Opportunity");
record.Id = '{!Opportunity.Id}';

var retriveOpptyLineItems = sforce.connection.query("Select PricebookEntry.Product2.Name, Quantity, TotalPrice From OpportunityLineItem WHERE OpportunityId = '{!Opportunity.Id}' and (NOT Name like '%Discount%')");

var strProductNames = '';
for(var i=0; i<retriveOpptyLineItems.records.length ; i++){
strProductNames += 'PRODUCT NAME: ' + retriveOpptyLineItems.records[i].PricebookEntry.Product2.Name + ' --- QUANTITY: ' + retriveOpptyLineItems.records[i].Quantity + ' --- TOTAL PRICE: $ ' + retriveOpptyLineItems.records[i].TotalPrice +',' + '\n ';
}

//eliminate the last ','
if(strProductNames.length>0){
strProductNames = strProductNames.substring(0,strProductNames.length-1);
}
record.Samples_Sent__c = strProductNames;

sforce.connection.update([record]);
window.location.reload();

 
Best Answer chosen by Stavros McGillicuddy
Stavros McGillicuddyStavros McGillicuddy
THank you for your help Kevin.
This is what finally worked for me
{!REQUIRESCRIPT("/soap/ajax/32.0/connection.js")}
{!REQUIRESCRIPT("/soap/ajax/32.0/apex.js")}

var opp = new sforce.SObject("Opportunity");
opp.Id = '{!Opportunity.Id}';

result = sforce.connection.query("Select PricebookEntry.Product2.Name, Quantity, TotalPrice From OpportunityLineItem WHERE OpportunityId = '{!Opportunity.Id}' and (NOT Name like '%Discount%')");
records = result.getArray("records");

var strProductNames = '';
for(var i=0; i<records.length ; i++){
 strProductNames += 'PRODUCT NAME: ' + records[i].PricebookEntry.Product2.Name + ' --- QUANTITY: ' + records[i].Quantity + ' --- TOTAL PRICE: $ ' + records[i].TotalPrice +',\n';
}

if(strProductNames.length>0){
 strProductNames = strProductNames.substring(0,strProductNames.length-2);
}
opp.Samples_Sent__c = strProductNames;

sforce.connection.update([opp]);
window.location.reload();

 
 

All Answers

Kevin CrossKevin Cross
I do not have my test environment up to verify, but I suspect the issue is how SOQL translates results.  If there only is one row IIRC, it will return an OpportunityLineItem versus with multiple you get List<OpportunityLineItem> (or your records array).  In other words, the code likely is failing becasue OpportunityLineItem.records is not valid.  What you can do instead is see if variable retriveOpptyLineItems is an instance of OpportunityLineItem then process as retriveOpptyLineItems.TotalPrice if not as retriveOpptyLineItems.records[i].TotalPrice for example.
Kevin CrossKevin Cross
P.S. by convention, I normally use ++i to increment variable before body of loop versus after but notice in the documentation (https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_calls_query.htm) they show both the java and C# code with ++i instead of i++.  Potentially there is a technical reason for this, so you may want to try that as well.
Stavros McGillicuddyStavros McGillicuddy
Thanks Kevin. I'm afraid being a noob, I am not understanding what you mean. The code above was put together with a lot of help from the discussion forums. 
Kevin CrossKevin Cross
Okay.  See if these https://developer.salesforce.com/docs/atlas.en-us.ajax.meta/ajax/sforce_api_ajax_more_samples_asynch.htm and https://developer.salesforce.com/docs/atlas.en-us.ajax.meta/ajax/sforce_api_ajax_more_samples_asynch.htm explain better.  My point was that .records may not be a valid method in the result object from the query.  In the linked examples for Javascript as I see that is what you are using, you will see that they call result.getArray("records") or in your call retriveOpptyLineItems.getArray("records") before performing loop on new variable "records".  In that code, it shows the proper i++ I would expect, so you can ignore my comment about ++i.
Stavros McGillicuddyStavros McGillicuddy
THank you for your help Kevin.
This is what finally worked for me
{!REQUIRESCRIPT("/soap/ajax/32.0/connection.js")}
{!REQUIRESCRIPT("/soap/ajax/32.0/apex.js")}

var opp = new sforce.SObject("Opportunity");
opp.Id = '{!Opportunity.Id}';

result = sforce.connection.query("Select PricebookEntry.Product2.Name, Quantity, TotalPrice From OpportunityLineItem WHERE OpportunityId = '{!Opportunity.Id}' and (NOT Name like '%Discount%')");
records = result.getArray("records");

var strProductNames = '';
for(var i=0; i<records.length ; i++){
 strProductNames += 'PRODUCT NAME: ' + records[i].PricebookEntry.Product2.Name + ' --- QUANTITY: ' + records[i].Quantity + ' --- TOTAL PRICE: $ ' + records[i].TotalPrice +',\n';
}

if(strProductNames.length>0){
 strProductNames = strProductNames.substring(0,strProductNames.length-2);
}
opp.Samples_Sent__c = strProductNames;

sforce.connection.update([opp]);
window.location.reload();

 
 
This was selected as the best answer