Saturday, July 27, 2024

Trigger to prevent deletion of account if it has associated contact in salesforce

The PrevAccountDeletion trigger on the Account object is designed to prevent the deletion of any account that has associated contacts. It runs before the account deletion operation. The trigger collects the IDs of the accounts being deleted and checks for associated contacts by querying the Contact object. If any account has associated contacts, it adds an error message to the account record, stopping the deletion process. This ensures that accounts with related contacts cannot be removed, maintaining data integrity within the Salesforce system.

trigger PrevAccountDeletion on Account (before delete) {

    // Hold IDs of accounts that have associated contacts

    Set<Id> accountIdsWithContacts = new Set<Id>();

    // IDs of accounts being deleted

    Set<Id> accountIdsToDelete = Trigger.oldMap.keySet();

    // Find contacts associated with the accounts being deleted

for (Contact contact : [SELECT AccountId FROM Contact WHERE AccountId IN :accountIdsToDelete]) {

        accountIdsWithContacts.add(contact.AccountId);

    }

    // prevent deletion if it has associated contacts

    for (Account acc : Trigger.old) {

        if (accountIdsWithContacts.contains(acc.Id)) {

            acc.addError('This account has associated contacts and cannot be deleted.');

        }

    }

}

Sunday, April 21, 2024

OAuth 2.0 Web Server Flow to integrate two salesforce orgs

This flow is used to integrate an external web app with the Salesforce API, it implements the OAuth 2.0 authorization code grant type. With this flow, the server hosting the web app must be able to protect the connected app’s identity, defined by the client ID and client secret.

Throughout this topic, we'll dive into the key concepts of the Web Server Flow,  and provide a step-by-step guide on how to implement it between two Salesforce orgs say ORG A and ORG B.

By the end of this session, you'll have a clear understanding of how to leverage the Web Server Flow to create robust integrations that facilitate smooth collaboration and data sharing between Salesforce environments. Let's get started!

The below steps explain the process involved in webserver flow.

  • Request an Authorization Code
  • Authenticate the User and Grant Access to the App
  • Receive a Callback
  • Request an Access Token
  • Receive an Access Token

  • Post Request


Let's start,

ACTIVITIES WE NEED TO DO IN ORG B.

1) Create a Connected App in ORG B.

2) Create a Webservice in ORG B which will be invoked from ORG A.

Create A Connected App In ORG B:

The connected app configured above under "How to configure a Connected App for the OAuth 2.0 Client Credentials Flow?" will work for web server flow as well as we have also enabled "Require Secret for Web Server Flow" check box. The below image also highlights callback URL of ORG A.






Create A Webservice As Shown Below In ORG B:

The createAccountRecord class is an Apex REST service that allows external systems to create Account records in a Salesforce org. It is exposed as a REST resource with the URL mapping '/createAccountRecord/*', meaning it can be accessed via HTTP requests.

This service defines a POST method, createAccount(), which expects JSON data containing information about the Accounts to be created. Upon receiving a request, the method deserializes the JSON payload, creates Account records based on the provided data, and attempts to insert them into the database.

If the insertion is successful, the method returns 'Success'. Otherwise, it returns 'Failure'.

The incoming JSON payload should adhere to the structure defined by the responseWrapper inner class, which includes fields such as Name, Description, Type, and Industry for each Account record.

This REST service provides a simple yet effective means for external systems to programmatically create Account records in the Salesforce org, facilitating seamless integration and data synchronization.

@RestResource(urlMapping='/createAccountRecord/*')

   global with sharing class createAccountRecord {

     @HttpPost

      global Static string createAccount(){

      RestRequest req = RestContext.request;

      RestResponse res = Restcontext.response;

      string jsonString=req.requestBody.tostring();

      system.debug('jsonString'+jsonString);

      boolean successCheck;

      List<responseWrapper> wRespList=(List<responseWrapper>) JSON.deserialize(jsonString,List<responseWrapper>.class);

      Account obj=new Account();

      List<Account> accList= new List<Account>();

      for(responseWrapper wResp: wRespList){

      obj.Name=wResp.Name;

      obj.Description=wResp.Description;

      obj.Type=wResp.Type;

      obj.Industry=wResp.Industry;

      accList.add(obj);

      }

      try{

      if(accList.size() > 0){

      Insert accList;

      successCheck=true;

      }

      }

      catch(Exception e){

      successCheck=false;

      }

      if(successCheck)

      return 'Success';

      else

      return 'Failure';

      }

 

      global class responseWrapper{

 

       global string Name;

       global string Description;

       global string Type;

       global string Industry;

 

      }

 

   }


