• Zachary Alexander 30
  • NEWBIE
  • 10 Points
  • Member since 2017

  • Chatter
    Feed
  • 0
    Best Answers
  • 1
    Likes Received
  • 0
    Likes Given
  • 5
    Questions
  • 5
    Replies
I'm trying to understand why I had to deactivate a trigger (code below) in order to prevent a SOQL Queries 101 problem.

It doesn't utilize any SOQL queries (to the best of my knoweldge) and it never changed any field values that could cause other triggers to fire. This is verified beyond shadow of doubt.

Can somebody please help me to understand what is happening?
 
trigger Trig_SetClinicalSignOffUser on Inviscid__Session__c (before insert, before update) {
    
    //Retrieve metadata record
    Trigger_Switch__mdt[] switchList = [SELECT MasterLabel, Turn_Trigger_On__c FROM Trigger_Switch__mdt WHERE MasterLabel = 'Trig_SetClinicalSignOffUser'];
    If(switchList[0].Turn_Trigger_On__c == True) {
        
        If(Trigger.IsInsert) {
            For (Inviscid__Session__c x : Trigger.New) {
                If (x.Inviscid__Status__c == 'Reviewed / Ready for Billing') {
                    x.Inviscid__Clinical_Sign_Off_User__c = UserInfo.getUserId();
                    x.Inviscid__Clinical_Sign_Off_Date__c = System.Now();
                }
            }
        }

        If(Trigger.IsUpdate) {
            For (Inviscid__Session__c x : Trigger.New) {
                Inviscid__Session__c oldX = Trigger.oldMap.get(x.Id);
                If (x.Inviscid__Status__c == 'Reviewed / Ready for Billing' && oldX.Inviscid__Status__c != 'Reviewed / Ready for Billing') {
                    x.Inviscid__Clinical_Sign_Off_User__c = UserInfo.getUserId();
                    x.Inviscid__Clinical_Sign_Off_Date__c = System.Now();
                }
            }
        }
    }
}

 
Hello All,

I found some code online to help me create a custom Rollup-Summary solution. It works great in Sandbox. But the system says that one of the queries is non-selective (at least when I did a big delete event).

How is it non-selective? The WHERE clause is based upon a lookup field (which is about as specific an index as possible).

Here is the code:
 
public class RollUpSummaryUtility {
    //the following class will be used to house the field names
    //and desired operations
    public class fieldDefinition {
        public String operation {get;set;}
        public String childField {get;set;}
        public String parentField {get;set;}
        public fieldDefinition (String o, String c, String p) {
            operation = o;
            childField = c;
            parentField = p;
        }
    }
    public static void rollUpTrigger(list<fieldDefinition> fieldDefinitions,
                                     list<sObject> records, String childObject, String childParentLookupField,
                                     String parentObject, String queryFilter) {
                                         //Limit the size of list by using Sets which do not contain duplicate
                                         //elements prevents hitting governor limits
                                         set<Id> parentIds = new set<Id>();
                                         for(sObject s : records) {
                                             parentIds.add((Id)s.get(childParentLookupField));
                                         }
                                         //populate query text strings to be used in child aggregrator and
                                         //parent value assignment
                                         String fieldsToAggregate = '';
                                         String parentFields = '';
                                         for(fieldDefinition d : fieldDefinitions) {
                                             fieldsToAggregate += d.operation + '(' + d.childField + ') ' +
                                                 ', ';
                                             parentFields += d.parentField + ', ';
                                         }
                                         //Using dynamic SOQL with aggergate results to populate parentValueMap
                                         String aggregateQuery = 'Select ' + fieldsToAggregate +
                                             childParentLookupField + ' from ' + childObject + ' where ' +
                                             childParentLookupField + ' IN :parentIds ' + queryFilter + ' ' +
                                             ' group by ' + childParentLookupField;
                                         //Map will contain one parent record Id per one aggregate object
                                         map<Id, AggregateResult> parentValueMap =
                                             new map <Id, AggregateResult>();
                                         for(AggregateResult q : Database.query(aggregateQuery)){
                                             parentValueMap.put((Id)q.get(childParentLookupField), q);
                                         }
                                         //list of parent object records to update
                                         list<sObject> parentsToUpdate = new list<sObject>();
                                         String parentQuery = 'select ' + parentFields + ' Id ' +
                                             ' from ' + parentObject + ' where Id IN :parentIds';
                                         //for each affected parent object, retrieve aggregate results and
                                         //for each field definition add aggregate value to parent field
                                         for(sObject s : Database.query(parentQuery)) {
                                             Integer row = 0; //row counter reset for every parent record
                                             for(fieldDefinition d : fieldDefinitions) {
                                                 String field = 'expr' + row.format();
                                                 AggregateResult r = parentValueMap.get(s.Id);
                                                 //r will be null if no records exist
                                                 //(e.g. last record deleted)
                                                 if(r != null) {
                                                     Decimal value = ((Decimal)r.get(field) == null ) ? 0 :
                                                     (Decimal)r.get(field);
                                                     s.put(d.parentField, value);
                                                 } else {
                                                     s.put(d.parentField, 0);
                                                 }
                                                 row += 1; //plus 1 for every field definition after first
                                             }
                                             parentsToUpdate.add(s);
                                         }
                                         //if parent records exist, perform update of all parent records
                                         //with a single DML statement
                                         if(parentsToUpdate.Size() > 0) {
                                             update parentsToUpdate;
                                         }
                                     }
}

