Friday, February 28, 2020

Steps To Connect Marketing Cloud and Salesforce Org

Before installing Marketing Cloud Connect, you need to keep the following Things in your mind –
  1. Review the Features page to understand compatibility and product versions.
  2. Marketing Cloud Connect requires a relationship between a single Marketing Cloud account and one or more Salesforce Org. Your Marketing Cloud account must be provisioned and enabled for use with Marketing cloud Connect prior to connection.
  3. Subscriber Key is required for Marketing Cloud Connect. If it is not enabled in your Marketing Cloud account, complete a Subscriber Key Migration before proceeding with the connection process.
  4. Ensure four custom tabs are available in your Salesforce org
  5. Salesforce users must have a license for the Marketing Cloud and a license for Salesforce CRM, for example, the Sales Cloud, to leverage most out of Marketing Cloud Connect functionality.

User Types and Permissions –

  1. Install Marketing cloud – Paste the following URL for installing the marketing cloud package.
  2. After login, select install for admin only, all users, or specific profiles.
  3. Click Install.
  4. Click Continue.

After installing following permissions are used –

  1. Click on Setup ——-> Click Customize —-> Click users —–> Click Page Layouts—–> Edit the user page layout.
  2. Add the Marketing Cloud for AppExchange User field.
  3. Add the Marketing Cloud for AppExchange Admin field Click on Save button.
  4. Click on Setup —–> Click Manage Users ——–> Click Users ——–> Edit the Salesforce CRM administrator user.
  5. Enable Marketing Cloud for AppExchange User. Enable Marketing Cloud for AppExchange Admin.
  6. Click on save

Setup salesforce system users –

  1. Click on Setup —–> click Manage Users—-> Click Users
  2. Create a new user or update an existing user with the following settings:-
    • User License – Salesforce
    • Profile – System Administrator
  3. Click on Save button.
  4. Edit the Salesforce system user.
  5. Ensure the user has the System Administrator profile applied.
  6. Check the Marketing Cloud for AppExchange Admin checkbox.
  7. Check the Marketing Cloud for Appexchange User checkbox.
  8. Click on save button.

Steps to Login to Marketing cloud org –

  1. Navigate to Email Studio —> Click Admin ——> Click Salesforce Integration —–> Click Edit.
  2. Select Scope by User if applicable for your data access configuration.
  3. If prompted, click Upgrade to Connected App ——->Click Connect Account.
  4. if you are not logged in to the Sales or Service Cloud as your Salesforce system user in a separate tab, you are prompted to log in.
  5. Click OK and log in as the system user.

Steps to create a Marketing cloud user API-

  1. Click on Email Studio—–> Click Admin ——> Click My Users —-> Click Create Name the user so it can be easily identified (eg. API-user-1234).
  2. Enter your email address as the Reply Email and Notification Email Addresses.
  3. Enter a unique username.
  4. Leave the External ID field blank, unless required by your organization.
  5. Set a Time Zone.
  6. Set a Culture Code.
  7. Check the API User checkbox.
  8. Create a temporary password.
  9. If you are using a non-enterprise 2.0 account, set the following roles and permissions on this page:
    • User Permissions: NONE
    • Marketing Cloud Permissions and Roles: NONE
    • Select Email Application Select Mobile Connect (if applicable)
    • Select Marketing Cloud Administrator role.
    • Save the new Marketing Cloud API user.
  10. If you are using an enterprise 2.0 account, continue to set roles and permissions as follows-
    • Click My Users from Email Studio Admin
    • Select the Marketing Cloud API User
    • Click Manage Roles
    • Click Edit Roles and Assign the following roles: Marketing Cloud Administrator
    • Save the roles for the Marketing Cloud API user

Connecting the Marketing cloud API User –

  1. Click on Email Studio —-> Click Admin —–> Click My Users —-> Select the API user.
  2. Click Integrate for Salesforce.com Status —–>Enter the Salesforce system user username —–>Save the settings.
  3. The Salesforce.com Status field updates to “Integrated” if the connection is successful.

Steps to Assign a Business Unit –

  1. In the Marketing Cloud, navigate to Email Studio.
  2. Click Admin —-> Click My Users —-> Select the Marketing Cloud API User.
  3. Click Manage Business Units at the top of the Users table.
  4. Ensure the selection under Default Business Unit is the top-level business unit.
  5. In the Associated Business Units section, select all business units to be used with Marketing Cloud Connect.
  6. Save the changes to the Marketing Cloud API User.

