Friday, 21 February 2025

Two-Way Account Data Integration

 Account data submitted in Salesforce → Sent to External API → Account created in the external system → External System ID stored in Salesforce.

Two-Way Integration: Synchronizing Accounts Between Salesforce and an External System
1. User Submits Account Form
The user enters Name, Email, and Phone in a Lightning Web Component (LWC).
Clicking Submit triggers a call to an Apex method (sendAccountData).
2. Data Sent to External API
The Apex method sends account details to an external system via an API request.
The external system creates a new account and returns a unique External System ID.
3. Account Created in Salesforce
A new Account record is inserted in Salesforce.
The response from the external system is processed:
If an id is received, it is stored in the External_Id__c field on the Salesforce Account.
If no ID is returned, an appropriate message is stored.
4. Two-Way Synchronization Achieved
Salesforce and the external system are now linked via the External System ID.
Future updates can be synchronized based on this ID for real-time integration.

Monday, 3 February 2025

How to Debug: Console, HRA, and Apex Debug Logs Salesforce

 Explanation of Log Content:

Console.log:

Used for frontend debugging in JavaScript or Lightning Web Components (LWC).

Logs messages, variables, and errors to the browser console.


HRA.log:

A custom log file for a Human Resources Application.

Tracks application events, warnings, and errors for auditing and debugging purposes.


Apexdebug.log:

Generated by Salesforce for debugging Apex code.

Captures execution details, SOQL queries, debug statements, and exceptions.

These logs are essential for troubleshooting, monitoring, and improving applications. The content and structure will vary depending on the specific use case and the system being debugged.

Understanding Logs: Console.log, HRA.log, and Apex Debug.log

Monday, 28 October 2024

Multi-step Contact Form In LWC

Screen 1
Title: "Personal Information"
Caption: "Please enter your basic personal details, including your first and last name."
Screen 2
Title: "Contact Details"
Caption: "Provide your primary contact information, including email and phone number."
Screen 3
Title: "Review & Submit"
Caption: "Review the information provided, then click Submit to save your details."

Apex Code 

public  class ContactController {
    @AuraEnabled
    public static String saveContact(Contact contact) {
        try {
            // Insert or update contact record
            if (contact.Id == null) {
                insert contact;
            } else {
                update contact;
            }
            return 'Contact saved successfully!';
        } catch (Exception ex) {
            throw new AuraHandledException('Error saving contact: ' + ex.getMessage());
        }
    }
}

Js ContactRegistration

import { LightningElement,track } from 'lwc';
import saveContact from '@salesforce/apex/ContactController.saveContact';
export default class ContactRegistration extends LightningElement {
@track isScreen1 = true;
    @track isScreen2 = false;
    @track isScreen3 = false;
    @track firstName = '';
    @track lastName = '';
    @track phone = '';
    @track email = '';

    handleInputChange(event) {
        const field = event.target.dataset.id;
        this[field] = event.target.value;
    }

    goToScreen2() {
        this.isScreen1 = false;
        this.isScreen2 = true;
    }

    goToScreen1() {
        this.isScreen1 = true;
        this.isScreen2 = false;
    }

    goToScreen3() {
        this.isScreen2 = false;
        this.isScreen3 = true;
    }

    async submitContact() {
        const contactData = {
            FirstName: this.firstName,
            LastName: this.lastName,
            Phone: this.phone,
            Email: this.email
        };

        try {
            const result = await saveContact({ contact: contactData });
            alert(result); // Show success message
            this.resetForm();
        } catch (error) {
            alert('Error: ' + error.body.message);
        }
    }

    resetForm() {
        this.isScreen1 = true;
        this.isScreen2 = false;
        this.isScreen3 = false;
        this.firstName = '';
        this.lastName = '';
        this.phone = '';
        this.email = '';
    }
}

Html ContactRegistration
<template>
    <template if:true={isScreen1}>
        <lightning-input label="First Name" value={firstName} onchange={handleInputChange} data-id="firstName"></lightning-input>
        <lightning-input label="Last Name" value={lastName} onchange={handleInputChange} data-id="lastName"></lightning-input>
        <lightning-button label="Next" onclick={goToScreen2}></lightning-button>
    </template>

    <template if:true={isScreen2}>
        <lightning-input label="Phone" value={phone} onchange={handleInputChange} data-id="phone"></lightning-input>
        <lightning-input label="Email" value={email} onchange={handleInputChange} data-id="email"></lightning-input>
        <lightning-button label="Previous" onclick={goToScreen1}></lightning-button>
        <lightning-button label="Next" onclick={goToScreen3}></lightning-button>
    </template>

    <template if:true={isScreen3}>
        <p>Review your information and click Submit to save the contact.</p>
        <lightning-button label="Previous" onclick={goToScreen2}></lightning-button>
        <lightning-button label="Submit" onclick={submitContact}></lightning-button>
    </template>
