Friday, 22 April 2016

Service cloud Phone Systems









Allows for telephony to be integrated with the support/call center application.
•PBX – Private Branch Exchange system is the initial starting point for all calls into the support center. Allows organizations to receive multiple phone calls at one time
 
 
•ACD – Automatic Call Distributor uses intelligent routing to direct calls to the appropriate agent.
 
      The Automatic Call Distributor (ACD), also referred to as the phone switch, provides the ability to route calls to the most appropriate customer service representative by matching specific types of calls to available representatives who have certain designated customer servicing skills.  ACD software can be used to generate standard and customized reports for evaluating real-time and historical call statistics.

 
•IVR – An Interactive Voice Response system will prompt customer/caller for reason for calling.
 
      Interactive Voice Response (IVR), is used to provide call prompting and self-service functions to customers using the phone channel.  Call prompting can be used to identify the caller and type of request prior to call routing for more effective service.  Self-service options allow the customer to perform relatively simple servicing tasks without speaking to a customer service representative.
 
 
 

Wednesday, 13 April 2016

Rest API in Salesforce | Execute Rest API on workbench | Test class for Rest API


Now learning in salesforce to much easy as compare to our time. The Salesforce Trailhead now offers a fun way to learn everything related to Salesforce Integration
1) https://developer.salesforce.com/trailhead/module/apex_integration_services?utm_campaign=trailhead&utm_source=sfdc&utm_medium=chatter-success

Pleae check above Trailhead module for detail knowledge of web service.

REST API

The Force.com REST API lets you integrate with Force.com applications using simple HTTP methods, in either XML or JSON formats, making this an ideal API for developing mobile applications or external clients. Force.com also supports Apex REST, which lets you create Web services on Force.com using Apex





Create REST Apex class


@RestResource(urlMapping='/api/Account/*')
global with sharing class MyFirstRestAPIClass
{
@HttpGet
global static Account doGet()
{
RestRequest req = RestContext.request;
RestResponse res = RestContext.response;
String AccNumber = req.requestURI.substring(req.requestURI.lastIndexOf('/')+1);
Account result = [SELECT Id, Name, Phone, Website FROM Account WHERE AccountNumber = :AccNumber ];
return result;
}

@HttpDelete
global static void doDelete()
{
RestRequest req = RestContext.request;
RestResponse res = RestContext.response;
String AccNumber = req.requestURI.substring(req.requestURI.lastIndexOf('/')+1);
Account result = [SELECT Id, Name, Phone, Website FROM Account WHERE AccountNumber = :AccNumber ];
delete result;
}

@HttpPost
global static String doPost(String name,String phone,String AccountNumber )
{
Account acc = new Account();
acc.name= name;
acc.phone=phone;
acc.AccountNumber =AccountNumber ;
insert acc;

return acc.id;
}

}


