July 29, 2020

How to fetch all the custom settings and update all the email data type field values with some value in Salesforce?

Sample Code:

Map < String, Schema.SObjectType > gd = Schema.getGlobalDescribe();

for ( String objectName : gd.keySet() ) {

    Schema.SObjectType result = gd.get( objectName );
  
    if ( result.getDescribe().isCustomSetting() ) {
        
        String query = 'SELECT ';
        List < String > listFields = new List < String >();
        Map < String, Schema.SObjectField > objectFields = result.getDescribe().fields.getMap();
        for ( String s : objectFields.keySet() ) {
          
            /* Checking whether the Field type is Email or Field Label contains Email */
            if ( String.valueOf( objectFields.get( s ).getDescribe().getType() ) == 'Email' ||
                 ( String.valueOf( objectFields.get( s ).getDescribe().getLabel() ).contains( 'Email' ) &&
                   String.valueOf( objectFields.get( s ).getDescribe().getType() ) == 'String' ) ) {
          
                system.debug( 'Inside' );
                query += s + ',';
                listFields.add( s );
          
            }
          
        }
      
        if ( listFields.size() > 0 ) {
      
            query = query.removeEnd( ',' );
            query += ' FROM ' + objectName;
            List < sObject > listRecords = Database.query( query );
          
            if ( listRecords.size() > 0 ) {
          
                for ( sObject obj : listRecords ) {
              
                    for ( String strField : listFields ) {
                       
                        if ( obj.get( strField ) != null )
                            obj.put( strField, obj.get( strField ) + '.test' );
                  
                    }
              
                }
              
                update listRecords;
          
            }
      
        }

    }
    
}

July 28, 2020

Email Notifications through Time Triggered Flow in Salesforce

Organization-Wide Email Addresses


Email Template


Email Alert


Schedule-Triggered Flow

Output:




July 27, 2020

How to close the Chat tab when the conversation is ended in Salesforce Chat in Lightning Experience?

Sample Code:

ChatEnd.cmp:


<aura:component implements="flexipage:availableForAllPageTypes" access="global">
   
    <lightning:conversationToolkitAPI aura:id="conversationKit" />
    <lightning:workspaceAPI aura:id="workspace"/>
   
    <aura:handler event="lightning:conversationChatEnded" action="{!c.onChatEnded}" />
   
</aura:component>

ChatEndController.js:

({
   
    onChatEnded: function(cmp, evt, helper) {
       
        /*var conversation = cmp.find( "conversationKit" );
        var recordId = evt.getParam( "recordId" );
        console.log( "recordId:" + recordId );*/
        var workspaceAPI = cmp.find( "workspace" );
        workspaceAPI.getFocusedTabInfo().then( function( response ) {
            var focusedTabId = response.tabId;
            console.log( 'Focused Tab is ' + focusedTabId );
            workspaceAPI.closeTab( { tabId: focusedTabId } );
        })
        .catch(function( error ) {
            console.log( 'Error is' + JSON.stringify( error ) );
        });
       
    }
   
})


July 22, 2020

Units of Capacity in Routing Configurations and Capacity in Presence Configurations Salesforce

If you choose Routing Configurations Unit Capacity as 1 and Presence Configurations Capacity as 5, each agent will be able to handle 5 chats at a time.

Routing Configurations


Presence Configurations




One Chat Transcript Accepted by the user, the workload is 2 out of 4 and the Capacity is 50%.

Two Chats(Full capacity):


July 20, 2020

How to pass data from one LWC component to another LWC in Salesforce?

Sample Code:

Apex Class:


public with sharing class ExampleController {

    @AuraEnabled(cacheable=true)
    public static List < Account > fetchAccounts() {

        return [ SELECT Id, Name, Industry FROM Account LIMIT 10 ];
      
    }
  
}

Sample.html:

