Apex “Deep Clone” Controller

November 19th, 2009

I wrote the following code at the Admin To Hero App Building Workshop and it was very popular. I think we used the code on 3 or 4 projects that day so I thought I’d post it to help everyone out.

Essentially it is a Visualforce page and Apex Controller that allows you to do a “deep clone” of an object and it’s line items for a master-detail relationship. So I created a “Clone with Items” custom button on a page layout that invokes the Visualforce page that clones a purchase order header and its line items.

PurchaseOrderClone – Visualforce page

1
2
3
4
5
6
 
<apex:page standardController="Purchase_Order__c"
     extensions="PurchaseOrderCloneWithItemsController"
     action="{!cloneWithItems}">
     <apex:pageMessages />
</apex:page>

PurchaseOrderCloneWithItemsController – Apex controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
 
public class PurchaseOrderCloneWithItemsController {
 
    //added an instance varaible for the standard controller
    private ApexPages.StandardController controller {get; set;}
     // add the instance for the variables being passed by id on the url
    private Purchase_Order__c po {get;set;}
    // set the id of the record that is created -- ONLY USED BY THE TEST CLASS
    public ID newRecordId {get;set;}
 
    // initialize the controller
    public PurchaseOrderCloneWithItemsController(ApexPages.StandardController controller) {
 
        //initialize the stanrdard controller
        this.controller = controller;
        // load the current record
        po = (Purchase_Order__c)controller.getRecord();
 
    }
 
    // method called from the VF's action attribute to clone the po
    public PageReference cloneWithItems() {
 
         // setup the save point for rollback
         Savepoint sp = Database.setSavepoint();
         Purchase_Order__c newPO;
 
         try {
 
              //copy the purchase order - ONLY INCLUDE THE FIELDS YOU WANT TO CLONE
             po = [select Id, Name, Ship_To__c, PO_Number__c, Supplier__c, Supplier_Contact__c, Date_Needed__c, Status__c, Type_of_Purchase__c, Terms__c, Shipping__c, Discount__c from Purchase_Order__c where id = :po.id];
             newPO = po.clone(false);
             insert newPO;
 
             // set the id of the new po created for testing
               newRecordId = newPO.id;
 
             // copy over the line items - ONLY INCLUDE THE FIELDS YOU WANT TO CLONE
             List<Purchased_Item__c> items = new List<Purchased_Item__c>();
             for (Purchased_Item__c pi : [Select p.Id, p.Unit_Price__c, p.Quantity__c, p.Memo__c, p.Description__c From Purchased_Item__c p where Purchase_Order__c = :po.id]) {
                  Purchased_Item__c newPI = pi.clone(false);
                  newPI.Purchase_Order__c = newPO.id;
                  items.add(newPI);
             }
             insert items;
 
         } catch (Exception e){
             // roll everything back in case of error
            Database.rollback(sp);
            ApexPages.addMessages(e);
            return null;
         }
 
        return new PageReference('/'+newPO.id+'/e?retURL=%2F'+newPO.id);
    }
 
}

TestPurchaseOrderCloneWithController – Test class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
 
@isTest
private class TestPurchaseOrderCloneWithController {
 
    static testMethod void testPOCloneController() {
 
       // setup a reference to the page the controller is expecting with the parameters
        PageReference pref = Page.PurchaseOrderClone;
        Test.setCurrentPage(pref);
 
        // setup a ship to account
        Account shipTo = new Account();
        shipTo.Name = 'PSAV 6FOO';
        shipTo.Type = 'Supplier';
        insert shipTo;
 
        // create new po record
        Purchase_Order__c po = new Purchase_Order__c();
        po.Date_Needed__c = Date.newInstance(2020,01,01);
        po.Ship_To__c = shipTo.id;
        insert po;
 
        // create a line item for the po
        Purchased_Item__c pi1 = new Purchased_Item__c();
        pi1.Description__c = 'My item';
        pi1.Purchase_Order__c = po.id;
        pi1.Quantity__c = 1;
        pi1.Unit_Price__c = 10;
        insert pi1;
 
        // Construct the standard controller
        ApexPages.StandardController con = new ApexPages.StandardController(po);
 
        // create the controller
        PurchaseOrderCloneWithItemsController ext = new PurchaseOrderCloneWithItemsController(con);
 
        // Switch to test context
        Test.startTest();
 
        // call the cloneWithItems method
        PageReference ref = ext.cloneWithItems();
        // create the matching page reference
        PageReference redir = new PageReference('/'+ext.newRecordId+'/e?retURL=%2F'+ext.newRecordId);
 
        // make sure the user is sent to the correct url
        System.assertEquals(ref.getUrl(),redir.getUrl());
 
        // check that the new po was created successfully
        Purchase_Order__c newPO = [select id from Purchase_Order__c where id = :ext.newRecordId];
        System.assertNotEquals(newPO, null);
        // check that the line item was created
        List<Purchased_Item__c> newItems = [Select p.Id From Purchased_Item__c p where Purchase_Order__c = :newPO.id];
        System.assertEquals(newItems.size(),1);
 
        // Switch back to runtime context
        Test.stopTest();
 
    }
 
}
VN:F [1.9.3_1094]
Rating: 10.0/10 (3 votes cast)
VN:F [1.9.3_1094]
Rating: +1 (from 1 vote)
Apex "Deep Clone" Controller, 10.0 out of 10 based on 3 ratings
Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Mixx
  • Google Bookmarks
  • Blogplay

Categories: Apex, Code Sample, Salesforce, Visualforce

Leave a comment

Comments Feed2 Comments

  1. Don.at.RWD

    This is great, thanks for sharing.

    How difficult would it be to extend this to deep clone Opportunities?

    VA:F [1.9.3_1094]
    Rating: 0.0/5 (0 votes cast)
    VA:F [1.9.3_1094]
    Rating: 0 (from 0 votes)
  2. Jeff Douglas

    @Don, it’s essentially the same concept. Here are some details: http://community.salesforce.com/t5/Apex-Code-Development/Trigger-to-clone-opportunity-and-opportunity-products/m-p/117353

    VN:F [1.9.3_1094]
    Rating: 0.0/5 (0 votes cast)
    VN:F [1.9.3_1094]
    Rating: 0 (from 0 votes)

Leave a comment

Feed

http://blog.jeffdouglas.com / Apex “Deep Clone” Controller

WordPress Appliance - Powered by TurnKey Linux