As you can see, the class is annotated with @RestResource(urlMapping='/api/Account/*).
The base endpoint for Apex REST is
https://instance.salesforce.com/services/apexrest/.

The URL mapping is appended to the base endpoint to form the endpoint for your REST service.
For example, in the class example, the REST endpoint is
https://instance.salesforce.com/services/apexrest/api/Account/.


Test Class for REST API

@IsTest
private class MyFirstRestAPIClassTest
{
    static testMethod void testGetMethod()
    {
        Account acc = new Account();
        acc.Name='Test';
        acc.AccountNumber ='12345';
        insert acc;
        
        RestRequest request = new RestRequest();
        request.requestUri ='/services/apexrest/api/Account/12345';
        request.httpMethod = 'GET';
        RestContext.request = request;
        Account acct = MyFirstRestAPIClass.doGet();
        System.assert(acct != null);
        System.assertEquals('Test', acct.Name);
        
    }

    static testMethod void testPostMethod()
    {
        RestRequest request = new RestRequest();
        request.requestUri ='/services/apexrest/api/Account/12345';
        request.httpMethod = 'POST';
        RestContext.request = request;
        String strId = MyFirstRestAPIClass.doPost('Amit','2345678','12345');
        System.assert(strId !=null );
    }

    static testMethod void testDeleteMethod()
    {
        Account acc = new Account();
        acc.Name='Test';
        acc.AccountNumber ='12345';
        insert acc;
        
        RestRequest request = new RestRequest();
        request.requestUri ='/services/apexrest/api/Account/12345';
        request.httpMethod = 'DELETE';
        RestContext.request = request;
        MyFirstRestAPIClass.doDelete();
        
        List<Account> ListAcct = [SELECT Id FROM Account WHERE Id=:acc.id];
        System.assert(ListAcct.size() ==0 );
    }

}


Execute your Apex REST class in workbench

Step 1:- Open https://workbench.developerforce.com/
Step 2:- Select Environment as Production and select the checkbox to agree the terms and condition then select Login with Salesforce.


NOTE:- If you are already login then only above step will work other wise you need to enter user name and password.

Step 3:- In the Workbench tool select Utilities > REST Explorer



Step 4:- In the REST Explorer window paste the following url in the box

Create Account Call
Method :- Post
URL :- /services/apexrest/api/Account
Body:-
{
  "name" : "Test Rest",
  "phone" : "123456789",
  "AccountNumber" : "12345"

}



Get Account Call

Method :- Get
URL :- /services/apexrest/api/Account/12345
Body:- NA




Please check below post for more information
1) https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_rest_methods.htm
2) https://developer.salesforce.com/page/Getting_Started_with_the_Force.com_REST_API





<<PREVIOUS       NEXT>>







Tuesday, 5 April 2016

Mass Delete | Delete from List View


Step 1:-  Create a Mass Delete button on account object 

Setup->Accounts->Buttons, Links, and Actions


Then Click on New Button or Link Button.


Then add below code in your button
{!REQUIRESCRIPT("/soap/ajax/9.0/connection.js")}

var records = {!GETRECORDIDS( $ObjectType.Account )};

if (records[0] == null) {
alert("Please select at least one record.")
}
else
{
var errors = [];
var result = sforce.connection.deleteIds(records);
if (result && result.length)
{
var numFailed = 0;
var numSucceeded = 0;
for (var i = 0; i < result.length; i++)
{
var res = result[i];
if (res && res.success == 'true')
{
numSucceeded++;
}
else
{
var es = res.getArray("errors");
if (es.length > 0)
{
errors.push(es[0].message);
}
numFailed++;
}
}
if (numFailed > 0)
{
alert("Failed: " + numFailed + "\nSucceeded: " + numSucceeded + " \n Due to: " + errors.join("\n"));
}
else
{
alert("Number of records deleted: " + numSucceeded);
}
}
window.location.reload();
}

Step 2:- Add button on List view

Setup -> Accounts->Account Search Layouts


Then add button in Account List view

Step 3:- Finally ready to use :-



Reference document which i followed :-
1) https://help.salesforce.com/HTViewHelpDoc?id=links_useful_custom_buttons_mass_delete.htm

You can install custom buttons from the Mass Delete app at http://sites.force.com/appexchange.
Thanks
Amit Chaudhary

Wednesday, 30 March 2016

Wrapper Class in Salesforce | Select All Java Script | Add to Grid

Problem :- 
How can I display a table of records with a check box and then process only the records that are selected?

Solution:- 
Wrapper class.

A wrapper or container class is a class, data structure, or an abstract data type whose instances are a collections of other objects.It is a custom object defined by Salesforce developer where he defines the properties of the wrapper class. Within Apex & Visualforce this can be extremely helpful to achieve many business scenarios within the Salesforce CRM software.

Using Wrapper classes we can have the ability to check few records from the displayed list and process them for some action




