Wednesday, 28 August 2024

Available Values of context variables in before and after events

 Before insert  ==>Trigger.new.


After insert    ==>Trigger.new,Trigger.newMap.


Before update ==>Trigger.new,Trigger.newMap,Trigger.old,Trigger.oldMap.


After update   ==>Trigger.new,Trigger.newMap,Trigger.old,Trigger.oldMap.


Before delete   ==>Trigger.old,Trigger.oldMap.


After delete     ==>Trigger.old,Trigger.oldMap.


After undelete ==>Trigger.new,Trigger.newMap.

Tuesday, 27 August 2024

use of Type.forName() in apex

 How can we put Type.forName() to better use in Apex?


In Salesforce Apex, there's a method called `Schema.getGlobalDescribe()` that helps developers get information about all the objects in Salesforce. 


This can be useful, but it can also use up a lot of computer resources, like CPU and memory. 


This method is like a double-sided sword! 


You can take advantage of it however, if things go wrong it can hurt you too. 


Let's focus more on the downsides.


This can be a problem, especially if your Salesforce organization has many custom objects and fields, and it can cause your code to run slowly and hit some limits on how much CPU time it can use.


Imagine you want to get information about just one object.


But if you use this method incorrectly, you might end up getting information about all the objects in your Salesforce.


This can slow things down and cause issues. 


This is called an anti-pattern. (Now what's an anti-pattern? We will save it for another day).


What's the solution then?


You will take advantage of  'Type.forName'.


Find the code below to understand how to use it.




Monday, 26 August 2024

Data flow into and outside of Data Cloud

 Here is the summary of Data flow into and outside of Data Cloud(DC):


Step 1: Data will flow as a Data Streams into Data cloud in three different ways(Batch,Streaming,Virtual)


 Batch : Sales or Service or Other Salesforce objects will flow into DC from multiple Orgs in every 10mins,B2C Commerce Cloud or Salesforce Marketing Cloud will flow into DC from each Org in every 1 hour or every 1 day.

 Streaming : Experience Cloud or Websites or Mobile Apps through APIs and SDKs from multiple sources into DC in every 2 mins or immediately.

 Virtual : Snowflake Data into DC immediately.


Step 2: The data inside DC gets stored into Data Lake Objects (DLOs)


Step 3: From DLOs we do the Data transformations and Mappings into other DC specific object called Data Model Objects(DMOs).


Step 4: The Data from DMOs takes either of or three different paths:

 Path 1 : The data from DMOs will flow into Calculated Insights(CIs) in every 1 hour. From CIs to Data Actions(DA) in every 1 hour.


 Path 2 : The data from DMOs will flow into Streaming Insights(SIs) in every 5 mins. From SIs to Data Actions(DA) in every 1 hour.


 Path 3 : The data from DMOs will flow into Identity Resolution (IRs) and from IRs to Unified Profiles(UPs) in every 1 day.


Step 5: The Data from the above 2 paths Path 1 and 2 stored in Data Actions will then Transformed and sent into Sales Cloud or Service Cloud or Slack or SFMC Journeys in every 1 hour.


Step 6: The Data from the above path 3 and the Data in SI of path 2 will be sent to Segmentation in every 1 hour. Then to Activation. 


Step 7: The Data from Activation will be sent to SFMC,B2C Commerce Cloud,AWS and other destinations through APIs.


In a nutshell, The data is collected from several sources in multiple formats will be Mapped,Unified, Enriched as a single profile and will be stored back into Target systems for further utilzations.



Thursday, 15 August 2024

Some of the cool things SF will automatically take care of when it comes to sharing tables

 1. If you change owner - all manual shares with Row Cause as Manual will be truncated .


2. If you insert duplicate share records - salesforce will automatically do the duplicate management 


3. If you change the account on the contact associated to the community user all manual shares of the user will be truncated


If you do not want the manual shares to be truncated ( when owner changes / community user’s account changes ) use custom Apex sharing reason when inserting the share records.

Get started with new Data Cloud instance

 1) Assign User Permissions


