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
SGulSGul 

Maintaining Attachment history in Salesforce

Hi,

We have a requirement where attachment history need to be maintained along with attachment content in a separate object. evry time when attachment is uploaded, updated or deleted from the system should get logged and attachment contents should be retained in history table. Salesforce doesn't have provision for tracking history related to attachments as per my knowledge.

 

So i am creating a custom object attachmenthistory to cater to this and writing trigger on attachment whch is logging the entire information to history object. but i am facing following challenges while saving the body of attachment:

Approach 1 :  

Rich Text Area field in Custom object supports storing only 1 MB Data. I tried to save the encoded data of attachment to this field , but it supports only 1 MB data max while i can receive attachments upto 5MB.

Conversion of attachment body data to binary is not working as rich text area field ha limitation of 32768 characters only. It throws error even for saving data for 1 MB file

 

Approach 2:

Inserting the attachment directly in Attachment History via Future Class.

and In trigger of attachment , put check that attachment relating to history, log need not to be maintained.

This will work but in that case there is limitation on number of invocations for Future Class. 200 per user license per 24 hours. we are expecting bulk of attachments to be uploaded into the system at time of migration of data.

 

Is there any other alternative to cater to this requirement?please help.

Thanks.

 

SGulSGul

trigger can be deactivated at time of migration and batch class can be written to insert history related to attachments at time of migration. but in daily callouts there is possibility of hitting the future invocation governor limit.

bob_buzzardbob_buzzard

Is there any reason why you wouldn't store the attachment in its native form against the attachment history object?

 

E.g. when an attachment is inserted, you create the attachment history object, store information about who/when etc on that object, and then clone the attachment and set the parent id of the cloned version to the attachment history object id.

SGulSGul

Hi Bob,

we have requirement like this only that we need to maintain the attachment history log.

I have got your point but how can i clone attachment to point to History object through code, that's the question ?

inside attachment trigger i can't insert a new record related to attachment whose parent id points to history object.

Can we insert the attachment in its own trigger??? No i guess ..


bob_buzzard wrote:

Is there any reason why you wouldn't store the attachment in its native form against the attachment history object?

 

E.g. when an attachment is inserted, you create the attachment history object, store information about who/when etc on that object, and then clone the attachment and set the parent id of the cloned version to the attachment history object id.


 

bob_buzzardbob_buzzard

As attachment is an sobject, it will support the clone method.  If you have your attachments in a list you can also invoke deepclone on that to create a clone of all sobjects in the list.

 

Why can't you insert the cloned attachment in the trigger?  I can't see any reason why that wouldn't work.

 

Something like the following - not compiled but hopefully you get the idea:

 

 

List<Attachment_History__c> hist=new Attachment_History__c();
List<Attachment> attsWithParent=[select id, name, Parent.Name, Parent.id from Attachment where id in :trigger.new];
for (Attachment a : attsWithParent)
{
   // exclude attachments created for history purpose
   if (!a.Parent instanceof Attachment_History__c)
   {
      Attachment_History__c histEle=new Attachment_History__c();
      // fill in more details here
      hist.add(histEle);
   }
}

insert hist;

List<Attachment> clonedAtts=new List<Attachment>();
for (Integer idx=0; idx<attsWithParent(); idx++)
{
   if (!a.Parent instanceof Attachment_History__c)
   {
      Attachment cloneAtt=attsWithParent[idx].clone(false, true);
      cloneAtt.parentId=hist[idx].id;
      clonedAtts.add(cloneAtt);
   }
}

insert clonedAtts.



 

 

SGulSGul

oh that's cool, so u mean to say that we can insert attachments even in its own After Insert and After Update Trigger?

I thought salesforce wont allow u to insert/update the same object in its own triggers.

bob_buzzardbob_buzzard

One thing that you can't do is carry out a DML update an object that is currently being processed by a before trigger, but that won't be an issue in your scenario.

 

The challenge when inserting/updating in triggers is to ensure that you don't introduce infinite recursion, hence checking the type of the parent before cloning.

SGulSGul

Got your point Bob...Yes you are right that in this scenario that will be possible as i willnot be updating the same data that is being processed.. :)

 

I am working on optimizing the stuff now.

Since cloning the related attachment evry time wil eat up the data storage space...So I am taking one another approach which is working perfectly.. Let me know if it sounds good according to you.

i.e.

while inserting/updating attachment, to maintain history i am putting attachment id in one of the field of history table

and using hyperlink function in formula field,  opening the attachment in new window.

Thus saving the space of Attachment since eventually its pointing to existing attachment.

 

and Before deletion i am creating new attachment from the attachment to be deleted

with parent id  to one of related history id. 

Then modiying the associated records of history with the updated Attachment Id.

 

In this case i am able to save the space and at the same time i am able to retain the attachment. :)

 

 

bob_buzzardbob_buzzard

That sounds fine as long as you don't want to see the changes to the attachment body as part of the history, as it will always point at the latest version of the attachment.

SGulSGul

Yeah thats true Bob, but I can not see any option to edit the body content of Attachment in Salesforce.

 

As whenever Edit is clicked correspnding to any attachment we can modify only following paramters:

Private,

File name

Description

 

That means If we want to change the body content , we will have to upload a new attachment.

Is there anyway out where i can change the body content of attachment in salesforce???

bob_buzzardbob_buzzard

You might be able to change the content by altering the body field in apex and saving it.  

 

What I meant, though, was that if you clone the attachment each time through, you would have the different forms of the attachment body available through the attachment record itself.

SGulSGul

Thanks Bob but I am asking for provision on front end to user for changing the body content.

Can user change the body content through front end of Salesforce.

When i am clicking on Edit corresponding to attchment, its not giving me any provision for updating the content.

bob_buzzardbob_buzzard

The only way a user could change the content as (opposed to overwriting the attachment) through the front end is via a visualforce page.  You'd back an apex:inputfile with an attachment, and then replace the body of the stored attachment with the body of the uploaded.

SGulSGul

If VF is the only way out there to provide facility of changing Body Content of Attachment, then the optimised approach is the best i think.

As in our application, this facility is not being given to user, they will be using only Standard Salesforce Attachment update functionality from front end.

 

Let me know your inputs on same.

I appreciate the kind of response you are sending.Thanks a lot for all the pointers and help :)


bob_buzzard wrote:

The only way a user could change the content as (opposed to overwriting the attachment) through the front end is via a visualforce page.  You'd back an apex:inputfile with an attachment, and then replace the body of the stored attachment with the body of the uploaded.