Concepts or coding lessons of Salesforce that you can implement easily

Showing posts with label apex. Show all posts
Showing posts with label apex. Show all posts

What is the use of nextStartDate in Salesforce?




Starting from the specified target date returns the next date when business hours are open.
If the specified target date falls within business hours, this target date is returned.


Let say, you have specified the hours when your support team is available to serve your customers.

And there is Case open outside the business hours then what will be nextStartDate of your Business Hours? See below...

Syntax:


public static Datetime nextStartDate(String businessHoursId, Datetime targetDate)

The following example I am using System.Today() as a  target date.
Sample Apex Code:


// Get the default business hours
BusinessHours busshrs = [SELECT Id FROM BusinessHours WHERE IsDefault = true];
// If it is within the business hours. The returned time will be in the local time zone
Datetime nextStart = BusinessHours.nextStartDate(busshrs.id, System.today());
System.debug('Next Business Hours Start Date is => ' + nextStart);

Example/Use Case:


Business hours for your Salesforce Org are 9 AM to 6 PM. So there are 2 results based on below:

1. If you execute the above code within the business hours, then it will return today's date.
2. If you execute the above code outside the business hours, then it will return next open business date.


Latest Salesforce Interview Questions and Answers:



More Salesforce Blogs:

Check out Salesforce Daily Limit Only in 5 Simplest Steps
Learning Pagination In Salesforce Is Not Difficult At All ! You Just Need 3 Easy Steps
How To Learn Get Field Values From Visualforce Page To Apex Class Controller Without Losing Your Mind
Main Difference Between ISBLANK And ISNULL in Salesforce
How To Get Total Amount Of Records Processed In Batch Job In 10 Minutes And Still Look Your Best 
Export VisualForce Data into Excel Sheet in 3 Easiest Steps
7 Easy Steps to Generate Apex Class From WSDL In Salesforce
Simplest Way To Find Number of Days Between Two Dates in Salesforce
3 Easy Steps To Send Emails With Attachment From Your Apex Class In Salesforce
How Insert Comma In Formula Fields Can Help You Improve Your Productivity
Simple Guidance For You In Access Of Subquery Field Value Using Apex - Upwards Traversal.
Access Subquery Field Value Using Apex in 2 Easy Steps- Downwards Traversal

How Learning Enable Inline Editing In Visual Force Pages Could Save Your Money And Time


Enjoy! If you have any questions, comments etc. please feel free to let me know. As always, please feel free to get in touch me as I would be more than happy to assist you with any of your Salesforce development needs.

Territory Management In Salesforce Can Increase Your Profit !!!

Territory management is important and critical to businesses of any size i.e. Large businesses, Medium and Small.
Territories align to sales team, defined on the basis of geography, sales potential, history, product-based, or a combination of factors.
With the help of Territory management, companies can make the most of sales team resources at minimum cost.

Territory management is an account sharing system that grants access to accounts based on the characteristics of the accounts. It enables your company to structure your Salesforce data and users the same way you structure your sales territories.

Mostly your salesforce organization has a private sharing model, and you want to grant access to accounts based on criteria then Territory management is a solution.

Key points of Territory Management:

1. An Opportunity can assigned to only one Territory.
2. One territory can have unlimited number of Users and Users can assign to any number of territories.
3. One territory can have unlimited number of Accounts and Accounts can assign to any number of territories.

Territory management in Opportunity object:


Requirement: Access TerritoryId of Opportunity in Apex class.
Solution: Easily you can access TerritoryId of Opportunity using Apex class. Once you enables Territory Management into salesforce organization then Territory lookup is created in Opportunity Object which is Standard Field.

Apex Code:

trigger OpportunityTerritoryManagement on Opportunity (before insert, before update) {
    if(Trigger.isBefore){
// Create Set which store opportunity`s territoryId
        Set<Id> setOpptyTerritoryIds = new Set<Id>();
        for(Opportunity objOppty : Trigger.New){
            if(Trigger.isInsert || Trigger.isUpdate){
              if(objOppty.TerritoryId != null){
                setOpptyTerritoryIds.add(objOppty.TerritoryId);
      }
            }
        }
        // Populate Territory details of assigned Territory of Opportunity.
        if(setOpptyTerritoryIds.size() > 0){
            Map<Id, Territory> mapOpptyTerritory = new Map<Id, Territory>([SELECT Id, Name, ParentTerritoryId, ForecastUserId, Description FROM Territory WHERE Id IN :setOpptyTerritoryIds]);
        }
    }
}


