Prady
Prady

Reputation: 11330

Clone an opportunity and its lineitems programatically in salesforce

I have a scenario where i need to clone a opportunity and its lineitems when the contract End date is today. The opp line item has field called Product_Family_c. i would have to clone only those opp whose lineitems have renewaltype_c as monthly. I am stuck at how i can clone over the oli items and assign the new oppty ids to the oli items.

   todays=date.today();
    system.debug('todays'+todays);      
    for(opportunity o:[select Auto_Renew__c,Contract_lenght_in_months__c,Contract_End_Date__c,id from opportunity where Auto_Renew__c='Yes' and Contract_End_Date__c =:todays ])
    {
        SetOppId.add(o.id);
        MapOpp.put(o.id,o);
    }
    system.debug('SetOppId'+SetOppId);
    system.debug('MapOpp'+MapOpp);
    for(OpportunityLineItem oli:[select OpportunityId from OpportunityLineItem where Product_Family__c='Monthly' and OpportunityId in :SetOppId])
    {
        SetOppIdtoRenew.add(oli.OpportunityId);
        Mapoli.put(oli.id,oli);

    }
    system.debug('SetOppIdtoRenew'+SetOppIdtoRenew);
    for(id a:SetOppIdtoRenew)
    {
        //MapOpp.get(a).Contract_End_Date__c=MapOpp.get(a).Contract_End_Date__c.addDays(1);
        //MapOpp.get(a).Contract_End_Date__c=MapOpp.get(a).Contract_End_Date__c.addMonths(integer.valueof(MapOpp.get(a).Contract_lenght_in_months__c));
        Lstopp.add(new opportunity(name=MapOpp.get(a).name+' renewal '+string.valueof(date.today()),
                                 Contract_lenght_in_months__c=MapOpp.get(a).Contract_lenght_in_months__c,
                                 Contract_End_Date__c=MapOpp.get(a).Contract_End_Date__c.addMonths(integer.valueof(MapOpp.get(a).Contract_lenght_in_months__c))+1,
                                 StageName=MapOpp.get(a).StageName,
                                 CloseDate=MapOpp.get(a).CloseDate
                            //   ,<fieldname>=MapOpp.get(a).<fieldname>... for all the fields you ned to copy over
                                 ));

    }
    system.debug('Lstopp'+Lstopp);
    insert Lstopp;

Upvotes: 1

Views: 6890

Answers (1)

mmix
mmix

Reputation: 6298

You were thinking in the right direction. However, before you assign OppID to line item you must insert the opportunity. I imagine this kind of breaks your transactional control, but you can always use Database save points to make the whole operation atomic.

For example:

    SavePoint sp = Database.setSavepoint();
    try {
        upsert newOpportunities;
        // now create line items and assign IDs
    }   
    catch (Exception ex) {
        Database.rollback(sp);      
        // cleanup
    }

In order to map old opportunities to new ones, you need a Map<ID, Opportunity> and a List and fill them with the same new opportunities to eb able to reuse new IDs in a mapping manner (I used pseudo code, if you have trouble interpreting it, let me know)

foreach(oldopp) {
   newopp = clone oldopp;
   list.add(newopp);
   map.put(oldopp.id, newopp);
}
upsert list;
// now we have new oppids for cloned items, use them to map

foreach(oldlineitem) {
   newlineitem = clone oldlineitem;
   newlineitem.OpportunityId = map.get(oldlineitem.OpportunityId).Id;
   ...
}
upsert listofnewlineitems;

}

Upvotes: 1

Related Questions