0

I have created a custom field(lookup field to opportunity) on Content version object that would denote the opportunity id that file is connected to. The custom field is Opportunity__c. Here is the apex trigger I worked on, but it gives me null in the custom field.

Trigger on Contentversion:

trigger populateOpportunityID on ContentVersion (after insert) {

 Set<Id> contentDocumentIdSet = new Set<Id>();

 for(ContentVersion cv:trigger.new)
{
    if(cv.ContentDocumentId != null)
    {
        contentDocumentIdSet.add(cv.ContentDocumentId);
    }
}

ContentDocumentLink cdl = [SELECT ContentDocumentId, LinkedEntityId FROM ContentDocumentLink WHERE ContentDocumentId IN:contentDocumentIdSet Limit 1];

List<Opportunity> oppList = [SELECT Id, name FROM Opportunity where Id =:cdl.LinkedEntityId];   

List<ContentVersion> cvList = [SELECT Id, Opportunity__c, ContentDocumentId FROM ContentVersion where Id IN: Trigger.newMap.keySet()];

for(ContentVersion cv:cvList)
{
    if(oppList.size() > 0)
    {
        for(Opportunity a : oppList){
            cv.Opportunity__c = a.Id; 
        }
    }
    else{
        cv.Opportunity__c = null;
    }           
}
update cvList;
}

Trigger on ContentDocumentLink:

trigger OpportunityId on ContentDocumentLink (after insert) {


Set<Id> contentDocIds = new Set<Id>();

for(ContentDocumentLink temp:trigger.new)

{

    if(temp.LinkedEntity.Type=='Opportunity')

    {

       contentDocIds.add(temp.ContentDocumentId); 

    }

}

 List<sObject> cvList = [select id, Opportunity__c, Checksum, ContentBodyId, 
 ContentDocumentId, ContentLocation, ContentModifiedById,
 ContentModifiedDate, ContentSize, ContentUrl, Description, 
 ExternalDataSourceId, ExternalDocumentInfo1,
 ExternalDocumentInfo2, FeaturedContentBoost, FeaturedContentDate, 
 FileExtension, FileType, FirstPublishLocationId, IsAssetEnabled, 
 IsLatest,IsMajorVersion, NegativeRatingCount,  Origin, 
 OwnerId, PathOnClient, PositiveRatingCount, PublishStatus, RatingCount, 
 ReasonForChange, SharingOption,SharingPrivacy,
 TagCsv, TextPreview, Title, VersionNumber, VersionData, LinkedEntityId__c 
 FROM ContentVersion WHERE ContentDocumentId IN :contentDocIds AND IsLatest = 
 true]; 


  }
0

2 Answers 2

0

Your trigger should look something like this ....

Map<Id,Id> oppoIdsByContentDocumentId = new Map<Id,Id>();  // the xref
ContentVersion[] cvs = new List<ContentVersion>();         // for updating CV

for (ContentDocumentLink cdl: Trigger.new) {               // build xref for CDLs of Oppos only
  if (cdl.LinkedEntityId.getSobjectType() == Opportunity.SObjectType) {
    oppoIdsByContentDocumentId.put(cdl.ContentDocumentId,cdl.LinkedEntityId);
  }
}

if (!oppoIdsByContentDocumentId.keySet().isEmpty()) {
  for (ContentVersion cv : // Find the latest ContentVersion for the xref'd ContentDocumentIds
    [SELECT Id, ContentDocuemntId FROM ContentVersion WHERE ContentDocumentId IN :oppoIdsByContentDocumentId.keySet() 
                                       AND IsLatest = TRUE] ) {
    cvs.add(new ContentVersion (
       Id = cv.Id, Opportunity__c = oppoIdsByContentDocumentId.get(cv.ContentDocumentId));

  }
}

update cvs; // if empty, no DML is burned so no need to test for empty
0
2

When a ContentVersion is first inserted to create a new file, it has no ContentDocument or ContentDocumentLink associated with it. These are created later.

Hence this

if(cv.ContentDocumentId != null)
{
    contentDocumentIdSet.add(cv.ContentDocumentId);
}

will never execute on creation of a new file (only upon uploading a new version of an existing file), and these queries

ContentDocumentLink cdl = [SELECT ContentDocumentId, LinkedEntityId FROM ContentDocumentLink WHERE ContentDocumentId IN:contentDocumentIdSet Limit 1];
List<Opportunity> oppList = [SELECT Id, name FROM Opportunity where Id =:cdl.LinkedEntityId];   

will always be empty in that circumstance.

This code also has several key limitations:

  • It only processes one ContentDocumentLink per ContentDocument; sharing files to multiple entities, such as users or files, is common.
  • It in fact only processes one ContentDocumentLink per trigger invocation; i.e., it is not bulkified.
  • It does not react to new sharing events, i.e., adding a ContentDocumentLink to an existing ContentDocument, which would require another trigger.
  • It stores only one Opportunity Id per ContentVersion, regardless of to what (and to how many whats) the version and document are shared.

I believe you'll need at least two triggers (one on ContentVersion and one on ContentDocumentLink) to achieve your objective, but I remain unconvinced of the correctness of this approach. I'd strongly recommend you review the design of this large, complex integration system you're building with an experienced Salesforce architect.

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .