Tuesday, 19 December 2017

Salesforce: Restrict User from Deleting Files Once Record Status Changed

Salesforce: Restrict User from Deleting Files Once Record Status Changed

Business Requirement: 

There is a custom object in Salesforce having a status field. If the status of that record is marked as "Completed" user is not allowed to attach/upload new files with it, nor user can upload new version of file nor he can delete file.

Solution:

On the front end we see Files object ,its related list and tab and in my requirement data is saved from front end in files. From back-end  Salesforce use 3 diffrent object.
  1. Content Document
  2. Content Version
  3. Content Document Link

ContentDocument object is to retrieve, query, update, and delete the latest version of a document, but not a content pack, in a library or a file in Chatter.

Use the ContentVersion object to create, query, retrieve, search, edit, and update a specific version of a Salesforce CRM Content document or Chatter file.
So in order to achieve this functionality we have to write trigger on all three objects.

Content Document Trigger:

trigger ContentDocumentTrg on ContentDocument (before delete,before update) {
    
    Map<Id,String> MapOfStatus = new Map<Id,String>();
    Set<Id> SetOfCdl = new Set<Id>();
    Set<Id> SetOfCd = new Set<Id>();
    map<Id,Id> MapOfCdNCdl = new map<Id,Id>();
    if(Trigger.IsUpdate){
    for(ContentDocument cd :Trigger.new){
    SetOfCd.add(cd.Id);
    }
    }
    if(Trigger.Isdelete){
    for(ContentDocument cd :Trigger.old){
    SetOfCd.add(cd.Id);
    }
    }
   
    for(ContentDocumentLink cdl : [SELECT LinkedEntityId,ContentDocumentId FROM ContentDocumentLink WHERE ContentDocumentId IN:SetOfCd]){
    string cdlentityId = cdl.LinkedEntityId;
    if (cdlentityId.substring(0,3) == 'a0h') {
    SetOfCdl.add(cdl.LinkedEntityId);
    MapOfCdNCdl.put(cdl.ContentDocumentId, cdl.LinkedEntityId);
    }
    }
MapOfStatus = ContectDocLinkHandler.CheckStatus(SetOfCdl);
if(Trigger.IsUpdate){
for(ContentDocument cd :Trigger.new){
Id cdlId = MapOfCdNCdl.get(cd.Id);
if(MapOfStatus.get(cdlId) == 'Completed'){
cd.addError('Sorry you cannot add/update this file.');
}
}
}
if(Trigger.Isdelete){
for(ContentDocument cd :Trigger.old){
Id cdlId = MapOfCdNCdl.get(cd.Id);
if(MapOfStatus.get(cdlId) == 'Completed'){
cd.addError('Sorry you cannot delete this file.');
}
}
}
}

Content Version Trigger


trigger ContentVersionTrg on ContentVersion (before update) {
    
    if(Trigger.IsBefore && (Trigger.IsInsert || Trigger.IsUpdate)){
   
    Map<Id,String> MapOfStatus = new Map<Id,String>();
    Set<Id> SetOfCdl = new Set<Id>();
    Set<Id> SetOfCd = new Set<Id>();
    map<Id,Id> MapOfCdNCdl = new map<Id,Id>();
    for(ContentVersion cv :Trigger.new){
    SetOfCd.add(cv.ContentDocumentId);
    }
    system.debug('Set Of Content Doc'+SetOfCd);
    for(ContentDocumentLink cdl : [SELECT LinkedEntityId,ContentDocumentId FROM ContentDocumentLink WHERE ContentDocumentId IN:SetOfCd]){
    string cdlentityId = cdl.LinkedEntityId;
//Hard coding start 3 character of my custom object
    if (cdlentityId.substring(0,3) == 'a0h') {
   
    SetOfCdl.add(cdl.LinkedEntityId);
    MapOfCdNCdl.put(cdl.ContentDocumentId, cdl.LinkedEntityId);
    }
    }
MapOfStatus = ContectDocLinkHandler.CheckStatus(SetOfCdl);
for(ContentVersion cv :Trigger.new){
Id cdlId = MapOfCdNCdl.get(cv.ContentDocumentId);
if(MapOfStatus.get(cdlId) == 'Completed'){
cv.addError('Sorry you cannot add/update this file');
}
}
    }
}

Content Document Link Trigger:

trigger ContectDocLinkTrg on ContentDocumentLink (before delete,before update) {
    set<Id> SetOfCdlLinkId = new set<Id>();
    map <Id,String> MapOfStatus = new map<Id,String>();
    
for(ContentDocumentLink cdl :Trigger.old){
SetOfCdlLinkId.add(cdl.LinkedEntityId);
}
MapOfStatus = ContectDocLinkHandler.CheckStatus(SetOfCdlLinkId);
for(ContentDocumentLink cdl :Trigger.old){
if(MapOfStatus.get(cdl.LinkedEntityId) == 'Completed'){
cdl.addError('Sorry you cannot delete this file');
}
}
}

Content Document Link Handler :

public without sharing class ContectDocLinkHandler {

       
 // function used to check status of Jira Issue object as complete
    public Static Map<Id,String> CheckStatus(set<Id> SetOfCdl)
    {
    map <Id,String> MapOfJIStatus = new map<Id,String>();
   
   
    if(SetOfCdl.size() > 0){
    for(Jira_Issues__c js : [select Id, Status__c from Jira_Issues__c where Id IN: SetOfCdl]){
    MapOfJIStatus.put(js.Id, js.Status__c);
    }
    }
    return MapOfJIStatus;
    }
}

Happy Coding !!! 

7 comments:

  1. Thank you.Well it was nice post and very helpful information on salesforce Online course Hyderabad

    ReplyDelete
  2. Thank you for your code. Something strange for me, a user can delete the file if he goes on file details page ?
    Then, do you have the test classes for your code ?

    ReplyDelete
  3. with this code i am able restrict edit/delete. need help on how i can allow user to create a new file.

    ReplyDelete