• Ty Whitfield
  • NEWBIE
  • 105 Points
  • Member since 2014

  • Chatter
    Feed
  • 0
    Best Answers
  • 0
    Likes Received
  • 1
    Likes Given
  • 34
    Questions
  • 41
    Replies

I have a scheduled flow that queries all Contacts and confirms which are still active and updates the Account. 

However, I keep receiving the "UNABLE_TO_LOCK_ROW: unable to obtain exclusive access to this record or 120 records" error.  I believe it is because of other processes/flows triggering.

I don't need any other processes to run for this Flow.  Is it possible to allow this Flow to run without triggering other Flows?

I have a Trigger and the associated Test Class  that I have set up in our sandbox. According to the Developer Console, I have a 95% coverage onmy trigger after running the Test Class.  However, when I try to deploy into production, I receive "Test coverage of selected Apex Trigger is 38.095%, at least 75% test coverage is required. 

Any idea as to why this is happening or has anyone else had this problem lately?

I've created a Lightning Component record page using lightning:recordForm.  The logic for what we wanted works, however, I've noticed that Rich Text, Long Text fields, etc. will go on past the page even using slds-truncate_container_25, wordwrap, css max-width.  Is there a way to fix this
<lightning:card iconName="utility:description" title="Description">   
            <table  class="slds-table slds-table_cell-buffer slds-table_bordered slds-table_striped slds-rich-text-area__content slds-grow slds-cell-wrap">
            <tr>
                <td >
                      <lightning:recordViewForm recordId="{!v.recordId}" objectApiName="Opportunity">   
                     <div style="max-width:300px" class="slds-box">
                  
                    <lightning:outputField fieldName="Description" />
                </div>                
                    
                  
                             
                        </lightning:recordViewForm>
                    
                  <!--  <lightning:recordForm  aura:id="myRecordForm" recordId="{!v.recordId}" objectApiName="Opportunity" fields="{!v.descriptionFields}" columns="1" mode="view"  >  
                         <lightning:outputField fieldName="Description" />
                    </lightning:recordForm>-->
                </td>
            </tr>
        </table>      
    </lightning:card>

Page View
I've tested my Lightning Component and it worked as expected and see Contacts for displayed in my component.  Another user looking at the same account sees "There are no Team Lead or Support contacts"
public  class accController {
    @AuraEnabled
    public static list<Contact> getTrainingSubscription(Id recordId)
    {
        List<Contact> Conlist = [Select Id, Training_Subscription_User__c, Name, Email, Contact_Status__c, Last_Training_Login_Date__c from Contact where AccountId= :recordId and Training_Subscription_User__c = true ORDER By Contact_Status__c];
        return Conlist;
    }

    @AuraEnabled
    public static list<Contact> getSupportUsers(Id recordId)
    {
        List<Contact> Conlist =  [SELECT Id, Email,My_ASCI_Role__c,Name,  Experience__c FROM Contact WHERE  AccountId=:recordId AND (My_ASCI_Role__c = 'Team Lead' OR My_ASCI_Role__c = 'Support User') order by My_ASCI_Role__c desc];
        return Conlist;
    }

     @AuraEnabled
    public static decimal getAverageExperience(Id recordId)
    {      

      
        List<Contact> acctContacts = [SELECT Id, Email,My_ASCI_Role__c,Name,  Experience__c FROM Contact WHERE  AccountId=:recordId AND (My_ASCI_Role__c = 'Team Lead' OR My_ASCI_Role__c = 'Support User') order by My_ASCI_Role__c desc];
              integer j = 0; 
        decimal avgExperience = 0;
            while(j <  acctContacts.size())
            {
              avgExperience = avgExperience + acctContacts[j].Experience__c;
                   
                j++;
            } 
        
        if(acctContacts.size() != null && acctContacts.size() != 0)
        {
            avgExperience = (avgExperience / acctContacts.size());
        }
        return avgExperience;
    }

     @AuraEnabled
    public static Integer getSubPurchased(Id recordId)
    {    
       List<Account>  acct = [Select Id, Training_Subscription_Seats_Available__c FROM Account where Id= :recordId];  

      return   Integer.valueOf(acct[0].Training_Subscription_Seats_Available__c);
      
    }

     @AuraEnabled
    public static Integer getSubLeft(Id recordId)
    {      
        List<Account>  acct = [Select Id, Training_Subscription_Seats_Available__c FROM Account where Id= :recordId];  
        List <Contact>  acctContacts = [Select Id, Training_Subscription_User__c, Name, Email, Contact_Status__c, Last_Training_Login_Date__c from Contact where AccountId= :recordId and Training_Subscription_User__c = true ORDER By Contact_Status__c];
      
      return  Integer.valueOf(acct[0].Training_Subscription_Seats_Available__c) - acctContacts.size();
    }




     
       
}
 
<aura:component controller="accController" implements="flexipage:availableForRecordHome,force:hasRecordId" access="global" >
    <!--testComponentTrngSubSupportUsers-->
     <aura:attribute name="recordId" type="Id" access="global" />
    <aura:attribute name="ContactList" type="Contact[]" access="global" />
    <aura:attribute name="avg" type="Decimal" access="global" />
     <aura:handler name="init" value="{!this}" action="{!c.myAction}" access="global" />
     <lightning:card iconName="standard:case_wrap_up" title="Team Lead and Support User List">
     <aura:if isTrue="{!not(empty(v.ContactList))}">
         <center>Average Experience: <lightning:formattedNumber value="{!v.avg}"/> days</center>
    <table class="slds-table slds-table_cell-buffer slds-table_bordered slds-table_striped">
         <thead>
            <tr class="slds-text-title">
                <th  style="padding-left:10px;background-color: #0084c4 !important;background-image: none !important; color: #ffffff !important; font-size:100% !important; margin:0 !important; border:none !important;" scope="col">
                    <div class="slds-truncate" title="Name">Name</div>
                </th>
                <th  style="background-color: #0084c4 !important;background-image: none !important; color: #ffffff !important; font-size:100% !important; margin:0 !important; border:none !important;" scope="col">
                    <div class="slds-truncate" title="Email">Email</div>
                </th>
                 <th  style="background-color: #0084c4 !important;background-image: none !important; color: #ffffff !important; font-size:100% !important; margin:0 !important; border:none !important;" scope="col">
                     <div class="slds-truncate" title="Experience">Experience</div>
                </th>
                <th  style="background-color: #0084c4 !important;background-image: none !important; color: #ffffff !important; font-size:100% !important; margin:0 !important; border:none !important;" scope="col">
                    <div class="slds-truncate" title="Role">My ASCI<br/>Role</div>
                </th>
            </tr>
        </thead>
        <tbody>
   
    <aura:iteration   items="{!v.ContactList}" var="con">
        <tr>
                    <td data-label="Name" style="padding-left:10px">
                        
                      
                         <div class="slds-truncate" title="">
                             <lightning:formattedUrl  value="{! '/' + con.Id}" label="{!con.Name}"  target="_blank" />
                             </div>
                    </td>
                    <td data-label="Email">
                        <div class="slds-truncate" title="">
                             <lightning:formattedUrl  value="{! '/' + con.Id}" label="{!con.Email}"  target="_blank" /></div>
                    </td>
             <td data-label="Experience">
                        <div class="slds-truncate" title=""><lightning:formattedNumber value="{!con.Experience__c}"/> days</div>
                    </td>
                    <td data-label="Role">
                        <div class="slds-truncate" title="">{!con.My_ASCI_Role__c}</div>
                    </td>
                </tr>
        
       
    </aura:iteration>
        </tbody>
         </table>
	  <aura:set attribute="else">
                <div Style="text-align : center">  There are no Team Lead or Support contacts </div>
            </aura:set>
        </aura:if>
    </lightning:card>
	
