+ Start a Discussion
CloudGeekCloudGeek 

Trigger on Attachment : help me bulkify

I have a requirement to check for the attachments on a Object;
If there are no attachments I have to clear some fields up on delete.
if only a single atatchment deleted and still some attachments left on the custom object - get the recent attachment values and update on the object (Parent = Account)

Please check the trigger code below:

trigger TestAttachments on Attachment (after insert,after delete) {

    
    
    //Variables
    Map<Id,Attachment> Account_TO_Attachment = new Map<Id,Attachment>();
    Map<Id,Integer> Account_TO_AttachmentCount = new Map<Id,Integer>();
    List<Account> updateAccounts = new List<Account>();
    List<ID> ListparentIDs = new List<ID>();
    
    if(trigger.isinsert)
    {
    
    
        //Take all Account Attachments only
        for(Attachment A : Trigger.new)
        {
            //Check the Parent Object and take only relevant
            String objectAPIName = (String) A.ParentId.getSObjectType().getDescribe().getName();
            System.debug('objectAPIName = '+ objectAPIName);
            if(objectAPIName.equalsIgnoreCase('Account')){
                    
                    Account_TO_Attachment.put(A.ParentId,A);
                    
            }        
                    
                    
        }
        
             
       
        
        for(Account Acc : [SELECT Id,Upload_Date__c,Upload_User__c,Upload_Link__c FROM Account where Id in :Account_TO_Attachment.keyset()])
        {
            if(Account_TO_Attachment.containskey(Acc.id)){
                Attachment temp = Account_TO_Attachment.get(Acc.Id);
                Acc.Upload_Date__c = (DateTime)temp.CreatedDate;
                Acc.Upload_User__c = temp.CreatedById;
                               
                updateAccounts.add(Acc);
            }
        }
        
        if(updateAccounts.size() > 0)
           update updateAccounts;
           
         } //End-Of-isInsert 
    
    //Delete Event
    
    if(trigger.isdelete)
        { 
            for(Attachment A : Trigger.old)
                {
                    ListparentIDs.add(A.ParentId);
                }

                    //List<Proposal__c> co = [select id, Attachment_Added__c from Proposal__c where id =: Trigger.old[0].ParentId];
                    List<Account> co = [select id,Upload_Date__c,Upload_User__c  from Account where id in: ListparentIDs];
         

            if(co.size()>0)         

                {                 

                List<Attachment> allChildren = [Select id from Attachment where parentid = :co[0].id];

                if(allChildren != null && allChildren.size() == 0)           

                    //co[0].Attachment_Added__c = false;             

                    update co;         

                }

        } //End Of Delete
    
    
    
    
    
    
    
    
    
    
    
}
 
Best Answer chosen by CloudGeek
SaranSaran
Hi Venkat,

I have written a trigger with your above reqs
 
trigger TestAttachments on Attachment (after insert,after delete) {
	
	list<account> accUpdatelist = new list<Account>();

	// Insert functionality.
	if(trigger.isInsert)
	{
		map<id , id> acc_att_map = new map<id, id>();

		for(Attachment att : Trigger.new)
		{
			if(att.parentId.getSObjectType() == 'Account')
				acc_att_map.put(att.ParentId , att.Id);
		}

		for(Account acc : [select id, Upload_Date__c,Upload_User__c,Upload_Link__c FROM Account where Id in acc_att_map.keyset()])
		{
			if(acc_att_map.containskey(Acc.id)){
	            
	            Attachment temp = trigger.newMap.get(acc_att_map.get(Acc.Id));
	            
	            Acc.Upload_Date__c = (DateTime)temp.CreatedDate;
	            Acc.Upload_User__c = temp.CreatedById;
	                           
	            accUpdatelist.add(Acc);
	        }
		}
		update accUpdatelist;
	}

	// Delete Functionality.

	if(trigger.isDelete)
	{
		set<id> accId = new set<Id>();
		for(Attachment att : Trigger.old)
		{
			if(att.parentId.getSObjectType() == 'Account')
				accId.add(att.ParentId);
		}

		for(Account acc : [select id, Upload_Date__c,Upload_User__c,Upload_Link__c, 
						   (select id, createdDate, createdById from Attachments order by createdDate DESC) from account where id in: accId])
		{
			if(!acc.Attachments.isEmpty)
			{
				Attachment temp = acc.Attachments.get(0);
	            
	            Acc.Upload_Date__c = (DateTime)temp.CreatedDate;
	            Acc.Upload_User__c = temp.CreatedById;

	            accUpdatelist.add(acc);
			}else
			{
				Acc.Upload_Date__c = null;
	            Acc.Upload_User__c = null;

	            accUpdatelist.add(acc);
			}
		}
		update accUpdatelist;
	}

}

Hope this might help you to solve your issue.

Thanks

All Answers

ManojjenaManojjena
Hi Venkat,

What exactly your requirment is ,Do you want to update few fields like  (Upload_Date__c,Upload_User__c,Upload_Link__c,.Attachment_Added__c ) in account and after deleting that you need to make all fields null .

Please confirm else post your reqirment for which we can help you .
CloudGeekCloudGeek
Hi,

Here is my requirement:
When any attachment is deleted for the accounts,I have to CLEAR the fields on ACCOUNT when all attachments are deleted.
If there are still any attachments exist for the account - Need to update the fields with teh most recent attachment values of those fields.

 
SaranSaran
Hi Venkat,

