hoping someone can help me with this issue.
We have a requirement to migrate all .pdf attachments (purchase orders) from the Contract object in our current SFDC org. to the Account object in our new SFDC org.
Finding which attachments to migrate is simple enough:
SELECT Name, ID, ParentID
FROM Attachment
WHERE (
ParentID IN (
SELECT ID
FROM Contract
)
AND
Name LIKE '%.pdf'
)
The problem I'm having is finding a way to place the related AccountID on the Attachment record, either by updating the ParentID or maybe even in the description field.
Basically we have:
Account.Opportunity.Contract.Attachment.pdf
and we want to move the Attachment to relate to the Account directly, but can only traverse one level up from Attachment.
I believe this stems from the fact that the Parent relationship on Attachment is polymorphic.
Does anyone know a way to achieve this in Salesforce?
If I can't find a way I guess I'll take the AccountID from the Contract record and use a Vlookup table in Excel to update them.
Thanks for any help
EDIT:
So I've come up with this class, and it works perferctly - except for it hitting governor limits. Could someone familiar with writing Batch Apex help me convert it to run in Batch please? I have zero experience with Batch Apex.
global class AttachmentReparentPDFsToAccount {
webservice static string reparentPDFs () {
// Set containing the Ids of the Accounts that will be migrated
Set<Id> accountIdSet = new Set<Id> {};
for (Account acc:[SELECT Id FROM Account WHERE (Type = 'Subscriber' OR Type = 'Ex-Subscriber' OR Type = 'Division' OR Type = 'EDU SUBSCRIBER')]){
accountIdSet.add(acc.Id);
System.debug('No. of valid accounts: ' + accountIdSet.size());
}
// Set containing the Ids of the Contracts that will be migrated
Set<Id> contractIdSet = new Set<Id> {};
for (Contract con:[SELECT Id FROM Contract WHERE AccountId IN :accountIdSet]){
contractIdSet.add(con.Id);
System.debug('No. of valid contracts: ' + contractIdSet.size());
}
// Create the map that will contain ContractId => Contract.AccountId
Map<Id,Id> contractToAccountMap=new Map<Id,Id>();
// Lists of attachments to be created then deleted
List<Attachment> attachmentsToDelete = new List<Attachment>();
List<Attachment> attachmentsToCreate = new List<Attachment>();
// Populate the map with the ContractId and AccountId related to the Contract
for(Contract ctr:[Select Id,AccountId from Contract where Id in:contractIdSet]){
contractToAccountMap.put(ctr.Id,Ctr.AccountId);
}
// Attachment tempAtt = new Attachment();
// Update the parentId of the attachment, changing from the ContractId to the related AccountId
for(Attachment att:[SELECT Name, Id, Body, ParentId From Attachment WHERE ((Name LIKE '%.pdf') AND (ParentId IN :contractIdSet))]){
if(contractToAccountMap.get(att.ParentID)!=null){
Attachment tempAtt = new Attachment ( name = att.name, body = att.body, parentId = contractToAccountMap.get(att.ParentID));
// tempAtt.ParentID = contractToAccountMap.get(att.ParentID);
attachmentsToCreate.add(tempAtt);
attachmentsToDelete.add(att);
}
}
// Update the list of attachments
insert attachmentsToCreate;
delete attachmentsToDelete;
System.debug('No. of attachments to be created; ' + attachmentsToCreate.size());
// Return the no. of attachments that have been reparented
String listSize = String.valueOf(attachmentsToCreate.size());
listSize += ' attachments have been reparented to their root Accounts.';
return(listSize);
}
}
Thanks again!