- 6. März 2017

Lightning Experience: Anhänge bei der Lead Konvertierung

Heute möchte ich Ihnen einen Einblick in eine ganz spezielle Lightning Herausforderung geben. Mit Lightning Experience ist es derzeit im Standard nicht möglich, Anhänge bei der Lead Konvertierung zu übertragen, wie Sie hier sehen können.

Hintergrund

Einer meiner Kunden benutzt Leads, um sogenannte Prospects im Detail zu qualifizieren. Bei der Leadkonvertierung benötigt der Kunde alle gesammelten Informationen des Leads auf dem Account, um damit verschiedene Opportunities abwickeln zu können.

Überlegungen

Da es keinen bekannten Weg gibt, diese Anforderung mit Salesforce Standardtools umzusetzen, wird ein Apex Trigger benötigt.

Dafür ist es zunächst wichtig zu wissen, welches Objekt die Anhang-zu-Objekt Beziehung enthält. In Lightning Experience werden diese im Objekt ContentDocumentLink abgebildet. Die wichtigsten Felder sind dabei ContentDocumentId und LinkedEntityId. ContentDocumentId repräsentiert dabei das Dokument bzw. den Anhang und LinkedEntityId steht für das Objekt, also bspw. den Lead, an dem der Anhang hängt.

Die nächste Überlegung beschäftigt sich mit der Frage nach dem Trigger-Typ (before, after) und der Art des Triggers (insert, update, delete, …). Die Leadkonvertierung ist eine Update-Operation. Dabei bekommt der Lead den Status isConverted = true und erhält eine ConvertedAccountId. Um ein Dokument an den Account anhängen zu können, muss dieser zum Zeitpunkt, wenn der Trigger ausgeführt wird, bereits angelegt sein. Sonst ist es nicht möglich, auf die Daten zugreifen zu können. Dies ist im ‘after’ Kontext der Fall, wenn der Account bereits auf der Datenbank gespeichert, aber noch nicht eingecheckt wurde (siehe dazu Triggers and Order of Execution). Es gilt also einen after update Trigger zu erstellen.

Umsetzung

Nach den Vorüberlegungen ist es nun möglich, eine Lösung in der Salesforce Entwicklungsumgebung zu erstellen.

Im Folgenden finden Sie Beispiel-Code für die Umsetzung. Dieser Code ist in einem best practice Trigger Pattern umgesetzt. Dieses benutzt eine Klasse namens LeadAfterUpdateTriggerHandler, um vorher alle Leadobjekte vom after update Trigger zu sammeln und gemeinsam zu verarbeiten. Dafür stellt die Klasse zwei Maps (mapOldLeads und mapNewLeads) zur Verfügung. Diese beinhalten die Zustände der Leads vor und nach der Konvertierung.

    1. Das erste Beispiel zeigt eine Helper Methode, die alle konvertierten Leads aus dem Trigger filtert und als Set der Methode transferLeadAttachmentsToAccount übergibt. Dadurch lassen sich leicht andere Methoden hinzufügen, die weitere Zusatzaufgaben während der Lead-Konvertierung übernehmen könnten.
public static void advancedLeadConversion(Map<Id, Lead> mapOldLeads, Map<Id, Lead> mapNewLeads) {
    Set<Id> setLeadIds = new Set<Id>();
    for(Id newLeadId : mapNewLeads.keySet()){
        if(mapOldLeads.get(newLeadId).isConverted == false && mapNewLeads.get(newLeadId).isConverted == true){
            setLeadIds.add(newLeadId);
        }
    }
    if(setLeadIds.isEmpty())
        return;
    transferLeadAttachmentsToAccount(setLeadIds, mapNewLeads);
}

 

    1. Das zweite Beispiel zeigt das Vorgehen, um die Anhänge vom Lead zum Account zu bekommen. Das ContentDocumentLink Objekt wird genutzt, um alle Anhänge pro Lead gesammelt an den Account zu hängen. Wichtig hierbei ist, dass bestehende Einträge in ContentDocumentLink gelöscht werden, da keine doppelten ContentDokumentId‘s vorkommen dürfen. Es ist also nicht möglich, dasselbe Dokument gleichzeig an zwei Objekte zu hängen.
public static void transferLeadAttachmentsToAccount(Set<Id> setLeadIds, Map<Id, Lead> mapNewLeads) {
    Map<Id,List> mapOfAttsPerLeadIdToInsert = new Map<Id,List>();
    List<ContentDocumentLink> listOfAttachmentsToDelete = [select Id, ContentDocumentId, LinkedEntityId, ShareType from ContentDocumentLink where LinkedEntityId in :setLeadIds];
    for(ContentDocumentLink cdl : listOfAttachmentsToDelete){
        ContentDocumentLink newCdl = new ContentDocumentLink(ContentDocumentId = cdl.ContentDocumentId, LinkedEntityId = mapNewLeads.get(cdl.LinkedEntityId).ConvertedAccountId, ShareType = cdl.ShareType);
        if(mapOfAttsPerLeadIdToInsert.containsKey(cdl.LinkedEntityId)){
            mapOfAttsPerLeadIdToInsert.get(cdl.LinkedEntityId).add(newCdl);
        }else{
            mapOfAttsPerLeadIdToInsert.put(cdl.LinkedEntityId, new List<ContentDocumentLink>{newCdl});
        }
    }
    List<ContentDocumentLink> listOfAttachmentsToInsert = new List<ContentDocumentLink>();
    for(List listOfAttachments : mapOfAttsPerLeadIdToInsert.values()){
        listOfAttachmentsToInsert.addAll(listOfAttachments);
    }
    delete listOfAttachmentsToDelete;
    insert listOfAttachmentsToInsert;
}

Ich hoffe ich konnte Ihnen mit diesem Lösungsvorschlag helfen und wünsche Ihnen viel Erfolg der Umsetzung.

Sie interessieren sich für Lightning Experience?
Salesforce Consultant Alexander Herrmann

Haben Sie Fragen oder Anregungen? Verfassen Sie einen Kommentar oder melden Sie sich per Mail bei info@mindsquare.de. Unser Team wird Ihnen schnellstmöglich antworten.

SHARE


Schreiben Sie einen Kommentar

Bitte füllen Sie alle mit * gekennzeichneten Felder aus. Ihre E-Mail Adresse wird nicht veröffentlicht.