back to blog
Display all Opportunities Related to a Competitor Account
November 15 2021 • 25 min read

BUSINESS CHALLENGE

Having multiple competitors for an Opportunity is common. Knowing the number of opportunities per competitor and the value gives guidance to the sales professionals on how to proceed with it. Standard Salesforce provides the opportunities for an account but not for the competitor accounts. If you want to display all the opportunities with the competitor account mentioned, we have a solution for you.

An Aura component can be used to display all the opportunities for a given competitor.

This component can be placed on the Competitor’s account page so that we can view the list of all those opportunities associated with the Competitor.

dcao10 1

The Aura component can either be created directly in the developer console or it can be created and deployed from VSCode to the required org.

USING DEVELOPER CONSOLE

  1. Create an Apex controller
  2. Create a Lightning Aura component
  3. Place the component on the page

1. CREATE AN APEX CONTROLLER

  1. Open the developer console in your Salesforce org and click on File → New → Apex class, enter a name for your Apex class CompetitorAccountOppController and click Ok.

    dcao1

    dcao2

  2. The following Apex class retrieves all the opportunities with respect to Competitor accounts. This use case has an opportunity to be associated with two Competitors.

    public class CompetitorAccountOppController {
        @AuraEnabled
        public static List<Opportunity> retrieveOpportunities(String recordId){
            return [SELECT Name, Id, Account.Name, Amount, StageName, CloseDate  FROM Opportunity WHERE  Competitor_1__r.Id = :recordId OR Competitor_2__r.Id = :recordId ];
        }  
    }
  3. Save this file and use this Apex class as controller for the Component.

  4. The @AuraEnabled annotation enables client server-side access to an Apex controller method. Providing this annotation makes your methods available to your Lightning components (both Lightning web components and Aura components). Only methods with this annotation are exposed.

