Showing posts with label Salesforce. Show all posts
Showing posts with label Salesforce. Show all posts

Friday, January 24, 2020

How To Disable The Switch To Lightning Experience For An User

If you want to disable to switch to lightning experience link a user ,please follow below steps.

1. Identify the list of users to whom you want to disable this feature

2.Find out all the profiles related to these list of users

3. Goto each profile and Click on Edit

4. Uncheck the Lightning Experience User setting under the Administrative Permissions.


5. Now users will not get this switch permission .



Please follow,bookmark,subscribe this site to receive daily updates.

Facebook - https://www.facebook.com/ILoveCodingYou/?ref=bookmarks


Hope this helps you..Enjoy..!

How To Restrict The Record Edit/Modification Access Only To Record Owner and System Admin

If you have a requirement like the record can only be modified either by the owner of the record or the system administration .Other than this if any user tried to modify the record we shouldn't allow them to modify it.

Please use the validation rule to achieve this with below conditions check.

AND( 
     NOT(ISNEW()),
     NOT(OR($Profile.Name == 'System Administrator', $User.Id == OwnerId))
   )


Please follow,bookmark,subscribe this site to receive daily updates.

Facebook - https://www.facebook.com/ILoveCodingYou/?ref=bookmarks


Hope this helps you..Enjoy..!

Wednesday, January 8, 2020

How To Populate A Map With List or Set (Where Collections As a Value) in Salesforce

As a developer most of the times we will be working on collections.One of the most common used collection in salesforce is maps.

Creating a simple maps(value as a string,integer,object etc..) is very easy
  • Map<String,String>
  • Map<String,Integer>
  • Map<key,objects>
The real picture comes into scenario when we want to build some complex maps(where value of a map it self again a collection like list,set etc) 
  • Map<String,list<Account>>
  • Map<integer,set<integer>>
  • Map<AccountId,list<Conatct>>
Most common mistakes that we do while building this complex maps are
  • Old value gets overrides by new values.
  • When your in loop you map always ends up with just holding the last record in list/set.
  • Didn't checking whether value is already is exist or not.
Scenario:

Let take a take I want to create a map which will takes case status as key and it's value is all the cases comes under the same status.

Map<String,List<Case>> mapStatusToCases = new Map<String,List<Case>>()

for( Case cs: [SELECT id,Status,CaseNumber FROM Case limit 20])
{
 //Check whether with same status any record is already is added to map or not
 
 if(mapStatusToCases.containsKey(cs.Status)) 
 {
    // If you directly put this case into the map it will overrides all the existing cases,
   // which is not correct.So get all the existing records and store it list/set.
  List<Case> existingCase = mapStatusToCases.get(cs.Status);
  //add this new record to existing list  
  existingCase.add(cs);
  // now put the same status into the map with all latest case records(existing+new),
  // because key is same so it will overrides existing values with this latest list
  mapStatusToCases.put(cs.Status,existingCase); 
 }
 
 else // this executes if the status is not there in map(it means coming first time)
 {
     //prepare variable of map value type
  List<case> lstNewCases = new List<Case>();
  // adding a new record
  lstNewCases.add(cs); 
  // add the new status as a key and case as a value into map
  mapStatusToCases.put(cs.Status,lstNewCases); 
 }
}

System.debug('All Key Set...'+mapStatusToCases.keySet());
System.debug('All Values in Map...'+mapStatusToCases.values());
System.debug('Complete Map Details...'+mapStatusToCases);

For better understanding in above I have written each statement in a separate line. The same code can also be written in an optimized way as shown below.Both are valid and same.


Map<String,List<Case>> mapStatusToCases = new Map<String,List<Case>>()

for( Case cs: [SELECT id,Status,CaseNumber FROM Case limit 20])
{
 //Check whether with same status any record is already is added to map or not
 
 if(mapStatusToCases.containsKey(cs.Status)) 
 {
  //this statement mapStatusToCases.get(cs.Status) will returns the list
  //So,I'm adding new record to existing list directly
  mapStatusToCases.get(cs.Status).add(cs); 
 }
 
 else // this executes if the status is not there in map(it means coming first time)
 {
     //Delcared a new list and directly adding a new record to that
  mapStatusToCases.put(cs.Status,new List<Case>{cs}); 
 }
}