ACTIVITIES WE NEED TO DO IN ORG A.

Request an Authorization Code:

Hit the below URL to get the authorization code.

https://farukh-dev-ed.lightning.force.com/services/oauth2/authorize?
client_id=Client_Id_Of_ConnectedApp_From_OrgB&
redirect_uri=https://myknowndomain-dev-ed.my.salesforce.com/services/oauth2/callback&
response_type=code

If you’re not familiar with these types of calls, don’t worry. Let’s break it down into its individual components.

Component 1:

https://farukh-dev-ed.lightning.force.com/services/oauth2/authorize

This address is the Salesforce instance’s OAuth 2.0 authorization endpoint of ORG B. It’s the endpoint where your connected apps send OAuth authorization requests.

Component 2:

client_id=Client_Id_Of_ConnectedApp_From_OrgB

The client ID is the connected app’s consumer key from ORG B.

Component 3:

redirect_uri=https://myknowndomain-dev-ed.my.salesforce.com/services/oauth2/callback

The redirect URI is where users are redirected after a successful authorization. In our case it corresponds to ORG A callback URL. The redirect URI is the connected app’s callback URL, which you can also find on the connected app’s Manage Connected Apps page.

This image shows the callback URL that corresponds with the code samples.



Component 4:

response_type=code

The response type tells Salesforce which OAuth 2.0 grant type the connected app is requesting. The response type of code indicates that the connected app is requesting an authorization code.

After you successfully hit the URL, you will be asked to login into Salesforce ORG B. One you logged in with ORG B credentials you will be redirected to below URL as shown below. As you can see the below URL has auth code as highlighted.

https://myknowndomain-dev-ed.my.salesforce.com/services/oauth2/callback?code=aPrxsh*********************************************8Xg%3D%3D

Now, next step is to get the access token and do callout to ORG B to POST account creation request using the auth code obtained above.

The provided code demonstrates an integration scenario where an Apex class interacts with Salesforce REST APIs to perform various operations, such as obtaining an access token, querying data, and making callouts to another Salesforce org.

Here's a breakdown of the key functionalities:

responseWrapper Class: Defines a wrapper class to represent the response from the OAuth token request. It includes fields such as id, access_token, and instance_url.

cKey and cSecret: Variables to store the client ID and client secret obtained from a Custom Metadata Type named Store_Cred__mdt.

Connection Parameter Retrieval: Retrieves the client ID and client secret from the Store_Cred__mdt Custom Metadata Type.

Authentication Code and URI: Defines the authorization code and redirect URI required for the OAuth token request.

Request Body Construction: Constructs the request body for the OAuth token request including the grant type, client ID, client secret, authorization code, and redirect URI.

OAuth Token Request: Sends a POST request to the OAuth token endpoint to obtain an access token using the constructed request body.

Deserialization: Deserializes the response from the OAuth token request into the responseWrapper class.

API Callout: Constructs a callout request to another Salesforce org's Apex REST endpoint (createAccountRecord) to create an Account record.

Setting Headers and Body: Sets the necessary headers (Authorization and Content-Type) and request body for the callout.

Sending Callout Request: Sends the callout request to create an Account record in the target Salesforce org.

Handling Response: Checks the response status code to determine if the callout was successful.

This code demonstrates a typical integration flow where Salesforce Apex code interacts with Salesforce REST APIs to authenticate, exchange data, and perform operations across different Salesforce orgs.

Copy paste the below code in execute anonymous window in ORG A and replace the authCode with the authCode obtained above during authorization request.

public class responseWrapper {

