Monday, September 29, 2014

Quote to Cash Certification Overview

Quote-to-Cash Certification, is a free certification program designed for quoting and contracting knowledge. This certification consists of five video modules, followed by an online test to earn certification badge.

You need to register for this course on http://www.apttus.com/certification/ . After registration, you will get access to 5 training videos and study guide which will help you to clear the certification quiz.

In short, Quote to cash is integrated package of below mentioned functionality:
  • Integrated CPQ, contract management & revenue management-
  • Compensation management that incents reps to offer better deals-
  • Echo sign e-Signature for speedy quoting and contract cycles
  • Sync order details to enterprise resource planning (ERP) and Salesforc

Different modules involved:
  • Quote-to-Cash- Introduction and its benefits
  • Introduction to Configure, Price, Quote (CPQ)
  • Minimizing Risk & Maximizing Revenue with Contract Management
  • Getting Real Insight Into Cash with Effective Revenue Management
  • Quote-to-Cash Success on Salesforce1

This training module will give you functional knowledge of Quote to cash process, helps in understanding CPQ and will explain what are challenges customers are facing to close deals faster . It also describe the functionality provide by APTTUS –Quote to cash package in order to deal with all the challenges while proposing deals or closing the deals.

Features which I like the most in Quote to cash:
  • 100% native to Salesforce so need to integrate it with any 3rd party quoting tool.
  • Guide selling: It provide an ability to configure this app in such a way that sales reps can ask question from customer related to their requirement s and interest and system will populate the suggested products
  • Marked as favorites:  Sales reps can specify products or combination of different products as favorites so that they don’t have to search it every time.
  • Ability to configure discounts at account or partner level, quote level and quote line item level.
  • Availability of API’s related to all CPQ functionality so that developers can customize the app based on customer requirements.
  • Ability to configure E-commerce for external customer easily by using Exposed API’s provided by APTTUS.

Friday, September 12, 2014

Using the Force.com CLI

Force.com CLI tool allows you to interact directly with Force.com from your command-line.
Functionality includes exporting metadata and packages created in SFDC to a local directory, browsing data objects, executing SOQL queries, executing APEX code,managing custom objects etc.


Download Force.CLI from https://force-cli.heroku.com/

Download Force.com CLI executable file and store it in some folder. Suppose my folder name is "CLI Demo" present in E: drive.


Now Open Command prompt  and go to CLI Demo Folder and use below commands:
E:\CLI Demo>force version


If you are getting version information then it means CLI is configured correctly. Otherwise if you getting some error, then set system variable by navigating computer->my properties-Advanced system settings->Environment variables. Provide CLI Demo folder location in path variable.


Once Force.com CLI is configured properly, then we can use it to export package created in SFDC to local directory. Follow below steps:
  1. Create a package: Go to SetUp-> Create->Packages. Create a new package and include all elements which you want to export from SFDC.
  2.          Now you can go to command prompt and enter following commands:
             First we need to login to SFDC instance in order to fetch package

        For Production and developer sandbox use
        force login -i=login.salesforce.com  -u=USERNAME  -p=PASSWORD+SECURITYTOKEN
                           or
        force login -u=USERNAME  -p=PASSWORD+SECURITYTOKEN

       For Sandbox
        force login -i=test.salesforce.com -u=USERNAME  -p=PASSWORD+SECURITYTOKEN

            To fetch package details:

      force fetch package PACKAGENAME --unpack

      In our case package name is “ForceCLIDemoPackage” so enter

      fetch package ForceCLIDemoPackage --unpack


Now metadata folder is created in CLI Demo folder which contain all components information present in package. If you open it, you will see package.xml containing all components list.


Note: If you deploy components in SFDC org using Workbench, then Force.com CLI will help you create package.xml file easily. You don’t have to manually create package.xml file. Just create package in your source org and Fetch it with Force.com CLI and the zip all contents (package.xml and all folders present in ForceCLIDemoPackage). After this deploy the zip file using workbench to target org.