Can somebody tell me what I am missing?
Dear Salesforce Gods,

Hear my prayer! My goal is to sync Outlook with a highly customized calendar in Salesforce that shows custom object records (rather than tasks, events, etc.).

So far, I have identified two possible methods of accomplishing my holy mission:
(1) Purchase an expensive 3rd Party app (LinkPoint360, Zyn, etc.)
(2) Use a trigger / workflow to create a "twin" Event record matched against every custom object record. Then use Salesforce to Outlook based on the Event records.

I kneel down and beg for guidance! Which is likely to be the better choice? Are there pitfalls or limitations I'm not aware of with option #2 that my push me toward option #1?

Or is there a different and holier path I may yet trod upon?


Thanks,
Zachary Alexander
To the Salesforce Gods,

I beseech thee for thine aid, oh Beneficent Dieties who doth inhabit this Wondrous Realm. Forsooth... *ahem*... I'm trying to make a POST callout to a vendor's website from our Salesforce instance. In all cases, I am getting back 302 Found. Normally, this just requires catching the return URL redirect and resubmitting the POST, but that is not working in this case. The vendor says that their site is set to always redirect to a home page rather than giving an error.

After working with one of the vendor's technicians, he has confirmed that the header / body of the request from Salesforce is correct (I'll include some code below). Please note: the code shown below does not contain the 302 Found redirect loop -- the loop always fails after hitting the redirect page so I've simplified the code below by ommitting it.

Has anyone else encountered an error like this? Is it the vendor's fault somehow? They're sandbox is chronically down. Maybe they're blocking access?

Or... is there something obviously wrong with the code?

------------CODE-------------

public class CatalystPatientInsert {
   
    public static HttpResponse makePostCallout() {
       
        //Help for this class found at "https://salesforce.stackexchange.com/questions/11015/basic-http-authentication"
        String username = 'HiddenUserName;
        String password = 'HiddenPassword;
       
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        String url = 'https://sandbox.vendor.com/api/students/';
        request.setEndpoint(url);
        request.setMethod('POST');
        Blob headerValue = Blob.valueOf(username +':'+password);
        String authorizationHeader = 'Basic ' + EncodingUtil.base64Encode(headerValue);
        system.debug(authorizationHeader);
        request.setHeader('Authentication', authorizationHeader);
        request.setHeader('User-Agent','CompanyName');
        request.setHeader('Content-Type', 'application/json');
       
        //Help for this class found at "https://developer.salesforce.com/forums/?id=906F0000000BQ30IAG"
        JsonHelpWrapper jwrap = new JsonHelpWrapper('ThapistId1', 'TherapistId2', 'JJ',
                               'Test2', null, '2014-03-26T10:05:44', '2014-03-26T10:05:44',
                               'm', true, '2014-03-26T10:05:44', null,
                               'test, jj', 'Diagnosis X', false,
                               'America/New_York');
       
        String requestValue = JSON.serialize(jwrap);
        System.debug(requestValue);
        request.setBody(requestValue);
        HttpResponse response = http.send(request);
        // Parse the JSON response
        if (response.getStatusCode() != 201) {
            System.debug('The status code returned was not expected: ' + response.getStatusCode() + ' ' + response.getStatus());
            System.debug(response.getHeader('Location'));

        } else {
            System.debug(response.getBody());
        }
        return response;
       
    }
   
}
I am trying to modify the technique of Deepak Anand found here: https://success.salesforce.com/answers?id=90630000000hW5tAAE. The objective is create a "NEXT" and "PREVIOUS" button for records.

Basically, I've confirmed that this code works:

var cycleAccounts = {!GETRECORDIDS( $ObjectType.ts2__Application__c )};

if(cycleAccounts.length >= 1){
   localStorage['CycleAccounts'] = cycleAccounts;
   location.replace('/' + cycleAccounts[0]);
}


