function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
JennyK5JennyK5 

Clone Opportunity with Related lists

I am building a clone opportunity controller which is cloning opportunity, bid__c and and BidAccount__c  a parent, child and grandchild relationship. everything in the code is working fine except the grandchild records BidAccount are getting related to the old Child record ( bid)  I am not sure what I am doing wrong.
Please see the code sample below:
//This class is used to clone the Existing Opportunity and related Bids.

public class CloneOpportunityRebidController
{
   
   

    //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 Opportunity extOpportunity {get;set;}
  
    // set the id of the record that is created
    public ID newRecordId {get;set;}

    // initialize the controller
    public CloneOpportunityRebidController(ApexPages.StandardController controller)
    {
        //initialize the stanrdard controller
        this.controller = controller;
        // load the current record
        extOpportunity = (Opportunity)controller.getRecord();
        
    }

    // method called from the VF's action attribute to clone the Case
    public PageReference cloneOpportunity()
    {
        // setup the save point for rollback
        Savepoint sp = Database.setSavepoint();
        Opportunity newOpportunity;
        List <Bid__c> extBid;
        List <BidAccount__c>extOpportunityBidAccts;
       
        try {
   // Fetch source Opportunity fields to populate(clone)for target Opportunity           
            extOpportunity = [
                select Id,Name,LeadRating__c,OpportunityClassification__c,LeadSource
                    
                from Opportunity
                where id =: extOpportunity.id];
                 
             
            if(extOpportunity != null)
            {
                newOpportunity = extOpportunity.clone(false);
                insert newOpportunity;
                // set the id of the new Opportunity created for testing
                newRecordId = newOpportunity.id;
                   
                //newOpportunity is a copy of the opportunity with bids not copied over and extOpportunity is old opportunity
                // from which we want to copy over the bids
                //Get list of Bids from the old opportunity to populate into the new opportunity
                //extBid= the bid data from collection of Bids where the bids opportunity is equal to
                //existing opportunity

                extBid =  [
                    select ID, Opportunity__c
                    from Bid__c
                    where Opportunity__c =:extOpportunity.id];
               
         
                List<Bid__c> insertextBid = new List <Bid__c>();
               
                //extBid = the bid data from collection of bids where the bid's opportununity equals the existing opportunity
               
               
                if(extBid != null){  // if existing opportunity returned a collection of Bids
                    for(Bid__c extOpportunityBid :extBid) // Every Bid in a collection of Bid is called extOpportunityBid
                    {
                      
                      Bid__c newextOpportunityBid = extOpportunityBid.clone(False); //Made a copy of the Bid
                        newextOpportunityBid.Opportunity__c = newRecordId; 
                      
                        extOpportunityBidAccts = [
                    SELECT Bid__r.Id,Account__c,Bid__c, Bid__r.Name, Bid__r.Opportunity__c,Name
                            from BidAccount__c
                            where Bid__r.Opportunity__c =:extOpportunity.id];
                        List<BidAccount__c>insertBidAccount=new list<BidAccount__c>();
                        if(extOpportunityBidAccts != null) { 
                            for(BidAccount__c extOpportunityBidAccount :extOpportunityBidAccts) // Every Account in a collection of Bid is called extOpportunityBidAccount
                            {
                                
                                BidAccount__c newextOpportunityBidAccount = extOpportunityBidAccount.clone(False); //Made a copy of the BidAccount
                               newextOpportunityBidAccount.Bid__r.Opportunity__c= newRecordId;  
                               
                                InsertBidAccount.add(newextOpportunityBidAccount);
                                 
                            }
                            insert InsertBidAccount;
                           
                       }
                        InsertextBid.add(newextOpportunityBid);
                    }
                    insert InsertextBid;
                }
                //// Insert BidAccounts for every Bid.
    
            }
        } catch (Exception e){
            // roll everything back in case of errors
           
            Database.rollback(sp);
           
            ApexPages.addMessages(e);
           
            return null;
         }

        return new PageReference('/'+newOpportunity.id+'/e?retURL=%2F'+newOpportunity.id);
    }

}

Shashikant SharmaShashikant Sharma
You are inserting insert InsertBidAccount before insert InsertextBid; that means you are not populating Bid__c in the new BidAccount record. You need to insert Bid records first and than the insert BidAccount. To maintain the reference you need to use 

Map<Id, Index> mapIdOfOldBidrecordToIndexOfNewItems = new Map<Id, Index>();