Once all the relevant licenses have been procured and access has been provided, the first step is to assign yourself the Data Cloud Admin / Marketing Admin Permission Set. 


2) Configure and Create Additional Permissions


Next, create and assign an additional permission set to support proper generation. Assign the new permission set to your user. 


3) Provision Your Instance


Once completed, you will notice (it may require a refresh) that the Data Cloud App and Setup are now available. You can begin the one-time process of provisioning your instance. 


Tuesday, 6 August 2024

Annotations in Apex

 𝗔𝗻𝗻𝗼𝘁𝗮𝘁𝗶𝗼𝗻𝘀 𝗮𝗻𝗱 𝗧𝗵𝗲𝗶𝗿 𝗨𝘀𝗲𝘀

1. @𝗔𝘂𝗿𝗮𝗘𝗻𝗮𝗯𝗹𝗲𝗱: Exposes methods to Lightning components for client-side calls.

2. @𝗗𝗲𝗽𝗿𝗲𝗰𝗮𝘁𝗲𝗱: Marks methods/classes as outdated for future removal.

3. @𝗙𝘂𝘁𝘂𝗿𝗲: Runs methods asynchronously, ideal for callouts.

4. @𝗜𝗻𝘃𝗼𝗰𝗮𝗯𝗹𝗲𝗠𝗲𝘁𝗵𝗼𝗱: Allows methods to be called from Flows.

5. @𝗜𝗻𝘃𝗼𝗰𝗮𝗯𝗹𝗲𝗩𝗮𝗿𝗶𝗮𝗯𝗹𝗲: Exposes variables in methods for Flow integration.

6. @𝗜𝘀𝗧𝗲𝘀𝘁: Marks classes/methods for unit testing.

7. @𝗧𝗲𝘀𝘁𝗦𝗲𝘁𝘂𝗽: Prepares test data for use across tests.

8. @𝗧𝗲𝘀𝘁𝗩𝗶𝘀𝗶𝗯𝗹𝗲: Makes private members accessible in tests.

9. @𝗝𝘀𝗼𝗻𝗔𝗰𝗰𝗲𝘀𝘀: Controls JSON serialization/deserialization.

10. @𝗡𝗮𝗺𝗲𝘀𝗽𝗮𝗰𝗲𝗔𝗰𝗰𝗲𝘀𝘀𝗶𝗯𝗹𝗲: Shares code across namespaces.

11. @𝗥𝗲𝗮𝗱𝗢𝗻𝗹𝘆: Retrieves up to 1,000,000 rows; no DML allowed.

12. @𝗥𝗲𝗺𝗼𝘁𝗲𝗔𝗰𝘁𝗶𝗼𝗻: Exposes methods to JavaScript in Visualforce.

13. @𝗦𝘂𝗽𝗽𝗿𝗲𝘀𝘀𝗪𝗮𝗿𝗻𝗶𝗻𝗴𝘀: Suppresses warnings to clean up console messages.

Friday, 2 August 2024

LWC Workspace API methods

 The lightning/platformWorkspaceApi module provides LWC Workspace API methods to control workspace tabs and subtabs in a Lightning console app.


Below wire adapters are available for Lightning console apps.

EnclosingTabId()      — Returns the ID of the enclosing tab.

IsConsoleNavigation() — Determines whether the app it’s used within uses console navigation.


ex :


import { LightningElement, wire } from 'lwc';

import { IsConsoleNavigation,EnclosingTabId } from 'lightning/platformWorkspaceApi';


// wire service to fetch if the component is inside a console app

@wire(IsConsoleNavigation)

    isConsoleNavigation;   //Returns true if console navigation is present, false otherwise.

@wire(EnclosingTabId) 

   enclosingTabId;        //Returns the enclosing tab ID if the caller component is within a tab, or null otherwise.



openTab()—Opens a new workspace tab. If the tab is already open, the tab is focused.


