I am trying to write a trigger that will transfer attachments from a Task object to the related Opportunity object from emails & attachments using Salesforce for Outlook. I have the basic trigger code written to do the transfer. But after some research I found that the WhatId is not available after insert when created from SFO. I found that you can call a @future method to then complete the transfer if the WhatId is Null.
The problem is that in the @future method I am looping through the list of tasks collected from the Ids passed to it. I am then querying to find the attachments linked to the task. I know I should not put SOQL inside the loop but a subquery would not allow the select of the body of the attachments. I will clean it up later. But I still do not understand why the reference to the task iteration variable in the select statement will not return any results. The exact same loop structure and select are in the base trigger and work fine.
Like I said I will clean this up to be better code, but I am trying to finish this for a demo that will show we can modify the default actions of Salesforce for Outlook as far as the attachments go.
I will include both the trigger code and class code along with a sample of the log.
trigger Task_Transfer_Attachments on Task (after insert, after undelete) {
//Create a List to store the Ids of Attachments to be deleted
List<Id> forDeletionIds = new List<Id>();
List<Id> tasks = new List<Id>();
//List<Attachment> AttachToUpdate = new List<Attachment>();
for (Task t : trigger.new){
String taskWhatId = String.valueof(t.WhatId);
if (taskWhatId == null){
tasks.add(t.Id);
System.debug('~~~~~~ WhatId String =' + t.WhatId );
Continue;
}
//Get the attachments for the task
System.debug('~~~~~~ Parent String =' + t.WhatId );
for(Attachment AttachToUpdate : [select id,name,body from Attachment where parentid = :t.Id ]){
//Check if the task is related to an opportunity
if (taskWhatId.substring(0,3) == '006' ){
Attachment newA = New Attachment(
Name = AttachToUpdate.Name,
Body = AttachToUpdate.Body,
//ContentType = 'image/jpeg',
//Description = 'Account Photo',
OwnerId = t.OwnerId,
ParentId = t.WhatId
);
//Insert the new Attachment
insert newA;
//Add the now duplicate Attachment ID to a list
forDeletionIds.add(AttachToUpdate.Id);
//}
}
}
}
//Call a @future method to transfer attchments created by SFO
if (tasks.size() > 0) {
System.debug('~~~~~~ Call Future Method =' + tasks );
Task_Transfer_Future.FutureTransferAttachMethod(tasks);
}
//List and then delete all duplicate Attachments
List<Attachment> forDeletion = [SELECT Id FROM Attachment WHERE Id IN :forDeletionIds];
delete forDeletion;
}
public with sharing class Task_Transfer_Future {
@future
public static void FutureTransferAttachMethod(List<id> taskIds){
List<Id> forDeletionIds = new List<Id>();
list <id> tasks = taskIds;
//list <Attachment> AttachToUpdate = new list <Attachment>();
list <task> theTasks = [select Id, WhatId, OwnerId from task where ID IN :tasks];
for (task t : theTasks){
String taskWhatId = String.valueof(t.WhatId);
//Get the attachments for the task
System.debug('~~~~~~ What ID = ' + t.WhatId + ' t.Id = ' + t.id );
list <Attachment> AttachToUpdate = [select id,name,body from Attachment where parentid = :t.id ];
for(Attachment a : AttachToUpdate ){
if (taskWhatId.substring(0,3) == '006' ){
System.debug('~~~~~~ Loop Attach =' + a.Id );
Attachment newA = New Attachment(
Name = a.Name,
Body = a.Body,
OwnerId = t.OwnerId,
ParentId = t.WhatId
);
//Insert the new Attachment
insert newA;
//Add the now duplicate Attachment ID to a list
forDeletionIds.add(a.Id);
}
}
}
//List and then delete all duplicate Attachments
List<Attachment> forDeletion = [SELECT Id FROM Attachment WHERE Id IN :forDeletionIds];
delete forDeletion;
}
}
Log sample:
|USER_DEBUG|[11]|DEBUG|~~~~~~ What ID = 0067000000azvv8AAA t.Id = 00TV0000008DqwuMAC
SYSTEM_METHOD_EXIT|[11]|System.debug(ANY)
SOQL_EXECUTE_BEGIN|[12]|Aggregations:0|SELECT id, name, body FROM Attachment WHERE parentid = :tmpVar1
SOQL_EXECUTE_END|[12]|Rows:0
after insert
trigger. As such, how could there be any Attachments whose parent is the task being inserted? Attachments can't be added to any object until the object has been committed.