</template>

Tuesday, 8 October 2024

Triggering Change Data Capture (CDC) for Automated Sync of Salesforce Accounts with External System on Create/Update Events

When an Account is created, fields like Document_Name__c, Account Name, and AnnualRevenue should be automatically populated (or updated) in an external system.

These fields should also be automatically populated in Salesforce, and this should happen when the account is first created.

Updated Requirements

Document_Name__c: Automatically generated when an Account is created. 

Account Name and AnnualRevenue: Sent to the external system when the account is created, and potentially populated with specific data from the external system as well.

Trigger 

trigger AccountChangeEventTrigger on AccountChangeEvent (after insert) {

    List<String> insertIds = new List<String>();

    List<String> updateIds = new List<String>();

    for (AccountChangeEvent event : Trigger.New) {

        if (event.ChangeEventHeader.getChangeType() == 'CREATE') {

            insertIds.add(event.ChangeEventHeader.getRecordIds()[0]);

        } else if (event.ChangeEventHeader.getChangeType() == 'UPDATE') {

            updateIds.add(event.ChangeEventHeader.getRecordIds()[0]);

        }

    }

    if (!insertIds.isEmpty()) {

        List<Account> newAccounts = [SELECT Id, Name, AnnualRevenue, Document_Name__c FROM Account WHERE Id IN :insertIds];

        for (Account acc : newAccounts) {

            ExternalService.sendAccount(acc.Document_Name__c, acc.Name, acc.AnnualRevenue);

        }

    }

    if (!updateIds.isEmpty()) {

        List<Account> updatedAccounts = [SELECT Id, Name, AnnualRevenue, Document_Name__c FROM Account WHERE Id IN :updateIds];

        for (Account acc : updatedAccounts) {

   ExternalService.sendAccount(acc.Document_Name__c, acc.Name, acc.AnnualRevenue);

        }

    }

}

Apex Class

public class ExternalService {

    

    @future(callout=true)

    public static void sendAccount(String documentId, String accountName, Decimal annualRevenue) {

        try {

            List<FirestoreConfig__mdt> configs = [SELECT API_Key__c, Endpoint_URL__c FROM FirestoreConfig__mdt LIMIT 1];

            if (configs.isEmpty()) {

                return;

            }

            String apiKey = configs[0].API_Key__c;

            String endpoint = configs[0].Endpoint_URL__c;

            HttpRequest req = new HttpRequest();

            Http http = new Http();

            String finalEndpoint = endpoint + documentId + '?key=' + apiKey;

            req.setMethod('PATCH');

            req.setEndpoint(finalEndpoint);

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

            String body = '{' +

                '"fields": {' +

                    '"accountName": {"stringValue": "' + accountName + '"},' +

                    '"annualRevenue": {"doubleValue": ' + annualRevenue + '}' +

                '}' +

            '}';

            req.setBody(body);

            HttpResponse res = http.send(req);

            if (res.getStatusCode() == 200 || res.getStatusCode() == 201) {

            } else {

                System.debug('Error updating account in ExternalSystem: ' + res.getStatusCode() + ' - ' + res.getBody());

            }

        } catch (Exception e) {

            System.debug('Exception: ' + e.getMessage());

        }

    }

}

Sunday, 6 October 2024

Triggering Platform Events for Contact Creation and Sending Data to External Systems

 how to publish a Platform Event when a Contact record is created and send this contact data to External Systems using a Salesforce custom Apex class with a callout.

Steps:

Trigger on Contact Creation: This trigger publishes a platform event when a Contact record is inserted.

Platform Event Trigger: This trigger listens to the Platform Event and sends the data to External Systems using an Apex class.

Apex Class for External Systems Integration: A class that performs a callout to the External Systems API to send the contact data.

Custom Metadata Type (for External Systems Configuration): The External Systems API key and endpoint URL are stored in custom metadata to allow flexibility and security.

trigger ContactTrigger on Contact (after insert) {

    List<ContactCreationEvent__e> events = new List<ContactCreationEvent__e>();

    for (Contact contact : Trigger.New) {

           String fullName = contact.FirstName + ' ' + contact.LastName;

        ContactCreationEvent__e event = new ContactCreationEvent__e(

            Name__c = fullName,

            Age__c = contact.Age__c // Ensure Age__c is a custom field on Contact

        );

        // Add the event to the list

        events.add(event);

    }

    if (!events.isEmpty()) {

        EventBus.publish(events);

    }

}

2. Platform Event Trigger to Handle the Event and Call External Systems

trigger ContactCreationEventTriggers on ContactCreationEvent__e (after insert) {

    for (ContactCreationEvent__e event : Trigger.New) {

        ExternalService.sendContactToExternal(event.Name__c, event.Age__c);

    }

}