import { LightningElement, wire } from 'lwc';

import { IsConsoleNavigation, openTab } from 'lightning/platformWorkspaceApi';


 @wire(IsConsoleNavigation) isConsoleNavigation;


 async openTab() {

        // Ensure that we're in a console app

        if (!this.isConsoleNavigation) {

            return;

        }


        // Open contact list a new tab

        await openTab({

            pageReference: {

                type: 'standard__objectPage',

                attributes: {

                    objectApiName: 'Contact',

                    actionName: 'list'

                }

            },

            focus: true,

            label: 'Contacts List'

        });

    } 


refreshTab()—Refreshes a workspace tab or a subtab specified by the tab ID.

import { LightningElement, wire } from 'lwc';

import {IsConsoleNavigation,getFocusedTabInfo,refreshTab } from 'lightning/platformWorkspaceApi';


 @wire(IsConsoleNavigation) isConsoleNavigation;


    async refreshTab() {

        // Ensure that we're in a console app

        if (!this.isConsoleNavigation) {

            return;

        }


        // Refresh current tab

        const { tabId } = await getFocusedTabInfo();

        await refreshTab(tabId, {

            includeAllSubtabs: true

        });

    }

focusTab()—Focuses a workspace tab or subtab.

getAllTabInfo()—Returns information about all open tabs.


import { LightningElement, wire } from 'lwc';

import {focusTab,IsConsoleNavigation,getFocusedTabInfo,getAllTabInfo } from 'lightning/platformWorkspaceApi';


 @wire(IsConsoleNavigation) isConsoleNavigation;


    async focusNextTab() {

        // Ensure that we're in a console app

        if (!this.isConsoleNavigation) {

            return;

        }


        // Get current tab and figure out which tab is next

        const { tabId } = await getFocusedTabInfo();

        const allTabs = await getAllTabInfo();

        const selectedTabIndex = allTabs.findIndex(

            (possibleNextTab) => possibleNextTab.tabId === tabId

        );

        const nextTabId = allTabs[selectedTabIndex + 1].tabId;


        // Focus on next tab

        await focusTab(nextTabId);

    }

closeTab()—Closes a workspace tab or subtab.



import { LightningElement, wire } from 'lwc';

import {closeTab,IsConsoleNavigation,getFocusedTabInfo } from 'lightning/platformWorkspaceApi';


 @wire(IsConsoleNavigation) isConsoleNavigation;


    async closeTab() {

        // Ensure that we're in a console app

        if (!this.isConsoleNavigation) {

            return;

        }


        // Close current tab

        const { tabId } = await getFocusedTabInfo();

        await closeTab(tabId);

    }


disableTabClose()—Prevents a workspace tab or subtab from closing.

getFocusedTabInfo()—Returns information about the focused workspace tab or subtab.


import { LightningElement, wire } from 'lwc';

import {disableTabClose,IsConsoleNavigation,getFocusedTabInfo } from 'lightning/platformWorkspaceApi';

@wire(IsConsoleNavigation) isConsoleNavigation;


    async disableTabClose(event) {

        // Ensure that we're in a console app

        if (!this.isConsoleNavigation) {

            return;

        }


        // Toggle the ability to close the tab

        const close = event.detail.checked;

        const { tabId } = await getFocusedTabInfo();

        await disableTabClose(tabId, close);

    }

openSubtab()—Opens a subtab within a workspace tab. If the subtab is already open, the subtab is focused.


import { LightningElement, wire } from 'lwc';

import {IsConsoleNavigation,EnclosingTabId,openSubtab } from 'lightning/platformWorkspaceApi';

@wire(IsConsoleNavigation) isConsoleNavigation;

    @wire(EnclosingTabId) enclosingTabId;


    findEnclosingTabAndOpenSubtab() {

        // Ensure that we're in a console app and that we have a tab open

        if (!this.isConsoleNavigation || !this.enclosingTabId) {

            return;

        }


        // Open sub tab

        openSubtab(this.enclosingTabId, {

            pageReference: {

                type: 'standard__objectPage',

                attributes: {

                    objectApiName: 'Account',

                    actionName: 'list'

                }

            }

        });

    }