The problem is that I need to get a list of Master-Detail field values instead of ID field values (I'm trying to find the parents, not the records themselves) and I cannot get the following modification of the code to work.

{!REQUIRESCRIPT('/soap/ajax/29.0/connection.js')}
{!REQUIRESCRIPT('/soap/ajax/29.0/apex.js')}
 
var cycleApplications = {!GETRECORDIDS( $ObjectType.ts2__Application__c )};
 
var cycleCandidates = sforce.connection.retrieve('ts2__Candidate_Contact__c', 'ts2__Application__c', cycleApplications);
 
var cycleAccounts = [];
 
var count = 0;
 
if (cycleApplications[0] == null) {
alert(‘Please select at least one record to update.’);
 
} else
 
{
for (var a = 0; a < cycleCandidates.length; a++) {
var desiredID = cycleCandidates[a].ts2__Candidate_Contact__c;
count++;
cycleAccounts.push(desiredID);
}}
 
if(cycleAccounts.length >= 1){
   localStorage['CycleAccounts'] = cycleAccounts;
   location.replace('/' + cycleAccounts[0]);
}


Does anybody know where I am going wrong? It seems to work at first (I am successfully getting the ID of the first parent record), but I do not appear to be getting any other values.
Dear Salesforce Gods,

Hear my prayer! My goal is to sync Outlook with a highly customized calendar in Salesforce that shows custom object records (rather than tasks, events, etc.).

So far, I have identified two possible methods of accomplishing my holy mission:
(1) Purchase an expensive 3rd Party app (LinkPoint360, Zyn, etc.)
(2) Use a trigger / workflow to create a "twin" Event record matched against every custom object record. Then use Salesforce to Outlook based on the Event records.

I kneel down and beg for guidance! Which is likely to be the better choice? Are there pitfalls or limitations I'm not aware of with option #2 that my push me toward option #1?

Or is there a different and holier path I may yet trod upon?


Thanks,
Zachary Alexander
I'm trying to understand why I had to deactivate a trigger (code below) in order to prevent a SOQL Queries 101 problem.

It doesn't utilize any SOQL queries (to the best of my knoweldge) and it never changed any field values that could cause other triggers to fire. This is verified beyond shadow of doubt.

Can somebody please help me to understand what is happening?
 
trigger Trig_SetClinicalSignOffUser on Inviscid__Session__c (before insert, before update) {
    
    //Retrieve metadata record
    Trigger_Switch__mdt[] switchList = [SELECT MasterLabel, Turn_Trigger_On__c FROM Trigger_Switch__mdt WHERE MasterLabel = 'Trig_SetClinicalSignOffUser'];
    If(switchList[0].Turn_Trigger_On__c == True) {
        
        If(Trigger.IsInsert) {
            For (Inviscid__Session__c x : Trigger.New) {
                If (x.Inviscid__Status__c == 'Reviewed / Ready for Billing') {
                    x.Inviscid__Clinical_Sign_Off_User__c = UserInfo.getUserId();
                    x.Inviscid__Clinical_Sign_Off_Date__c = System.Now();
                }
            }
        }

        If(Trigger.IsUpdate) {
            For (Inviscid__Session__c x : Trigger.New) {
                Inviscid__Session__c oldX = Trigger.oldMap.get(x.Id);
                If (x.Inviscid__Status__c == 'Reviewed / Ready for Billing' && oldX.Inviscid__Status__c != 'Reviewed / Ready for Billing') {
                    x.Inviscid__Clinical_Sign_Off_User__c = UserInfo.getUserId();
                    x.Inviscid__Clinical_Sign_Off_Date__c = System.Now();
                }
            }
        }
    }
}

 
To the Salesforce Gods,

I beseech thee for thine aid, oh Beneficent Dieties who doth inhabit this Wondrous Realm. Forsooth... *ahem*... I'm trying to make a POST callout to a vendor's website from our Salesforce instance. In all cases, I am getting back 302 Found. Normally, this just requires catching the return URL redirect and resubmitting the POST, but that is not working in this case. The vendor says that their site is set to always redirect to a home page rather than giving an error.

After working with one of the vendor's technicians, he has confirmed that the header / body of the request from Salesforce is correct (I'll include some code below). Please note: the code shown below does not contain the 302 Found redirect loop -- the loop always fails after hitting the redirect page so I've simplified the code below by ommitting it.

Has anyone else encountered an error like this? Is it the vendor's fault somehow? They're sandbox is chronically down. Maybe they're blocking access?

Or... is there something obviously wrong with the code?

------------CODE-------------

public class CatalystPatientInsert {
   
