function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
NehashriNehashri 

Trigger on files to prevent deletion

Hi,
I have a trigger on Attachment which prevents the user from deletingior updating the attachment if the parent custom Object Inventory status is marked as 'Final'. we are switching to lightning so I cant use Attachment anymore since they cant add attachments from the page. how can i write the same logic using Content file, how do i get the parent id?
Here is the logic of Attachment trigger:

Schema.DescribeSObjectResult inv = Inventory_Exception__c.sObjectType.getDescribe();
String invKeyPrefix = inv.getKeyPrefix();
if(trigger.isUpdate){
        for(Attachment a :trigger.new){
            if(invKeyPrefix == String.valueOf(a.parentId).left(3) &&
               [select status__c from Inventory_Exception__c where id = :a.parentId].status__c =='Final'){
                   a.adderror('This attachment could not be modified because this exception record is marked as Final.');
               }
        }


    if(trigger.isDelete){
        for(Attachment a :trigger.old){
            if(invKeyPrefix == String.valueOf(a.parentId).left(3) &&
               [select status__c from Inventory_Exception__c where id = :a.parentId].status__c =='Final'){
                   a.adderror('This attachment could not be deleted because this exception record is marked as Final.');
               }
        }
Best Answer chosen by Nehashri
NehashriNehashri
 I wanted to post a solution just in case someone visits this thread in future. For delete, according to an unpublished salesforce article, The trigger needs to be on ContentDocument instead of ContentDocumentLink object. For my particular scenario, I needed to add an error message if a user tries to delete a file attached to an inventory record which is in Final stage.
 
trigger ContentDocTrigger on ContentDocument (before delete) {
    
   
    
    //get prefix of Inventory exception record
    Schema.DescribeSObjectResult inv = Inventory_Exception__c.sObjectType.getDescribe();
    String invKeyPrefix = inv.getKeyPrefix();
    
    List<Id> contentDocId = new List<Id>();
    Map<Id, Id> contDocLinkedMap = new Map<Id, Id>();
    if(trigger.IsDelete){
        for(ContentDocument con : Trigger.old){
            System.debug(Trigger.old);
            System.debug(con.Id);
            contentDocId.add(con.Id);
        }
        for(ContentDocumentLink cdl : [SELECT ContentDocumentId, LinkedEntityId FROM ContentDocumentLink WHERE ContentDocumentId IN : contentDocId]){
            contDocLinkedMap.put(cdl.ContentDocumentId, cdl.LinkedEntityId);
            System.debug('map ' +contDocLinkedMap);
            
            
        }
        
        for(ContentDocument cdoc : Trigger.Old){
            //contDocLinkedMap.get(cdoc.Id) will give the LinkedEntityId
            if(invKeyPrefix == String.valueOf(contDocLinkedMap.get(cdoc.Id)).left(3) &&
               [select status__c from Inventory_Exception__c where id = :contDocLinkedMap.get(cdoc.Id)].status__c =='Final'){
                   cdoc.adderror('This attachment could not be added because this exception record is marked as Final.');
               }
            
        }
        
        
        
        
    }


}

 

All Answers

NehashriNehashri
Update: Thjis trigger works on insert and update but not on delete.
trigger ContentDocLinkTrigger on ContentDocumentLink (before insert, before update, before delete ) {
    
    Schema.DescribeSObjectResult inv = Inventory_Exception__c.sObjectType.getDescribe();
    String invKeyPrefix = inv.getKeyPrefix();
    
    if(trigger.isInsert){
        for(ContentDocumentLink a :trigger.new){
            if(invKeyPrefix == String.valueOf(a.LinkedEntityId).left(3) &&
               [select status__c from Inventory_Exception__c where id = :a.LinkedEntityId].status__c =='Final'){
                   a.adderror('This attachment could not be added because this exception record is marked as Final.');
               }
        }
    }
    
    
    if(trigger.isUpdate){
        for(ContentDocumentLink a :trigger.new){
            if(invKeyPrefix == String.valueOf(a.LinkedEntityId).left(3) &&
               [select status__c from Inventory_Exception__c where id = :a.LinkedEntityId].status__c =='Final'){
                   a.adderror('This attachment could not be added because this exception record is marked as Final.');
               }
        }
    }
    
    if(trigger.isDelete){
        for(ContentDocumentLink a :trigger.old){
            if(invKeyPrefix == String.valueOf(a.LinkedEntityId).left(3) &&
               [select status__c from Inventory_Exception__c where id = :a.LinkedEntityId].status__c =='Final'){
                   a.adderror('This attachment could not be added because this exception record is marked as Final.');
               }
        }
    }


}
NehashriNehashri
 I wanted to post a solution just in case someone visits this thread in future. For delete, according to an unpublished salesforce article, The trigger needs to be on ContentDocument instead of ContentDocumentLink object. For my particular scenario, I needed to add an error message if a user tries to delete a file attached to an inventory record which is in Final stage.
 
trigger ContentDocTrigger on ContentDocument (before delete) {
    
   
    
    //get prefix of Inventory exception record
    Schema.DescribeSObjectResult inv = Inventory_Exception__c.sObjectType.getDescribe();
    String invKeyPrefix = inv.getKeyPrefix();
    
    List<Id> contentDocId = new List<Id>();
    Map<Id, Id> contDocLinkedMap = new Map<Id, Id>();
    if(trigger.IsDelete){
        for(ContentDocument con : Trigger.old){
            System.debug(Trigger.old);
            System.debug(con.Id);
            contentDocId.add(con.Id);
        }
        for(ContentDocumentLink cdl : [SELECT ContentDocumentId, LinkedEntityId FROM ContentDocumentLink WHERE ContentDocumentId IN : contentDocId]){
            contDocLinkedMap.put(cdl.ContentDocumentId, cdl.LinkedEntityId);
            System.debug('map ' +contDocLinkedMap);
            
            
        }
        
        for(ContentDocument cdoc : Trigger.Old){
            //contDocLinkedMap.get(cdoc.Id) will give the LinkedEntityId
            if(invKeyPrefix == String.valueOf(contDocLinkedMap.get(cdoc.Id)).left(3) &&
               [select status__c from Inventory_Exception__c where id = :contDocLinkedMap.get(cdoc.Id)].status__c =='Final'){
                   cdoc.adderror('This attachment could not be added because this exception record is marked as Final.');
               }
            
        }
        
        
        
        
    }


}

 
This was selected as the best answer
Priyanshu guptaPriyanshu gupta
Trigger to prevent Delete Content document Link  from Account Object:-

Trigger:-

trigger ContentDocumentLinkTrigger on ContentDocumentLink (before delete,before insert) {
    
    if(Trigger.isBefore ){ 
        
        if(Trigger.isdelete ){ 
            ContentDocumentLinkTriggerFunction.restrictDeleteFiles(Trigger.oldMap);
        }
    }
}

Trigger Handler:-

public static void restrictDeleteFiles(Map<id,ContentDocumentLink> mapContentDocument) {

    Set<Id> oldIdContentDoc = new Set<Id>();
    oldIdContentDoc = mapContentDocument.keySet();
    List<Id> linkIds = new List<Id>();    
        //get doc links by trigger records on ContentDocment.
        List<ContentDocumentLink> doclinks = [SELECT LinkedEntityId, ContentDocumentId FROM ContentDocumentLink 
                                              WHERE Id IN: oldIdContentDoc ];
        for(ContentDocumentLink doclink : doclinks){
            linkIds.add(doclink.LinkedEntityId); 
        }
        //get Candidate Records which are linked to ContentDocumentLink via LinkedEntityId with Age > 18.
        Map<Id, Account> candidates = new  Map<Id, Account>([SELECT Name FROM Account  
                                                                        WHERE Id IN :linkIds AND Rating='Hot']);
        //Collect ContentDocumentIds which link to Candidate > 18. 
        for(ContentDocumentLink doclink : doclinks){
            if(candidates.get(doclink.LinkedEntityId) != null){
                //idDoc.add(doclink.ContentDocumentId);
                
                //doclink.LinkedEntityId.addError('Cannot delete a Note from an Escalated Issue that has been closed already'); 
                
                SObject  actualRecord = mapContentDocument.get(doclink.Id);
                actualRecord.addError('Cannot delete a Note from an Escalated Issue that has been closed already'); 
            }
        }
    }

Hope this will also help. :)