3. Apex Class to Integrate with ExternalSystem

public class ExternalService {

    @future(callout=true)

    public static void sendContactToExternal(String contactName, Decimal age) {

        try {

            List<FirestoreConfig__mdt> configs = [SELECT API_Key__c, Endpoint_URL__c FROM FirestoreConfig__mdt LIMIT 1];

            if (configs.isEmpty()) {

                return;

            }

            String apiKey = configs[0].API_Key__c;

            String endpoint = configs[0].Endpoint_URL__c;

            HttpRequest req = new HttpRequest();

            Http http = new Http();

            String finalEndpoint = endpoint + '?key=' + apiKey;

            req.setMethod('POST');

            req.setEndpoint(finalEndpoint);

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

            String body = '{' +

                '"fields": {' +

                    '"name": {"stringValue": "' + contactName + '"},' +

                    '"age": {"integerValue": ' + age + '}' +

                '}' +

            '}';

            req.setBody(body);

            HttpResponse res = http.send(req);

            if (res.getStatusCode() == 200 || res.getStatusCode() == 201) {

                

            } else {

                System.debug('Error sending contact to Firestore: ' + res.getStatusCode() + ' - ' + res.getBody());

            }

        } catch (Exception e) {

            System.debug('Exception: ' + e.getMessage());

        }

    }

}


Friday, 6 September 2024

RestAPI To Display Nifty 50 Historical Data

 Apex Class QuandlApiService


public class QuandlApiService {

    @AuraEnabled(cacheable=true)

    public static String fetchNifty50Data() {

        try {

            // Fetch custom metadata for API configuration

            API_Configuration__mdt config = [SELECT API_Endpoint__c, API_Key__c FROM API_Configuration__mdt WHERE DeveloperName = 'Quandl_Nifty50' LIMIT 1];            

            // Create an HTTP request

            HttpRequest req = new HttpRequest();

            Http http = new Http();

            // Set the endpoint URL with the API key from metadata

            String url = config.API_Endpoint__c + '?api_key=' + config.API_Key__c;

            req.setEndpoint(url);

            req.setMethod('GET');

            // Send the request and get the response

            HttpResponse res = http.send(req);

            // Check the status code for success

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

                // Parse the JSON response

                Map<String, Object> responseMap = (Map<String, Object>) JSON.deserializeUntyped(res.getBody());

                Map<String, Object> dataset = (Map<String, Object>) responseMap.get('dataset');

                // Debug the response structure

                System.debug('Full Response: ' + responseMap);

                // Get the list of column names

                List<Object> columnNames = (List<Object>) dataset.get('column_names');

               // Get the actual data

                Object rawData = dataset.get('data');

                // Debug the raw data

                System.debug('Raw Data: ' + rawData);

                // Initialize the result

                String result = 'Nifty50 Data:\n';

                // Handle different data structures

                if (rawData instanceof List<List<Object>>) {

                    // Handle List of Lists

                    List<List<Object>> data = (List<List<Object>>) rawData;

                    for (List<Object> row : data) {

                        for (Integer i = 0; i < columnNames.size(); i++) {

                            result += (String) columnNames[i] + ': ' + String.valueOf(row[i]) + ', ';

                        }

                        result += '\n';

                    }

                } else if (rawData instanceof List<Object>) {

                    // Handle Flat List

                    List<Object> data = (List<Object>) rawData;

                    for (Integer i = 0; i < columnNames.size(); i++) {

                        result += (String) columnNames[i] + ': ' + String.valueOf(data[i]) + '\n';

                    }

                } else {

                    result += 'Unexpected data format';

                }

                return result;

            } else {

                return 'Failed to fetch data. Status code: ' + res.getStatusCode();

            }

        } catch (Exception e) {

            System.debug('Error occurred: ' + e.getMessage());

            return 'Error occurred: ' + e.getMessage();

        }

    }

}

Nifty50Card Js Code 


import { LightningElement,wire,track } from 'lwc';

import fetchNifty50Data from '@salesforce/apex/QuandlApiService.fetchNifty50Data';

export default class Nifty50Data extends LightningElement {

@track data;

@track error;

 @wire(fetchNifty50Data)

    wiredNifty50Data({ error, data }) {

        if (data) {

            this.data = data;

            this.error = undefined;

        } else if (error) {

            this.data = undefined;

            this.error = error.body.message;

        }

    }

}


Nifty50Card Html Code

<template>

    <lightning-card title="Nifty50 Data">

        <template if:true={data}>

            <pre>{data}</pre>

        </template>

        <template if:true={error}>

            <p class="slds-text-color_error">{error}</p>

        </template>

    </lightning-card>

</template>

Please Click Link Output Result 

OUTPUT