<template>

    <div class="slds-theme--default">

        <template if:true={isLoaded}>
            <lightning-spinner alternative-text="Loading..." variant="brand">
        </lightning-spinner>
    </template>

    <template for:each={accounts.data} for:item="acc">
       
        <div key={acc.Id}>

            <c-record-view-form rec-id={acc.Id}
                                    s-object-name="Account"
                                    field-name1="Name"
                                    field-name2="Industry"
                                    field-name3="NumberOfEmployees"
                                    onloading={handleLoading}
                                    ondoneloading={handleDoneLoading}>               
            </c-record-view-form>

        </div>

    </template>

    </div>
  
</template>

Sample.js:

import { LightningElement, wire } from 'lwc';
import { NavigationMixin } from 'lightning/navigation';
import fetchAccounts from '@salesforce/apex/ExampleController.fetchAccounts';

export default class Sample extends NavigationMixin( LightningElement ) {

    accounts;
    isLoaded = false;

    @wire(fetchAccounts)
    accounts;

    handleLoading() {

        this.isLoaded = true;

    }

    handleDoneLoading() {

        this.isLoaded = false;

    }

}

Sample.js-meta.xml:

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>48.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__Tab</target>
    </targets>
</LightningComponentBundle>

recordViewForm.html:

<template>
    <lightning-record-view-form record-id={recId}
                                object-api-name={sObjectName}
                                density="compact">
        <div class="slds-box">
            <lightning-output-field field-name={fieldName1}>
            </lightning-output-field>
            <lightning-output-field field-name={fieldName2}>
            </lightning-output-field>
            <lightning-output-field field-name={fieldName3}>
            </lightning-output-field>
        </div>
    </lightning-record-view-form>
</template>

recordViewForm.js:

import { LightningElement, api } from 'lwc';

export default class RecordViewForm extends LightningElement {
   
    @api recId;
    @api sObjectName;
    @api fieldName1;
    @api fieldName2;
    @api fieldName3;
   
}

recordViewForm.js-meta.xml:

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>48.0</apiVersion>
    <isExposed>true</isExposed>
</LightningComponentBundle>


Output:


July 14, 2020

lightning-tree-grid with row level action in Salesforce Lightning

LWC HTML:

<template>

    <div class="slds-p-around_medium lgc-bg">

        <div class="slds-m-bottom_small">

            <lightning-button
                label="Collapse All"
                onclick={clickToCollapseAll}>
            </lightning-button>
            <lightning-button
                label="Expand All"
                onclick={clickToExpandAll}>
            </lightning-button>
          
        </div>
      
        <lightning-tree-grid columns = {gridColumns}
                                data = {gridData}
                                key-field = "Id"
                                hide-checkbox-column = true
                                onrowaction={handleRowAction}>
        </lightning-tree-grid>

    </div>
  
</template>


LWC JS:

import { LightningElement, track, wire } from 'lwc';
import { NavigationMixin } from 'lightning/navigation';
import fetchAccounts from '@salesforce/apex/ExampleController.fetchAccounts';

export default class Sample extends NavigationMixin( LightningElement ) {

    @track gridColumns = [{
        type: 'text',
        fieldName: 'Name',
        label: 'Name'
    },
    {
        type: 'text',
        fieldName: 'Industry',
        label: 'Industry'
    },
    {
        type: 'text',
        fieldName: 'FirstName',
        label: 'FirstName'
    },
    {
        type: 'text',
        fieldName: 'LastName',
        label: 'LastName'
    },
    {
        type: 'button',
        typeAttributes: {
            label: 'View'
        }
    }];
    @track gridData;