</aura:component>
 
({
 myAction : function(component, event, helper) 
    {
        var ConList = component.get("c.getSupportUsers");
        ConList.setParams
        ({
            recordId: component.get("v.recordId")
        });
        
        ConList.setCallback(this, function(data) 
                           {
                               component.set("v.ContactList", data.getReturnValue());
                           });
        $A.enqueueAction(ConList);
        
        
        var avg = component.get("c.getAverageExperience");
        avg.setParams
        ({
            recordId: component.get("v.recordId")
        });
        
        avg.setCallback(this, function(data) 
                           {
                               component.set("v.avg", data.getReturnValue());
                           });
        $A.enqueueAction(avg);
        
        
 }
})

I've tried the code below (removed some items for confidentiality) but I receive the "made it to the query locator" debug message but never receive the "made it to the execute" debug.  I'm calling it by entering

batchGenerateAssets be = new batchGenerateAssets();
database.executeBatch(be);

in Execute Anonymous Window of the Developer Console

 

What am I doing wrong?

global class batchGenerateAssets implements Database.Batchable<sObject>, Database.AllowsCallouts{

 public String query = 'Select Id, PakSize__c, ProductFamily, UsageEndDate, Product2Id  FROM Asset WHERE SerialNumber = \'**Generate**\' ';

global Database.QueryLocator start(Database.BatchableContext BC)
{   
     System.debug('made it to querylocator');

    return Database.getQueryLocator(query);
}

global void execute(Database.BatchableContext BC, List<Asset> assetList) {
System.debug('made it to execute');
      
  ///////////////////////////////////////////////////////////////////////////////
    

      
}   
      global void finish(Database.BatchableContext BC)
      {
      }
}

 
Our external website frequently makes API calls to Salesforce.  We want to notify customers that a portion of our site may be down when Salesforce has an issue.  Is there a way to programmatically tell upon user login, if the our instance has an outage and/or just have an incident reported?
I have a Visualforce page using a StandardController with an extension.  Everything works fine but when there are more than 100 items, and I hit the Save (updateSave()) button, I initialliy received the  "Apex governor limit warning".  I then changed the updateSave() to what is below and I then received Too many future calls: 51.

VFP
<apex:page standardController="Asset" docType="html-5.0"   lightningStylesheets="true" recordSetVar="assets" extensions="AssetUpdateController" tabStyle="Asset">
  <!-- Begin Default Content REMOVE THIS -->
<apex:form >
    <apex:pageBlock >
      <apex:pageMessages />
      <center>
       <apex:selectList value="{!productVersionItem}"   size="1" id="typeSelect">               
                  <apex:selectOptions value="{!dropProductVersionItems}"/>
                   <apex:actionSupport event="onchange"  action="{!rePopulateAzzets}"  >
                   </apex:actionsupport>                   
                </apex:selectList>
                </center><br />
      <apex:pageBlockButtons >
        <apex:commandButton value="Mark Listed Items as Inactive" 
                            action="{!groupMarkInactive}"/>
                             <apex:commandButton id="saveBtn" value="Save" action="{!updateSave}" />

          <apex:commandButton id="cancelBtn" value="Cancel" action="{!cancel}" />

      </apex:pageBlockButtons>
      <apex:pageBlockTable value="{!azzets}" 
                           var="ass">
       
        <apex:column headerValue="Asset Name">
     
          <apex:outputField value="{!ass.Name}"/>
        </apex:column>
        <apex:column headerValue="Quantity">
          <apex:outputField value="{!ass.Quantity}"/>
        </apex:column>
        
         <apex:column headerValue="PakSize">
          <apex:outputField value="{!ass.PakSize__c}"/>
        </apex:column>
         <apex:column headerValue="Product Family">
          <apex:outputField value="{!ass.ProductFamily}"/>
        </apex:column>
         <apex:column headerValue="Serial Number">
          <apex:outputField value="{!ass.SerialNumber}"/>
        </apex:column>
         <apex:column headerValue="Satus">
          <apex:inputField value="{!ass.Status}"/>
        </apex:column>
         <apex:column headerValue="Price">
          <apex:outputField value="{!ass.Price}"/>
        </apex:column>
         <apex:column headerValue="Purchase Date">
          <apex:outputField value="{!ass.PurchaseDate}"/>
        </apex:column>
      </apex:pageBlockTable>      
    </apex:pageBlock>
  </apex:form>
  <!-- End Default Content REMOVE THIS -->
</apex:page>

Controller
public  class AssetUpdateController {
      // TestAssetUpdateController
    @AuraEnabled
    public List<Asset> azzets{get;set;}   
    public String AcctId {get;set;} 
    public String productFamilyId {get;set;} 
    Public String productVersionItem{get;set;}
    Public List<SelectOption> dropProductVersionItems {get;set;}
    