Territory management in Account object:


Requirement: Access TerritoryId of Account in Apex class.
Solution: This is not easy as Opportunity. You need to write extra code to access TerritoryId of Account using Apex class. If Territory Management is enable then Territory lookup create on Opportunity object not on Account object. You need extra queries on different object to access TerritoryId of Account.

Steps to Access TerritoryId of Account in Apex class:
1. Query in Account Share object.
2. Query in Group object from where access RelatedId.
3. Query in Territory object to Populate Territory details of assigned Territory of Account.

Apex Code:

trigger AccountTerritoryManagement on Account (before update) {
  if(Trigger.isBefore){
    // Create Set which store Account Territory Id
    Set<Id> setAccTerritoryIds = new Set<Id>();
    Map<Id, Id> mapAccountShare = new Map<Id, Id>();
    Map<Id, Id> mapGroup = new Map<Id, Id>();
    Map<Id, Territory> mapUserTerritory = new Map<Id, Territory>();
    
    //Query in Account Share object
    List<AccountShare> listOfAccountShare = [SELECT Id, UserOrGroupId, AccountId FROM AccountShare WHERE RowCause = 'Territory' AND AccountId IN :Trigger.newMap.keyset()];
    
    for(AccountShare objAcctShare : listOfAccountShare){
      mapAccountShare.put(objAcctShare.AccountId, objAcctShare.UserOrGroupId);         
    }   
    
    //Query in Group object from where access RelatedId
    List<Group> listOfGroup = [SELECT Id, RelatedId FROM Group WHERE Type = 'Territory' AND Id IN :mapAccountShare.Values()];
    
    //Map of Group object
    for(Group objGroupRecord : listOfGroup){
      mapGroup.put(objGroupRecord.Id, objGroupRecord.RelatedId);         
    }
    
    // Populate Territory details of assigned Territory of Account.
    if(!mapGroup.isEmpty()){
      //Query in Territory object
      Map<Id, Territory> mapTerritories = new Map<Id, Territory>([SELECT Id, Name, ParentTerritoryId, ForecastUserId, Description FROM Territory WHERE Id IN:mapGroup.Values()]);
    }
  }
}

If you want more details on Territory Management the check Salesforce Documentation.

Enjoy! If you have any questions, comments etc. please feel free to let me know. As always, please feel free to get in touch me as I would be more than happy to assist you with any of your Salesforce development needs.

Next Post: Import CSV file In Salesforce using Apex in 3 Easiest Steps

Import CSV file In Salesforce using Apex in 3 Easiest Steps

Salesforce does not read the excel file into apex. To overcome for this either we can covert excel file to CSV and import csv file using below code.

We can import data using data loader But sometime there is requirement when end users do not want to use Apex Data loader. 

Client want custom page to load data in salesforce.

Here I am explaining Import CSV file In Salesforce using Apex. Below is the code snippet which import CSV file from apex. In this blog, I have one visual force page and one controller associated with it. 

Visual force page have Import Accounts into Salesforce button. 
Once user click on the button, I am sending email using apex code. 

Step 1: Go to setup and Create one Apex Controller

public class importDataFromCSVController {

  public Blob csvFileBody{get;set;}
  public String csvAsString{get;set;}
  public String[] csvFileLines{get;set;}
  public List<account> accountlist{get;set;}
  public importDataFromCSVController(){
    csvFileLines = new String[]{};
    accountlist= New List<Account>(); 
  }
  
  public void importCSVFile(){
       try{
             // Read CSV file body and store it in variable
              csvAsString = csvFileBody.toString();
  
            // Split CSV String to lines
             csvFileLines = csvAsString.split('\n'); 
           
            // Iterate CSV file lines and retrieve one column at a time.
             for(Integer i=1; i < csvFileLines.size(); i++){
               Account accObj = new Account() ;
               String[] csvRecordData = csvFileLines[i].split(',');
               accObj.name = csvRecordData[0] ;             
               accObj.accountnumber = csvRecordData[1];
               accObj.Type = csvRecordData[2];
               accObj.AccountSource = csvRecordData[3];   
               accObj.Industry = csvRecordData[4];                                                                             
               accountlist.add(accObj);   
             }
            // if all correct then insert Account into Org
             if(accountlist.size()>0)
             insert accountlist;
        }
        catch (Exception e)
        {
            ApexPages.Message errorMessage = new ApexPages.Message(ApexPages.severity.ERROR,'An error has occured while importing data into Salesforce. Please make sure input csv file is correct');
            ApexPages.addMessage(errorMessage);
        }  
  }
}