setTabHighlighted()—Highlights the specified tab with a different background color and a badge. 

Tab highlights don’t persist after reloading a Lightning console app.


import { LightningElement, wire } from 'lwc';

import { IsConsoleNavigation,getFocusedTabInfo,setTabHighlighted } from 'lightning/platformWorkspaceApi';


 @wire(IsConsoleNavigation) isConsoleNavigation;


    async highlightTab(event) {

        // Ensure that we're in a console app

        if (!this.isConsoleNavigation) {

            return;

        }


        // Toggle highlight for current tab

        const highlighted = event.detail.checked;

        const { tabId } = await getFocusedTabInfo();

        setTabHighlighted(tabId, highlighted, {

            pulse: true,

            state: 'success'

        });

    }


setTabIcon()—Sets the icon and alternative text of the specified tab.


import { LightningElement, wire } from 'lwc';

import { IsConsoleNavigation,getFocusedTabInfo,setTabIcon } from 'lightning/platformWorkspaceApi';


const TAB_ICON = 'utility:animal_and_nature';

const TAB_ICON_ALT_TEXT = 'Animal and Nature';


@wire(IsConsoleNavigation) isConsoleNavigation;


    async setTabIcon() {

        // Ensure that we're in a console app

        if (!this.isConsoleNavigation) {

            return;

        }


        // Change current tab icon

        const { tabId } = await getFocusedTabInfo();

        setTabIcon(tabId, TAB_ICON, {

            iconAlt: TAB_ICON_ALT_TEXT

        });

    }

setTabLabel()—Sets the label of the specified tab.


import { LightningElement, wire } from 'lwc';

import {IsConsoleNavigation,getFocusedTabInfo,setTabLabel} from 'lightning/platformWorkspaceApi';


const TAB_LABEL = 'Awesome Label';


 @wire(IsConsoleNavigation) isConsoleNavigation;


    async setTabLabel() {

        // Ensure that we're in a console app

        if (!this.isConsoleNavigation) {

            return;

        }


        // Change current tab label

        const { tabId } = await getFocusedTabInfo();

        setTabLabel(tabId, TAB_LABEL);

   }



getTabInfo()—Returns information about the specified tab.


import { LightningElement, wire } from 'lwc';

import { EnclosingTabId, getTabInfo } from 'lightning/platformWorkspaceApi';


@wire(EnclosingTabId) tabId;


    isSubTab;


    connectedCallback(event) {

        if (this.tabId) {

            getTabInfo(this.tabId).then((tabInfo) => {

                this.isSubtab = tabInfo.isSubTab;

            });

        }

    }


NavigationMixin module in LWC

 We know that the NavigationMixin module is used for navigating between different pages or components within the Salesforce Lightning Experience, Salesforce Mobile App, and Lightning communities from an LWC.


The NavigationMixin adds two APIs to your component's class.


1) [NavigationMixin.Navigate](pageReference, [replace]) - A component calls this API to navigate to another page in the application.


    ex :

      this[NavigationMixin.Navigate]({

            type: 'standard__recordPage',

            attributes: {

                recordId: this.yourRecordId,

                objectApiName: 'Account',

                actionName: 'view'

            },

        });

2) [NavigationMixin.GenerateUrl](pageReference) - A component calls this API to get a promise that resolves to the resulting URL. The component can use the URL in the href attribute of an anchor. It can also use the URL to open a new window using the window.open(url) browser API.


Example of opening up a window in a new Tab


 // Generate a URL to a User record page

 this[NavigationMixin.GenerateUrl]({

   type: 'standard__recordPage',

   attributes: {

     recordId: this.yourRecordId,

     actionName: 'view',

  },

 }).then((url) => {

  // Opens the tab in new page

  window.open(url, "_blank");

});