    public AssetUpdateController(ApexPages.StandardSetController controller) {
        AcctId = System.currentPageReference().getParameters().get('Id');
        productFamilyId= System.currentPageReference().getParameters().get('PFId');
        getAzzets();
        
    }
    
    
    public List<Asset> getAzzets() {
        
        azzets = [Select Name, PurchaseDate, Price, Status, SerialNumber, ProductFamily, PakSize__c, Quantity 
                  From Asset where Account.id = :AcctId order by ProductFamily ASC];  
        
        dropProductVersionItems = new List<SelectOption>();
        dropProductVersionItems.add(new SelectOption('Filter By Version','Filter By Version'));
        
        //  List <Asset> productFamily = [SELECT ProductFamily  From Asset where Account.id = :AcctId Group by ProductFamily order by ProductFamily DESC];
        
        
        integer i = 0;
        while(i <  azzets.size())
        { 
            if (i==0) {
                dropProductVersionItems.add(new SelectOption(azzets[i].ProductFamily,azzets[i].ProductFamily));
                
            }else{
                if( (azzets[i].ProductFamily != azzets[i-1].ProductFamily))
                {
                    dropProductVersionItems.add(new SelectOption(azzets[i].ProductFamily,azzets[i].ProductFamily));
                }
                
            }
            
            i++;
        }           
        return azzets;    
        
    }
    
    public void rePopulateAzzets() {
        
        azzets = [Select Name, PurchaseDate, Price, Status, SerialNumber, ProductFamily, PakSize__c, Quantity 
                  From Asset where Account.id = :AcctId and ProductFamily = :productVersionItem];  
        
        
        
    }
    
    public void groupMarkInactive() {
        
        Integer i =0;
        while(i <  azzets.size())
        {
            azzets[i].Status = 'Inactive';
            i++;
        }               
        
    }
    
    public Pagereference updateSave() {  
        PageReference newpage = new Pagereference('/lightning/r/'+AcctId + '/related/Assets/view');
        try{
           // new code to work around Govenor Limit
            for(List<Asset> azzetsList : azzets)
            {
                for(Asset aAsset : azzetsList)
                {

                }
                Database.update(azzets);
            }

         // end new code to eliminate Governor Limit

        // Code below works but will cause Governor limit error if too many 
            // azzets.save();
           
            
        }catch(exception e){
            ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.CONFIRM,e.getMessage()));
        }             
        
        newpage.setRedirect(true);        
        return newpage;
        
    }
    
    public Pagereference cancel(){
        
        PageReference newpage = new Pagereference('/'+AcctId);
        
        newpage.setRedirect(true);
        
        return newpage;
        
    }
}

​​​​​​​
I have successfully been able to add an emailMessage to SF via the API.  I will need to do one of the two options:
  1. Not have SF send the email to the recipient once added.  This is because we have already sent the email and just placing a copy in SF for our records
  2. Have the ability to change the fromAddress via the API.  If we remove the email sent from our website and only have the SF one to be sent, we will need to change the from email address.  I have added the email to the Organization-Wide Email addresses and associated it to the correct profile, however, I don't know where to switch it.
 
SingleEmailMessage emailMessage = new SingleEmailMessage();
            if (!string.IsNullOrEmpty(templateid))
            {
                emailMessage.templateId = templateid;
            }
            else
            {
                emailMessage.subject = subject;
                emailMessage.htmlBody = Server.UrlDecode(body) ;
            }

            emailMessage.toAddresses = new String[] { email };
            emailMessage.saveAsActivity = true;
            emailMessage.targetObjectId = contactId;

            SingleEmailMessage[] messages = { emailMessage };
            SendEmailResult[] results = binding.sendEmail(messages);

            if (results[0].success)
            {
                // Console.WriteLine("The email was sent successfully.");
            }
            else
            {
                SendEmail("xxxxxx@xxx.com", "Error SingleEmailMessage add", "The email failed to send: " + results[0].errors[0].message);

            }


            sflogout();

 
I have an apex function that while doing other tasks, also make a web call out.  I am not sure how to write a test for this.  I've found documentation for when I need to test a function that returns a HttpResponse but in my case the function returns a PageReference.

Controller Code
public  PageReference finalize() {
        
        String specialSerial;
        
        Integer i = 0;
        Integer size = products.size();
        test = '';
        List<List<String>> productswithSerial = new List<List<String>>{};
      
            ....

  string serial =   generate(prod2.ProductFamilyID__c, String.valueOf(products[i].Pak_Size__c));

.....
}

 
    public  string generate(decimal productFamily, string pak) {
        HttpRequest req = new HttpRequest();              
        HttpResponse res2 = new HttpResponse(); 
        Http http = new Http();
        req.setEndpoint('xxxxxxxxxxxxxxxx');              
        req.setMethod('GET');                  
        res2 = http.send(req);              
        if(res2.getstatusCode() == 200 && res2.getbody() != null){   
            return res2.getbody();
            //   test = test + '<br/>' + res2.getbody();                  
        }else{
            return 'Invalid';
        }
    }


My Test Code
Test.setMock(HttpCalloutMock.class, new MockHttpResponseGenerator());
        
        // Call method to test.
        // This causes a fake response to be sent
        // from the class that implements HttpCalloutMock. 
        HttpResponse res = tsc.finalize();
        
        // Verify response received contains fake values
        String contentType = res.getHeader('Content-Type');
        System.assert(contentType == 'application/json');
        String actualValue = res.getBody();
        String expectedValue = '{"xxxxxxxxxxxxxxxxxx"}';
        System.assertEquals(actualValue, expectedValue);
        System.assertEquals(200, res.getStatusCode());

I'm getting the error on this line "HttpResponse res = tsc.finalize();" which states "Illegal assignment from System.PageReference to System.HttpResponse" which I understand but don't know how to work-around.
 
This is strange.  I have apex:messages that work correctly in Lightning, however, in Classic they do not show.  After some researching, I tried putting the messages in an outputText.  But then it doesn't render with the set styling.  So for example, it renders the text in white but if I set it to black, red or any other color, it just ignores it and still puts it in white.  Any ideas?  Below are code snippets.
 
<div >
 <apex:Messages style="color:white;font-size:1.3em;font-weight:bold"/>

 <apex:outputText rendered="errorStatus" style="color:#ff0606;" value="{!errorMsg}" id="msg"/>


 </div>
 
