Cron expression for scheduling jobs in Salesforce

In this post, I am going to share the information about Cron expression for scheduling jobs in Salesforce

Cron Expression

Cron Expression syntax :-
“Seconds Minutes Hours Day_of_month Month Day_of_week optional_year”

The following are the values for the expression:

Name Value
Seconds 0–59
Minutes 0-59
Hours 0-23
Day_of_month 1-31
Month 1-12
Day_of_week 1-7
optional_year null or 1970–2099

Cron Expression Examples

Expression Description
0 0 0 ? * * * at 12:00 AM every day
0 0 10 ? * * at 10.00 AM every day
0 0 10 * * ? at 10.00 AM every day
0 0 10 * * ? * at 10.00 AM every day
0 0 15 ? * * * at 3:00 PM every day
0 0-5 15 * * ? Every minute starting at 3:00 PM and ending at 3:05 PM, every day
0 15 17 ? * MON-FRI at 5:15 PM every Monday, Tuesday, Wednesday, Thursday and Friday
0 15 10 15 * ? at 5:15 PM on the 15th day of every month
0 15 17 ? * 6#3 at 5:15 PM on the third Friday of every month
0 0 18 ? * 6L runs the last Friday of every month at 6:00 PM.
‘0 30 * * * *’; every 30 minutes
0 0 12 * * ? at 12:00 PM every day
0 0 23 * * ? 2016 runs every day at 11:00 PM during the year 2016.
? – No Value
* – All Values
L – Last
– Chandra V [01/12/2019]

Custom Data Table With Pagination And Checkbox Functionality In Salesforce Lightning

In this post I am  going to show how we can create custom lightning data table with client side JavaScript pagination buttons and row level checkbox functionality using salesforce lightning component. In this component we’ll also persist checkbox checked state on pagination.

 
Apex Controller : dataTableCtrl
public class dataTableCtrl{
    @AuraEnabled
    public static List<accountListWrapper> fetchAccountWrapper(){     
        List<accountListWrapper> lstaccountListWrapper = new List<accountListWrapper>();
        // query account records and create 'accountListWrapper' class instance for each record. 
        for(Account acc : [Select id,Name,Type,Phone
                           From Account
                           Limit 1000]){
                               // by default checkbox should be false 
                               lstaccountListWrapper.add(new accountListWrapper(false,acc));
                           }
        // return the 'lstaccountListWrapper' list 
        return lstaccountListWrapper;
    }
    
    /* wrapper class */  
    public class accountListWrapper {
        @AuraEnabled public boolean isChecked {get;set;}
        @AuraEnabled public  account objAccount{get;set;}
        public accountListWrapper(boolean isChecked, account objAccount){
            this.isChecked = isChecked;
            this.objAccount = objAccount;
        }
    }
}
 
Lightning Component
 
<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction"
access="global"
controller="dataTableCtrl">
<!-- call doInit method on component load -->
<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
<!-- aura attributes to store data/values -->
<aura:attribute name="listOfAllAccounts" type="list"/>
<aura:attribute name="PaginationList" type="list"/>
<aura:attribute name="selectedCount" type="integer" default="0"
description="selected Records Count"/>
<aura:attribute name="startPage" type="Integer" />
<aura:attribute name="endPage" type="Integer"/>
<aura:attribute name="totalRecordsCount" type="Integer"/>
<aura:attribute name="pageSize" type="Integer" default="4"
description="number of records to be display on per page"/>
<aura:attribute name="currentPage" type="integer" default="1"/>
<aura:attribute name="totalPagesCount" type="integer"/>
<aura:attribute name="bNoRecordsFound" type="boolean"/>
<aura:if isTrue="{!v.bNoRecordsFound}">
<!--display error message if there is no records available -->
<div class="slds-notify slds-notify_alert slds-theme_alert-texture slds-theme_info" role="alert">
<span class="slds-assistive-text">error</span>
<h2>No record found.</h2>
</div>
<aura:set attribute="else">
<!-- lightning:button to get selected rows data -->
<div class="slds-clearfix slds-m-around_small">
<div class="slds-clearfix">
<div class="slds-float_right">
<lightning:button variant="destructive"
label="Get Selected Records"
onclick="{! c.getSelectedRecords }"
disabled="{!v.selectedCount == 0}"/>
</div>
</div>
</div>
<!-- display total record and selected record count -->
<p class="slds-m-around_small">
<span class="slds-badge slds-badge_lightest" style="display:inline-block">
Total Records : {!v.selectedCount > 0 ? v.selectedCount + '/' : ''} {!v.totalRecordsCount} 
</span>
</p>
 