public with sharing class WrapperDemoController {
   
    public List<AccountWrapper> listAccountWrapper {get; set;}
    public List<Account> selectedAccounts{get;set;}

    public WrapperDemoController ()
    {
            listAccountWrapper = new List<AccountWrapper>();
            searchRecord();
    }
   
    public void searchRecord()
    {
        listAccountWrapper.clear();
            for(Account a: [select Id, Name,BillingState, Website, Phone ,Active__c from Account limit 10])
            {
                listAccountWrapper.add(new AccountWrapper(a));
            }
    }

    public void processSelected()
    {
        selectedAccounts = new List<Account>();
        selectedAccounts.clear();
        for(AccountWrapper wrapAccountObj : listAccountWrapper)
        {
            if(wrapAccountObj.selected == true)
            {
                selectedAccounts.add(wrapAccountObj.acc);
            }
        }
    }

    public void ActivateData()
    {
        for(Account acc : selectedAccounts )
        {
            acc.Active__c ='Yes';
        }
        update selectedAccounts ;
        searchRecord();
    }

    public void DeActivateData()
    {
        for(Account acc : selectedAccounts )
        {
            acc.Active__c ='No';
        }
        update selectedAccounts ;
        searchRecord();
    }
   


    // This is our wrapper/container class.
    public class AccountWrapper
    {
        public Account acc {get; set;}
        public Boolean selected {get; set;}
        public AccountWrapper(Account a)
        {
            acc = a;
            selected = false;
        }
    }

}
Page

<apex:page controller="WrapperDemoController">
    <script type="text/javascript">
        function selectAllCheckboxes(obj,receivedInputID){
            var inputCheckBox = document.getElementsByTagName("input");
            for(var i=0; i<inputCheckBox.length; i++){
                if(inputCheckBox[i].id.indexOf(receivedInputID)!=-1){
                    inputCheckBox[i].checked = obj.checked;
                }
            }
        }
    </script>
    <apex:form >
        <apex:pageBlock id="PB1">
            <apex:pageBlockButtons >
                <apex:commandButton value="Add to Grid" action="{!processSelected}" rerender="table2,PB2"/>
            </apex:pageBlockButtons>

            <apex:pageblockSection title="All Accounts" collapsible="false" columns="1">
                <apex:pageBlockTable value="{!listAccountWrapper}" var="accWrap" id="table" title="All Accounts">
                    <apex:column >
                        <apex:facet name="header">
                            <apex:inputCheckbox onclick="selectAllCheckboxes(this,'inputId')"/>
                        </apex:facet>
                        <apex:inputCheckbox value="{!accWrap.selected}" id="inputId"/>
                    </apex:column>
                    <apex:column value="{!accWrap.acc.Name}" />
                    <apex:column value="{!accWrap.acc.BillingState}" />
                    <apex:column value="{!accWrap.acc.Phone}" />
                    <apex:column value="{!accWrap.acc.Active__c}" />
                </apex:pageBlockTable>


            </apex:pageblockSection>
        </apex:pageBlock>
       
        <apex:pageBlock id="PB2" >
            <apex:pageBlockButtons >
                <apex:commandButton value="Activate" action="{!ActivateData}" rerender="PB1,PB2"/>
                <apex:commandButton value="DeActivate" action="{!DeActivateData}" rerender="PB1,PB2"/>
            </apex:pageBlockButtons>

                <apex:pageBlockTable value="{!selectedAccounts}" var="c" id="table2" title="Selected Accounts">
                    <apex:column value="{!c.Name}" headerValue="Account Name"/>
                    <apex:column value="{!c.BillingState}" headerValue="Billing State"/>
                    <apex:column value="{!c.Phone}" headerValue="Phone"/>
                    <apex:column value="{!c.Active__c}" headerValue="Active"/>
                </apex:pageBlockTable>
        </apex:pageBlock>

       
    </apex:form>
</apex:page>


Some Other useful like :-
1) https://developer.salesforce.com/page/Wrapper_Class

Thanks
Amit Chaudhary

 

Saturday, 12 March 2016

Dynamic Query | Select All Field in SOQL | Select * Form Account


Dynamic Select * Form Account Query in salesforce


public Void GetAllField()
{
String query ='';
String SobjectApiName = 'Account';
Map<String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe();
Map<String, Schema.SObjectField> fieldMap = schemaMap.get(SobjectApiName).getDescribe().fields.getMap();

String strFields = '';

for(String fieldName : fieldMap.keyset() )
{
if(strFields == null || strFields == '')
{
strFields = fieldName;
}else{
strFields = strFields + ' , ' + fieldName;
}
}

query = 'select ' +
strFields + ' from ' + SobjectApiName + ' Limit 10 ';

List <Account> accList = Database.query(query);

}