if(Opp.StageName != 'Closed Won')
        {
            stageStatus = Opp.StageName;
            pageStatus = false;
            errorStatus = true;
            ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR,'The opportunity has not been won yet. You must mark the opportunity as Closed Won before finalizing it!'));
            errorMsg = 'The opportunity has not been won yet. You must mark the opportunity as Closed Won before finalizing it!';
        }

 
I can successfully post an email to Salesforce using the EmailMessage Object, however when I send a link, something like below, it strips out a portion of the URL parameters.  See below 

Link sent
https://www.xxxxxx.com/en-us/reset-password?login=xxx@somecompany.com&id=441810

Instead, I get 
https://www.xxxxxx.com/en-us/reset-password?login=xxx@somecompany.com


Anyone know why or how to fix?
 

In my class I have 3 global variables that I set on page load.  Then when a user clicks a button, those variables are used in a method that is invoked on click. This works fine.  However, when writing my test class, I keep receiving attempt to dereference a null object and it is pointing to those three variables.  

How do you set those variables within a test class?


 

I've created a VF page with controller in Lightning.  I found out that a department that hasn't migrated to Lightning yet also needs access.  However, when I go to add the VF page to the page layout in Classic, it isn't shown.  Is there a way to make it available in Classic.

Here is the VF page code
<apex:page lightningStylesheets="true" action="{!loadPage}" Controller="TrainingSubscriptionListController"  >
  <!-- Begin Default Content REMOVE THIS -->
  <apex:outputtext value="{!tmp}" escape="false" id="tblHTML"/>
  <!-- End Default Content REMOVE THIS -->
</apex:page>

and here is the contoller code
public class TrainingSubscriptionListController {
    @AuraEnabled
    Public List<Contact> acctContacts {get;set;}
    public string tmp {get;set;}
    
    public void loadPage(){
        string AcctId = System.currentPageReference().getParameters().get('Id');
        acctContacts = [Select Id, Training_Subscription_User__c, Name, Email from Contact where AccountId= :AcctId and Training_Subscription_User__c = true];
        
           tmp =     '<table id="myTable"  style="width:100%; table-layout: auto;" cellspacing="0" cellpadding="10"><tr>' + 
                '<td style="padding:15px; background-color: #0084c4 !important;background-image: none !important; color: #ffffff !important; font-size:100% !important; margin:0 !important; border:none !important;">' +
                '<b>Name</b></td>' + 
                // '<td style="width:50px; background-color: #0084c4 !important;background-image: none !important; color: #ffffff !important; font-size:100% !important; margin:0 !important; border:none !important;">' +
                //'</td>' +
                '<td style=" background-color: #0084c4 !important;background-image: none !important; color: #ffffff !important; font-size:100% !important; margin:0 !important; border:none !important;">' +
                '<b>Email</b></td>' +
                
                '</tr>';
            
            integer i = 0;              
            while(i <  acctContacts.size())
            {
                tmp = tmp + '<tr><td style="padding:15px;"><a href="/' + acctContacts[i].Id + '">' + acctContacts[i].Name + '</a></td><td style="padding:5px;"><a href="/' + acctContacts[i].Id + '">' + acctContacts[i].Email  +  '</a></td></tr>';
                i++;
            }
         tmp = tmp + '</table>';
    }

}

I've created custom fields for the Contact and Account objects.  The Contact fields are immediately available and can be queried with no problem.  The Account fields are not for some strange reason.  They have the same exact permissions, are visible in all page layouts, waited a couple of days to see if it was slow in updating, I've opened them up so that it is totally editable and yet nothing seems to work.  I can see the fields and query in Data Loader and Workbench.

Any ideas?
I have a VF page for the Account page that I needed to create in order to display Contacts that had a specific field check.  It simply queries Contacts with that field selected and displays.  When I tried to push this into production, I keep getting code coverage errors but I'm not sure how to create a test case for this.

Here is the Apex Code
public class TrainingSubscriptionListController {
    @AuraEnabled
    Public List<Contact> acctContacts {get;set;}
    public string tmp {get;set;}
    
    public void loadPage(){
        string AcctId = System.currentPageReference().getParameters().get('Id');
        acctContacts = [Select Id, Training_Subscription_User__c, Name, Email from Contact where AccountId= :AcctId and Training_Subscription_User__c = true];
        
           tmp =     '<table id="myTable"  style="width:100%; table-layout: auto;" cellspacing="0" cellpadding="10"><tr>' + 
                '<td style="padding:15px; background-color: #0084c4 !important;background-image: none !important; color: #ffffff !important; font-size:100% !important; margin:0 !important; border:none !important;">' +
                '<b>Name</b></td>' + 
                // '<td style="width:50px; background-color: #0084c4 !important;background-image: none !important; color: #ffffff !important; font-size:100% !important; margin:0 !important; border:none !important;">' +
                //'</td>' +
                '<td style=" background-color: #0084c4 !important;background-image: none !important; color: #ffffff !important; font-size:100% !important; margin:0 !important; border:none !important;">' +
                '<b>Email</b></td>' +
                
                '</tr>';
            
            integer i = 0;           
    
            
            while(i <  acctContacts.size())
            {
                tmp = tmp + '<tr><td style="padding:15px;"><a href="/' + acctContacts[i].Id + '">' + acctContacts[i].Name + '</a></td><td style="padding:5px;"><a href="/' + acctContacts[i].Id + '">' + acctContacts[i].Email  +  '</a></td></tr>';
                i++;
            }
         tmp = tmp + '</table>';
    }

}

I tried running it against this test but it fails as well.
@isTest
public class TestMultipleAdminCheck {
    @isTest static void TestContact() {
        Test.startTest();
        Account acct = new Account(Name='Test Account', Training_Subscription_Seats_Available__c = 1, Number_of_Support_Users__c = 1);
        insert acct;
        Contact cont1 = new Contact(FirstName='User', LastName='One',                                     
                                    AccountId=acct.Id, My_ASCI_Role__c = 'Support User');
        Contact cont2 = new Contact(FirstName='User', LastName='Two',                                     
                                    AccountId=acct.Id, My_ASCI_Role__c = 'Admin User', Training_Subscription_User__c = true);
        Contact cont3 = new Contact(FirstName='User', LastName='Three',                                     
                                    AccountId=acct.Id,    My_ASCI_Role__c = 'General User');
        Contact cont4 = new Contact(FirstName='User', LastName='Four',             
                                    AccountId=acct.Id,   My_ASCI_Role__c = 'Support User');
        insert cont1;
        insert cont2;
        insert cont3;
        insert cont4;
        
        
        Test.stopTest();
        
    }
    
}