    public static HttpResponse makePostCallout() {
       
        //Help for this class found at "https://salesforce.stackexchange.com/questions/11015/basic-http-authentication"
        String username = 'HiddenUserName;
        String password = 'HiddenPassword;
       
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        String url = 'https://sandbox.vendor.com/api/students/';
        request.setEndpoint(url);
        request.setMethod('POST');
        Blob headerValue = Blob.valueOf(username +':'+password);
        String authorizationHeader = 'Basic ' + EncodingUtil.base64Encode(headerValue);
        system.debug(authorizationHeader);
        request.setHeader('Authentication', authorizationHeader);
        request.setHeader('User-Agent','CompanyName');
        request.setHeader('Content-Type', 'application/json');
       
        //Help for this class found at "https://developer.salesforce.com/forums/?id=906F0000000BQ30IAG"
        JsonHelpWrapper jwrap = new JsonHelpWrapper('ThapistId1', 'TherapistId2', 'JJ',
                               'Test2', null, '2014-03-26T10:05:44', '2014-03-26T10:05:44',
                               'm', true, '2014-03-26T10:05:44', null,
                               'test, jj', 'Diagnosis X', false,
                               'America/New_York');
       
        String requestValue = JSON.serialize(jwrap);
        System.debug(requestValue);
        request.setBody(requestValue);
        HttpResponse response = http.send(request);
        // Parse the JSON response
        if (response.getStatusCode() != 201) {
            System.debug('The status code returned was not expected: ' + response.getStatusCode() + ' ' + response.getStatus());
            System.debug(response.getHeader('Location'));

        } else {
            System.debug(response.getBody());
        }
        return response;
       
    }
   
}
Hi 

Whenever I add an apex:tabpanel component to a vf page the new Files related list upload button doesn't upload the selected file.  Once I remove the apex:tabpanel component then Files start uploading

<pre>

<apex:page standardController="Account">

    <!-- component causing issue -->
    <apex:tabPanel ></apex:tabPanel>
    
    <!-- classic attachments related list works regardless of apex:tabpanel component-->
    <apex:relatedList subject="{!account.id}" list="CombinedAttachments" />
    
    <!-- new salesforce files related list doesn't work with apex:tabpanel component -->
    <apex:relatedList subject="{!account.id}" list="AttachedContentDocuments" />
    
</apex:page>

</pre>
I am trying to modify the technique of Deepak Anand found here: https://success.salesforce.com/answers?id=90630000000hW5tAAE. The objective is create a "NEXT" and "PREVIOUS" button for records.

Basically, I've confirmed that this code works:

var cycleAccounts = {!GETRECORDIDS( $ObjectType.ts2__Application__c )};

if(cycleAccounts.length >= 1){
   localStorage['CycleAccounts'] = cycleAccounts;
   location.replace('/' + cycleAccounts[0]);
}


The problem is that I need to get a list of Master-Detail field values instead of ID field values (I'm trying to find the parents, not the records themselves) and I cannot get the following modification of the code to work.

{!REQUIRESCRIPT('/soap/ajax/29.0/connection.js')}
{!REQUIRESCRIPT('/soap/ajax/29.0/apex.js')}
 
var cycleApplications = {!GETRECORDIDS( $ObjectType.ts2__Application__c )};
 
var cycleCandidates = sforce.connection.retrieve('ts2__Candidate_Contact__c', 'ts2__Application__c', cycleApplications);
 
var cycleAccounts = [];
 
var count = 0;
 
if (cycleApplications[0] == null) {
alert(‘Please select at least one record to update.’);
 
} else
 
{
for (var a = 0; a < cycleCandidates.length; a++) {
var desiredID = cycleCandidates[a].ts2__Candidate_Contact__c;
count++;
cycleAccounts.push(desiredID);
}}
 
if(cycleAccounts.length >= 1){
   localStorage['CycleAccounts'] = cycleAccounts;
   location.replace('/' + cycleAccounts[0]);
}


Does anybody know where I am going wrong? It seems to work at first (I am successfully getting the ID of the first parent record), but I do not appear to be getting any other values.

Hi All, I was using the Find Nearby app in the appexchange. We use contracts extensively so I wanted to add a button to access the find nearby mapping. Effectively I retreive the contract Ids and then convert them into account Ids to pass to Find Nearby. I had been using what I believe to be SOQL or AJAX to accomplish this:

 

{!REQUIRESCRIPT("/soap/ajax/19.0/connection.js")} 
var checked = {!GETRECORDIDS($ObjectType.Contract)}; 
var q = "Select Contract.AccountId From Contract Where Contract.Id In " + "('" + checked.toString().replace(/,/g, "','") + "')"; 
var result = sforce.connection.query(q); 
var records = result.getArray("records"); 
var accountids = ""; 
var first = true; 
for (var i=0; i < records.length; i++) { 
var record = records[i]; 
if (first) { 
first = false; 
} else { 
accountids = accountids + ","; 
} 
accountids = accountids + record.AccountId; 
} 
window.location= "/apex/FN__FindNearbymap?alids="+escape(accountids);

 

 

Unfortunately, my button does not work anymore. We use professional edition and we had temporary access to data loader. Due to this fact, we also had API access when we normally shouldn't. I programmed the button unknowingly ignoring the fact that we would lose API access eventually. I am unable to figure out a way to get the account Ids to return. Whatever Objecttype I use, it returns the contract Ids.