Step 2: Create Visual force Page

<apex:page controller="importDataFromCSVController" sidebar="false" showHeader="false">
    <apex:form >
        <apex:pagemessages />
        <apex:pageBlock >
            <apex:pageBlockSection columns="4"> 
                  <apex:inputFile value="{!csvFileBody}"  filename="{!csvAsString}"/>
                  <apex:commandButton value="Import Accounts into Salesforce" action="{!importCSVFile}"/>
            </apex:pageBlockSection>
        </apex:pageBlock>
        <apex:pageBlock >
           <apex:pageblocktable value="{!accountlist}" var="acc">
              <apex:column value="{!acc.name}" />
              <apex:column value="{!acc.AccountNumber}" />
              <apex:column value="{!acc.Type}" />
              <apex:column value="{!acc.Phone}" />
              <apex:column value="{!acc.Fax}" />
        </apex:pageblocktable>
     </apex:pageBlock>
   </apex:form>
</apex:page>

Step 3: Download csv file into local machine. Click here to download CSV file. 

CSV will be like:
















Visualforce page have Preview button, you can click on that Preview button. 
OR 
Go to an URL and type or you can paste below URL (Change the salesforceinstancename with your salesforce org URL).

Go to : https://salesforceinstancename/apex/Import_Data_From_CSV .
Load the downloaded CSV file and Click on Import Accounts into Salesforce button

Output:










Note: If the CSV file size are large then you will hit a apex governor limit such as the the 6M byte heap space or the 10 seconds of CPU or the 10,000 rows of DML or the "Regex too complicated" error when importing a large amount of data from a CSV file.

There are other ways to import data into Salesforce.
Check out my other blog: 5 Quick Steps To Install Apex Data Loader.


Enjoy! If you have any questions, comments etc. please feel free to let me know. As always, please feel free to get in touch me as I would be more than happy to assist you with any of your Salesforce development needs.

Next post: Check out Salesforce Daily Limit Only in 5 Simplest Steps

Learning Pagination In Salesforce Is Not Difficult At All ! You Just Need 3 Easy Steps

It is very easy to implement pagination using standard set controller provided by salesforce in visualforce page. You can decide how many records should be displayed in every page also you can easily navigate through pages, move directly to first, last page or to next or previous pages using standard set controller. 

Pagination is very useful when you want to display 1000+ records on visual force page. Without pagination if you try to display 1000+ records on visualforce page then you face visualforce error "Collection size xxxx exceeds maximum size of 1000"

Below example displaying all opportunities in visualforce page with pagination. Default page size 10.

Step 1: Create apex class

public class OpportunitiesPaginationController{
    Public Integer size{get;set;} 
    Public Integer noOfRecords{get; set;} 
    public List<SelectOption> paginationSizeOptions{get;set;}
         
    public OpportunitiesPaginationController(){
        size=10;
        paginationSizeOptions = new List<SelectOption>();
        paginationSizeOptions.add(new SelectOption('5','5'));
        paginationSizeOptions.add(new SelectOption('10','10'));
        paginationSizeOptions.add(new SelectOption('20','20'));
        paginationSizeOptions.add(new SelectOption('50','50'));
        paginationSizeOptions.add(new SelectOption('100','100'));
    }
     
    public ApexPages.StandardSetController setCon {
        get {
            if(setCon == null) {                
                setCon = new ApexPages.StandardSetController(Database.getQueryLocator(
                      [select id,Name,AccountId,Account.name,Amount,StageName,CloseDate from Opportunity]));
                setCon.setPageSize(size);  
                noOfRecords = setCon.getResultSize();
            }            
            return setCon;
        }
        set;
    }
     
    //Changes the size of pagination
    public PageReference refreshPageSize() {
         setCon.setPageSize(size);
         return null;
    }
    // Initialize variable setCon from below method and return a list of opportunity record    
     
    public List<Opportunity> getOpportunities() {
         return (List<Opportunity>) setCon.getRecords();
    }
}


Step 2: Create Visualforce Page