Thanks ,
Amit Chaudhary

Thursday, 25 February 2016

Batch Apex in salesforce | Test class for Batch job | how to schedule batch job


Batch Apex
A Batch class allows you to define a single job that can be broken up into manageable chunks that will be processed separately.


When to use Batch Apex

One example is if you need to make a field update to every Account in your organization. If you have 10,001 Account records in your org, this is impossible without some way of breaking it up. So in the start() method, you define the query you're going to use in this batch context: 'select Id from Account'. Then the execute() method runs, but only receives a relatively short list of records (default 200). Within the execute(), everything runs in its own transactional context, which means almost all of the governor limits only apply to that block. Thus each time execute() is run, you are allowed 150 queries and 50,000 DML rows and so on. When that execute() is complete, a new one is instantiated with the next group of 200 Accounts, with a brand new set of governor limits. Finally the finish() method wraps up any loose ends as necessary, like sending a status email.


Sample Batch Apex

1) Start method is automatically called at the beginning of the apex job. This method will collect record or objects on which the operation should be performed. These record are divided into subtasks & passes those to execute method.

2) Execute Method performs operation which we want to perform on the records fetched from start method.

3) Finish method executes after all batches are processed. Use this method to send confirmation email notifications.



global class AccountUpdateBatchJob implements Database.Batchable<sObject>
{
    global Database.QueryLocator start(Database.BatchableContext BC)
    {
        String query = 'SELECT Id,Name FROM Account';
       
        return Database.getQueryLocator(query);
    }
    global void execute(Database.BatchableContext BC, List<Account> scope)
    {
        for(Account a : scope)
        {
            a.Name = a.Name + 'Updated by Batch job';
        }
        update scope;
    }
    global void finish(Database.BatchableContext BC) {
    }
}




Calling on Batch Apex

            AccountUpdateBatchJob obj = new AccountUpdateBatchJob();
            DataBase.executeBatch(obj);




Scheduler Class For Batch Apex


global class AccountUpdateBatchJobscheduled implements Schedulable 
{
    global void execute(SchedulableContext sc) 
    {
        AccountUpdateBatchJob b = new AccountUpdateBatchJob(); 
        database.executebatch(b);
    }
}
Please check below post for scheduler test class

URL :- http://amitsalesforce.blogspot.in/2017/07/how-to-write-test-class-for-scheduler.html



How to Schedule scheduler class

There are two option we have schedule the scheduler classes.
1) By System Scheduler.
2) By Developer console

System Scheduler.

Step 1) Click on Setup->Apex class. Then search Schedule Apex button.

Step 2) Select the scheduler class and set Time like below screen shot.




By Developer console 

Execute below code from developer console :-

AccountUpdateBatchJobscheduled m = new AccountUpdateBatchJobscheduled();
String sch = '20 30 8 10 2 ?';
String jobID = system.schedule('Merge Job', sch, m);



Test Class


@isTest
public class AccountUpdateBatchJobTest
{
    static testMethod void testMethod1()
    {
        List<Account> lstAccount= new List<Account>();
        for(Integer i=0 ;i <200;i++)
        {
            Account acc = new Account();
            acc.Name ='Name'+i;
            lstLead.add(acc);
        }
       
        insert lstAccount;
       
        Test.startTest();

            AccountUpdateBatchJob obj = new AccountUpdateBatchJob();
            DataBase.executeBatch(obj);
           
        Test.stopTest();
    }
}


Limits in Batch Apex

