Monday, 5 June 2017

Roll Up Summary Trigger | SUM Child Records | Aggregate Query

Roll Up Summary Trigger: SUM


Scenario:

Sum Cost field(Cost__c) values on Contact(s)(all Contacts related to an Account)and display on Account Record in field-TotalCost(Total_Cost__c).
Behaviour:
Same a SUM Roll Up Summary Field

trigger ContactTrigger on Contact (after insert) {
  ContactTriggerHandler.CalculateTotalCost(Trigger.new);
}

public class ContactTriggerHandler{
  public static void CalculateTotalCost(List<Contact> contactList){
    List<Account> accountList = new List<Account>();
Set<Id> accountIds = new Set<Id>();
for(Contact con:contactList){
 accountIds.add(con.AccountId);
}
//This Map stores Account Id as a Key and related Total Cost as Value
Map<Id,Double> AccountId_Key_TotalCost_ValueMap = new Map<Id,Double>();
//Aggregate query is used to store Sum of all related Cost Fields on Contact
for(AggregateResult con  : [SELECT AccountId,SUM(Cost__c) maxcost
   FROM Contact WHERE AccountId IN :accountIds
GROUP BY AccountId]) {
 AccountId_Key_TotalCost_ValueMap.put((Id)con.get('AccountId'),(Double)con.get('maxcost'));          
}
//Logic to update Total_Cost__c values appropriately
// based on AccountId_Key_TotalCost_ValueMap Map and put null/zero if none of the related
// Contact records exist
for(Account acc : [SELECT Total_Cost__c FROM Account WHERE Id IN : accountIds]) {
 if(AccountId_Key_TotalCost_ValueMap.ContainsKey(acc.Id)){                      
   acc.Total_Cost__c = AccountId_Key_TotalCost_ValueMap.get(acc.Id);
 }
      else{
   acc.Total_Cost__c = 0;
 }
 accountList.add(acc);                          
}
 // These variables are used to ids of Successful records and error messages
 Set<Id> successItemIds       = new Set<Id>();
 Set<String> errorItems       = new Set<String>();
if(accountList.size()>0) {
 Database.saveResult[] saveResultItems  = Database.update(accountList,false);
 for (Database.saveResult sr : saveResultItems) {
   if(sr.isSuccess()){
 successItemIds.add(sr.getId());
}
else{
 for(Database.Error err : sr.getErrors()) {
   errorItems.add(err.getMessage());
 }
}
 }
}
 // Iteration of Contact Records is done once again to make sure multiple errors 
       // are shown in case if multiple errors are thrown
       if(errorItems.size() > 0 ){
         for(Contact con: contactList) {
           if(!successItemIds.contains(con.AccountId)){
             for(String err: errorItems) {
               con.addError(err);
             }        
           }                      
        }
     }  
  }
}

Sunday, 5 February 2017

How to call apex method on press of Enter Key in Salesforce?

Sample Code Snippet:

<apex:page>
  <apex:form>
<apex:inputText id="zipCode" value="{!zipCodeFromSearch}"
                           onkeypress="return pressEnter(event)">
       <apex:actionFunction action="{!searchStoreOnAddress}" name="enterFunc"/>
    </apex:inputText>
</apex:form>
<script type='text/javascript'>
function pressEnter(ev)  {
if (window.event && window.event.keyCode == 13 || ev.which == 13) {
enterFunc();
return false;
} else {
return true;
}
}
</script>

</apex:page>


  • searchStoreOnAddress is the apex method
  • When User press Enter Key in Text Box then Javascript function-pressEnter(event)  is executed which calls action function(by enterFunc()) and then actionFunction executes searchStoreOnAddress controller method.

Wednesday, 20 July 2016

Fetch RecordType Id without Query Salesforce

//get Case's Internal record type Id
Id recordTypeId  = Schema.SObjectType.Case.getRecordTypeInfosByName().get('Internal').getRecordTypeId();
  • Here I am fetching Internal Record Type of Case Object
  • Internal is label of Record Type not Developer Name

Saturday, 16 July 2016

Salesforce Components names for ANT tool|Package.xml


Sample Package.xml

<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
    <!-- Custom Object Tab, Web Tab and Visualforce tab -->
    <types>
        <members>Employee__c</members>
        <name>CustomTab</name>
    </types>
    <types>
        <members>*</members>
        <name>ApexClass</name>
    </types>
    <types>
        <members>*</members>
        <name>ApexComponent</name>
    </types>
    <types>
        <members>*</members>
        <name>ApexPage</name>
    </types>
    <types>
        <members>*</members>
        <name>ApexTrigger</name>
    </types>
    <types>
        <members>*</members>
        <name>CustomApplication</name>
    </types>
    <types>
        <members>Activity.Closed__c</members>
        <name>CustomField</name>
    </types>
    <types>
        <members>*</members>
        <members>Account</members>
        <name>CustomObject</name>
    </types>
    <types>
        <members>*</members>
        <name>CustomTab</name>
    </types>
    <types>
        <members>Images/Logo.png</members>
        <name>Document</name>
    </types>
<!--     For retrieving and deploying Email Templates, folder name is mandatory       -->
    <types>
        <members>unfiled$public/Test_Notification</members>
        <members>EmailTemplates/InquiryPortal</members>
        <name>EmailTemplate</name>
    </types>
    <types>
        <members>*</members>
        <name>HomePageComponent</name>
    </types>
    <types>
        <members>*</members>
        <name>HomePageLayout</name>
    </types>