<apex:page controller="OpportunitiesPaginationController" tabStyle="Opportunity" sidebar="false">
    <apex:form >
        <apex:actionFunction name="refreshPageSize" action="{!refreshPageSize}" status="fetchStatus" reRender="pbId"/>
        <apex:pageBlock id="pbId">
            <apex:pageBlockSection title="All Opportunities" collapsible="false" columns="1">
                <apex:pageBlockTable value="{!Opportunities}" var="oppObj">
                     
                    <apex:column headerValue="Opportunity Name">
                        <a href="/{!oppObj.id}" target="_blank" ><apex:outputField value="{!oppObj.Name}"/></a>
                    </apex:column>
                     
                    <apex:column headerValue="Account Name">
                        <a href="/{!oppObj.AccountId}" target="_blank" ><apex:outputField value="{!oppObj.Account.name}"/></a>
                    </apex:column>
                     
                    <apex:column headerValue="Amount">
                        <apex:outputField value="{!oppObj.Amount}"/>
                    </apex:column>
                     
                    <apex:column headerValue="Stage">
                        <apex:outputField value="{!oppObj.StageName}"/>
                    </apex:column>
                     
                    <apex:column headerValue="Close Date">
                        <apex:outputField value="{!oppObj.CloseDate}"/>
                    </apex:column>
                </apex:pageBlockTable>
                 
                <apex:panelGrid columns="8"> 
                 
                <apex:selectList value="{!size}" multiselect="false" size="1" onchange="refreshPageSize();">
                    <apex:selectOptions value="{!paginationSizeOptions}"/>
                </apex:selectList>
                 
                <apex:commandButton status="fetchStatus" reRender="pbId" value="First" action="{!setCon.first}" disabled="{!!setCon.hasPrevious}" title="First Page"/> 
  
                <apex:commandButton status="fetchStatus" reRender="pbId" value="Previous" action="{!setCon.previous}" disabled="{!!setCon.hasPrevious}" title="Previous Page"/> 
  
                <apex:commandButton status="fetchStatus" reRender="pbId" value="Next" action="{!setCon.next}" disabled="{!!setCon.hasNext}" title="Next Page"/> 
  
                <apex:commandButton status="fetchStatus" reRender="pbId" value="Last" action="{!setCon.last}" disabled="{!!setCon.hasNext}" title="Last Page"/> 
  
                <apex:outputText >{!(setCon.pageNumber * size)+1-size}-{!IF((setCon.pageNumber * size)>noOfRecords, noOfRecords,
                     (setCon.pageNumber * size))} of {!noOfRecords}
                </apex:outputText> 
                       
                <apex:outputPanel >                      
                    <apex:actionStatus id="fetchStatus" >
                        <apex:facet name="start" >
                          <img src="/img/loading.gif" />                    
                        </apex:facet>
                    </apex:actionStatus>
                </apex:outputPanel> 
  
            </apex:panelGrid>  
            </apex:pageBlockSection>
        </apex:pageBlock>
    </apex:form>
</apex:page>


Step 3: Click on Preview button of visualforce page



Or 
You can Go to the URL and type (Change the yoursalesforceinstance with your salesforce org URL)

https://yoursalesforceinstance.com/apex/OpportunitiesPagination.













When you use pagination, an exception is thrown when there are modified rows in the collection. This includes any new rows added to the collection through an extension action. The handling of error messages in this case follows the standard behavior and can either be displayed upon the page. For example, you can use the <apex:pageMessages> or <apex:messages> component to display an error message to the user.


Pros and Cons of Choosing This Pagination Tool


Pros:
  • Manages data sets on the server, which reduces page state and increases performance
  • Allows you to paginate over large data sets that have up to 10,000 records
  • Includes built-in functionality such as next, previous, first, last, getResultSize, and other methods that can simplify your page
  • Allows you to paginate forward and backward or to any page within the result set
  • Uses a server-side cursor to cache the entire result set, so results will not change if data changes in the database while a user is paginating from one page to the next.
Cons:
  • Has built-in functionality that results in a very small increase in view state size
  • Can be used only in Apex.

There is a good article about pagination in Apex here: https://developer.salesforce.com/page/Paginating_Data_for_Force.com_Applications that lists various options.

Enjoy! If you have any questions, comments, please feel free to let me know. 

As always, please feel free to get in touch me as I would be more than happy to assist you with any of your Salesforce development needs.

Next post: How To Learn Get Field Values From Visualforce Page To Apex Class Controller Without Losing Your Mind

How To Learn Get Field Values From Visualforce Page To Apex Class Controller Without Losing Your Mind

Here I am explaining Get Field Values From Visualforce Page To Apex Class Controller. Below is the sample code snippet, I have created one controller class and one visual force page associated with it. 

Visual force page has to Submit button. 