Available commands:
   login     Log in to force.com
   logout    Log out from force.com
   logins    List force.com logins used
   active    Show or set the active force.com account
   whoami    Show information about the active account
   sobject   Manage standard & custom objects
   field     Manage sobject fields
   record    Create, modify, or view records
   bulk      Load csv file use Bulk API
   fetch     Export specified artifact(s) to a local directory
   export    Export metadata to a local directory
   fetch     Export specified artifact(s) to a local directory
   import    Import metadata from a local directory
   query     Execute a SOQL statement
   apex      Execute anonymous Apex code
   oauth     Manage ConnectedApp credentials
   version   Display current version
   update    Update to the latest version
   push      Deploy single artifact from a local directory
   password  See password status or reset password
   help      Show this help

Run 'force help [command]' for details.





Tuesday, June 10, 2014

Displaying all submitted records for an approval process along with their status in VF Page

Few days back, I got requirement from one of my friends to list all approval process in Visualforce Page in picklist and when user select any approval process, the system should display all the records which are submitted for approval along with their status.
In order to achieve this, I have created a VF page and used REST API to get list of all approval process present in org. After getting the list of approval process in JSON, I parsed the response and displayed the approval process names in picklist. When user select particular approval process, system will query all processinstances records and then with the help of TargetObjectid, it will fetched the Ojbect name. Then system will match the object name related to approval process with object related to targetobjectid.
If it got matched, then processInstance record will be stored in list and will be displayed to user.

VF Page Snapshot:









Notes:

  • First create remote site setting with Remote Site URL as https://xxx.salesforce.com where xxx domain name like ap1,na1 etc.
  • I tried to filter the number of processInstance records by putting where clause but it didn't work for me. So I queried all processInstance records.
  • We can specify where clause on createddate or lastmodifieddate by giving an option to user to select date range. We can display two more fields as startdate and enddate on VF page and system will display only processinstance records created or modified between these 2 dates.

Looking forward to your comments and suggestions.

Below is VF Page Code:

<apex:page controller="DisplayApprovedRecordsController" action="{!FetchAllApprovalProcess}">
<apex:form >
    <apex:pageblock title="Approval processess List">      
        <apex:pageblocksection columns="3">
            <apex:pageblockSectionItem >
                <apex:outputLabel value="Select" for="apr"></apex:outputLabel>
                <apex:selectList value="{!selectedApprovalProcess}" size="1" id="apr">
                    <apex:selectOptions value="{!ApprovalWrapperList}"></apex:selectOptions>
                    <apex:actionsupport event="onchange" action="{!FindRecords}"/>
                </apex:selectList>
            </apex:pageblockSectionItem>          
        </apex:pageblocksection>      
        <apex:pageblockSection title="Approved Records" columns="1" >
            <apex:pageblockTable value="{!recordList}" var="rec" rendered="{!recordList.size>0}">
                <apex:column headerValue="Name">
                    <apex:outputlink value="/{!rec.TargetObjectId}">{!rec.TargetObject.name}</apex:outputlink>
                </apex:column>              
                <apex:column headerValue="Status">
                    <apex:outputText value="{!rec.status}"></apex:outputText>
                </apex:column>
            </apex:pageblockTable>          
            <apex:outputpanel rendered="{!recordList.size==0}">
                <apex:outputText value="No records to display"></apex:outputText>
            </apex:outputpanel>      
        </apex:pageblockSection>
    </apex:pageblock>
</apex:form>
</apex:page>

Apex Class Code:

public class DisplayApprovedRecordsController {
    public List<ApprovalWrapper> ApprovalProcessList{get;set;}//list to store all approval process
    public String selectedApprovalProcess{get;set;}
    Public list<ProcessInstance> recordList{get;set;} //list to store processInstance records to display on UI