Any help will be appreciated.
I have a checkbox field on the Contact object and would like to display all contacts that have that field selected to be displayed on the Account object.

What is the best way to accomplish this?
I have a picklist field on the Contact record but I only want one person from each account to have one of the picklist values selected in this case "Admin User".  The other picklist values may have mulitple contacts with the same item selected, just the Admin user needs to be unique.  

I'm assuming that I would have to write a trigger on Contact edit but how do I display the error to the user about to update the record?
So I have a pageblocktable that I populate with 
Public List<OpportunityLineItem> oppLineItem {get;set;}
 oppLineItem = [Select Id, Discount, ListPrice, TotalPrice,  PricebookEntryId, Product2Id, ProductCode, Name, Quantity,  UnitPrice, Description FROM OpportunityLineItem WHERE OpportunityId = :oppId];
What I would like to have happen is to group by Name and generate a sum for the Quantity. 

Is that possible or is there a better option than pageblocktable.  Note, I was only using the pageblocktable as I am not sure of how many items will be returned with the query.
 
I have a pageBlockTable that has things like Price, Discount and Total Price that are being populated by OpportunityLineItem List.  However, I need to add two Input fields (Upgrade Discount and New List Price) in each row.  When a user updates the Upgrade Discount for that Line Item, calculate what the new List price will be.

So in the screenshot below you can see that I want to adjust the New List Price for Test Product 2 after entering 30 .  The New List Price should be the List Price ($25,900) - the Upgrade Discount (30%)

User-added image
Salesforce will be ending support for Legacy SOAP API version 6 and lower.  I'm trying to confirm what SOAP version our app is using for the Outbound messages.  I tried to following the instructions given by the email by going into Workbench, exporting the EventLogFile and looking for API_Type.  However, I don't see that field. 

When I export via the Data Loader or the Salesforce Event Log File Browser, I don't see that field but do see something called API version.  Is that what I'm looking for?
I've created a Lightning Component record page using lightning:recordForm.  The logic for what we wanted works, however, I've noticed that Rich Text, Long Text fields, etc. will go on past the page even using slds-truncate_container_25, wordwrap, css max-width.  Is there a way to fix this
<lightning:card iconName="utility:description" title="Description">   
            <table  class="slds-table slds-table_cell-buffer slds-table_bordered slds-table_striped slds-rich-text-area__content slds-grow slds-cell-wrap">
            <tr>
                <td >
                      <lightning:recordViewForm recordId="{!v.recordId}" objectApiName="Opportunity">   
                     <div style="max-width:300px" class="slds-box">
                  
                    <lightning:outputField fieldName="Description" />
                </div>                
                    
                  
                             
                        </lightning:recordViewForm>
                    
                  <!--  <lightning:recordForm  aura:id="myRecordForm" recordId="{!v.recordId}" objectApiName="Opportunity" fields="{!v.descriptionFields}" columns="1" mode="view"  >  
                         <lightning:outputField fieldName="Description" />
                    </lightning:recordForm>-->
                </td>
            </tr>
        </table>      
    </lightning:card>

Page View
I've tested my Lightning Component and it worked as expected and see Contacts for displayed in my component.  Another user looking at the same account sees "There are no Team Lead or Support contacts"
public  class accController {
    @AuraEnabled
    public static list<Contact> getTrainingSubscription(Id recordId)
    {
        List<Contact> Conlist = [Select Id, Training_Subscription_User__c, Name, Email, Contact_Status__c, Last_Training_Login_Date__c from Contact where AccountId= :recordId and Training_Subscription_User__c = true ORDER By Contact_Status__c];
        return Conlist;
    }

    @AuraEnabled
    public static list<Contact> getSupportUsers(Id recordId)
    {
        List<Contact> Conlist =  [SELECT Id, Email,My_ASCI_Role__c,Name,  Experience__c FROM Contact WHERE  AccountId=:recordId AND (My_ASCI_Role__c = 'Team Lead' OR My_ASCI_Role__c = 'Support User') order by My_ASCI_Role__c desc];
        return Conlist;
    }

     @AuraEnabled
    public static decimal getAverageExperience(Id recordId)
    {      

      
        List<Contact> acctContacts = [SELECT Id, Email,My_ASCI_Role__c,Name,  Experience__c FROM Contact WHERE  AccountId=:recordId AND (My_ASCI_Role__c = 'Team Lead' OR My_ASCI_Role__c = 'Support User') order by My_ASCI_Role__c desc];
              integer j = 0; 
        decimal avgExperience = 0;
            while(j <  acctContacts.size())
            {
              avgExperience = avgExperience + acctContacts[j].Experience__c;
                   
                j++;
            } 
        
        if(acctContacts.size() != null && acctContacts.size() != 0)
        {
            avgExperience = (avgExperience / acctContacts.size());
        }
        return avgExperience;
    }

     @AuraEnabled
    public static Integer getSubPurchased(Id recordId)
    {    
       List<Account>  acct = [Select Id, Training_Subscription_Seats_Available__c FROM Account where Id= :recordId];  

      return   Integer.valueOf(acct[0].Training_Subscription_Seats_Available__c);
      
    }

     @AuraEnabled
    public static Integer getSubLeft(Id recordId)
    {      
        List<Account>  acct = [Select Id, Training_Subscription_Seats_Available__c FROM Account where Id= :recordId];  
        List <Contact>  acctContacts = [Select Id, Training_Subscription_User__c, Name, Email, Contact_Status__c, Last_Training_Login_Date__c from Contact where AccountId= :recordId and Training_Subscription_User__c = true ORDER By Contact_Status__c];
      
      return  Integer.valueOf(acct[0].Training_Subscription_Seats_Available__c) - acctContacts.size();
    }




     
       
}
 