    @wire(fetchAccounts)
    accountTreeData({ error, data }) {

        console.log( 'Inside wire' );
        if ( data ) {

            var tempData = JSON.parse( JSON.stringify( data ) );
            console.log( 'Data is ' + tempData );
            /*var tempjson = JSON.parse( JSON.stringify( data ).split( 'Contacts' ).join( '_children' ) );
            console.log( 'Temp JSON is ' + tempjson );*/
            for ( var i = 0; i < tempData.length; i++ ) {

                tempData[ i ]._children = tempData[ i ][ 'Contacts' ];
                delete tempData[ i ].Contacts;

            }
            this.gridData = tempData;

        } else if ( error ) {
         
            if ( Array.isArray( error.body ) )
                console.log( 'Error is ' + error.body.map( e => e.message ).join( ', ' ) );
            else if ( typeof error.body.message === 'string' )
                console.log( 'Error is ' + error.body.message );

        }

    }

    clickToExpandAll( e ) {
        const grid =  this.template.querySelector( 'lightning-tree-grid' );
        grid.expandAll();
    }

    clickToCollapseAll( e ) {

        const grid =  this.template.querySelector( 'lightning-tree-grid' );
        grid.collapseAll();
     
    }

    handleRowAction( event ) {
       
        const row = event.detail.row;
        this[NavigationMixin.Navigate]({
            type: 'standard__recordPage',
            attributes: {
                recordId: row.Id,
                actionName: 'view'
            }
        });

    }

}

Apex Class:

public with sharing class ExampleController {

    @AuraEnabled(cacheable=true)
    public static List < Account > fetchAccounts() {

        return [ SELECT Id, Name, Industry, ( SELECT Id, FirstName, LastName FROM Contacts ) FROM Account LIMIT 10 ];
      
    }
  
}

Output:


Work Item Size and Agent Capacity Salesforce Chat


Omni-Channel is a work routing system.
Omni-Channel works on the concept of Work Items. Each time a case is assigned to a queue, a work item is created and pushed to the agents. Omni-Channel tracks the number of work items assigned to an agent based on number of primary tabs related to the work items are open.
Set how much work your agents can handle at once. Size your chats relative to agent capacity so that agents can handle multiple chats, but aren't overworked.
In Work Item Size, set the amount of an agent’s capacity that one work item consumes.
In Agent Capacity, set the agent’s total capacity.
Units of Capacity indicates the amount of an agent’s overall capacity that’s consumed when the agent is assigned a work item from queues that are associated with this configuration.

The Capacity setting in the presence configuration the agent is assigned to determines the agent’s overall capacity. When the agent is assigned a work item from the queue that’s associated with this configuration, the Capacity Weight is subtracted from the agent’s overall capacity. Agents can be assigned work items until their overall capacity reaches 0.

You can select a Capacity Weight or a Capacity Percentage, but not both.

https://help.salesforce.com/articleView?id=000338278&type=1&mode=1

July 11, 2020

How to handle multiple records from Flow for Einstein Bot in Salesforce?

1. Create a Collection variable in Einstein Bot builder. Use [System]Object and make sure to select Contains List.
2. Add Question in the Dialog and use Dynamic choice with input from the Collection Variable.
3. Create an Output variable in Flow as List of object.
4. Create an Input variable in Flow as text for a message to send it to the Bot from flow.
5. Create an Input variable in flow as text to get input from Bot in Flow.

Flow Configuration:








Bot Configuration:





Output:



July 9, 2020

lightning-record-edit-form example for quick updating the data Salesforce LWC

Sample Code:

LWC HTML:

<template>

    <div class="slds-box slds-theme_default">

        <lightning-record-edit-form object-api-name="Case" 
                                    onsuccess={handleSuccess}
                                    record-id={recordId}>

           
            <div class="slds-grid slds-wrap"> 
                <div class="slds-col slds-size_1-of-2">                             
                    <lightning-input-field field-name="Task_1_Completed__c"> 
                    </lightning-input-field> 
                </div> 
                <div class="slds-col slds-size_1-of-2"> 
                    <lightning-input-field field-name="Task_2_Completed__c"> 
                    </lightning-input-field> 
                </div> 
                <div class="slds-col slds-size_1-of-2">                             
                    <lightning-input-field field-name="Task_3_Completed__c"> 
                    </lightning-input-field> 
                </div> 
            </div>      
            <lightning-button class="slds-m-top_small" 
                              type="submit" 
                              label="Update"> 
                            </lightning-button>                           

        </lightning-record-edit-form>

    </div>