    public List<selectoption> getApprovalWrapperList(){
        List<selectoption> temp=new List<selectoption>();
        temp.add(new selectoption('','--Select--'));
        for(String ap:approvalMap.keyset()){
            temp.add(new selectoption(ap,ap));
        }
        return temp;
    }
    public DisplayApprovedRecordsController (){
        ApprovalProcessList=new List<ApprovalWrapper>();
        recordList=new list<ProcessInstance> ();
    }
    public map<String,ApprovalWrapper> approvalMap=new map<String,ApprovalWrapper>();
    public void FetchAllApprovalProcess(){      
        HttpRequest req = new HttpRequest();
        req.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionID());
        req.setHeader('Content-Type', 'application/json');
        String domainUrl=URL.getSalesforceBaseUrl().toExternalForm();
        system.debug('********domainUrl:'+domainUrl);
        String endpointUrl=domainUrl+'/services/data/v30.0/process/approvals/';
        req.setEndpoint(endpointUrl);
        req.setMethod('GET');      
        Http h = new Http();
        HttpResponse res = h.send(req);
        system.debug(res.getBody());
        String ss=res.getBody();
        string newjsondata = ss.replace('"object"','"objectName"');
       
        // Parse entire JSON response.
        JSONParser parser = JSON.createParser(newjsondata );
        while (parser.nextToken() != null) {
            // Start at the array of invoices.
            if (parser.getCurrentToken() == JSONToken.START_ARRAY) {
                while (parser.nextToken() != null) {
                    // Advance to the start object marker to
                    //  find next approval process object.
                    if (parser.getCurrentToken() == JSONToken.START_OBJECT) {
                        // Read entire  approval process object
                        ApprovalWrapper apr= (ApprovalWrapper)parser.readValueAs(ApprovalWrapper.class);
                        system.debug('Approval name: ' + apr.name);
                        system.debug('Id: ' + apr.id);
                        ApprovalProcessList.add(apr);
                        // Skip the child start array and start object markers.
                        parser.skipChildren();
                    }
                }
            }
        }
        system.debug('********ApprovalProcessList:'+ApprovalProcessList);
        for(ApprovalWrapper aw:ApprovalProcessList){
            approvalMap.put(aw.name,aw);
        }
}
public Pagereference FindRecords(){
recordList=new list<ProcessInstance> ();
        if(selectedApprovalProcess!=null && selectedApprovalProcess!=''){
            recordList=new list<ProcessInstance> ();
            String queryString='Select Id, TargetObjectId,TargetObject.name, Status From ProcessInstance Limit 10000';
            System.debug('*********queryString:'+queryString);
            List<ProcessInstance> temp=Database.query(queryString);
            ApprovalWrapper aw=new ApprovalWrapper();
            aw=approvalMap.get(selectedApprovalProcess);
            String ObjName=aw.objectName;
            recordList=new List<Processinstance>();
            For(ProcessInstance sb:temp){
                String ObjectName=String.valueof(sb.TargetObjectId.getSObjectType());
                system.debug('****ObjectName:'+ObjectName);
                if(Objectname.equalsignorecase(ObjName)){
                    recordList.add(sb);
                }
            }
            System.debug('*********recordList:'+recordList);
       }
        return null;
    }    
    public class ApprovalWrapper{
        public String description{get;set;}
        public String id{get;set;}
        public String name{get;set;}
        public String objectName{get;set;}
        public Integer sortOrder{get;set;}
    }
}

Monday, November 26, 2012

Viewing and Editing all Custom Settings in Visualforce Page


To see or edit custom setting records, we navigate to each custom setting, click on manage button and edit/ view custom settings records.

In order to avoid this navigation for all custom setting, I thought of creating a VF page where we can select custom setting present in organization and view/ edit records related to the selected custom settings on the same VF Page.

In order to achieve this, I have created a VF page named as "Sunil_CSDetails". Also I have created a batch class which will check for custom settings present in organization and will store their API names in one custom object (say "CS_Name__c"). You can use standard name field or custom text field (say "Name__c") to store API name of custom object.