System.debug('All Key Set...'+mapStatusToCases.keySet());
System.debug('All Values in Map...'+mapStatusToCases.values());
System.debug('Complete Map Details...'+mapStatusToCases);

OutPut:




Please watch this space more useful stuff.

Please follow,bookmark,subscribe this site to receive daily updates.

Facebook - https://www.facebook.com/ILoveCodingYou/?ref=bookmarks


Hope this helps you..Enjoy..!







Wednesday, January 1, 2020

Few Scheduled Jobs Got Stopped Working Suddenly in Salesforce

If you have figured out that some of your scheduled jobs got stopped working suddenly.. There could be same issue which we have run into and figure out eventually after some time..

As the year got changed, while scheduling the jobs initially if you have mentioned a year as 2019 or till 2019 in your cron string expression then all your scheduled jobs comes under this category would have been stopped since Jan 1st 2020 at 12:00Am.

There could be some other reasons which might cause the issue but this is the one of route cause we have to cross as year got changed. 

Wish you a happy new year to everyone...



Tuesday, December 31, 2019

typeAttributes in lightning-datatable or lightning:datatable

Basically typeAttributes are the one of the major building blocks of <lightning-datatable>(in LWC) or <lightning:datatable> (in Aura).This will help us to format the data types /output display and attaching some of actions to your data displayed in table at each cell level ,row level or at the columns level.

The typeAttributes are attached to each columns data type when your specifying the columns for your data table in your java script file.

Each typeAttributes is having pre-defined set of attributes/properties basis on the data type of your column (your defining at the time of columns for table).

Usually each column definition will have below properties.

{ 
  label: 'Issue Type',  //Column Header Shown in Table
  fieldName: 'Issue_type__c', //Api name of filed 
  type:"text",   // tells text,date,url,email etc..
  initialWidth: 90 //column width
}

After attaching the typeAttributes the sample code looks like below.The sample code will create a column with name Case Number and Looks like a button ,on click of it you can fire rowAction automatically.


{
        label: 'Case Number',
        type: 'button',
        initialWidth: 90,
        typeAttributes: {
            iconName: 'action:preview',
            title: 'Preview',
            variant: 'border-filled',
            alternativeText: 'View',
            disabled: false,
            label: { fieldName: 'CaseNumber' }, // to assign the value dynamically
            name: { fieldName: 'Case_Age__c' }, // to assign the value dynamically
        }
    },

//other colums

At any time if you want to set any of the typeAttribute object attribute dynamically please use below syntax


  attributeName: { fieldName: 'api name of column/any other variable' }
          

As I have mentioned on the top each typeAttributes will have some set of properties based on the data type of your column.

If you want to know what are the available attributes for each datatype please refer below.




Sample Column Code With typeAttributes:


const datatableColums =[
 //Column 1 of type Url
    {
        label: 'Customer Name', fieldName: 'nameUrl', type: 'url',
        typeAttributes: {
            label: { fieldName: 'Name' },
            target: '_top'
        }
    },
 
 //Column 2 of type button 
 {
        label: 'PNR',
        type: 'button',
        initialWidth: 90,
        typeAttributes: {
            iconName: 'action:preview',
            title: 'Preview',
            variant: 'border-filled',
            alternativeText: 'View',
            disabled: false,
            label: { fieldName: 'Pnr__c' },
            name: { fieldName: 'Pnr__c' },

        }
    },
 
 //Column 3 of type date 
 {
        label: "Closed Date",
        fieldName: "ClosedDate",
        type: "date",
        typeAttributes:{
            weekday: "long",
            year: "numeric",
            month: "long",
            day: "2-digit"
        }
    }
]

Please watch this space more useful stuff.

Please follow,bookmark,subscribe this site to receive daily updates.

Facebook - https://www.facebook.com/ILoveCodingYou/?ref=bookmarks


Hope this helps you..Enjoy..!






How To Build A Global Search URL In Lightning Experience Using JavaScript

If your in lightning experience on click of any actionable item you want to take the user to the Global Search and perform the search action using the dynamic search string.To get the url of the global search in lightning using java script please refer the below code.


var searchStr = 'Sree'; //Search String
var stringToEncode = '{"componentDef":"forceSearch:search","attributes":{"term":"'+searchStr+ '","scopeMap":{"type":"TOP_RESULTS"},"context":{"disableSpellCorrection":false,"SEARCH_ACTIVITY":{"term":"'+ searchStr + '"}}}}';
var encodedStr = btoa(stringToEncode); //Base64 encoding
var redirectUrl='/one/one.app?source=aloha#'+encodedStr;