1) Up to five queued or active batch jobs are allowed for Apex
2) Cursor limits for different Force.com features are tracked separately. For example, you can have 50 Apex query cursors, 50 batch cursors, and 50 Visualforce cursors open at the same time.
3) A maximum of 50 million records can be returned in the Database.QueryLocator object. If more than 50 million records are returned, the batch job is immediately terminated and marked as Failed
4) If the start method returns a QueryLocator, the optional scope parameter of Database.executeBatch can have a maximum value of 2,000. If set to a higher value, Salesforce chunks the records returned by the QueryLocator into smaller batches of up to 2,000 records. If the start method returns an iterable, the scope parameter value has no upper limit; however, if you use a very high number, you may run into other limits.
5) If no size is specified with the optional scope parameter of Database.executeBatch, Salesforce chunks the records returned by the start method into batches of 200, and then passes each batch to the execute method.Apex governor limits are reset for each execution of execute.
6) The start, execute, and finish methods can implement up to 10 callouts each
7) The maximum number of batch executions is 250,000 per 24 hours
8) Only one batch Apex job's start method can run at a time in an organization. Batch jobs that haven’t started yet remain in the queue until they're started. Note that this limit doesn’t cause any batch job to fail and execute methods of batch Apex jobs still run in parallel if more than one job is running


Some Useful link :-

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_batch_interface.htm
https://developer.salesforce.com/docs/atlas.en-us.apex_workbook.meta/apex_workbook/apex_batch_intro.htm


Friday, 5 February 2016

Types of Sharing in Salesforce



1. Force.com Managed Sharing
Force.com managed sharing involves sharing access granted by Force.com based on record ownership, the role hierarchy, and sharing rules:

  • 1.1 Record Ownership :- Each record is owned by a user or optionally a queue for custom objects, cases and leads. The record owner is automatically granted Full Access, allowing them to view, edit, transfer, share, and delete the record.
  • 1.2 Role Hierarchy :- The role hierarchy enables users above another user in the hierarchy to have the same level of access to records owned by or shared with users below. Consequently, users above a record owner in the role hierarchy are also implicitly granted Full Access to the record, though this behavior can be disabled for specific custom objects. The role hierarchy is not maintained with sharing records. Instead, role hierarchy access is derived at runtime. For more information, see “Controlling Access Using Hierarchies” in the Salesforce online help.
  • 1.3 Sharing Rules :-Sharing rules are used by administrators to automatically grant users within a given group or role access to records owned by a specific group of users. Sharing rules cannot be added to a package and cannot be used to support sharing logic for apps installed from Force.com AppExchange. Sharing rules can be based on record ownership or other criteria. You can't use Apex to create criteria-based sharing rules. Also, criteria-based sharing cannot be tested using Apex. All implicit sharing added by Force.com managed sharing cannot be altered directly using the Salesforce user interface, SOAP API, or Apex.


2. User Managed Sharing, also known as Manual Sharing
User managed sharing allows the record owner or any user with Full Access to a record to share the record with a user or group of users. This is generally done by an end-user, for a single record. Only the record owner and users above the owner in the role hierarchy are granted Full Access to the record. It is not possible to grant other users Full Access. Users with the “Modify All” object-level permission for the given object or the “Modify All Data” permission can also manually share a record. User managed sharing is removed when the record owner changes or when the access granted in the sharing does not grant additional access beyond the object's organization-wide sharing default access level.

3. Apex Managed Sharing
Apex managed sharing provides developers with the ability to support an application’s particular sharing requirements programmatically through Apex or the SOAP API. This type of sharing is similar to Force.com managed sharing. Only users with “Modify All Data” permission can add or change Apex managed sharing on a record. Apex managed sharing is maintained across record owner changes.
https://developer.salesforce.com/page/Using_Apex_Managed_Sharing_to_Create_Custom_Record_Sharing_Logic 

trigger Hiring_Manager_Job_Share on Job__c (after insert) {
    if(trigger.isInsert)
 {
  List<Job__Share> jobShares  = new List<Job__Share>();

  for(Job__c job : trigger.new)
  {
   Job__Share hiringManagerShare = new Job__Share();
   hiringManagerShare.ParentId = job.Id;
   hiringManagerShare.UserOrGroupId = job.Hiring_Manager__c;
   hiringManagerShare.AccessLevel = 'edit';
   hiringManagerShare.RowCause = Schema.Job__Share.RowCause.Hiring_Manager_Access__c;
   jobShares.add(hiringManagerShare);
  }
    Database.SaveResult[] jobShareInsertResult = Database.insert(jobShares,false);
    }
}