<!-- data table start-->
<table class="slds-table slds-table_bordered slds-table_cell-buffer">
<thead>
<tr class="slds-text-title_caps">
<!--header checkbox for select all-->
<th style="width:3.25rem;" class="slds-text-align_right">
<div class="slds-form-element">
<div class="slds-form-element__control">
<label class="slds-checkbox">
<ui:inputCheckbox disabled="{!v.totalRecordsCount == 0}"
aura:id="selectAllId"
change="{!c.selectAllCheckbox}"/>
<span class="slds-checkbox_faux"></span>
<span class="slds-form-element__label"></span>
</label>
</div>
</div>
</th>
<th scope="col">
<div class="slds-truncate" title="Name">Name</div>
</th>
<th scope="col">
<div class="slds-truncate" title="Phone">Phone</div>
</th>
<th scope="col">
<div class="slds-truncate" title="Type">Type</div>
</th>
</tr>
</thead>
<tbody>
<aura:iteration items="{!v.PaginationList}" var="obj">
<tr>
<th scope="row" class="slds-text-align_right" style="width:3.25rem;">
<div class="slds-form-element">
<div class="slds-form-element__control">
<label class="slds-checkbox">
<ui:inputCheckbox text="{!obj.objAccount.Id}"
value="{!obj.isChecked}"
change="{!c.checkboxSelect}"/>
<span class="slds-checkbox_faux"></span>
<span class="slds-form-element__label text"></span>
</label>
</div>
</div>
</th>
<th scope="row">
<div class="slds-truncate" title="{!obj.objAccount.Name}">
                                    {!obj.objAccount.Name}
</div>
</th>
<th scope="row">
<div class="slds-truncate" title="{!obj.objAccount.Phone}">
<lightning:formattedPhone value="{!obj.objAccount.Phone}"/>
</div>
</th>
<th scope="row">
<div class="slds-truncate" title="{!obj.objAccount.Type}">
                                    {!obj.objAccount.Type}
</div>
</th>
</tr>
</aura:iteration>
</tbody>
</table>
<!-- DataTable End -->
<br/>
<!--  Pagination Buttons Start -->
<div class="slds-align_absolute-center">
<lightning:button label="Previous"
disabled="{!v.startPage == 0}"
onclick="{!c.navigation}"
variant="brand"
iconName="utility:back"
name="previous"/>
<span class="slds-badge slds-badge_lightest"
style="margin-right: 10px;margin-left: 10px;">
                    Page {!v.currentPage} out of {!v.totalPagesCount}
</span>
<lightning:button label="Next"
disabled="{!(v.endPage + 1) >= v.totalRecordsCount}"
onclick="{!c.navigation}"
variant="brand"
iconName="utility:forward"
iconPosition="right"
name="next"/>
</div>
<!--  Pagination Buttons End -->
</aura:set>
</aura:if>
</aura:component>
 
Java Script Controller
 