<aura:component controller="accController" implements="flexipage:availableForRecordHome,force:hasRecordId" access="global" >
    <!--testComponentTrngSubSupportUsers-->
     <aura:attribute name="recordId" type="Id" access="global" />
    <aura:attribute name="ContactList" type="Contact[]" access="global" />
    <aura:attribute name="avg" type="Decimal" access="global" />
     <aura:handler name="init" value="{!this}" action="{!c.myAction}" access="global" />
     <lightning:card iconName="standard:case_wrap_up" title="Team Lead and Support User List">
     <aura:if isTrue="{!not(empty(v.ContactList))}">
         <center>Average Experience: <lightning:formattedNumber value="{!v.avg}"/> days</center>
    <table class="slds-table slds-table_cell-buffer slds-table_bordered slds-table_striped">
         <thead>
            <tr class="slds-text-title">
                <th  style="padding-left:10px;background-color: #0084c4 !important;background-image: none !important; color: #ffffff !important; font-size:100% !important; margin:0 !important; border:none !important;" scope="col">
                    <div class="slds-truncate" title="Name">Name</div>
                </th>
                <th  style="background-color: #0084c4 !important;background-image: none !important; color: #ffffff !important; font-size:100% !important; margin:0 !important; border:none !important;" scope="col">
                    <div class="slds-truncate" title="Email">Email</div>
                </th>
                 <th  style="background-color: #0084c4 !important;background-image: none !important; color: #ffffff !important; font-size:100% !important; margin:0 !important; border:none !important;" scope="col">
                     <div class="slds-truncate" title="Experience">Experience</div>
                </th>
                <th  style="background-color: #0084c4 !important;background-image: none !important; color: #ffffff !important; font-size:100% !important; margin:0 !important; border:none !important;" scope="col">
                    <div class="slds-truncate" title="Role">My ASCI<br/>Role</div>
                </th>
            </tr>
        </thead>
        <tbody>
   
    <aura:iteration   items="{!v.ContactList}" var="con">
        <tr>
                    <td data-label="Name" style="padding-left:10px">
                        
                      
                         <div class="slds-truncate" title="">
                             <lightning:formattedUrl  value="{! '/' + con.Id}" label="{!con.Name}"  target="_blank" />
                             </div>
                    </td>
                    <td data-label="Email">
                        <div class="slds-truncate" title="">
                             <lightning:formattedUrl  value="{! '/' + con.Id}" label="{!con.Email}"  target="_blank" /></div>
                    </td>
             <td data-label="Experience">
                        <div class="slds-truncate" title=""><lightning:formattedNumber value="{!con.Experience__c}"/> days</div>
                    </td>
                    <td data-label="Role">
                        <div class="slds-truncate" title="">{!con.My_ASCI_Role__c}</div>
                    </td>
                </tr>
        
       
    </aura:iteration>
        </tbody>
         </table>
	  <aura:set attribute="else">
                <div Style="text-align : center">  There are no Team Lead or Support contacts </div>
            </aura:set>
        </aura:if>
    </lightning:card>
	
</aura:component>
 
({
 myAction : function(component, event, helper) 
    {
        var ConList = component.get("c.getSupportUsers");
        ConList.setParams
        ({
            recordId: component.get("v.recordId")
        });
        
        ConList.setCallback(this, function(data) 
                           {
                               component.set("v.ContactList", data.getReturnValue());
                           });
        $A.enqueueAction(ConList);
        
        
        var avg = component.get("c.getAverageExperience");
        avg.setParams
        ({
            recordId: component.get("v.recordId")
        });
        
        avg.setCallback(this, function(data) 
                           {
                               component.set("v.avg", data.getReturnValue());
                           });
        $A.enqueueAction(avg);
        
        
 }
})

I've tried the code below (removed some items for confidentiality) but I receive the "made it to the query locator" debug message but never receive the "made it to the execute" debug.  I'm calling it by entering

batchGenerateAssets be = new batchGenerateAssets();
database.executeBatch(be);

in Execute Anonymous Window of the Developer Console

 

What am I doing wrong?

global class batchGenerateAssets implements Database.Batchable<sObject>, Database.AllowsCallouts{

 public String query = 'Select Id, PakSize__c, ProductFamily, UsageEndDate, Product2Id  FROM Asset WHERE SerialNumber = \'**Generate**\' ';

global Database.QueryLocator start(Database.BatchableContext BC)
{   
     System.debug('made it to querylocator');

    return Database.getQueryLocator(query);
}

global void execute(Database.BatchableContext BC, List<Asset> assetList) {
System.debug('made it to execute');
      
  ///////////////////////////////////////////////////////////////////////////////
    

      
}   
      global void finish(Database.BatchableContext BC)
      {
      }
}

 
I have a Visualforce page using a StandardController with an extension.  Everything works fine but when there are more than 100 items, and I hit the Save (updateSave()) button, I initialliy received the  "Apex governor limit warning".  I then changed the updateSave() to what is below and I then received Too many future calls: 51.

VFP
<apex:page standardController="Asset" docType="html-5.0"   lightningStylesheets="true" recordSetVar="assets" extensions="AssetUpdateController" tabStyle="Asset">
  <!-- Begin Default Content REMOVE THIS -->
<apex:form >
    <apex:pageBlock >
      <apex:pageMessages />
      <center>
       <apex:selectList value="{!productVersionItem}"   size="1" id="typeSelect">               
                  <apex:selectOptions value="{!dropProductVersionItems}"/>
                   <apex:actionSupport event="onchange"  action="{!rePopulateAzzets}"  >
                   </apex:actionsupport>                   
                </apex:selectList>
                </center><br />
      <apex:pageBlockButtons >
        <apex:commandButton value="Mark Listed Items as Inactive" 
                            action="{!groupMarkInactive}"/>
                             <apex:commandButton id="saveBtn" value="Save" action="{!updateSave}" />

          <apex:commandButton id="cancelBtn" value="Cancel" action="{!cancel}" />

      </apex:pageBlockButtons>
      <apex:pageBlockTable value="{!azzets}" 
                           var="ass">
       
        <apex:column headerValue="Asset Name">
     
          <apex:outputField value="{!ass.Name}"/>
        </apex:column>
        <apex:column headerValue="Quantity">
          <apex:outputField value="{!ass.Quantity}"/>
        </apex:column>
        
         <apex:column headerValue="PakSize">
          <apex:outputField value="{!ass.PakSize__c}"/>
        </apex:column>
         <apex:column headerValue="Product Family">
          <apex:outputField value="{!ass.ProductFamily}"/>
        </apex:column>
         <apex:column headerValue="Serial Number">
          <apex:outputField value="{!ass.SerialNumber}"/>
        </apex:column>
         <apex:column headerValue="Satus">
          <apex:inputField value="{!ass.Status}"/>
        </apex:column>
         <apex:column headerValue="Price">
          <apex:outputField value="{!ass.Price}"/>
        </apex:column>
         <apex:column headerValue="Purchase Date">
          <apex:outputField value="{!ass.PurchaseDate}"/>
        </apex:column>
      </apex:pageBlockTable>      
    </apex:pageBlock>
  </apex:form>
  <!-- End Default Content REMOVE THIS -->
