본문 바로가기

Salesforce/미니과제

<미니과제_완료> 리드소스별 계약금액&계약수

조건절에 스테이지명과 리드소스에 대한 정보를 넣고 돌렸을 때 왜 결과가 안 나오나 싶었다. 이렇게 저렇게 조합하여 계속 조회해보니 위와 같이 'Closed Won' 에 해당하는 Lead Source 중 내가 원하는 조건값이 없다는 것을 알게 되었다.

StageName = 'Closed Won' AND LeadSource = 'Inbound'

StageName = 'Closed Won' AND LeadSource = 'Outbound Call'

StageName = 'Closed Won' AND LeadSource = 'Outbound Mail'

StageName = 'Closed Won' AND LeadSource = 'Paid Lead'


해당 데이터의 Lead Source를 직접 변경해야 겠다

그렇게 하려고 보니

선택할 수 있는 리드소스가 많은 것을 보고 이것을 편집할 수 있는지 Set Up의 오브젝트 매니저로 들어가보았다

Opportunity의 Lead Source 필드를 보니 활설화된 밸류가 아래와 같이 존재하였다.

다른 밸류들을 그래프에서 사용하는 형태로 옮겨줘야 겠다

 

리드소스를 기준으로 sort 해보았다. 어떤 데이터를 수정해야 하는지 알기 위해서이다. 

두 번째로 많은 비중을 차지하는 리드소스는 현재 비활성화 되어 있어서 이를 활성화해주고 해당 데이터를 내가 필요한 리드소스에 꽂으려고 한다

 

추출해오려고 하는 밸류를 직접 타이핑하여 입력 후 변경하길 원하는 밸류를 선택한 뒤 replace 누르면 리드소스의 값이 변경된다

리드소스 값이 'External Referral '-> 'Paid Lead' 변경된 것을 확인할 수 있다

 'External Referral ' 해당 리스소스는 Deactivate 를 클릭하여 준다

 

이와 동일한 방식으로 아래 리드소스 내용도 수정하였다

  • 'Partner' -> 'Inbound'
  • 'Trade Show' -> 'Outbound Call'

 


데이터를 수정하여 주고나서 위 쿼리를 실행했을 때 결과가 잘 집계되는 것을 확인할 수 있다

 

SELECT AVG(Amount) FROM Opportunity WHERE StageName = 'Closed Won'AND LeadSource ='Outbound Mail' 

SELECT AVG(Amount) FROM Opportunity WHERE StageName = 'Closed Won'AND LeadSource ='Outbound Call' 

SELECT AVG(Amount) FROM Opportunity WHERE StageName = 'Closed Won'AND LeadSource ='Inbound' 

SELECT AVG(Amount) FROM Opportunity WHERE StageName = 'Closed Won'AND LeadSource ='Paid Lead'


    /* KPI_AvgContractValue_byLeadSource */
    @AuraEnabled(cacheable = false) 
    public static List<AggregateResult> avgAmtbyInbound(){
        return [SELECT AVG(Amount) FROM Opportunity WHERE StageName = 'Closed Won'AND LeadSource ='Inbound' WITH SECURITY_ENFORCED];
    }

    @AuraEnabled(cacheable = false) 
    public static List<AggregateResult> avgAmtbyOutCall(){
        return [SELECT AVG(Amount) FROM Opportunity WHERE StageName = 'Closed Won'AND LeadSource ='Outbound Call' WITH SECURITY_ENFORCED];
    }

    @AuraEnabled(cacheable = false) 
    public static List<AggregateResult> avgAmtbyOutMail(){
        return [SELECT AVG(Amount) FROM Opportunity WHERE StageName = 'Closed Won'AND LeadSource ='Outbound Mail' WITH SECURITY_ENFORCED];
    }

    @AuraEnabled(cacheable = false) 
    public static List<AggregateResult> avgAmtbyPaidLead(){
        return [SELECT AVG(Amount) FROM Opportunity WHERE StageName = 'Closed Won'AND LeadSource ='Paid Lead' WITH SECURITY_ENFORCED];
    }

LWC 작업과 화면출력 테스팅