Log in to your Salesforce org Again –

  1. Click Setup —-> Click Manage Apps —–> Connected Apps —–> Salesforce Marketing Cloud.
  2. Click on Edit Policies —–> Under Permitted Users, select Admin approved users are pre-authorized.
  3. If a warning message appears, click OK.
  4. Under IP Relaxation, select Relax IP restrictions.
  5. Under Refresh Token Policy, select Immediately expire refresh token.
  6. Save changes.
  7. Click on Setup —–> Click Manage Users —–> Click Permission Sets
  8. Click New —-> Give the permission set a memorable name. For example, Marketing Cloud Connected App.
  9. Validate the generated API name and ensure this field has the desired value. Save the permission set.
  10. Again Click on Setup —-> Click Manage Users —-> Click Permission Sets.
  11. Click the name of the newly created permission —-> Click Manage Assignments —-> Click Add Assignments
  12. Select the users who need to access the connected app.
    • This typically matches the users that access Marketing Cloud Connect.
  13. Ensure the Salesforce system user is selected for access—>Click Assign—> Click done

In Sales and Service cloud –

  1. Click Setup —-> Click Manage App —-> Connected Apps —-> Salesforce Marketing Cloud —-> Manage Permission Sets.
  2. Select the newly created permission set.
  3. Save changes.
  4. Click on Marketing Cloud tab.
    • If you are using a Marketing Cloud Production Support environment, Click Advanced Settings and select Sandbox from the Marketing Cloud Environment list.
  5. Click Connect to Marketing Cloud.
  6. Enter the username and password for the Marketing Cloud Connect API User.
  7. Click Login.

Friday, February 7, 2020

Difference between Queues and Flex Queues

Normally, a Batch Job which has not started yet will assume the status of Queued. The batch which is currently being processed will be in the InProgress status. Batch jobs usually have the limit of five queued or active jobs simultaneously. With Flex Queues, any jobs that are submitted for execution but are not processed immediately by the system go in holding status and are placed in a separate queue (the Apex flex queue).
Up to 100 batch jobs can be in the holding status. When system resources become available, the system picks up jobs from the Apex flex queue and moves them to the batch job queue. The status of these moved jobs changes from Holding to Queued. Queued jobs get executed when the system is ready to process new jobs and they will then go to InProgress status.
This would give you an impression that a lot of jobs are in holding status and are stuck. They actually are placed in the Apex flex queue and are waiting to be picked up when system resources are available.

Difference between Batchable, Queueable, and Future methods

All async code can run in to stale data. The difference between Batchable, Queueable, and Future methods is how they're designed to behave. Batchable calls were designed to allow for heavy asynchronous processing. But, it was the only asynchronous code at one point, and it was too "heavy" in terms of resource usage, and had a lot of baggage associated with it. It required a long time to process and was often used only to handle callouts or things that were slightly longer than a normal transaction could handle.
So, next came future methods. Unlike Batchable methods, they were lighter on resources and perfect for doing that job that Batchable was doing before, but much more efficiently. Unfortunately, it was too efficient. You didn't know when the job was done (no Job ID), and it only had a limited amount of space to store data (the reason why it only accepted primitives and collections thereof).
In response to feedback, a third version of asynchronous code was designed: Queueable. It was lighter than Batchable, but it gave you a Job ID and let you store complex data patterns. The lesser resources it used compared to batchable also meant higher limits. Queueable was meant to be a hybrid between the limited future methods and the resource-hungry Batchable interface.
So, to get back to your question: you should always avoid passing in entire SObjects, especially if they may change between serialization and execution. If you need heavy processing, you probably want Batchable, while if you want normal-sized transactions with increased limits, you probably want Queueable. Of course, you can still use future methods if you don't need to monitor the results of the execution, and they'll continue to work for the foreseeable future.

Wednesday, February 5, 2020

Check type of object in Lightning controller.js

({
    doInit: function(cmp) {
        var recId = cmp.get('v.recordId');
        var recIdSubString = recId.substring(0, 3);
       
        if(recIdSubString=='00U'){
            cmp.set("v.objectType", "Event");
        }
       
        if(recIdSubString=='500'){
            cmp.set("v.objectType", "Case");
        }
    }
})

Saturday, February 1, 2020

Create Multiple Account with Add/Remove Functionality in Lighting Component

CreateMultipleAccount.cmp

<aura:component controller="CreateMultipleAccountController" Implements="flexipage:availableForRecordHome,force:hasRecordId">
 
    <aura:attribute name="accountList" type="Account[]"/>
 
    <div class="slds-m-around--xx-large">
        <div class="slds-float_right slds-p-bottom_small">
            <h1 class="slds-page-header__title">Add Row
                <lightning:buttonIcon iconName="utility:add"  size="large" variant="bare" alternativeText="Add" onclick="{!c.addRow}"/>
            </h1>
        </div>
        <div class="container-fluid">     
            <table class="slds-table slds-table_bordered slds-table_cell-buffer">
                <thead>
                    <tr class="slds-text-title_caps">
                        <th scope="col">
                            <div class="slds-truncate">#</div>
                        </th>
                        <th scope="col">
                            <div class="slds-truncate" title="Account Name">Account Name</div>
                        </th>
                        <th scope="col">
                            <div class="slds-truncate" title="Account Number">Account Number</div>
                        </th>
                        <th scope="col">
                            <div class="slds-truncate" title="Phone">Phone</div>
                        </th>
                        <th scope="col">
                            <div class="slds-truncate" title="Action">Action</div>
                        </th>
                    </tr>
                </thead> 
                <tbody>   
                    <aura:iteration items="{!v.accountList}" var="acc" indexVar="index">
                        <tr>
                            <td>
                                {!index + 1}
                            </td>
                            <td>
                                <lightning:input name="accName" type="text" required="true" maxlength="50" label="Account Name" value="{!acc.Name}" />
                            </td>
                            <td>
                                <lightning:input name="accNumber" type="text"  maxlength="10" label="Account Number" value="{!acc.AccountNumber}" />
                            </td>
                            <td>
                                <lightning:input name="accPhone" type="phone" maxlength="10" label="Phone" value="{!acc.Phone}" />
                            </td>
                            <td>
                                <a onclick="{!c.removeRow}" data-record="{!index}">
                                    <lightning:icon iconName="utility:delete" size="small" alternativeText="Delete"/>
                                    <span class="slds-assistive-text">Delete</span>
                                </a>
                            </td>
                        </tr>
                    </aura:iteration>
                </tbody>
            </table>
            <div class="slds-align_absolute-center slds-p-top_small">
                <lightning:button variant="brand" label="Submit" title="Brand action" onclick="{!c.save}" />
            </div>
        </div>
    </div>
</aura:component>

CreateMultipleAccountController.js
({
    addRow: function(component, event, helper) {
        helper.addAccountRecord(component, event);
    },
   
    removeRow: function(component, event, helper) {
        //Get the account list
        var accountList = component.get("v.accountList");
        //Get the target object
        var selectedItem = event.currentTarget;
        //Get the selected item index
        var index = selectedItem.dataset.record;
        accountList.splice(index, 1);
        component.set("v.accountList", accountList);
    },
   
    save: function(component, event, helper) {
        if (helper.validateAccountList(component, event)) {
            helper.saveAccountList(component, event);
        }
    },
})

CreateMultipleAccountHelper.js
({
    addAccountRecord: function(component, event) {
        //get the account List from component
        var accountList = component.get("v.accountList");
        //Add New Account Record
        accountList.push({
            'sobjectType': 'Account',
            'Name': '',
            'AccountNumber': '',
            'Phone': ''
        });
        component.set("v.accountList", accountList);
    },
   
    validateAccountList: function(component, event) {
        //Validate all account records
        var isValid = true;
        var accountList = component.get("v.accountList");
        for (var i = 0; i < accountList.length; i++) {
            if (accountList[i].Name == '') {
                isValid = false;
                alert('Account Name cannot be blank on row number ' + (i + 1));
            }
        }
        return isValid;
    },
   
    saveAccountList: function(component, event, helper) {
        //Call Apex class and pass account list parameters
        var action = component.get("c.saveAccounts");
        action.setParams({
            "accList": component.get("v.accountList")
        });
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                component.set("v.accountList", []);
                alert('Account records saved successfully');
            }
        });
        $A.enqueueAction(action);
    },
})