I have written a trigger with your above reqs
 
trigger TestAttachments on Attachment (after insert,after delete) {
	
	list<account> accUpdatelist = new list<Account>();

	// Insert functionality.
	if(trigger.isInsert)
	{
		map<id , id> acc_att_map = new map<id, id>();

		for(Attachment att : Trigger.new)
		{
			if(att.parentId.getSObjectType() == 'Account')
				acc_att_map.put(att.ParentId , att.Id);
		}

		for(Account acc : [select id, Upload_Date__c,Upload_User__c,Upload_Link__c FROM Account where Id in acc_att_map.keyset()])
		{
			if(acc_att_map.containskey(Acc.id)){
	            
	            Attachment temp = trigger.newMap.get(acc_att_map.get(Acc.Id));
	            
	            Acc.Upload_Date__c = (DateTime)temp.CreatedDate;
	            Acc.Upload_User__c = temp.CreatedById;
	                           
	            accUpdatelist.add(Acc);
	        }
		}
		update accUpdatelist;
	}

	// Delete Functionality.

	if(trigger.isDelete)
	{
		set<id> accId = new set<Id>();
		for(Attachment att : Trigger.old)
		{
			if(att.parentId.getSObjectType() == 'Account')
				accId.add(att.ParentId);
		}

		for(Account acc : [select id, Upload_Date__c,Upload_User__c,Upload_Link__c, 
						   (select id, createdDate, createdById from Attachments order by createdDate DESC) from account where id in: accId])
		{
			if(!acc.Attachments.isEmpty)
			{
				Attachment temp = acc.Attachments.get(0);
	            
	            Acc.Upload_Date__c = (DateTime)temp.CreatedDate;
	            Acc.Upload_User__c = temp.CreatedById;

	            accUpdatelist.add(acc);
			}else
			{
				Acc.Upload_Date__c = null;
	            Acc.Upload_User__c = null;

	            accUpdatelist.add(acc);
			}
		}
		update accUpdatelist;
	}

}

Hope this might help you to solve your issue.

Thanks
This was selected as the best answer
CloudGeekCloudGeek
Hi,

Thanks for the response.
Since the object I am dealing with is a CUSTOM OBJECT in stead of ACCOUNT, the sub-query was not allowed to write for that FOR-Loop in the Delete event.

Below is the code I have tried - Can you help me understand whether this is going to hit any SOQL LIMIT ?

public void callAfterDeleteMethods(List<Attachment> AList)
    {         
        //Local variables        
        set<Id> policyIDs = new set<Id>();
        List<Attachment> attachList = new List<Attachment>();
        Map<CUSTOM_OBJECT__c,List<Attachment>> Policy_TO_AttachmentList_Map = new Map<CUSTOM_OBJECT__c,List<Attachment>>();  //Map PUG-Object To Respective Attachment List
        List<CUSTOM_OBJECT__c> pugList;
        
        for(Attachment att : AList)          //Taking All Policy IDs in Context
        {
            String objectAPIName = (String) att.ParentId.getSObjectType().getDescribe().getName();
            System.debug('FROM Delete Method - objectAPIName = '+objectAPIName);
            if(objectAPIName.equalsIgnoreCase('CUSTOM_OBJECT__c'))
                    policyIDs.add(att.ParentId);
        }

        
        if(policyIDs.size()>0)    //if list of incoming list records to be deleted are not ZERO
        {        
              pugList = [SELECT Id,Upload_Date__c,User__c  FROM CUSTOM_OBJECT__c WHERE Id in: policyIDs];  //List to Hold PUG Objects
        }      
        
         if(pugList.size()>0)      
                {                 

                    for(CUSTOM_OBJECT__c pug : pugList)  //For each PUG Object get Attachments listed and Mapped
                      {
                            for(Attachment Att : [SELECT Id,CreatedDate,CreatedById FROM Attachment WHERE ParentId =: pug.Id ORDER BY createdDate DESC])
                                {
                                    attachList.add(Att);  //Make the list
                                }
                    
                            Policy_TO_AttachmentList_Map.put(pug,attachList); //Policy-Object --> Corresponding Attachment List
                    
                      }
                      
                      for(CUSTOM_OBJECT__c pug : pugList)
                      {
                          if(Policy_TO_AttachmentList_Map.containsKey(pug))
                          {
                              if(Policy_TO_AttachmentList_Map.get(pug).size()>0)  //if attachments exists for policy
                              {
                                    Attachment temp = Policy_TO_AttachmentList_Map.get(pug).get(0);          
                                    pug.Upload_Date__c = (Datetime)temp.CreatedDate;
                                    pug.User__c = temp.CreatedById;

                                    policyUpdatelist.add(pug);
                              }
                              else
                              {     
                                    pug.Upload_Date__c = null;
                                    pug.User__c = null;
               
                                    policyUpdatelist.add(pug);
                              }
                              
                          }
                      }
                     

                }

          update policyUpdatelist;

          firstRun = false;        //To Avoid Recursive Calls in the Context

        
    }//End-Of-Delete Method
SaranSaran
Hi venkat,

If that is the case you can copy paste the code in the above comment and replace Custom_Object__c instead of account. It will work the same way.

Hope this helps you to solve you problem.

Thanks,