Map records without Id to their related records

I recently encountered a task involving a multi-layered data structure. To outline the requirements concisely:

  • Trigger: The process is initiated by an Insert trigger, which supplies a list of newly added Leads.
  • Account Lookup: Each Lead within this list contains a reference to a corresponding Account.
  • Contact Mapping: The objective is to retrieve the primary Contact associated with each Account and establish a direct link between that Contact and its respective Lead.

Assumption

  • Leads are new and therefore no Id exist.
  • To simplify, we ignore every null value in lookups.
  • Also we will ignore all the conditions.

Solution

We know that we need to avoid Query in a loop, therefore, the crucial step involves constructing a Map that correlates Leads with their corresponding orders.

Integer counter = 0;
Map<Integer, Lead> newLeadMap = new Map<Integer, Lead>();
for (Lead l : newLeads) {
     newLeadMap.put(counter++, l);
}

Secondly, we will get all the Account Ids associated with Leads.

Set<Id> accountIdSet = new Set<Id>();
for (Integer key : leadMap.keySet()) {
     accountIdSet.add(leadMap.get(key).account__c);
}

And we query all Contacts that has a lookup to those Accounts.

List<Contact> contacts = [SELECT Id, AccountId
     FROM Contact
     WHERE AccountId IN :AccountIds];

Next, let’s get a map of Accounts with their corresponding Contacts.

Map<Id, List<Contact>> accountIdToContactListMap = new Map<Id, List<Contact>>();
for (Contact con : contacts) {
     List<Contact> contactList = accountIdToContactListMap.get(con.AccountId);
     if (contactList != null) {
          contactList.add(con);
          accountIdToContactListMap.put(con.AccountId, contactList);
     } else {
          accountIdToContactListMap.put(con.AccountId, new List<Contact>{ con });
     }
}

Now it’s easy to find the primary Contact.

Map<Id, Contact> accountIdToContactMap = new Map<Id, Contact>();
for (Id acctId : accountIdToContactListMap.keySet()) {
     Boolean primaryContactFound = false;
     for (Contact con : accountIdToContactListMap.get(acctId)) {
          if (con.Is_Primary__c == true) {
               accountIdToContactMap.put(con.AccountId, con);
               break;
          }
     }
}

Cool! Last thing to do is to Map primary Contacts with the Leads.

Map<Integer, Contact> result = new Map<Integer,Contact>();
for (Integer key : leadMap.keySet()) {
     Contact con = accountIdToContactMap.get(leadMap.get(key).account__c);

     result.put(key, con);
}

Remember that every Key value was a replacement for the Lead Id.

Read More

Salesforce CLI sf (v2) handy commands to work with Scratch orgs

Here are some handy Salesforce CLI sf (v2) commands for working with scratch orgs:


Remember to Uninstall the previous sfdx CLI before installing sf.

# installation
$ npm install sf

# create a DX project
$ sf project generate -n my-project

# authorize a default DevHub
$ sf org login web -d -a default-hub

# create a default scratch org
$ sf org create scratch -f config/project-scratch-def.json -a my-scratch-org -y 30 -d

# View the list of our orgs
$ sf org list

# generate a password for the default scratch org
$ sf org generate password

# push all local metadata changes to the scratch org
$ sf project deploy start

# assign permission set to the current user
$ sf org assign permset -n My_Permission_Set_Name

# run a script (for example to create sample data)
$ sf apex run -f ./scripts/setupMyObj.apex

# open the newly created default scratch org
$ sf org open

# org details including access token, username, password, alias, etc.
$ sf org display

# deploy or retrieve specific metadata
$ sf project deploy start -d force-app/main/default/lwc/myComponent
$ sf project retrieve start -m ApexClass:MyApexClass

# set or change org alias
$ sf alias set my-scratch-org=test-dev@example.com

# change default DevHub
$ sf config set target-org=me@myhub.org

# delete a scratch org
$ sf org delete scratch -o my-scratch-org
Read More

Salesforce source-based development

Salesforce DX allows developers to use Git and source repositories when doing any sorts of development on Salesforce platform.


Setup

Scratch orgs are a central feature of Salesforce DX. The Scratch org is a source-driven and disposable deployment of Salesforce code and metadata.

Dev Hub allows you to create and manage scratch orgs. It is also essential create and manage second-generation packages, and use Einstein features.


Install SFDX CLI

Open this link: https://developer.salesforce.com/tools/sfdxcli download and install the CLI compatible with your OS.

To check if the CLI has been installed correctly, type this in command prompt:

$ sfdx --version

sfdx-cli/7.132.0 win32-x64 node-v16.13.1

And to check for installed salesforce dx plugins:

$ sfdx plugins --core

@oclif/plugin-autocomplete 0.3.0 (core)
@oclif/plugin-commands 1.3.0 (core)
...


Update SFDX CLI

Occasionally you might need to update your CLI in order to work with the latest improvements.

