+ Start a Discussion
sam_Adminsam_Admin 

How to clone related records

I have 2 custom objects, object1(Parent) and object2(Child), i want a clone button on object1 so everytime i clone then it needs to carry over records from object2. I created this button but it doesn't carry over the related records, i know i haven't added any logic to carry the records yet but if anyone can help me here i would really appreciate it

https://na2.salesforce.com/{!object1__c.Id}/e?clone=1&retURL=%{!object1.Id}
sandeep vardhanapusandeep vardhanapu
You will have to write a trigger on object1(parent) to move the child records(object2) from the parent1 to parent 2 (created from the clone). https://na2.salesforce.com/{!object1__c.Id}/e?clone=1&retURL=%{!object1.Id} does not move the child records it only clones the existing record (not inserted untill you click on save).

hope this helps...

Sandeep.
Zuinglio Lopes Ribeiro JúniorZuinglio Lopes Ribeiro Júnior

Hello, 

Not sure if I got it right but if you are looking for a clone button that clones the parent and its children you can try the approach bellow.

First of all, you have to create a class with a webservice method that will be invoked by a custom button in the parent's object layout that will clone the parent and its children:
 
 
/**
* @description Helper class to clone parent and its children sObjects
*/
global without sharing class EnhancedCloneHelper {
       
    /**
    * @description Clone parent and its children
    * @param id of the parent sObject
    * @return String Serialized result
    */
    webservice static String clone (String sObjectId) {
        
        List<ParentSObject__c> parentSObjects;
        ParentSObject__c parent;
        CloneModel cloneModelResult = new CloneModel();
        
		// Parent query
        String query = String.format(
            'SELECT {0} FROM {1} WHERE Id = \'\'{2}\'\'',
            new String[] {
                String.join(
                    new List<String>(
                        ParentSObject__c.SObjectType.getDescribe().fields.getMap().keySet()
                    ),
                    ','
                ),
                String.valueOf(ParentSObject__c.SObjectType),
                sObjectId
           }
        );

        try {
            
            // Query and gets results
            parentSObjects = Database.query(query);         
            
			// Clone the original object. Here you can change anything without affecting the original sObject
            parent = parentSObjects[0].clone(false, true, false, false);
            parent.Name = parent.Name + ' CLONED';

            Database.insert(parent);
       
        } catch (DmlException error) {
            cloneModelResult.message = 'An error occurred while cloning the object.' + error.getMessage();
            return JSON.serialize(cloneModelResult);        
        }
        
        // Children query  
        query = String.format(
            'SELECT {0} FROM {1} WHERE ParentSObjectId__c = \'\'{2}\'\'',
            new String[] {
                String.join(
                    new List<String>(
                        ChildSObject__c.SObjectType.getDescribe().fields.getMap().keySet()
                    ),
                    ','
                ),
                String.valueOf(ChildSObject__c.SObjectType),
                sObjectId
           }
        );
        
        List<ChildSObject__c> children = new List<ChildSObject__c>();
        
        try {
            
            // Query and clone the children. Here you can change anything without affecting the original sObject
            for (ChildSObject__c child:(List<ChildSObject__c>)Database.query(query)) {
                children.add(child.clone(false,true,false,false));
            }
            
            // If there isn't any children ends the process and return success
            if (children.isEmpty()) {
                cloneModelResult.isSuccess = true;
                cloneModelResult.message = 'Object successfully cloned!';                
                cloneModelResult.url = getUrlRedirect(parent.Id);
                return JSON.serialize(cloneModelResult);
            }
            
			// Set the parent's Id
            for (ChildSObject__c child : children) {
                child.ParentSObjectId__c = parent.Id;
            }
        
            Database.insert(children);
    
            
        }  catch(DMLException error) {
            cloneModelResult.message = 'An error occurred while cloning the object.' + error.getMessage();;
            return JSON.serialize(cloneModelResult); 
        }
        
        // Return success at the end of the process
        cloneModelResult.isSuccess = true;
        cloneModelResult.message = 'Object and its children successfully cloned!';
        cloneModelResult.url = getUrlRedirect(parent.Id);
        
        return JSON.serialize(cloneModelResult);

    }

    private static String getUrlRedirect(String sObjectId){
        PageReference page = new PageReference('/'+ sObjectId);
        return page.getUrl();
    }
    
    global class CloneModel {
        Boolean isSuccess;
        String message;
        String url;
    }
}


After that, you will have to create a custom javascript button and place it at the parent's layout. Once clicked, the button will invoke the clone method and will clone the desired sObject.

User-added image


Button's code:
 
{!REQUIRESCRIPT("/soap/ajax/30.0/connection.js")} 
{!REQUIRESCRIPT("/soap/ajax/30.0/apex.js")}

var clonedSobjectResult = JSON.parse(sforce.apex.execute("EnhancedCloneHelper","clone", { sObjectId : "{!ParentSObject__c.Id}" }));

alert(clonedSobjectResult.message);

if(clonedSobjectResult.isSuccess){
  window.location = clonedSobjectResult.url;
}

This is one way to achieve what you are looking for. Keep in mind that you can change it as much as you want.

Hope to have helped. Regards.

Don't forget to mark your thread as 'SOLVED' with the answer that best helps you.
 
Zuinglio Lopes Ribeiro JúniorZuinglio Lopes Ribeiro Júnior
Don't forget to replace for correct APIs names in the apex class and the js code.
Brian KoblenzBrian Koblenz
There is a nice description that creates a cloner with (selectable) related lists at: http://christopheralunlewis.blogspot.com/2011/05/how-to-dynamically-clone-salesforce.html.

It walks you throught the steps in reasonable detail.

I think Zuinglio Lopes Ribeiro Junior likely has the right solution and I am hoping he might be able to respond to my recent post since his apex.execute() approach above might solve one of my problems!
sam_Adminsam_Admin
Thank you Zuinglio and Brian that helps a lot 
Brian KoblenzBrian Koblenz
Zuinglio,

Can you please explain how the following works:

080             // Set the parent's Id

081             for (ChildSObject__c child : children) {

082                 child.ParentSObjectId__c = parent.Id;

083             }

If I just have an object (detail) that has two master detail relationships could I just assign the object's ParentSObjectId__c to a different master?  Or is there something special going on with your code that somehow knows the right "parent" to update?
 
Abhishek Kumar 469Abhishek Kumar 469
Can anyone help me for writing test class for clone button parent record to child object.