({
doInit: function(component, event, helper) {
helper.doInitHelper(component, event);
},
 
/* javaScript function for pagination */
navigation: function(component, event, helper) {
var sObjectList = component.get("v.listOfAllAccounts");
var end = component.get("v.endPage");
var start = component.get("v.startPage");
var pageSize = component.get("v.pageSize");
var whichBtn = event.getSource().get("v.name");
// check if whichBtn value is 'next' then call 'next' helper method
if (whichBtn == 'next') {
component.set("v.currentPage", component.get("v.currentPage") + 1);
helper.next(component, event, sObjectList, end, start, pageSize);
}
// check if whichBtn value is 'previous' then call 'previous' helper method
else if (whichBtn == 'previous') {
component.set("v.currentPage", component.get("v.currentPage") - 1);
helper.previous(component, event, sObjectList, end, start, pageSize);
}
},
 
selectAllCheckbox: function(component, event, helper) {
var selectedHeaderCheck = event.getSource().get("v.value");
var updatedAllRecords = [];
var updatedPaginationList = [];
var listOfAllAccounts = component.get("v.listOfAllAccounts");
var PaginationList = component.get("v.PaginationList");
// play a for loop on all records list 
for (var i = 0; i < listOfAllAccounts.length; i++) {
// check if header checkbox is 'true' then update all checkbox with true and update selected records count
// else update all records with false and set selectedCount with 0  
if (selectedHeaderCheck == true) {
listOfAllAccounts[i].isChecked = true;
component.set("v.selectedCount", listOfAllAccounts.length);
} else {
listOfAllAccounts[i].isChecked = false;
component.set("v.selectedCount", 0);
}
updatedAllRecords.push(listOfAllAccounts[i]);
}
// update the checkbox for 'PaginationList' based on header checbox 
for (var i = 0; i < PaginationList.length; i++) {
if (selectedHeaderCheck == true) {
PaginationList[i].isChecked = true;
} else {
PaginationList[i].isChecked = false;
}
updatedPaginationList.push(PaginationList[i]);
}
component.set("v.listOfAllAccounts", updatedAllRecords);
component.set("v.PaginationList", updatedPaginationList);
},
 
checkboxSelect: function(component, event, helper) {
// on each checkbox selection update the selected record count 
var selectedRec = event.getSource().get("v.value");
var getSelectedNumber = component.get("v.selectedCount");
if (selectedRec == true) {
getSelectedNumber++;
} else {
getSelectedNumber--;
component.find("selectAllId").set("v.value", false);
}
component.set("v.selectedCount", getSelectedNumber);
// if all checkboxes are checked then set header checkbox with true   
if (getSelectedNumber == component.get("v.totalRecordsCount")) {
component.find("selectAllId").set("v.value", true);
}
},
 
getSelectedRecords: function(component, event, helper) {
var allRecords = component.get("v.listOfAllAccounts");
var selectedRecords = [];
for (var i = 0; i < allRecords.length; i++) {
if (allRecords[i].isChecked) {
selectedRecords.push(allRecords[i].objAccount);
}
}
alert(JSON.stringify(selectedRecords));
}
})
 
Java Script Helper
 
({
/* doInitHelper funcation to fetch all records, and set attributes value on component load */
doInitHelper : function(component,event){
var action = component.get("c.fetchAccountWrapper");
action.setCallback(this, function(response) {
var state = response.getState();
if (state === "SUCCESS"){
var oRes = response.getReturnValue();
if(oRes.length > 0){
component.set('v.listOfAllAccounts', oRes);
var pageSize = component.get("v.pageSize");
var totalRecordsList = oRes;
var totalLength = totalRecordsList.length ;
component.set("v.totalRecordsCount", totalLength);
component.set("v.startPage",0);
component.set("v.endPage",pageSize-1);
var PaginationLst = [];
for(var i=0; i < pageSize; i++){
if(component.get("v.listOfAllAccounts").length > i){
PaginationLst.push(oRes[i]);
}
}
component.set('v.PaginationList', PaginationLst);
component.set("v.selectedCount" , 0);
//use Math.ceil() to Round a number upward to its nearest integer
component.set("v.totalPagesCount", Math.ceil(totalLength / pageSize));
}else{
// if there is no records then display message
component.set("v.bNoRecordsFound" , true);
}
}
else{
alert('Error...');
}
});
$A.enqueueAction(action);
},
// navigate to next pagination record set   
next : function(component,event,sObjectList,end,start,pageSize){
var Paginationlist = [];
var counter = 0;
for(var i = end + 1; i < end + pageSize + 1; i++){
if(sObjectList.length > i){
if(component.find("selectAllId").get("v.value")){
Paginationlist.push(sObjectList[i]);
}else{
Paginationlist.push(sObjectList[i]);
}
}
counter ++ ;
}
start = start + counter;
end = end + counter;
component.set("v.startPage",start);
component.set("v.endPage",end);
component.set('v.PaginationList', Paginationlist);
},
// navigate to previous pagination record set   
previous : function(component,event,sObjectList,end,start,pageSize){
var Paginationlist = [];
var counter = 0;
for(var i= start-pageSize; i < start ; i++){
if(i > -1){
if(component.find("selectAllId").get("v.value")){
Paginationlist.push(sObjectList[i]);
}else{
Paginationlist.push(sObjectList[i]);
}
counter ++;
}else{
start++;
}
}
start = start - counter;
end = end - counter;
component.set("v.startPage",start);
component.set("v.endPage",end);
component.set('v.PaginationList', Paginationlist);
},
})