        public string id;

        public string access_token;

        public string instance_url;

    }

public string cKey;

public string cSecret;

List < Store_Cred__mdt > connectionParam = [SELECT Id, MasterLabel, client_id__c, client_secret__c from Store_Cred__mdt];

        if(connectionParam.size() >0){

        cKey=connectionParam[0].client_id__c;

        cSecret=connectionParam[0].client_secret__c;

        }

        System.debug('Store_Cred__mdt' + connectionParam);

        String authCode= 'aPrxsh*********************************************8Xg%3D%3D';

         // The below URI is the callback URL of ORG A

        String uri='https://myknowndomain-dev-ed.my.salesforce.com/services/oauth2/callback';

        String reqBody = 'grant_type=authorization_code&client_id=' + cKey + '&client_secret=' + cSecret + '&code=' + authCode + '&redirect_uri=' + uri ;

        Http h = new Http();

        HttpRequest req = new HttpRequest();

        req.setBody(reqBody);

        req.setMethod('POST');

       // Token end point of  ORG B

        req.setEndpoint('https://farukh-dev-ed.my.salesforce.com/services/oauth2/token');

        HttpResponse hresp = h.send(req);

        System.debug('hresp is'+hresp);

        System.debug('hresp body is'+hresp.getBody());

        responseWrapper wResp = (responseWrapper) JSON.deserialize(hresp.getBody(), responseWrapper.class);

        system.debug('reqBody '+reqBody );

        system.debug('wResp'+wResp );

        system.debug('Instance url' + wResp.instance_url);

        system.debug('session id' + wResp.access_token);

 

         List<Account> accList = new List<Account>();

// End point of ORG B where we will send POST request for account record creation

string endPoint = 'https://farukh-dev-ed.my.salesforce.com'+'/services/apexrest/createAccountRecord';

             accList=[SELECT Id,Name,Description,Type,Industry from account Order By createddate DESC Limit 1];

         Http h1 = new Http();

            HttpRequest req1 = new HttpRequest();

            req1.setHeader('Authorization', 'Bearer ' + wResp.access_token);

            req1.setHeader('Content-Type', 'application/json');

            req1.setMethod('POST');

            req1.setEndpoint(endPoint);

            req1.setBody(JSON.serialize(accList));

            HttpResponse hresp1 = h1.send(req1);

            system.debug('hresp1'+hresp1 );

            system.debug('hresp1.getStatusCode()'+hresp1.getStatusCode());

             system.debug('hresp1.getBody()'+hresp1.getBody());

            if (hresp1.getStatusCode() == 200) {

                system.debug('Callout Success');

            }


After executing the above code from developer console, the below image shows the log. You can also verify the account record will be created in ORG B.


Account record created in ORG B.



Saturday, March 30, 2024

Explain Javascript Async/Await?

"async and await make promises easier to write". async makes a function return a Promise while await makes a function wait for a Promise

Async Syntax:

The keyword async before a function makes the function return a promise:

Example:

async function myFunction() {

  return "Hello";

}

The above is the same as below:

function myFunction() {

  return Promise.resolve("Hello");

}

Await Syntax:

The await keyword can only be used inside an async function.

The await keyword makes the function pause the execution and wait for a resolved promise before it continues:

let value = await promise;

Let us understand this with an example,

function myFunction(some) {

  console.log('Inside myFunction');

}

async function promiseDemonstration(){

let myPromise = new Promise(function(myResolve, myReject) {

   let x = 0;

  if (x == 0) {

    myResolve("OK");

    console.log('Inside If');

    setTimeout(myFunction , 3000);

  } else {

    console.log('Inside else');

    myReject("Error");

  }

});

let value = await myPromise;

console.log('Awaiting Promise'+value);

myPromise.then(

  function(value) {

    console.log('Inside Value');

    myFunction(value);},

  function(error) {

    console.log('Inside Error');

    myFunction(error);}

);

}

promiseDemonstration();

Explain JavaScript Promise Object?

As we have seen earlier, With asynchronous programming, JavaScript programs can start long-running tasks, and continue running other tasks in parallel.