The format of url must be

     String redUrl = '/one/one.app?source=aloha#'+base64EncodedSearchString;

If you want to the same thing using apex please refer this post

Hope this helps you..Enjoy..!

How To Build A Global Search URL In Lightning Experience Using Apex

If your in lightning experience on click of any actionable item you want to take the user to the Global Search and perform the search action using the dynamic search string.To get the url of the global search in lightning using apex please refer the below code.


String searchStr = 'Sree'; //Search String
String stringToEncode = '{"componentDef":"forceSearch:search","attributes":{"term":"'+searchStr+ '","scopeMap":{"type":"TOP_RESULTS"},"context":{"disableSpellCorrection":false,"SEARCH_ACTIVITY":{"term":"'+ searchStr + '"}}}}';
String encodedStr = EncodingUtil.base64Encode(Blob.valueOf(stringToEncode)); //Base64 encoding
String redirectUrl='/one/one.app?source=aloha#'+encodedStr;

The format of url must be

     String redUrl = '/one/one.app?source=aloha#'+base64EncodedSearchString;

If you want to the same thing using java script please refer this post


Hope this helps you..Enjoy..!




Saturday, December 28, 2019

What is Salesforce API Portal?

This is the new feature of Salesforce which will help us to find all api details to connect with any of their platforms/entire ecosystem through apis.

We can also say it's one place store to check out all salesforce api details.

This will also shows what is the sample request and response details for each and every api.

It will also helps the developers to learn with an interactive document.

This helps the developer to connect with entire eco system.

This is built on Mulesoft API Community Manager.

Sample API/Clouds:

  • B2C Commerce Developer Sandbox API's
  • Einstein Prediction Service Scoring API
  • Einstein Vision and Einstein Language
  • Marketing Cloud REST API

For more details please check Salesforce Official Documentation.

Hope this helps you..Enjoy..!



Tuesday, December 17, 2019

LWC Toast Messages in Classic Environment Using Lightning Out

Usually we will use Lightning Out feature to use the any lightning components to worked/used in classic environment .Basically we will be embedding our lightning components inside the visual force page to use them in Classic environment.

If your using LWC Lightning Out feature and if you want to show the any notifications similar to apexpagemessages in visual force pages we will be using the toast messages in lightning environment.But unfortunately the toast messages will not work in classic environments.

To overcome this issue I have built a generic component with help of slds styles to bring the same style of toast messages so that we can use this component in classic as well.

genericToastMessages.html


<template>
    <template if:true={showAnyMsg}>
        <div class={notifcationThemeClass} role="alert">
            <span class="slds-assistive-text">{notificationtype}</span>
            <span class={notifcationContainerClass} title="Description of icon when needed">
                <svg class="slds-icon slds-icon_x-large" aria-hidden="true" xmlns="http://www.w3.org/2000/svg">
                    <use xlink:href={iconClass}></use>
                </svg>
            </span>
            <h2>{notificationmessage}</h2>
          
        </div>
    </template>
</template>

genericToastMessages.js


/* eslint-disable no-console */
/* eslint-disable no-unused-vars */
/* eslint-disable no-else-return */

import { LightningElement,api, track } from 'lwc';
export default class GenericToastMessages extends LightningElement {
    @api notificationtype; //='success';
    @api notificationmessage;//='All working!';
   
   get showAnyMsg()
   {
        if (this.notificationtype !== undefined && this.notificationmessage !== undefined)
            return true;
       else return false;
   }

   get notifcationThemeClass() {
     return (
            "slds-notify slds-notify_alert slds-theme_alert-texture slds-theme_" +this.notificationtype
        );
    }

    get notifcationContainerClass() {
       return (
            "slds-icon_container slds-icon-utility-" +this.notificationtype +" slds-m-right_x-small"
        );
    }

    get iconClass() {
        return (
            "/apexpages/slds/latest/assets/icons/utility-sprite/svg/symbols.svg#" + this.notificationtype
        );
    }
}

This component mainly takes 2 params as an input or attributes those are

  • notificationtype - success/error/warning/info
  • notificationmessage - Any message you want to show to user

How to call this component from other components

Just include the below 2 lines in your component where you want show notification


 <template if:true={showErrMsg} >