2. CREATE A LIGHTNING AURA COMPONENT

  1. In the Developer console click File → New → Lightning Component, enter the name of the component as DisplayCompetitorAcountOpportunities and click submit. On submit it creates an Aura Component bundle.

    dcao3

    dcao4

    dcao5

  2. A Component bundle consists of a component and all its related resources. Here we use the component and two of its resources i.e Javascript Controller and Style (CSS).

  3. On the right pane you can see the component and the list of its related resources. Click on the component or any other resource to open it.

  4. The following code is for the Component of the component bundle.

    DisplayCompetitorAcountOpportunities.cmp

    <aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId"
        controller="CompetitorAccountOppController" access="global">
        <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
        <aura:attribute name="cbaseURL" type="String"/>
        <aura:attribute name="recordId" type="String" />
        <aura:attribute name="CompetitorAccountOpportunities" type="Opportunity[]"/>
        <lightning:card variant="Narrow" class="slds-box slds-box_x-small slds-theme_shade" title="Opportunities" iconName="standard:opportunity"/> 
        <table class="slds-table slds-table_cell-buffer slds-table_bordered" aria-labelledby="element-with-table-label other-element-with-table-label">
                <thead>
                    <tr class="slds-line-height_reset">
                        <th class="" scope="col">
                            <div class="slds-truncate" title="Opportunity Name">Opportunity Name</div>
                            </th>
                        <th class="" scope="col">
                            <div class="slds-truncate" title="Account Name">Account Name</div>
                        </th>
                        <th class="" scope="col">
                            <div class="slds-truncate" title="Amount">Amount</div>
                        </th>
                        <th class="" scope="col">
                            <div class="slds-truncate" title="Stage">Stage</div>
                        </th>
                        <th class="" scope="col">
                            <div class="slds-truncate" title="Close Date">Close Date</div>
                        </th>
                    </tr>
                </thead>
                <tbody>
                    <aura:iteration var="opportunity" items="{!v.CompetitorAccountOpportunities}" indexVar="indx">
                        <tr class="slds-hint-parent">
                            <th data-label="Opportunity Name" scope="row">
                                <div class="slds-truncate" title="{!opportunity.Name}">
                                    <a href ="{!cbaseURL+'/lightning/r/Opportunity/'+opportunity.Id+'/view'}">{!opportunity.Name}</a>
                                </div>
                            </th>
                            <td data-label="Account Name">
                                <div class="slds-truncate" title="{!opportunity.Account.Name}">{!opportunity.Account.Name}</div>
                            </td>
                            <td data-label="Total Proposal Value($K)">
                                <div class="slds-truncate" title="{!opportunity.Amount}"><lightning:formattedNumber value="{!opportunity.Amount}" style="currency" currencyCode="USD"/></div>
                            </td>
                            <td data-label="Stage">
                                <div class="slds-truncate" title="{!opportunity.StageName}">{!opportunity.StageName}</div>
                            </td>
                            <td data-label="Close Date">
                                <div class="slds-truncate" title="{!opportunity.CloseDate}"><lightning:formattedDateTime value="{!opportunity.CloseDate}" month="numeric" year="numeric" day="numeric" /></div>
                            </td>
                        </tr>
                    </aura:iteration>
                </tbody>
            </table>
    </aura:component>
  5. Here we used a lightning card to display the icon and title on the page (Similar to standard Account to Opportunities), and data tables to display the records.

  6. The following code is for the Javascript Controller of the bundle.

    DisplayCompetitorAcountOpportunitiesCntroller.js

    ({
        doInit : function(component, event, helper) {
            var urlString = window.location.href;
            var baseURL = urlString.substring(0, urlString.indexOf(".com")+4);
            component.set("v.cbaseURL", baseURL);
            var action = component.get("c.retrieveOpportunities");
            action.setParams({"recordId": component.get("v.recordId")});
            action.setCallback( this, function(response) {
               var state = response.getState();
               if (state === "SUCCESS") {
                   component.set("v.CompetitorAccountOpportunities", response.getReturnValue());
                   console.log(response.getReturnValue());
               }
           });
           $A.enqueueAction(action);
        }
    })
  7. This Javascript Controller retrieves the opportunities from the server using the Apex controller and sets the values to the View attribute -   CompetitorAccountOpportunities which is an array of Opportunities. Here it can be observed that CompetitorAccountOpportunities is declared in the component.

  8. The window.location.href returns the href(URL) of the current page which is used to retrieve the base url which is different in various environments.

  9. The icon style we used inside the lightning card of the component is mentioned below.

    DisplayCompetitorAcountOpportunities.css

    .THIS .slds-media {
        padding-top: 0.5rem;
        padding-left: 1rem;
        display: flex;
        align-items: flex-start;  
    }
  10. Make sure to save each file of the component bundle separately.

3. PLACE THE COMPONENT ON THE PAGE

  1. Open any account in your org and click on gear icon at the top and click edit page.

    dcao6

  2. Once clicked, you will see this page.

    dcao7

  3. Newly created Aura components can be seen on the left pane of the screen (may need to scroll down) under the custom section.

  4. Drag and drop the component on the required section of the page.

  5. The Aura component here is used to display the related opportunities only for the Competitor Account page, so the component visibility has to be set accordingly.

  6. Click on the component. On the right pane, click on Add Filter under the Set component visibility. This will display a pop up like this -

    dcao8

  7. Click Advanced and under Field click Select

  8. Now select Record → Account Record Type → Record Type Name. Click Done.

    dcao9

  9. Now select the operator as Equal and in the value, enter the record type name Competitor. Click Done and save changes to the page.

    dcao10

  10. Head back to the Competitor account page and you will see the table being displayed in the related tab.

    dcao10 1

USING VS CODE

  1. Create Project with Manifest
  2. Create an Apex controller
  3. Create an Aura component
  4. Connect to the Org and deploy the Controller and the Component
  5. Place the component on the page

1. CREATE PROJECT WITH MANIFEST IN VS CODE

  1. Open Vscode and click Ctrl + Shift + p in windows and  cmd + Shift + p in mac to open the command palette.

  2. Search for SFDX: Create Project with Manifest and select it.

    dcao11

  3. Select Standard project template, enter the project name, hit enter and choose the folder in your system where you wish to save the project.

    dcao12

    dcao13