</apex:page>

Controller
public  class AssetUpdateController {
      // TestAssetUpdateController
    @AuraEnabled
    public List<Asset> azzets{get;set;}   
    public String AcctId {get;set;} 
    public String productFamilyId {get;set;} 
    Public String productVersionItem{get;set;}
    Public List<SelectOption> dropProductVersionItems {get;set;}
    
    public AssetUpdateController(ApexPages.StandardSetController controller) {
        AcctId = System.currentPageReference().getParameters().get('Id');
        productFamilyId= System.currentPageReference().getParameters().get('PFId');
        getAzzets();
        
    }
    
    
    public List<Asset> getAzzets() {
        
        azzets = [Select Name, PurchaseDate, Price, Status, SerialNumber, ProductFamily, PakSize__c, Quantity 
                  From Asset where Account.id = :AcctId order by ProductFamily ASC];  
        
        dropProductVersionItems = new List<SelectOption>();
        dropProductVersionItems.add(new SelectOption('Filter By Version','Filter By Version'));
        
        //  List <Asset> productFamily = [SELECT ProductFamily  From Asset where Account.id = :AcctId Group by ProductFamily order by ProductFamily DESC];
        
        
        integer i = 0;
        while(i <  azzets.size())
        { 
            if (i==0) {
                dropProductVersionItems.add(new SelectOption(azzets[i].ProductFamily,azzets[i].ProductFamily));
                
            }else{
                if( (azzets[i].ProductFamily != azzets[i-1].ProductFamily))
                {
                    dropProductVersionItems.add(new SelectOption(azzets[i].ProductFamily,azzets[i].ProductFamily));
                }
                
            }
            
            i++;
        }           
        return azzets;    
        
    }
    
    public void rePopulateAzzets() {
        
        azzets = [Select Name, PurchaseDate, Price, Status, SerialNumber, ProductFamily, PakSize__c, Quantity 
                  From Asset where Account.id = :AcctId and ProductFamily = :productVersionItem];  
        
        
        
    }
    
    public void groupMarkInactive() {
        
        Integer i =0;
        while(i <  azzets.size())
        {
            azzets[i].Status = 'Inactive';
            i++;
        }               
        
    }
    
    public Pagereference updateSave() {  
        PageReference newpage = new Pagereference('/lightning/r/'+AcctId + '/related/Assets/view');
        try{
           // new code to work around Govenor Limit
            for(List<Asset> azzetsList : azzets)
            {
                for(Asset aAsset : azzetsList)
                {

                }
                Database.update(azzets);
            }

         // end new code to eliminate Governor Limit

        // Code below works but will cause Governor limit error if too many 
            // azzets.save();
           
            
        }catch(exception e){
            ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.CONFIRM,e.getMessage()));
        }             
        
        newpage.setRedirect(true);        
        return newpage;
        
    }
    
    public Pagereference cancel(){
        
        PageReference newpage = new Pagereference('/'+AcctId);
        
        newpage.setRedirect(true);
        
        return newpage;
        
    }
}

​​​​​​​
I have successfully been able to add an emailMessage to SF via the API.  I will need to do one of the two options:
  1. Not have SF send the email to the recipient once added.  This is because we have already sent the email and just placing a copy in SF for our records
  2. Have the ability to change the fromAddress via the API.  If we remove the email sent from our website and only have the SF one to be sent, we will need to change the from email address.  I have added the email to the Organization-Wide Email addresses and associated it to the correct profile, however, I don't know where to switch it.
 
SingleEmailMessage emailMessage = new SingleEmailMessage();
            if (!string.IsNullOrEmpty(templateid))
            {
                emailMessage.templateId = templateid;
            }
            else
            {
                emailMessage.subject = subject;
                emailMessage.htmlBody = Server.UrlDecode(body) ;
            }

            emailMessage.toAddresses = new String[] { email };
            emailMessage.saveAsActivity = true;
            emailMessage.targetObjectId = contactId;

            SingleEmailMessage[] messages = { emailMessage };
            SendEmailResult[] results = binding.sendEmail(messages);

            if (results[0].success)
            {
                // Console.WriteLine("The email was sent successfully.");
            }
            else
            {
                SendEmail("xxxxxx@xxx.com", "Error SingleEmailMessage add", "The email failed to send: " + results[0].errors[0].message);

            }


            sflogout();

 
I can successfully post an email to Salesforce using the EmailMessage Object, however when I send a link, something like below, it strips out a portion of the URL parameters.  See below 

Link sent
https://www.xxxxxx.com/en-us/reset-password?login=xxx@somecompany.com&id=441810

Instead, I get 
https://www.xxxxxx.com/en-us/reset-password?login=xxx@somecompany.com


Anyone know why or how to fix?
 

In my class I have 3 global variables that I set on page load.  Then when a user clicks a button, those variables are used in a method that is invoked on click. This works fine.  However, when writing my test class, I keep receiving attempt to dereference a null object and it is pointing to those three variables.  

How do you set those variables within a test class?


 

I've created a VF page with controller in Lightning.  I found out that a department that hasn't migrated to Lightning yet also needs access.  However, when I go to add the VF page to the page layout in Classic, it isn't shown.  Is there a way to make it available in Classic.

Here is the VF page code
<apex:page lightningStylesheets="true" action="{!loadPage}" Controller="TrainingSubscriptionListController"  >
  <!-- Begin Default Content REMOVE THIS -->
  <apex:outputtext value="{!tmp}" escape="false" id="tblHTML"/>
  <!-- End Default Content REMOVE THIS -->
</apex:page>

and here is the contoller code
public class TrainingSubscriptionListController {
    @AuraEnabled
    Public List<Contact> acctContacts {get;set;}
    public string tmp {get;set;}
    