-Ranjith T [12/19/18]

Salesforce lead Queues

In Salesforce, Queues think about the board and relationship of records in Leads, Cases, and custom things. Lead Queues are particularly helpful in light of the fact that they license you to channel a social occasion Leads into a line reliant on a particular principles whereby customers in that line can ensure obligation regarding Leads. For example, you can make a Lead Queue to fitting as of late made Leads or those got from web by region/a territory (West Coast, North Pacific…etc) Today, I’ll be giving an associate on how with make a Leads Queue.

CREATION OF  TERRITORIES OR REGIONS:

First, we’re going to create a queue for each region.

To get started, go to Setup> Administration Setup> Manage Users> Queues and click New.

Name the Queue and on the other hand, you can assign an email address unequivocal for the line; customers in that line will get invigorates on exercises.

Next, pick the thing you have to make the line in.

Next, assign users to the queue. Alternatively, you can assign a Group of users to a queue. Then click Save.

ASSIGNING RULES FOR LEAD QUEUES

Now that you’ve built the queue, it’s time to create rules to automatically assign users to the appropriate region/territory queue. Go to Setup> Customize> Leads> Assigning Rules and click “New”. In Assignment Rules, you can prioritize the order of rules.Assigning Rules will run on an ascending order.

First, set the order of the rule.

Enter the criteria on which you want the Assignment Rule to apply
If you have multiple rules and depending on the logic, you can modify the logic of the rules right under the list.

Finally, enter the name of the queue you want the records with the above criteria to go to. click Save.

And now, users assigned to the queue can have a list view of all records in that queue where they can assign ownership accordingly. Only those users and users of higher hierarchy will have access to that list view.

Chandra V [11/26/2018]

How to Speed Up Internal Approval Processes in Salesforce

Without a standard procedure for inside endorsements, individuals may convey statements and agreements without approving the substance and what is being offered – from cost to the capacity to convey the proposed arrangement. Also, with no power over what statements and agreements are being conveyed, it is hard to oversee related dangers and vulnerabilities. Without appropriate procedures, making deals records requires a ton of manual work which is inclined to mistakes – and will require rounds of manual checking on for acknowledgment. So how might you accelerate inward endorsement forms? We take a gander at a couple of approaches to assist you with getting that green light quicker inside.

Implement thresholds

Before you can fabricate a normalized procedure for inward endorsements, you ought to consider the limits that really require an endorsement. So decide when things over a specific limit need more marks or approvers and assemble your procedure around these. By making limits for things over an edge you’ll wipe out bottlenecks that can back off citing and contracting. In addition you can give more opportunity to your groups to carry out their responsibility viably.

Speed up the flow of a document in an organisation

At the point when you have to get an endorsement for a statement or agreement, the speed of which you can get the archive through the different phases of endorsements is vital. Dealing with the coordinations of getting the report to the perfect individuals is significant and how you do this has an enormous ramifications on the speed.

Messages, gatherings and calls are on the whole legitimate methods of getting an endorsement yet some agony can be brought about by the following side of these. How would you make a point to keep track on who’s endorsed and what? At the point when you spare messages and meeting notes, it might be hard to locate these later on and sharing these may bring considerably more difficulties.

So what can you do to speed up the flow of a document in an organisation? The answer is a well-thought workflow. It will streamline the time it takes to coordinate the approval process by managing and tracking the different stages of the process. You can use workflows to send reminders, track responses, request changes and create a record of the entire internal approval process for future reference.

Setting up quote and contract approvals

Construct your work processes as indicated by the business rules. A case of an agreement endorsement process is one where any agreement must be affirmed by the top of a division before it moves onto the monetary group and from that point to the lawful group for audit. The archive moves along the procedure, and as and when each gathering favors or updates it, the report is put away halfway in for instance contract database and consequently refreshed with the goal that just a single variant of the agreement is accessible and that it is consistently state-of-the-art. When all gatherings have affirmed the archive, it is come back to the first proprietor of the report and is currently fit to be conveyed.

-Chandra V [11/04/2018]