2. CREATE AN APEX CONTROLLER

  1. Open command palette and search for SFDX: Create an Apex class and select it.

    dcao14

  2. Enter name of the Apex class and hit the enter button.

  3. The following code is for the Apex controller of the component

    public class CompetitorAccountOppController {
        
        @AuraEnabled
        public static List<Opportunity> retrieveOpportunities(String recordId){
            List<Opportunity> oppList = [SELECT Name, Id, Account.Name, Amount, StageName, CloseDate  FROM Opportunity WHERE  Competitor_1__r.Id = :recordId OR Competitor_2__r.Id = :recordId ];
            return oppList;
        }  
    }

3. CREATE AN AURA COMPONENT

  1. In the command palette search for SFDX: Create Aura Component and select it.

    dcao15

  2. Enter the Aura Component name DisplayCompetitorAcountOpportunities and hit the enter button.

  3. When you create the Aura component in VSCode an Aura bundle will be created. You can see it on the left pane.

    dcao16

  4. Open the file that ends with .cmp which is the component of the bundle and paste the following code.

    DisplayCompetitorAcountOpportunities.cmp

    <aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId"
        controller="CompetitorAccountOppController" access="global">
        <aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
        <aura:attribute name="cbaseURL" type="String"/>
        <aura:attribute name="recordId" type="String" />
        <aura:attribute name="CompetitorAccountOpportunities" type="Opportunity[]"/>
        <lightning:card variant="Narrow" class="slds-box slds-box_x-small slds-theme_shade" title="Opportunities" iconName="standard:opportunity"/> 
        <table class="slds-table slds-table_cell-buffer slds-table_bordered" aria-labelledby="element-with-table-label other-element-with-table-label">
                <thead>
                    <tr class="slds-line-height_reset">
                        <th class="" scope="col">
                            <div class="slds-truncate" title="Opportunity Name">Opportunity Name</div>
                            </th>
                        <th class="" scope="col">
                            <div class="slds-truncate" title="Account Name">Account Name</div>
                        </th>
                        <th class="" scope="col">
                            <div class="slds-truncate" title="Amount">Amount</div>
                        </th>
                        <th class="" scope="col">
                            <div class="slds-truncate" title="Stage">Stage</div>
                        </th>
                        <th class="" scope="col">
                            <div class="slds-truncate" title="Close Date">Close Date</div>
                        </th>
                    </tr>
                </thead>
                <tbody>
                    <aura:iteration var="opportunity" items="{!v.CompetitorAccountOpportunities}" indexVar="indx">
                        <tr class="slds-hint-parent">
                            <th data-label="Opportunity Name" scope="row">
                                <div class="slds-truncate" title="{!opportunity.Name}">
                                    <a href ="{!cbaseURL+'/lightning/r/Opportunity/'+opportunity.Id+'/view'}">{!opportunity.Name}</a>
                                </div>
                            </th>
                            <td data-label="Account Name">
                                <div class="slds-truncate" title="{!opportunity.Account.Name}">{!opportunity.Account.Name}</div>
                            </td>
                            <td data-label="Total Proposal Value($K)">
                                <div class="slds-truncate" title="{!opportunity.Amount}"><lightning:formattedNumber value="{!opportunity.Amount}" style="currency" currencyCode="USD"/></div>
                            </td>
                            <td data-label="Stage">
                                <div class="slds-truncate" title="{!opportunity.StageName}">{!opportunity.StageName}</div>
                            </td>
                            <td data-label="Close Date">
                                <div class="slds-truncate" title="{!opportunity.CloseDate}"><lightning:formattedDateTime value="{!opportunity.CloseDate}" month="numeric" year="numeric" day="numeric" /></div>
                            </td>
                        </tr>
                    </aura:iteration>
                </tbody>
            </table>
    </aura:component>
  5. Use the following code in Controller.js which is the Javascript file.

    DisplayCompetitorAcountOpportunitiesController.js

    ({
        doInit : function(component, event, helper) {
            var urlString = window.location.href;
            var baseURL = urlString.substring(0, urlString.indexOf(".com")+4);
            component.set("v.cbaseURL", baseURL);
            var action = component.get("c.retrieveOpportunities");
            action.setParams({"recordId": component.get("v.recordId")});
            action.setCallback( this, function(response) {
               var state = response.getState();
               if (state === "SUCCESS") {
                   component.set("v.CompetitorAccountOpportunities", response.getReturnValue());
                   console.log(response.getReturnValue());
               }
           });
           $A.enqueueAction(action);
        }
    })
  6. Select the file ending with .css and use the following code for the styling of the component.

    DisplayCompetitorAcountOpportunities.css

    .THIS .slds-media {
        padding-top: 0.5rem;
        padding-left: 1rem;
        display: flex;
        align-items: flex-start;  
    }