Once a user clicks on the button, I am sending email using apex code. 
Check below sample code:



Step 1. Create Apex Controller with name passparamFromVFtoController

Public with sharing class passparamFromVFtoController {
  Public string myInputQueryString{get;set;}
  Public string myoutputString{get;set;}
   
  Public void myInputQuery(){
   System.debug("Inserted string is :- "+ myInputQueryString);
   myoutputString = myInputQueryString ;
   System.debug("Output string is :- "+ myoutputString);
  }
}

Step 2. Create Visualforce Page with name passparamFromVFtoController
<apex:page controller="passparamFromVFtoController" sidebar="false" showHeader="false">
  <!-- Pass parameters from visualforce page to controller -->
  <apex:form >
    <apex:pageblock >
     Input your question=> <apex:inputText value="{!myInputQueryString}"/>
     <apex:commandButton value="Submit" reRender="DisplayInputQueryID" action="{!myInputQuery}"/>
    </apex:pageblock>
     <apex:pageblock >
       <b>Output : </b><apex:outputText value="{!myoutputString}" id="DisplayInputQueryID"/>
     </apex:pageblock>
    </apex:form>
</apex:page>

Output :

You can click on Preview button which is on Visualforce page 
OR 
You can Go to the URL and type (Change the salesforceinstancename with your salesforce org URL).


Go to : https://salesforceinstancename/apex/passparamFromVFtoController.



There is another way: JavaScript Remoting


JavaScript Remoting is a framework or tool that front end developers can use to make an AJAX request from a Visual force page directly to an Apex controller. JavaScript remoting allows you to run asynchronous action by separating the page from the controller and to perform tasks on the page without having reloading the entire page.
JavaScript Remoting is the well-organized and competent way of calling the controller in an asynchronous manner and passing data in from the page, because you are sure that you are passing only that data which you need each time that you make a call.

Step 1: Create an Apex controller called AccountRemoterClass

global with sharing class AccountRemoterClass {

    public String accountName { get; set; }
    public static Account account { get; set; }
    public AccountRemoterClass () { } // empty constructor
    
    @RemoteAction
    global static Account getAccount(String accountName) {
        account = [SELECT Id, Name, Phone, Type, NumberOfDepartments__c 
                   FROM Account WHERE Name = :accountName];
        return account;
    }

}

Step 2: Create a Visualforce page that looks like this:

<apex:page controller="AccountRemoterClass">
    <script type="text/javascript">
    function getRemoteAccount() {
        var accountName = document.getElementById('accountSearch').value;

        Visualforce.remoting.Manager.invokeAction(
            '{!$RemoteAction.AccountRemoterClass.getAccount}',
            accountName, 
            function(result, event){
                if (event.status) {
                    // Below line fetch Visualforce elements and DOM IDs for HTML
                    document.getElementById('remoteAcctId').innerHTML = result.Id
                    document.getElementById(
                        "{!$Component.block.blockSection.secondItem.acctNumEmployees}"
                        ).innerHTML = result.NumberOfEmployees;
                } else if (event.type === 'exception') {
                    document.getElementById("responseErrors").innerHTML = 
                        event.message + "<br/>\n<pre>" + event.where + "</pre>";
                } else {
                    document.getElementById("responseErrors").innerHTML = event.message;
                }
            }, 
            {escape: true}
        );
    }
    </script>

    <input id="accountSearch" type="text"/>
    <button onclick="getRemoteAccount()">Get An Account</button>
    <div id="responseErrors"></div>

    <apex:pageBlock id="block">
        <apex:pageBlockSection id="blockSection" columns="2">
            <apex:pageBlockSectionItem id="firstItem">
                <span id="remoteAcctId"/>
            </apex:pageBlockSectionItem>
            <apex:pageBlockSectionItem id="secondItem">
                <apex:outputText id="acctNumEmployees"/>
            </apex:pageBlockSectionItem>
        </apex:pageBlockSection>
    </apex:pageBlock>

</apex:page>

Below are the JavaScript Remoting Limits:


Remote call`s default response time is 30 seconds. If remote call taking longer time than 30 seconds then you will get a time out exception.
If your request requires more time to complete the transaction, then configure a longer timeout. You can setup it to 120 seconds. 
Most of the interviewer asks the question, what is the maximum response size of your remote call ?
Answer is : maximum 15 MB.

Enjoy! If you have any questions, comments etc. please feel free to let me know. As always, please feel free to get in touch me as I would be more than happy to assist you with any of your Salesforce development needs.