<!-- Home Page Custom Link -->
    <types>
        <members>*</members>
        <name>CustomPageWebLink</name>
    </types>
   <types> 
        <members>Account.My_Account_Team</members> 
        <name>ListView</name> 
   </types>
    <types>
        <members>Account-Account Layout</members>
        <name>Layout</name>
    </types>
    <types>
        <members>Analyst</members>
        <name>Profile</name>
    </types>
    <types>
        <members>ExtraReports</members>
        <members>ExtraReports/AnyOccupation</members>
        <name>Report</name>
    </types>
    <types>
        <members>*</members>
        <name>ReportType</name>
    </types>
    <types>
        <members>*</members>
        <name>StaticResource</name>
    </types>
    <types>
        <members>Contact.SelectTitle</members>
        <name>WebLink</name>
    </types>
    <types>
        <members>*</members>
        <name>PermissionSet</name>
    </types>

     <types>
        <members>*</members>
        <name>QuickAction</name>
    </types>
    <!-- 
 Workflow includes WorkflowFieldUpdate,
 WorkflowAlert, WorkflowOutboundMessage, WorkflowRule
    -->
    <types>
        <members>ObjectName.WorkFlowName</members>
        <name>Workflow</name>
    </types>  
    <types>
        <members>ObjectName.FieldUpdateName</members>
        <name>WorkflowFieldUpdate</name>
    </types>
    <types>
        <members>ObjectName.FieldUpdateName</members>
        <name>WorkflowAlert</name>
    </types>
    <types>
        <members>ObjectName.FieldUpdateName</members>
        <name>WorkflowOutboundMessage</members>
    </types>
    <types>
        <members>ObjectName.FieldUpdateName</members>
        <name>WorkflowRule</name>
    </types>
    <types>
        <members>ObjectName.FieldUpdateName</members>
        <name>WorkflowTask</name>
    </types>
<!--        Custom Button/Link         -->
   <types>
        <members>Directory_Edition__c.Final_Letter_Renewal</members>
        <name>WebLink</name>  
    </types>
<!--        Standard Tabs and Fields renames        -->
    <types>
          <members>*</members>
          <name>CustomObjectTranslation</name>
    </types>
<!--        Validation Rules        -->
    <types>
 <members>Object Name.Validation Name</members>
        <name>ValidationRule</name>
    </types>   
<!--        Record Types        -->
    <types>
 <members>Object Name.Record Type Name</members>
        <name>RecordType</name>
    </types>  
<!--       Role        -->
    <types>
          <members>*</members>
          <name>Role</name>
    </types>
<!--       Queue        -->
    <types>
          <members>*</members>
          <name>Queue</name>
    </types>
<!--       Public Group        -->
    <types>
          <members>*</members>
          <name>Group</name>
    </types>
<!--      Custom Labels        -->
    <types>
          <members>*</members>
          <name>CustomLabel</name>
    </types>
<!--      LetterHead       -->
 <types>
  <members>*</members>
  <name>Letterhead</name>
 </types> 
<!--      Process Builder and Flow  -->
    <types>
        <members>*</members>
        <name>Flow</name>

    </types>
    <version>36.0</version>
</Package>

Wednesday, 29 April 2015

Bulk Data | Visual Force | readOnly

Working with Large Sets of Data in Visualforce Page

Visualforce iteration components, such as<apex:pageBlockTable> and <apex:repeat>, are limited to a maximum of 1,000 items in the collection they iterate over.

Sometimes your Visualforce pages may need to work with or display larger sets of data, but not need to make modifications to that data;
for example, if you are providing custom reporting and analytics. Visualforce offers developers a “read-only mode”, which relaxes the limit on the number of rows which can be queried in one request, and increases the limit on the number of collection items which can be iterated over within the page.

Setting Read-Only Mode for an Entire Page
To enable read-only mode for an entire page, set the readOnly attribute on the <apex:page> component to true.

For example, here is a simple page that will be processed in read-only mode:
<apex:page controller="SummaryStatsController" readOnly="true">
    <p>Here is a statistic: {!veryLargeSummaryStat}</p>
</apex:page>
The controller for this page is also simple, but illustrates how you can calculate summary statistics for display on a page:

public class SummaryStatsController {
    public Integer getVeryLargeSummaryStat() {
        Integer closedOpportunityStats =
        [SELECT COUNT() FROM Opportunity WHERE Opportunity.IsClosed = true];
        return closedOpportunityStats;
    }
}

Note:
1. In read-only mode, total number of records retrieved by SOQL queries is up to 1 million rows.
2.With readOnly attribute maximum number of items in a collection that can be iterated over using    components such as <apex:dataTable>, <apex:dataList>, and <apex:repeat> is increased from 1,000 items to 10,000.
3.Read-only mode for the entire page can’t use data manipulation language (DML) operations.

Saturday, 18 January 2014

Roll Up Summary Trigger | COUNT

Roll Up Summary Trigger: Count Child Records.

Scenario:Count Total Contact records and display in Account Record in field-TotalContacts(Total_Contacts__c).

trigger ContactTrigger on Contact (after insert) {
     ContactTriggerHandler.countContacts(Trigger.new);
}

public class ContactTriggerHandler{
    public static void countContacts(List<Contact> contactList){
try{
Set<Id> accountIds = new Set<Id>();
for(Contact con:contactList){
accountIds.add(con.AccountId);
}    
Map<Id,List<Contact>> Map_accountId_contactList = new Map<id,List<Contact>>                                                                   ();
List<Account> accountList = new List<Account>();
accountList = [select ID, Total_Contacts__c,(SELECT id FROM Contacts) from                                                        Account WHERE Id IN:accountIds];
for(Account acc: accountList){
Map_accountId_contactList.put(acc.Id,acc.Contacts);
}
for(Account acc:accountList){  
    acc.Total_Contacts__c = (Map_accountId_contactList.get(acc.Id)).SIZE();
}
update accountList;
}
catch(Exception e){
system.Debug('An Error has occured::'+e.getMessage());
}
    }
}