4. CONNECT TO THE ORG AND DEPLOY CONTROLLER AND COMPONENT

  1. Open command palette and search for SFDX: Authorize an Org and select it.

    dcao17

  2. Choose your Org type and if it is custom, paste your orgs login url in the next step. On hitting enter you will be taken to the Salesforce login page in a browser. Enter the credentials and login.

  3. Head back to VSCode and you will see the notification SFDX: Authorize an Org successfully ran.

    dcao18

  4. Now right click on the Apex controller file and click SFDX: Deploy Source to Org, You should see the notification SFDX: Deploy source to Org successfully ran shortly.

    dcao19

  5. Right click on the entire Aura component folder and deploy it to Org, You should see the success notification shortly.

    dcao20

    dcao21

5. PLACE COMPONENT ON THE PAGE

Follow the last step in Use Developer Console section to place the component on the page and set the visibility accordingly.

NOTE

In order to deploy this code into production an Unit Test class should be written with enough code coverage for the Apex Controller.

Before inserting an object into the database in the test class, make sure to provide values to the required fields.

The required fields may vary with respect to each org depending on the requirement.

Here is the test class for the Apex controller

CompetitorAccountOppControllerTest

@IsTest
public class CompetitorAccountOppControllerTest {
    static String compAccountId;
    static List<Opportunity> oppList = new List<Opportunity>();
   
    static void setupMethod() {
        Account acc = new Account();
        acc.Name ='TestAccount';
        insert acc;
       
        Id Competitor_RecordTypeId = Schema.SObjectType.Account.getRecordTypeInfosByName().get('Competitor').getRecordTypeId();
        Account accCompt = new Account();
        accCompt.Name = 'TestCompAccount';
        accCompt.RecordTypeId = Competitor_RecordTypeId;
        insert accCompt;
       
        Account accCompt1 = new Account();
        accCompt1.Name = 'TestCompAccount1';
        accCompt1.RecordTypeId = Competitor_RecordTypeId;
        insert accCompt1;
       
        compAccountId = accCompt1.Id;
        Opportunity opt = new Opportunity();
        opt.Name = 'Testopt';
        opt.CloseDate = System.today();
        opt.StageName = 'Negotiation/Review';
        opt.Quantity__c = 5;
        opt.AccountId = acc.Id;
        opt.Competitor_1__c  = accCompt.id;
        opt.Competitor_2__c = accCompt1.id;
        oppList.add(opt);
    }
 
    @isTest static void whenNoOpportunitiesFound() {
        setupMethod();
        Test.startTest();
        List<Opportunity> compOpportunities = CompetitorAccountOppController.retrieveOpportunities(compAccountId);
        Test.stopTest();
        System.assertEquals(0, compOpportunities.size());
    }
   
    @isTest static void whenOpportunitiesFound() {
        setupMethod();
        insert oppList;
        Test.startTest();
        List<Opportunity> compOpportunities =  CompetitorAccountOppController.retrieveOpportunities(compAccountId);
        Test.stopTest();
        System.assertEquals(1, compOpportunities.size());
    }
}

WRAPPING IT UP

In this blog we have explained how to create an Aura component to display the list of related opportunities for the Competitor Account using the Developer console and also create and deploy it to the Org using VSCode.

Leave a Comment

Your email address will not be published

© 2024 Digital Biz Tech