import { LightningElement } from 'lwc';
import avgAmtbyInbound from "@salesforce/apex/KpiOpptyController.avgAmtbyInbound";
import avgAmtbyOutCall from "@salesforce/apex/KpiOpptyController.avgAmtbyOutCall";
import avgAmtbyOutMail from "@salesforce/apex/KpiOpptyController.avgAmtbyOutMail";
import avgAmtbyPaidLead from "@salesforce/apex/KpiOpptyController.avgAmtbyPaidLead";

export default class KpiAvgContractValue extends LightningElement {
    avg_AmtbyInbound;
    avg_AmtbyOutCall;
    avg_AmtbyOutMail;
    avg_AmtbyPaidLead;

    connectedCallback() {
   
      avgAmtbyInbound({
      }).then(data => {
          if(data) {
            console.log('data ====>>' + JSON.stringify(data)); // 데이터 로드 확인용 로그
            this.avg_AmtbyInbound = data[0].avgByInbound;
          }
      }).catch(error => {
          if(error && error.body && error.body.message) {
              this.showToast('Error', 'error', error.body.message);
          }
      });

      avgAmtbyOutCall({
      }).then(data => {
          if(data) {
            console.log('data ====>>' + JSON.stringify(data)); // 데이터 로드 확인용 로그
            this.avg_AmtbyOutCall = data[0].avgByOutCall;
          }
      }).catch(error => {
          if(error && error.body && error.body.message) {
              this.showToast('Error', 'error', error.body.message);
          }
      });

      avgAmtbyOutMail({
    }).then(data => {
        if(data) {
          console.log('data ====>>' + JSON.stringify(data)); // 데이터 로드 확인용 로그
          this.avg_AmtbyOutMail = data[0].avgByOutMail;
        }
    }).catch(error => {
        if(error && error.body && error.body.message) {
            this.showToast('Error', 'error', error.body.message);
        }
    });

    avgAmtbyPaidLead({
    }).then(data => {
        if(data) {
          console.log('data ====>>' + JSON.stringify(data)); // 데이터 로드 확인용 로그
          this.avg_AmtbyPaidLead = data[0].avgByPaidLead;
        }
    }).catch(error => {
        if(error && error.body && error.body.message) {
            this.showToast('Error', 'error', error.body.message);
        }
    });
   
    }
}

 


개발자도구의 Console 에서는 출력되는 것이 보이지만 화면에는 출력되지 않았다. 이전에도 같은 현상을 경험한 적이 있었다. 

 

 

 this.avg_AmtbyInbound = data[0].avgByInbound ;

위 코드를 아래와 같이 수정해주었다

this.avg_AmtbyInbound = data[0].expr0;

코드를 수정하니 화면에 출력되는 것을 확인할 수 있다.

다른 내용도 동일하게 수정하니 아래와 같이 잘 출력되는 것을 확인할 수 있다

 

 

그런데 시간이 좀 흐르면 이렇게 출력했을 때 화면에 데이터가 보이지 않는다. 그리고 개발자도구에서는 아래와 같이 출력된다. 그러면 처음에 입력했던 코드로 다시 수정해주어야 한다.


평균금액에 대한 데이터 출력을 완료하였다. 그럼 이제 계약건수의 집계데이터를 출력할 차례이다.

 

 

Developer Console 에서 테스트해보니 생각보다 간단하게 구현할 수 있을 것 같다

SELECT count(Id) FROM Opportunity WHERE StageName = 'Closed Won'AND LeadSource ='Outbound Mail' 

 

이 내용을 스테이지명만 바꾸면 된다

 


