Find your content:

Search form

You are here

Migrating attachments from one org. to another

 
Share

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

My Block Status

My Block Content