User will click on Refresh button in order to fetch all custom settings present in the organization. After clicking on Refresh button, user will see progress bar with status. When the operation is finished, a new button will appear on the page with a message to click on that button.


After clicking on "Display Options" button, the page will display a picklist with all available custom settings and records related to selected option.
Now you can select any custom settings present in organization and view related records. Click on "Edit" button in order to edit any custom settings records.

You can download zip file from the link below which contains apex classes, VF page and custom objects.

Download Apex class and VF Page code from here

Looking forward to your comments and views.





Refer Below Links for Salesforce Interview Questions

Tuesday, October 23, 2012

How to schedule an apex schedulable class to run after every 10 or 15 minutes

There are scenario in which we need to schedule apex class to run after every 10 minutes or 15 minutes. In order to achieve this requirement, we can create 2 apex scheduler classes. Whenever first scheduler will run, it will perform processing or operation and after that it will schedule second apex schedule class to run after specified interval (in below example, we have mentioned 10 minutes). When second scheduler will run it perform operation or processing and will schedule first apex schedule class to run after specified interval.

First apex scheduler class:

global class Scheduler01 implements Schedulable {
    global void execute(SchedulableContext SC)     
    {
        //Call other class method which will perform operations as it is 
        //recommended that all processing take place in a separate class
        doScheduling();
    }
    public void doScheduling(){
       try{
            dateTime dt=System.now().addMinutes(10); //you can specify 10 mins or 15     
                                                                              //mins or any interval
            String Csec,Cmin,Chr,Cday,Cmonth,CYear;
            Csec=String.valueof(dt.second());
            Cmin=String.valueof(dt.minute());
            Chr=String.valueof(dt.hour());
            Cday=String.valueof(dt.day());
            Cmonth=String.valueof(dt.month());
            CYear=String.valueof(dt.Year());
            String SchTimer=Csec+' '+Cmin+' '+Chr+' '+Cday+' '+Cmonth+' ? '+CYear;
            system.debug('*************SchTimer:'+SchTimer);
            Scheduler02 cas = new Scheduler02();
            system.schedule('Scheduler02: Running at '+System.now().format(), SchTimer, cas);
            //we will delete completed apex scheduled jobs for which state is DELETED

            for( CronTrigger c:[Select State,Id,EndTime,CronExpression From CronTrigger where  

                                        NextFireTime= null  AND State='DELETED' Limit 100]){
                    System.abortJob(c.id);
            }
        }
        catch(exception e){
        }
   }
}

Second apex Scheduler Class:


global class Scheduler02 implements Schedulable {

    global void execute(SchedulableContext SC){
        //Call other class method which will perform operations as it is 
        //recommended that all processing take place in a separate class
        doScheduling();
    }
    public void doScheduling(){
      try{
            dateTime dt=System.now().addMinutes(10);
            String Csec,Cmin,Chr,Cday,Cmonth,CYear;
            Csec=String.valueof(dt.second());
            Cmin=String.valueof(dt.minute());
            Chr=String.valueof(dt.hour());
            Cday=String.valueof(dt.day());
            Cmonth=String.valueof(dt.month());
            CYear=String.valueof(dt.Year());
            String SchTimer=Csec+' '+Cmin+' '+Chr+' '+Cday+' '+Cmonth+' ? '+CYear;
            system.debug('*************SchTimer:'+SchTimer);
            Scheduler01 cas = new Scheduler01();
            system.schedule('Scheduler01: Running at '+System.now().format(), SchTimer, cas);
            //we will delete completed apex scheduled jobs for which state is DELETED
            for( CronTrigger c:[Select State,Id,EndTime,CronExpression From CronTrigger  
                                where NextFireTime=null  AND State='DELETED' Limit 100]){
                    System.abortJob(c.id);
            }
        }
        catch(exception e){
        }
    }
}