컨트롤러에서 추가한 내용

 //2.계약건수집계
    @AuraEnabled(cacheable = false)
    public static List<AggregateResult> NrOfContract_byInbound(){
        return [SELECT COUNT(Id)countByInbound FROM Opportunity WHERE StageName = 'Closed Won'AND LeadSource ='Inbound' WITH SECURITY_ENFORCED];
    }

    @AuraEnabled(cacheable = false)
    public static List<AggregateResult> NrOfContract_byOutCall(){
        return [SELECT COUNT(Id)countByOutCall FROM Opportunity WHERE StageName = 'Closed Won'AND LeadSource ='Outbound Call' WITH SECURITY_ENFORCED];
    }

    @AuraEnabled(cacheable = false)
    public static List<AggregateResult> NrOfContract_byOutMail(){
        return [SELECT COUNT(Id)countByOutMail FROM Opportunity WHERE StageName = 'Closed Won'AND LeadSource ='Outbound Mail' WITH SECURITY_ENFORCED];
    }

    @AuraEnabled(cacheable = false)
    public static List<AggregateResult> NrOfContract_byPaidLead(){
        return [SELECT COUNT(Id)countByPaidLead FROM Opportunity WHERE StageName = 'Closed Won'AND LeadSource ='Paid Lead' WITH SECURITY_ENFORCED];
    }

자바스크립트에 계약건수 구현코드 추가

//2.계약건수집계
        NrOfContract_byInbound({
        }).then(data => {
            if(data) {
              console.log('data ====>>' + JSON.stringify(data)); // 데이터 로드 확인용 로그
              this.count_ContractbyInbound = data[0].countByInbound;
            }
        }).catch(error => {
            if(error && error.body && error.body.message) {
                this.showToast('Error', 'error', error.body.message);
            }
        });
   
        NrOfContract_byOutCall({
        }).then(data => {
            if(data) {
              console.log('data ====>>' + JSON.stringify(data)); // 데이터 로드 확인용 로그
              this.count_ContractbyOutCall = data[0].countByOutCall;
            }
        }).catch(error => {
            if(error && error.body && error.body.message) {
                this.showToast('Error', 'error', error.body.message);
            }
        });
   
        NrOfContract_byOutMail({
        }).then(data => {
          if(data) {
            console.log('data ====>>' + JSON.stringify(data)); // 데이터 로드 확인용 로그
            this.count_ContractbyOutMail = data[0].countByOutMail;
          }
        }).catch(error => {
          if(error && error.body && error.body.message) {
              this.showToast('Error', 'error', error.body.message);
          }
        });
   
        NrOfContract_byPaidLead({
        }).then(data => {
          if(data) {
            console.log('data ====>>' + JSON.stringify(data)); // 데이터 로드 확인용 로그
            this.count_ContractbyPaidLead = data[0].countByPaidLead;
          }
        }).catch(error => {
          if(error && error.body && error.body.message) {
              this.showToast('Error', 'error', error.body.message);
          }
        });

 

html

<lightning-card>
            Nr. of Contracts
            <p>Inbound :  {count_ContractbyInbound} </p>
            <p>Outbound Call :  {count_ContractbyOutCall}</p>    
            <p>Outbound Mail :  {count_ContractbyOutMail}</p>  
            <p>Paid Lead :  {count_ContractbyPaidLead}</p>
        </lightning-card>


<template>
     <lightning-card title="AVG CONTRACT VALUE by Lead Source">
        <lightning-card>
            Avg Contract Value
            <p>Inbound :  {avg_AmtbyInbound} </p>
            <p>Outbound Call :  {avg_AmtbyOutCall}</p>    
            <p>Outbound Mail :  {avg_AmtbyOutMail}</p>  
            <p>Paid Lead :  {avg_AmtbyPaidLead}</p>
        </lightning-card>

        <lightning-card>
            Nr. of Contracts
            <p>Inbound :  {count_ContractbyInbound} </p>
            <p>Outbound Call :  {count_ContractbyOutCall}</p>    
            <p>Outbound Mail :  {count_ContractbyOutMail}</p>  
            <p>Paid Lead :  {count_ContractbyPaidLead}</p>
        </lightning-card>
    </lightning-card>
 
</template>

import { LightningElement } from 'lwc';
import avgAmtbyInbound from "@salesforce/apex/KpiOpptyController.avgAmtbyInbound";
import avgAmtbyOutCall from "@salesforce/apex/KpiOpptyController.avgAmtbyOutCall";
import avgAmtbyOutMail from "@salesforce/apex/KpiOpptyController.avgAmtbyOutMail";
import avgAmtbyPaidLead from "@salesforce/apex/KpiOpptyController.avgAmtbyPaidLead";
import countOfContractbyInbound from "@salesforce/apex/KpiOpptyController.countOfContractbyInbound";
import countOfContractbyOutCall from "@salesforce/apex/KpiOpptyController.countOfContractbyOutCall";
import countOfContractbyOutMail from "@salesforce/apex/KpiOpptyController.countOfContractbyOutMail";
import countOfContractbyPaidLead from "@salesforce/apex/KpiOpptyController.countOfContractbyPaidLead";