    public void loadPage(){
        string AcctId = System.currentPageReference().getParameters().get('Id');
        acctContacts = [Select Id, Training_Subscription_User__c, Name, Email from Contact where AccountId= :AcctId and Training_Subscription_User__c = true];
        
           tmp =     '<table id="myTable"  style="width:100%; table-layout: auto;" cellspacing="0" cellpadding="10"><tr>' + 
                '<td style="padding:15px; background-color: #0084c4 !important;background-image: none !important; color: #ffffff !important; font-size:100% !important; margin:0 !important; border:none !important;">' +
                '<b>Name</b></td>' + 
                // '<td style="width:50px; background-color: #0084c4 !important;background-image: none !important; color: #ffffff !important; font-size:100% !important; margin:0 !important; border:none !important;">' +
                //'</td>' +
                '<td style=" background-color: #0084c4 !important;background-image: none !important; color: #ffffff !important; font-size:100% !important; margin:0 !important; border:none !important;">' +
                '<b>Email</b></td>' +
                
                '</tr>';
            
            integer i = 0;              
            while(i <  acctContacts.size())
            {
                tmp = tmp + '<tr><td style="padding:15px;"><a href="/' + acctContacts[i].Id + '">' + acctContacts[i].Name + '</a></td><td style="padding:5px;"><a href="/' + acctContacts[i].Id + '">' + acctContacts[i].Email  +  '</a></td></tr>';
                i++;
            }
         tmp = tmp + '</table>';
    }

}

I have a VF page for the Account page that I needed to create in order to display Contacts that had a specific field check.  It simply queries Contacts with that field selected and displays.  When I tried to push this into production, I keep getting code coverage errors but I'm not sure how to create a test case for this.

Here is the Apex Code
public class TrainingSubscriptionListController {
    @AuraEnabled
    Public List<Contact> acctContacts {get;set;}
    public string tmp {get;set;}
    
    public void loadPage(){
        string AcctId = System.currentPageReference().getParameters().get('Id');
        acctContacts = [Select Id, Training_Subscription_User__c, Name, Email from Contact where AccountId= :AcctId and Training_Subscription_User__c = true];
        
           tmp =     '<table id="myTable"  style="width:100%; table-layout: auto;" cellspacing="0" cellpadding="10"><tr>' + 
                '<td style="padding:15px; background-color: #0084c4 !important;background-image: none !important; color: #ffffff !important; font-size:100% !important; margin:0 !important; border:none !important;">' +
                '<b>Name</b></td>' + 
                // '<td style="width:50px; background-color: #0084c4 !important;background-image: none !important; color: #ffffff !important; font-size:100% !important; margin:0 !important; border:none !important;">' +
                //'</td>' +
                '<td style=" background-color: #0084c4 !important;background-image: none !important; color: #ffffff !important; font-size:100% !important; margin:0 !important; border:none !important;">' +
                '<b>Email</b></td>' +
                
                '</tr>';
            
            integer i = 0;           
    
            
            while(i <  acctContacts.size())
            {
                tmp = tmp + '<tr><td style="padding:15px;"><a href="/' + acctContacts[i].Id + '">' + acctContacts[i].Name + '</a></td><td style="padding:5px;"><a href="/' + acctContacts[i].Id + '">' + acctContacts[i].Email  +  '</a></td></tr>';
                i++;
            }
         tmp = tmp + '</table>';
    }

}

I tried running it against this test but it fails as well.
@isTest
public class TestMultipleAdminCheck {
    @isTest static void TestContact() {
        Test.startTest();
        Account acct = new Account(Name='Test Account', Training_Subscription_Seats_Available__c = 1, Number_of_Support_Users__c = 1);
        insert acct;
        Contact cont1 = new Contact(FirstName='User', LastName='One',                                     
                                    AccountId=acct.Id, My_ASCI_Role__c = 'Support User');
        Contact cont2 = new Contact(FirstName='User', LastName='Two',                                     
                                    AccountId=acct.Id, My_ASCI_Role__c = 'Admin User', Training_Subscription_User__c = true);
        Contact cont3 = new Contact(FirstName='User', LastName='Three',                                     
                                    AccountId=acct.Id,    My_ASCI_Role__c = 'General User');
        Contact cont4 = new Contact(FirstName='User', LastName='Four',             
                                    AccountId=acct.Id,   My_ASCI_Role__c = 'Support User');
        insert cont1;
        insert cont2;
        insert cont3;
        insert cont4;
        
        
        Test.stopTest();
        
    }
    
}

Any help will be appreciated.
I'm getting the following error when Checking the challenge for the Enable Salesforce Knowledge component of the Knowledge Basics module in Trailhead even though everything is set up correctly according to the article. Knowledge is enabled, the language is set and the user has the appropriate permission. What am I missing?

User-added image
User-added image
User-added image
I'm working on a project where (already sent) emails should be saved to Salesforce and matched with the corresponding Salesforce contact.
Creating new Emails is rather straightforward. For example using the simple_salesforce python library my code looks like this:
 
from simple_salesforce import Salesforce

[…]

sf = Salesforce(instance_url=instance_url, session_id=session_id)
sf.EmailMessage.create(
    {'FromAddress': 'foo@example.com',
     'ToAddress': 'bar@example.com',
     'Subject': 'Email: Fancy Subject', 
     'TextBody': 'lorem ipsum dolor sit amet',  
     'Status': 2
    })

This successfully creates a new EmailMessage but the message is not matched to the contact (assuming bar@example.com is an exisiting contact in Salesfored). This can be seen in numerous places in the Salesforce UI. For example:
It is not part of the contact's activity history
When looking at the Email Message details, the section “Sender and Recipients” is empty
When creating new emails using the Salesforce UI, the association is done correctly. Comparing my EmailMessage objects from the ones generate by Salesforce there is one obvious difference: ActivityId is not set for my objects.
When I'm trying to set ActivityId to a matching Contact ID I receive a Malformed Request Exception INSUFFICIENT_ACCESS_OR_READONLY.

Am I missing something? Is it somehow possible to create those associations using the API?
Can someone help me identify what is chewing up our API calls? As of 3 days ago, we started hitting our 20K limit every day, and prior to that we'd barely hit 1000. I've turned off all our coded integrations, and we're still hitting 20k. I looked at the SF reports, but they only tell me # of API calls by user. How can I see what the API calls are and where they are coming from to help me track down where the leak is???
  • March 14, 2015
  • Like
  • 2