<c-generic-toast-messages notificationtype="error/success"
 notificationmessage="All Records Updated successfully">
</c-generic-toast-messages>
        <div class="slds-m-bottom_x-small"></div>
</template>


Other way of doing is passing the type and messages dynamically even in your parent component.You can even find example in the post How To Select And Update Multiple Records Using LWC


 <template if:true={showErrMsg} >
<c-generic-toast-messages notificationtype={notifType} 
notificationmessage={notifMsg}>
</c-generic-toast-messages>
        <div class="slds-m-bottom_x-small"></div>
</template>


In the above code {notifTpe} and {notifMsg} are the parent component js controller variables where I'm setting the value basis on the server response.





Hope this helps you..Enjoy..!


Monday, December 16, 2019

System.JSONException: Apex Type unsupported in JSON: Object

You will receive this error when your parsing/deserialize  the JSON responses either user the JSON classes or JSON Parser classes.Please read the below points
  • When you deserialize the response into specified class type and if that class is having any field with data type "Object" you will receive this error.
  • When you any JSONToApex Converter or JSONToC# we will end up with this issue.
  • Please replace all the fields with Object data type into String/Integer etc..
Sample JSON:


{
  "item": [
    {
      "CONTRACT": 1001117406,
      "SOLD_TO": 10081120,
      "PURCH_NO_C":,
      "STREET": "1290 Hamner Ave",
      "STR_SUPPL1": "",
      "STR_SUPPL2":,     
    }
  ]
}

After Coverting JSONToApex:

public class Item
{
    public integer CONTRACT { get; set; }
    public integer SOLD_TO { get; set; }
    public object PURCH_NO_C { get; set; }
    public string STREET { get; set; }
    public string STR_SUPPL1 { get; set; }
    public object STR_SUPPL2 { get; set; }
}

public class RootObject
{
    public List<Item> item { get; set; }
}



Deserialize the JSON:

JSONParser parser = JSON.createParser('sampleJsonResponse');
 RootObject pr= (RootObject)parser.readValueAs(RootObject.class); 
//Here you will receive an error because the RootObject.class is having fields (PURCH_NO_C,STR_SUPPL2)  of type Object .

WorkAround:
Please change the wrapper class fields data type from Object to appropriate types as integer,double,string etc

public class Item
{
    public integer CONTRACT { get; set; }
    public integer SOLD_TO { get; set; }
    public string PURCH_NO_C { get; set; }
    public string STREET { get; set; }
    public string STR_SUPPL1 { get; set; }
    public string STR_SUPPL2 { get; set; }
}

public class RootObject
{
    public List<Item> item { get; set; }
}

Hope this helps you..Enjoy..!


Continuation Method is Not Getting Called In Salesforce APEX

Please check the below points

  • Check whether this class is linked with any visual force page/lightning components,if it's not linked to any one of this then it will not executed.

  • If it's in visual force page please check whether your adding reRender attribute on the <apex:commandButton> or <apex:outputlink> tag where your invoking the Continuation.

Hope this helps you..Enjoy..!

Thursday, December 12, 2019

Unable To Fetch The affinityToken From SessionId API In Live Agent REST API


  • According to the salesforce documentation to get the affinityToken first in headers you  have to set the X-LIVEAGENT-AFFINITY as null.
  • If your not setting or if your not passing this header without null value in your request will not receive any affinityToken.


Sample request without X-LIVEAGENT-AFFINITY header:








Sample request with X-LIVEAGENT-AFFINITY header:








Hope this helps you..Enjoy..!

Wednesday, December 11, 2019

How To Open a New Tab in Classic Console Using LWC Lightning Out

You have visual force and inside this your loading the LWC component using Lightning Out in Salesforce Classic Console.

Now,if you want to open a new sub tab (record detail page or visual force page) inside the console on click of a link (inside your LWC .html file) please use the below code.

test.html

<template>
     <lightning-card title="Additional Details" icon-name="custom:custom18">
       <template if:true={showform}>               
          <a href="javascript:srcUp('/apex/PageName?id=3773737');" target="_blank">Test</a>         
       </template>
    </lightning-card>
</template>

If it's not working or getting any issue please include the below 2 lines script files in your visual force page.

<apex:includeScript value="/soap/ajax/45.0/connection.js" />
<apex:includeScript value="/support/console/45.0/integration.js" />


