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){
        }
    }
}