Всем привет!
Сегодня хотелось бы поговорить с вами о дедупликации Оппортьюнитей. Вернее об отсутствии оной стандартной функциональности в Salesforce.
Что же нам делать, если есть задача реализовать логику, где по определенным полям оппортьюнити будут определяться как дубликаты? В этой статье рассмотрим один из способов решения данной задачи с помощью lightning component.
Для начала четко обрисуем задачу, которая перед нами стоит:
нужно реализовать функциональность, которая будет демонстрировать юзеру, что оппортьюнити, с которым он работает, имеет дубликаты;
задан список полей, по которому нужно определять, имеет ли данная оппортьюнити дубликаты.
Итак, приступим непосредственно к реализации.
Начнем с написания апекс-контроллер, главной целью которого будет сравнение текущей оппортьюнити со всеми другими оппортьюнитями по определенным полям (в нашем случае это Amount и LeadSource) и формирования списка дубликатов, который мы в будущем будем выводить на сам компонент. Пример контроллера:
global with sharing class OpportunityDeduplicationController {
@AuraEnabled
global static List <Opportunity> getDuplicatedOpporunities(String opportunityId) {
Opportunity currentOpportunity = getCurrentOpporunity(opportunityId);
List <Opportunity> duplicatedOpportunities = getDuplicatedOpporunitiesForCurrentOpportunity(currentOpportunity);
return duplicatedOpportunities;
}
@AuraEnabled
global static Opportunity getCurrentOpporunity(String opportunityId) {
Opportunity opp = [
SELECT Id, Name, LeadSource, Amount
FROM Opportunity
WHERE Id = :opportunityId
];
return opp;
}
private static List<Opportunity> getDuplicatedOpporunitiesForCurrentOpportunity(Opportunity opp) {
List<Opportunity> duplicatedOpps = [
SELECT Id, Name, LeadSource, Amount
FROM Opportunity
WHERE ((Id !=: opp.Id) AND
(((LeadSource =: opp.LeadSource) AND (LeadSource != null)) AND
(((Amount =: opp.Amount) AND (Amount != null)))))
];
return duplicatedOpps;
}
}
Далее приступим к написанию lightning компонента и js-контроллера. Этот компонент будет отображаться на странице, если список дубликатов не пустой. Также, добавим красный цвет текста для того, чтобы юзеру сразу бросалось в глаза, что он работает с оппортьюнити, которая имеет дубликаты. Для удобства юзера и для того, чтобы она не занимала много места на экране, секция по умолчанию будет свернута, ибо дубликатов может быть много и каждый раз скроллить — неудобно. Вот, собственно и все. Теперь взглянем на код компонента.
<aura:component controller="OpportunityDeduplicationController" implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction" access="global" >
<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>
<aura:attribute name="opportunityRecord" type="Opportunity" />
<aura:attribute name="duplicatedOpportunities" type="Opportunity[]" />
<aura:attribute name="url" type="String" />
<aura:if isTrue="{!not(empty(v.duplicatedOpportunities))}">
<div class="slds-card" style="background-color: white;">
<div style="font-size:18px; text-align:center; color:red; margin-top: 5px;">
Duplication warning
</div>
<div class="slds-section slds-is-close" aura:id="collapsibleSection" style="margin: 10px;">
<h3 class="slds-section__title">
<button aria-controls="deduplicationOpps" class="slds-button slds-section__title-action" style="margin-bottom: 10px;">
<span onclick="{!c.toggleSection}" data-auraId="collapsibleSection">
<lightning:icon iconName="utility:switch"
size="x-small"
class="slds-section__title-action-icon slds-button__icon_left"
alternativeText="button icon"
/>
</span>
<span class="slds-truncate" title="Duplicated Apps:">Duplicated Opportunities</span>
</button>
</h3>
<div class="slds-section__content" id="Opps" style="margin-left: 20px;">
<aura:iteration var="opportunity" items="{!v.duplicatedOpportunities}">
<div><a target="_blank" href="{!v.url +'/'+ opportunity.Id}">{!opportunity.Name}</a></div>
<br></br>
</aura:iteration>
</div>
</div>
</div>
</aura:if>
</aura:component>
В связке с компонентом работает и js-контроллер, который имеет два метода. Первый метод взаимодействует с апекс-контроллером и инициализирует список дубликатов значениями в зависимости от того, на каком оппортьюнити вы сейчас находитесь. Второй метод занимается сугубо сворачиванием/разворачиванием нашей секции. Код js-контроллера представлен ниже:
({
doInit : function(component, event, helper) {
component.set("v.url", window.location.origin);
let opportunityId = component.get("v.recordId");
let getOpportunityAction = component.get("c.getCurrentOpporunity");
getOpportunityAction.setParams({
"opportunityId": opportunityId
});
getOpportunityAction.setCallback(this, function(response) {
if (response.getState() === "SUCCESS"){
component.set('v.opportunityRecord', response.getReturnValue());
}
});
$A.enqueueAction(getOpportunityAction);
let getDuplicatedOppAction = component.get("c.getDuplicatedOpporunities");
getDuplicatedOppAction.setParams({
"opportunityId": opportunityId
});
getDuplicatedOppAction.setCallback(this, function(response) {
if (response.getState() === "SUCCESS"){
component.set('v.duplicatedOpportunities', response.getReturnValue());
}
});
$A.enqueueAction(getDuplicatedOppAction);
},
toggleSection : function(component, event, helper) {
var sectionAuraId = event.target.getAttribute("data-auraId");
var sectionDiv = component.find(sectionAuraId).getElement();
var sectionState = sectionDiv.getAttribute('class').search('slds-is-open');
if(sectionState == -1){
sectionDiv.setAttribute('class' , 'slds-section slds-is-open');
}else{
sectionDiv.setAttribute('class' , 'slds-section slds-is-close');
}
}
})
Закончив с написанием кода, остался один маленький штрих для завершения задания. А именно — вынести компонент на Lightning page в удобное место, где ваш юзер точно не упустит его из виду. По умолчанию конечный вид компонента будет такой -
А при нажатии на “Duplicated Opportunities”— компонент будет следующего вида:
Вот и все. Теперь юзер, работая с оппортьюнити, всегда будет знать, является ли данная оппортьюнити уникальной (по заранее заданным полям) или нет, что позволит предпринимать меры по дедупликации, если в таковых есть необходимость.
Спасибо за внимание, надеюсь эта статья была для вас полезной!