$ sfdx update


Sign up for Dev Hub account

Navigate to https://developer.salesforce.com/promotions/orgs/dx-signup. Here you can sign-up for a 30 day trial Dev Hub.

In real world production, you will use a permanent Dev Hub.

This org is already configured to act as a Dev Hub. However, to convert a normal org to a Dev Hub you should follow these steps:

  1. Setup
  2. Development -> Dev Hub (or search Dev Hub)
  3. Enable Dev Hub


Connect Dev Hub and CLI

We need to authenticate with DevHub so the SFDX can track it in the future:

$ sfdx force:auth:web:login -d -a DefaultHub

-d flag is to define a DevHub and -a will set an alias for it.

After a successful authentication we can use this command to view the list of our orgs:

$ sfdx force:org:list

=== Orgs
     ALIAS       USERNAME                           ORG ID              CONNECTED STATUS
───  ──────────  ─────────────────────────────────  ──────────────────  ────────────────
(D)  DefaultHub  ***@***.com  00D5g000004FOzsEAG  Connected

The --all flag can be used to view the expired orgs as well.

Note: Developer Edition DevHub is only valid for 30 days and a new DevHub must be created afterwards.

  ALIAS USERNAME ORG ID CONNECTED STATUS
(D) DefaultHub abc@xyz.com 00D5g000004jAhWEAU RefreshTokenAuthError

Logout in order to clean up the unwanted DevHub (non-Scratch) orgs:

$ sfdx force:auth:logout -u ***@***.com

Note: remember to Enable Dev Hub on the newly created Org.


Salesforce DX project

To begin we need to create a DX project:

Create project For this purpose we will use create within the project commands:

$ sfdx force:project:create -n my-project
  • We can use –projectname instead -n flag too.

This will create a basic project folder structure and required files in the specified directory.


Create Scratch Org

There are number of ways to do this.

One of the files that was created for us in the previous step was config/project-scratch-def.json. The easiest method is to use this definition to create our scratch org.

$ sfdx force:org:create -f config/project-scratch-def.json -a myScratchOrg --durationdays 30 --setdefaultusername
  • --setdefaultusername can be simplified to -s and will make the new scratch org our default working org.
  • -f specified the org definition
  • --durationdays indicates when the scratch org expires (in 1-30 days). The default duration is 7 days.
  • -a creates an alias

Alternatively, we can omit the project-scratch-def.json and specify values in the command:

$ sfdx force:org:create edition=Developer -a myScratchOrg -s -v devHub

After running the command we should get a success message:

Successfully created scratch org: 00DN0000000VT0XMAW, username: test-zoxah4mpz0t7@example.com

and the org list command should show us the new scratch org in the available orgs list:

$ sfdx force:org:list
=== Orgs
     ALIAS       USERNAME                           ORG ID              CONNECTED STATUS
───  ──────────  ─────────────────────────────────  ──────────────────  ────────────────
(D)  DefaultHub  ***@***.com  00D5g000004FOzsEAG  Connected

     ALIAS         USERNAME                       ORG ID              EXPIRATION DATE
───  ────────────  ─────────────────────────────  ──────────────────  ───────────────
(U)  myScratchOrg  test-zoxah4mpz0t7


Open the Scratch Org

You can now open the org

$ sfdx force:org:open -u <username/alias>

If we omit the -u <username/alias> the CLI will open the default scratch org.


VS Code Extensions

VS Code has several extensions that can assist us using SFDX. In fact, everything we did so far or we’ll be doing in later chapters can be done through these extensions.

Salesforce has combined most of these extensions under a single pack called Salesforce Extension Pack, including:

  • Salesforce CLI Integration
  • Apex: Provides code-editing features for the Apex
  • Apex Interactive Debugger
  • Apex Replay Debugger: presents the logged information
  • Lightning Web Components
  • SLDS Validator: simplifies working with Salesforce Lightning Design System

The new Salesforce Extension Pack (Expanded) extension features some other packages such as:

  • XML: XML Language Support by Red Hat
  • ESLint: Integrates ESLint JavaScript into VS Code.
  • Prettier: Code formatter
  • Apex PMD: PMD static analysis for Salesforce Apex
  • Apex Log Analyzer

After the installation is completed, your VS Code will have some integrated features to work with SFDX.

  • Create new project: F1 (ctrl+shift+p) -> SFDX: Crate Project
  • Create new Scratch Org: F1 -> SFDX: Crate a Default Scratch Org
  • Open scratch org: click on the rectangular icon beside your scratch org name on the VS Code status bar.


VS Code Extension

Salesforce recommends using VS Code along with Salesforce Extension Pack. Most of the commands presented at this tutorial are available via VS Code commands after installation of this package.



References

  • https://developer.salesforce.com/docs/atlas.en-us.packagingGuide.meta/packagingGuide/dev_hub_intro.htm
Read More