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!
Attribution to: Davin Casey
Possible Suggestion/Solution #1
From what i understand we basically need to re-parent the Attachments with Account Id
First migrate all as it is in current Org to the new org.
Then we can write a small snippet piece in execute anonymous to do the re-parenting .
I drafted a simple algorithm and you may need to tweak a little to get it working based on realtionship you have
1)Construct a map of Contract Id and Account Id(Map)(Query Contract ) 2)Query all the attachments which you want to reparent with parent Id 3)From the parent Id (i.e Contract ) also using the map of Contract Id and Account Id you can obtain the Account Id 4)Update the attachments with parent Id equal to the attachment Id (Query and iterate through each to change the parent Id and collect in list and update the List ) 5)Must be written in execute anonymous and executed (Try in sandbox first) 6)Hope you have less no of attachments not exceeding 10,000 ROWS
Map<Id,Id> mapofAcccIdIdbyContractId=new Map<Id,Id>();
Set<Id> setparentIds=new Set<Id> parentIds();
List<Attachment> lstattch=new List<Attachment>();
for(Attachment att:[SELECT Name, ID, ParentID WHERE Name LIKE '%.pdf']){
setparentIds.add(att.ParentID);
}
for(Contract ctr:[Select Id,AccountId from Contract where Id in:setparentIds]){
mapofAcccIdIdbyContractId.put(ctr.Id,Ctr.AccountId);
}
for(Attachment att:[SELECT Name, ID, ParentID WHERE Name LIKE '%.pdf']){
if(mapofAcccIdIdbyContractId.get(ParentID)!=null){
att.ParentID=mapofAcccIdIdbyContractId.get(ParentID);
lstattch.add(att);
}
}
update lstattch;
Attribution to: Mohith Shrivastava
This content is remixed from stackoverflow or stackexchange. Please visit https://salesforce.stackexchange.com/questions/1999