Let me know if you have issues.
JennyK5JennyK5
Thank you so much for your reply, I have modified the code as you mentioned but it is still adding the record to the old bid record. I did not understand the mapping cocept. Please see my code below







 if(extBid != null){  // if existing opportunity returned a collection of Bids
                    for(Bid__c extOpportunityBid :extBid) // Every Bid in a collection of Bid is called extOpportunityBid
                    {
                      
                      Bid__c newextOpportunityBid = extOpportunityBid.clone(False); //Made a copy of the Bid
                        newextOpportunityBid.Opportunity__c = newRecordId;
                        InsertextBid.add(newextOpportunityBid);
                    }
                    insert InsertextBid;
                }
                      
                        extOpportunityBidAccts = [
                    SELECT Bid__r.Id,Account__c,Bid__c, Bid__r.Name, Bid__r.Opportunity__c,Name
                            from BidAccount__c
                            where Bid__r.Opportunity__c =:extOpportunity.id];
                       
                        List<BidAccount__c>insertBidAccount=new list<BidAccount__c>();
                        if(extOpportunityBidAccts != null) { 
                            for(BidAccount__c extOpportunityBidAccount :extOpportunityBidAccts) // Every Account in a collection of Bid is called extOpportunityBidAccount
                            {
                                
                                BidAccount__c newextOpportunityBidAccount = extOpportunityBidAccount.clone(False);
                                //Made a copy of the BidAccount
                                  Map<Id, Name> mapIdOfOldBidrecordToNameOfNewItems = new Map<Id, Name>();
                               newextOpportunityBidAccount.Bid__r.Opportunity__c= newRecordId;
                             
        
                                InsertBidAccount.add(newextOpportunityBidAccount);
                            }
                            }
                            insert InsertBidAccount;
                       
                       }
Shashikant SharmaShashikant Sharma
Update some of your code as below : 

In this loop 
//initialize the map 
Map<Id, Index> mapIdOfOldBidrecordToIndexOfNewItems = new Map<Id, Index>();
for(Bid__c extOpportunityBid :extBid) // Every Bid in a collection of Bid is called extOpportunityBid
                    {
                     
                      Bid__c newextOpportunityBid = extOpportunityBid.clone(False); //Made a copy of the Bid
                        newextOpportunityBid.Opportunity__c = newRecordId;
                        InsertextBid.add(newextOpportunityBid);
                        //fill the map
                         mapIdOfOldBidRecordToIndexOfNewItems.put( extOpportunityBid.Id, InsertextBid.size() - 1 ) ;
                    }



in this loop

For( BidAccount__c extOpportunityBidAccts = [
                    SELECT Bid__r.Id,Account__c,Bid__c, Bid__r.Name, Bid__r.Opportunity__c,Name
                            from BidAccount__c
                            where Bid__r.Opportunity__c =:extOpportunity.id] ) {

// add this code instead of newextOpportunityBidAccount.Bid__r.Opportunity__c= newRecordId;

Integer indexOfBidInserted = mapIdOfOldBidRecordToIndexOfNewItems.get(extOpportunityBidAccts.Bid__c);
if( indexOfBidInserted != null ) {
     newextOpportunityBidAccount.Bid__c = InsertextBid.get(indexOfBidInserted).Id;
}

}


If there are any compile error resolve them or let me know if you have issues.


JennyK5JennyK5
Thank you again for sending the code, Only error I am getting now is unexpected token "catch" error.
Shashikant SharmaShashikant Sharma
It just that some } needs to be closed or something before catch block starts. try to see each brace start and end and make sure every thing is closed properly before catch starts.
JennyK5JennyK5
I fixed the brackets but I get an error of invalid type index error type,  on this line: Map<Id, Index> mapIdOfOldBidrecordToIndexOfNewItems = new Map<Id, Index>();
Thanks a lot for your patience! 
JennyK5JennyK5
Hi Shashikant,

I wanted to find out if there is any other suggestion because I am getting invalid Type Index error. the object Bid__c is a custom  object and BidAccount__c is also a custom object, 
Please see the updated code below;
if(extBid != null){  // if existing opportunity returned a collection of Bids
               Map<Id, Index> mapIdOfOldBidrecordToIndexOfNewItems = new Map<Id, Index>();  //initialize the map
                    for(Bid__c extOpportunityBid :extBid) // Every Bid in a collection of Bid is called extOpportunityBid
                    {
                       Bid__c newextOpportunityBid = extOpportunityBid.clone(False); //Made a copy of the Bid
                        newextOpportunityBid.Opportunity__c = newRecordId;
                        InsertextBid.add(newextOpportunityBid);
                       mapIdOfOldBidRecordToIndexOfNewItems.put( extOpportunityBid.Id, InsertextBid.size() - 1 ) ;  //fill the map
                    }
                    insert InsertextBid;
                }
                      
                        extOpportunityBidAccts = [SELECT Bid__r.Id,Account__c,Bid__c, Bid__r.Name, Bid__r.Opportunity__c,Name
                            from BidAccount__c where Bid__r.Opportunity__c =:extOpportunity.id];
                       
                        List<BidAccount__c>insertBidAccount=new list<BidAccount__c>();
                        if(extOpportunityBidAccts != null)
                        {
                            for(BidAccount__c extOpportunityBidAccount :extOpportunityBidAccts) // Every Account in a collection of Bid is called extOpportunityBidAccount
                            {
                                
                             BidAccount__c newextOpportunityBidAccount = extOpportunityBidAccount.clone(False); //Made a copy of the BidAccount
                            Integer indexOfBidInserted = mapIdOfOldBidRecordToIndexOfNewItems.get(extOpportunityBidAccts.Bid__c);
       if( indexOfBidInserted != null ) {
           newextOpportunityBidAccount.Bid__c = InsertextBid.get(indexOfBidInserted).Id;
}
                                {
             newextOpportunityBidAccount.Bid__c = InsertextBid.get(IdOfBidInserted).Id;
                                }
                            }
                        }
                    insert InsertBidAccount;
             }