Org2Org File Transfer in salesforce (code written in destination org)
Let's define the terms we will use in this blog post:
- Source org - The org that has all the files.
- Current org (destination) - The destination org where all files are to be fetched from the source org. Because all code will be written in the destination org only; no coding will be done in the source org.
- Get Session Token, Org Base URL of source org.
- Get Record Ids from which we need to get the related files.
- Hit the Salesforce REST APIs to fetch the files from source org.
- Create Content Version in current org (destination).
- Create Content Document Link in current org (destination) which will associate the file with the record you want.
- Ext_Record_Id__c - The record id of the record in the source org that we need to retrieve the files from.
- Processed_CV_Ids__c - All of the source org's Content Version ids that are saved in the current org will be added to this field, separated by semi-colon.
global class FetchFilesFromSourceOrgBatch implements Database.Batchable<sObject>, Database.AllowsCallouts {
global Set<Id> currentOrgRecordIds;
global String sourceSessionId;
global String sourceDomainURL;
global FetchFilesFromSourceOrgBatch(Set<Id> currentOrgRecordIds, String sourceSessionId, String sourceDomainURL){
this.currentOrgRecordIds = currentOrgRecordIds;
this.sourceSessionId = sourceSessionId;
this.sourceDomainURL = sourceDomainURL;
}
global Database.QueryLocator start(Database.BatchableContext BC) {
String query = 'SELECT ID, Ext_Record_Id__c, Processed_CV_Ids__c FROM Opportunity WHERE id IN :currentOrgRecordIds';
return Database.getQueryLocator(query);
}
global void execute(Database.BatchableContext BC, List<Opportunity> oppList) {
try {
// Batch size is 1.
Opportunity record = oppList[0];
String externalRecordId = record.Ext_Record_Id__c;
String currentOrgRecordId = record.id;
// Fetch all CDL associated with source record
String query_CDL_URL = sourceDomainURL + '/services/data/v58.0/query?q=SELECT+id,ContentDocumentId+FROM+ContentDocumentLink+WHERE+LinkedEntityId=\''+externalRecordId+'\'';
Http ht = new Http();
HttpRequest cdlReq = new HttpRequest();
cdlReq.setMethod('GET');
cdlReq.setEndpoint(query_CDL_URL);
cdlReq.setHeader('Content-Type','application/json');
cdlReq.setHeader('Authorization','OAuth '+sourceSessionId);
HttpResponse cdlRes = ht.send(cdlReq);
FetchFilesFromSourceOrgBatch.CDLRecordsWrapper cdlObj = new FetchFilesFromSourceOrgBatch.CDLRecordsWrapper();
FetchFilesFromSourceOrgBatch.CDLRecordsWrapper resCDL = cdlObj.parse(cdlRes.getBody());
String cdIds = '(';
for(cdlRecords cdl : resCDL.records) {
cdIds += '\'' + cdl.ContentDocumentId + '\',';
}
if(cdIds.endsWith(',')) {
cdIds = cdIds.substring(0, cdIds.length() - 1);
}
cdIds += ')';
String query_CV_URL = '';
if(record.Processed_CV_Ids__c!=null) {
String processedCVId = '(';
for(String cvId : record.Processed_CV_Ids__c.split(';')) {
processedCVId += '\'' + cvId + '\',';
}
if(processedCVId.endsWith(',')) {
processedCVId = processedCVId.substring(0, processedCVId.length() - 1);
}
processedCVId += ')';
query_CV_URL = sourceDomainURL + '/services/data/v58.0/query?q=SELECT+id,+title,+FileExtension+FROM+ContentVersion+WHERE+ContentDocumentId+IN+'+cdIds+'+AND+ID+NOT+IN+'+processedCVId+'+LIMIT+1';
} else {
query_CV_URL = sourceDomainURL + '/services/data/v58.0/query?q=SELECT+id,+title,+FileExtension+FROM+ContentVersion+WHERE+ContentDocumentId+IN+'+cdIds+'+LIMIT+1';
}
// Fetch all CV Id associated with source record
Http ht2 = new Http();
HttpRequest cvReq = new HttpRequest();
cvReq.setMethod('GET');
cvReq.setEndpoint(query_CV_URL);
cvReq.setHeader('Content-Type','application/json');
cvReq.setHeader('Authorization','OAuth '+sourceSessionId);
HttpResponse cvRes = ht.send(cvReq);
FetchFilesFromSourceOrgBatch.CVRecordsWrapper cvObj = new FetchFilesFromSourceOrgBatch.CVRecordsWrapper();
FetchFilesFromSourceOrgBatch.CVRecordsWrapper resCV = cvObj.parse(cvRes.getBody());
// We will fetch one file from source org at time and save it in current org.
System.enqueueJob(new FetchFilesFromSourceOrgQueue(currentOrgRecordId, resCV.records[0], sourceSessionId, sourceDomainURL));
} catch (Exception ex) {
System.debug('NO CV FOUND....'+ ex);
}
}
global void finish(Database.BatchableContext BC) {}
public class CDLRecordsWrapper{
public CDLRecords[] records;
public CDLRecordsWrapper parse(String json){
return (CDLRecordsWrapper) System.JSON.deserialize(json, CDLRecordsWrapper.class);
}
}
public class CDLRecords {
public String Id;
public String ContentDocumentId;
}
public class CVRecordsWrapper{
public CVRecord[] records;
public CVRecordsWrapper parse(String json){
return (CVRecordsWrapper) System.JSON.deserialize(json, CVRecordsWrapper.class);
}
}
public class CVRecord {
public String Id;
public String Title;
public String FileExtension;
}
}
public class FetchFilesFromSourceOrgQueue implements System.Queueable, Database.AllowsCallouts {
private Id currentOrgRecordId;
private FetchFilesFromSourceOrgBatch.CVRecord cvRecord;
private String sourceSessionId;
private String sourceDomainURL;
public FetchFilesFromSourceOrgQueue(Id currentOrgRecordId, FetchFilesFromSourceOrgBatch.CVRecord cvRecord, String sourceSessionId, String sourceDomainURL) {
this.currentOrgRecordId = currentOrgRecordId;
this.cvRecord = cvRecord;
this.sourceSessionId = sourceSessionId;
this.sourceDomainURL = sourceDomainURL;
}
public void execute(System.QueueableContext context) {
String getVersionDataURL = sourceDomainURL + '/services/data/v54.0/sobjects/ContentVersion/' +cvRecord.Id+ '/VersionData';
HttpRequest req0 = new HttpRequest();
req0.setEndpoint(getVersionDataURL);
req0.setMethod('GET');
req0.setHeader('Content-Type','application/json');
req0.setHeader('Authorization','OAuth '+sourceSessionId);
HTTPResponse res0 = new Http().send(req0);
if (res0.getStatusCode() == 200) {
// Create CV
String pathOnClient = cvRecord.Title + '.' + cvRecord.FileExtension;
ContentVersion cv = new ContentVersion(
Title= cvRecord.Title,
PathOnClient= pathOnClient,
ContentLocation= 'S',
VersionData= res0.getBodyAsBlob()
);
insert cv;
ContentVersion newCVRecord = [SELECT Id, ContentDocumentId FROM ContentVersion WHERE id = :cv.id LIMIT 1];
ContentDocumentLink cdl = new ContentDocumentLink(
ContentDocumentId=newCVRecord.ContentDocumentId,
LinkedEntityId=currentOrgRecordId,
ShareType='I',
Visibility='AllUsers'
);
insert cdl;
Opportunity record = [SELECT Id, Processed_CV_Ids__c FROM Opportunity WHERE id=:currentOrgRecordId LIMIT 1];
if(record.Processed_CV_Ids__c!=null) {
record.Processed_CV_Ids__c += ';'+cvRecord.Id;
} else {
record.Processed_CV_Ids__c = cvRecord.Id;
}
update record;
}
}
public class CDRecordsWrapper{
public CDRecords[] records;
public CDRecordsWrapper parse(String json){
return (CDRecordsWrapper) System.JSON.deserialize(json, CDRecordsWrapper.class);
}
}
class CDRecords {
public String ContentDocumentId;
}
}
Comments
Post a Comment