But, asynchronus programmes are difficult to write and difficult to debug.

Because of this, most modern asynchronous JavaScript methods don't use callbacks. Instead, in JavaScript, asynchronous programming is solved using Promises instead.

A Promise contains both the producing code and calls to the consuming code:

Promise Syntax:

let myPromise = new Promise(function(myResolve, myReject) {

// "Producing Code" (May take some time)

  myResolve(); // when successful

  myReject();  // when error

});

// "Consuming Code" (Must wait for a fulfilled Promise)

myPromise.then(

  function(value) { /* code if successful */ },

  function(error) { /* code if some error */ }

);

When the producing code obtains the result, it should call one of the two callbacks:

When     Call

Success     myResolve(result value)

Error     myReject(error object)

Promise Object Properties:

A JavaScript Promise object can be:

Pending

Fulfilled

Rejected

The Promise object supports two properties: state and result.

While a Promise object is "pending" (working), the result is undefined.

When a Promise object is "fulfilled", the result is a value.

When a Promise object is "rejected", the result is an error object.

myPromise.state      myPromise.result

"pending"      undefined

"fulfilled"      a result value

"rejected"      an error object

Let us understand the use of Promise with an example:

function displayValue(some) {

 console.log('Inside displayValue');

}

let myPromise = new Promise(function(myResolve, myReject) {

  let x = 0;

// The producing code (this may take some time)

  if (x == 0) {

    myResolve("OK");

  } else {

    myReject("Error");

  }

});

myPromise.then(

  function(value) {displayValue(value);},

  function(error) {displayValue(error);}

);

Output:

Inside displayValue


Let us understand the use of Promise with setTimeout.

Example Using Callback:

setTimeout( myFunction, 1000);

function myFunction() {

  console.log('Inside myFunction');

}

Output:

Inside myFunction

Example Using Promise:

function myFunction(some) {

  console.log('Inside myFunction');

}

let myPromise = new Promise(function(myResolve, myReject) {

   let x = 1;

  if (x == 1) {

    myResolve("OK");

    console.log('Inside If');

    setTimeout(myFunction , 3000);

  } else {

    console.log('Inside else');

    myReject("Error");

  }

});

myPromise.then(

  function(value) {

    console.log('Inside Value');

    myFunction(value);},

  function(error) {

    console.log('Inside Error');

    myFunction(error);}

);

Output:

Inside If
Inside Value
Inside myFunction

What are classes in Javascript and explain Inheritance?

A JavaScript class is not an object. It is a template for JavaScript objects. Use the keyword class to create a class. 

Always add a method named constructor().

class Employee {

  constructor(name, department) {

    this.name = name;

    this.department = department;

  }

}

The example above creates a class named "Employee".

The class has two initial properties: "name" and "department".

The example below uses the Employee class to create a Employee object.

const myEmp = new Employee("Farukh", IT);

The constructor method is called automatically when a new object is created. The constructor method is a special method.

It has to have the exact name "constructor".

Sample Example to demonstrate class use:

class Employee {

  constructor(name, department) {

    this.name = name;

    this.department = department;

  }

  displayValue() {

    console.log('Name is '+this.name);

    console.log('department is '+this.department);

  }

}

const myEmp = new Employee("Farukh", "IT");

myEmp.displayValue();

Output:

Name is Farukh

department is IT

Class Inheritance:

To create a class inheritance, use the extends keyword.

A class created with a class inheritance inherits all the methods from another class:

class Employee {

  constructor(name, department) {

    this.name = name;

    this.department = department;

  }

}

class Manager extends Employee {

  constructor(name, department, position) {

    super(name, department);

    this.position = position;

  }

  displayValue() {

    console.log('Name is '+this.name);

    console.log('department is '+this.department);

    console.log('position is '+this.position);

  }

}

const myEmp = new Manager("Farukh", "IT", "Consultant");

myEmp.displayValue();

Output:

Name is Farukh

department is IT

position is Consultant

The super() method refers to the parent class.

By calling the super() method in the constructor method, we call the parent's constructor method and gets access to the parent's properties and methods.