export default class KpiAvgContractValue extends LightningElement {
    avg_AmtbyInbound;
    avg_AmtbyOutCall;
    avg_AmtbyOutMail;
    avg_AmtbyPaidLead;
    count_ContractbyInbound;
    count_ContractbyOutCall;
    count_ContractbyOutMail;
    count_ContractbyPaidLead;

    connectedCallback() {
   
        avgAmtbyInbound({
        }).then(data => {
            if(data) {
              console.log('data ====>>' + JSON.stringify(data)); // 데이터 로드 확인용 로그
              this.avg_AmtbyInbound = data[0].avgByInbound;
              //this.avg_AmtbyInbound = data[0].expr0; //화면에 출력되지 않고 개발자도구에만 출력될 때 테스팅코드
            }
        }).catch(error => {
            if(error && error.body && error.body.message) {
                this.showToast('Error', 'error', error.body.message);
            }
        });

        avgAmtbyOutCall({
        }).then(data => {
            if(data) {
              console.log('data ====>>' + JSON.stringify(data)); // 데이터 로드 확인용 로그
              this.avg_AmtbyOutCall = data[0].avgByOutCall;
            }
        }).catch(error => {
            if(error && error.body && error.body.message) {
                this.showToast('Error', 'error', error.body.message);
            }
        });

        avgAmtbyOutMail({
        }).then(data => {
            if(data) {
              console.log('data ====>>' + JSON.stringify(data)); // 데이터 로드 확인용 로그
              this.avg_AmtbyOutMail = data[0].avgByOutMail;
 
            }
        }).catch(error => {
            if(error && error.body && error.body.message) {
                this.showToast('Error', 'error', error.body.message);
            }
        });

        avgAmtbyPaidLead({
        }).then(data => {
            if(data) {
              console.log('data ====>>' + JSON.stringify(data)); // 데이터 로드 확인용 로그
              this.avg_AmtbyPaidLead = data[0].avgByPaidLead;
            }
        }).catch(error => {
            if(error && error.body && error.body.message) {
                this.showToast('Error', 'error', error.body.message);
            }
        });

  //2.계약건수집계
        countOfContractbyInbound({
        }).then(data => {
            if(data) {
              console.log('data ====>>' + JSON.stringify(data)); // 데이터 로드 확인용 로그
              this.count_ContractbyInbound = data[0].countByInbound;
            }
        }).catch(error => {
            if(error && error.body && error.body.message) {
                this.showToast('Error', 'error', error.body.message);
            }
        });

        countOfContractbyOutCall({
        }).then(data => {
            if(data) {
              console.log('data ====>>' + JSON.stringify(data)); // 데이터 로드 확인용 로그
              this.count_ContractbyOutCall = data[0].countByOutCall;
            }
        }).catch(error => {
            if(error && error.body && error.body.message) {
                this.showToast('Error', 'error', error.body.message);
            }
        });

        countOfContractbyOutMail({
        }).then(data => {
          if(data) {
            console.log('data ====>>' + JSON.stringify(data)); // 데이터 로드 확인용 로그
            this.count_ContractbyOutMail = data[0].countByOutMail;
          }
        }).catch(error => {
          if(error && error.body && error.body.message) {
              this.showToast('Error', 'error', error.body.message);
          }
        });

        countOfContractbyPaidLead({
        }).then(data => {
          if(data) {
            console.log('data ====>>' + JSON.stringify(data)); // 데이터 로드 확인용 로그
            this.count_ContractbyPaidLead = data[0].countByPaidLead;
          }
        }).catch(error => {
          if(error && error.body && error.body.message) {
              this.showToast('Error', 'error', error.body.message);
          }
        });
   
   
    }
}