Hope this helps you..Enjoy..!

Monday, December 9, 2019

How To Store The Pre Chat Details in Live Agent Transcript Object Using REST API

In my previous post we have learn how to pass the pre-chat details in REST API and how it shown to agent etc .Now,if you want to store this information in ChatTranscript (Object Name -LiveChatTranscript ) for future reference we can do it easily just by setting few things the same request body by making some changes at "transcriptFields":[] property in the request.

This information will get stored only after agent has ended the chat conversation with customer and if has chosen a option to store the transcript.

First,please goto the ChatTranscript object and create a custom fields to store the required data.

In my scenario I want to store the product category and price .So,I have created 3 new fields as Category__c,Product_Category__c,Price_Range__c. Product which comes from the chat request I want to store it 2 custom fields called Category__c,Product_Category__c and Price range in Price_Range__c.


API Details:


Headers:
X-LIVEAGENT-API-VERSION:34
X-LIVEAGENT-AFFINITYaffinityToken from SessionId API
X-LIVEAGENT-SESSION-KEYkey from from SessionId API
X-LIVEAGENT-SEQUENCE:1
Content-Type:application/json



Sample Request:

{
  "organizationId": "000008afQ",
  "deploymentId": "57228",
  "buttonId": "57328",
  "sessionId": "id-from-response",
  "userAgent": "Lynx/2.8.8",
  "language": "en-US",
  "screenResolution": "1900x1080",
  "visitorName": "Frank Underwood",
  "prechatEntities": [
    
  ],
  "receiveQueueUpdates": true,
  "isPost": true,
  "prechatDetails": [
   {
      "label": "Price Range",
      "value": "20,000-30,000",
      "displayToAgent": true,
      "transcriptFields": [ "Price_Range__c"],
      "entityFieldMaps": [
        
      ]
    },
{ "label": "Product Category", "value": "Smart Phone", "displayToAgent": true, "transcriptFields": ["Category__c","Product_Category__c"], "entityFieldMaps": [ ] }, { "label": "Description", "value": "I'm looking for a mobile with 8GB RAM and 256 GB ROM ", "displayToAgent": true, "transcriptFields": [ ], "entityFieldMaps": [ ] } ] }

Sample Response:

["Ok","200"]

                                             Hope this helps you..Enjoy..!

Friday, December 6, 2019

Live Agent REST API To Send The Pre Chat Details

Let's take a use case ,where you have bot or some custom FAQs to handle the basic customer queries and but sometimes it's required to connect the customer with one of your executives using salesforce live agent chat.

Whenever your connecting the customer with agent,it's required to pass the pre-chat conversation details to agents so that it will help him/her to greet the customer with issue details and also helps to resolve the customer queries quickly.

Luckily Salesforce supports all these features in their REST API.Please take a look at the api details below.

API Details:


Headers:
X-LIVEAGENT-API-VERSION:34
X-LIVEAGENT-AFFINITYaffinityToken from SessionId API
X-LIVEAGENT-SESSION-KEY: key from from SessionId API
X-LIVEAGENT-SEQUENCE:1
Content-Type:application/json


Sample Request:

{
  "organizationId": "000008afQ",
  "deploymentId": "57228",
  "buttonId": "57328",
  "sessionId": "id-from-response",
  "userAgent": "Lynx/2.8.8",
  "language": "en-US",
  "screenResolution": "1900x1080",
  "visitorName": "Frank Underwood",
  "prechatEntities": [
    
  ],
  "receiveQueueUpdates": true,
  "isPost": true,
  "prechatDetails": [
    {
      "label": "Product Category",
      "value": "Smart Phone",
      "displayToAgent": true,
      "transcriptFields": [  ],
      "entityFieldMaps": [
        
      ]
    },
    {
      "label": "Price Range",
      "value": "20,000-30,000",
      "displayToAgent": true,
      "transcriptFields": [  ],
      "entityFieldMaps": [
        
      ]
    },
    {
      "label": "Description",
      "value": "I'm looking for a mobile with 8GB RAM and 256 GB ROM ",
      "displayToAgent": true,
      "transcriptFields": [   ],
      "entityFieldMaps": [
        
      ]
    }
  ]
}

Sample Response:

["Ok","200"]

How Agent Looks in Salesforce This Data:
After mouse over on Accept


In chat Transcript



Hope this helps you..Enjoy..!