</template>


LWC JS:

import { LightningElement, api } from 'lwc'; 
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
 
export default class CaseEditPage extends LightningElement { 
 
    @api recordId; 

    handleSuccess( event ) { 
         
        const toastEvent = new ShowToastEvent({ 
            title: 'Case Updated', 
            message: 'Case Updated Successfully!!!', 
            variant: 'success' 
        }); 
        this.dispatchEvent( toastEvent ); 
 
    }

}


LWC JS meta.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="CaseEscalation"> 
    <apiVersion>48.0</apiVersion> 
    <isExposed>true</isExposed>   
    <targets>     
        <target>lightning__RecordPage</target>     
    </targets>     
    <targetConfigs>     
        <targetConfig targets="lightning__RecordPage">     
            <property name="recordId" type="String" label="Record Id" description="Record Id"/>     
        </targetConfig>   
    </targetConfigs>    
</LightningComponentBundle>


Output:


July 8, 2020

Adding same user to multiple Chat configuration at a time in Salesforce

The chat capacity is defined in the configuration.

Users can be assigned to only one Chat configuration at a time. If you assign the same user to a second Chat configuration, the system removes that user from the first Chat configuration without warning you.

If a user is assigned a configuration at the profile and user levels, the user-level configuration overrides the configuration that’s assigned to the profile.

July 4, 2020

We can't load this chat, because something went wrong - Salesforce Chat Issue

1. Check the OWD on Chat Transcript Object.
If it is set to private, then you cannot view the Chat Transcript unless you are the owner or it is shared with you(Manual Sharing, Role Hierarchy, Sharing Rules, etc.)

2. Inspect in your browser.
a. Right Click on your browser and select Inspect.
b. Click Console tabs.
c. Check whether any custom Lightning components added are throwing any exceptions. In this case, remove the custom components added and try to view.

3. Query Body from Chat Transcript (LiveChatTranscript) object to check whether it is blank or null.

SELECT Body FROM LiveChatTranscript WHERE Id = '<Id of the Chat Transcript Record>'

July 2, 2020

lightning:recordEditForm getting Record Id after insert

Sample Code:

Component:

<aura:component implements="force:lightningQuickAction,force:hasRecordId" controller="NewCaseController">
   
    <lightning:recordEditForm objectApiName="Case" onsuccess="{!c.handleSuccess}" aura:id="myRecordForm">
        <lightning:messages />
        <lightning:inputField aura:id="field" fieldName="Subject" />
        <lightning:inputField aura:id="field" fieldName="Origin" />
        <lightning:inputField aura:id="field" fieldName="Reason" />
       
        <div class="slds-m-top_medium">
            <lightning:button type="submit" label="Save Record"/>
        </div>
    </lightning:recordEditForm>
   
</aura:component>

JavaScript Controller:

({
   
    handleSuccess: function(component, event, helper) {
       
        var payload = event.getParams().response;
        console.log( 'RecordId is ' + payload.id );
        var action = component.get( "c.updateTranscript" );
        action.setParams({
            recordId: component.get( "v.recordId" ),
            caseId: payload.id
        });
        action.setCallback( this, function( response ) {
            var state = response.getState();
            if ( state === "SUCCESS" ) {
               
                $A.get('e.force:refreshView').fire();
                $A.get("e.force:closeQuickAction").fire();
               
            }
        });
        $A.enqueueAction(action);
       
    }
   
})


Apex Controller:

public class NewCaseController {
   
    @AuraEnabled
    public static void updateTranscript( Id recordId, Id caseId ) {
       
        system.debug( 'Transcript Id is ' + recordId + ' and Case Id is ' + caseId );
        update new Case_Transcript__c( Id = recordId, Case__c = caseId );
       
    }

}

Output: