4

I am trying to clone an opportunityLineItem but I am getting an error :

Field is not writeable: OpportunityLineItem.Product2Id

public class OppLineItem {
public OpportunityLineItem objOpportunityLineItem{get;set;}
Pricebook2 pb = [Select id from Pricebook2 where isStandard = true limit 1];
public OppLineItem(ApexPages.StandardController controller) {
    objOpportunityLineItem = [SELECT Id,Opportunityid,
    ServiceDate,Product2id,TotalPrice,ListPrice,Asset__c,UnitPrice,Quantity,Description,Product2.Name FROM OpportunityLineItem WHERE ID =:controller.getId() limit 1];
}

public PageReference onSave(){
    PricebookEntry pbe = new PricebookEntry();
    pbe.Pricebook2Id= pb.id;
    pbe.Product2Id = objOpportunityLineItem.Product2id;
    pbe.UnitPrice = 1000;
    insert pbe;
    OpportunityLineItem oliClone = new OpportunityLineItem ();
    oliClone.Opportunityid = objOpportunityLineItem.Opportunityid;
    oliClone.ServiceDate = objOpportunityLineItem.ServiceDate;
    //oliClone.Product2id = objOpportunityLineItem.Product2id;
    oliClone.TotalPrice = objOpportunityLineItem.TotalPrice;
    //oliClone.ListPrice = objOpportunityLineItem.ListPrice;
    oliClone.Asset__c = objOpportunityLineItem.Asset__c;
    oliClone.UnitPrice = objOpportunityLineItem.UnitPrice;
    oliClone.Quantity = objOpportunityLineItem.Quantity;
    oliClone.Description = objOpportunityLineItem.Description; 
    insert oliClone; 
    Pagereference pr = new PageReference('/'+oliClone.Id+'?retUrl=/'+oliClone.Id);
    pr.setRedirect(true);
    return pr;
}

}
4
  • 6
    roduct2Id is a read-only field available in API version 30.0 and later for OpportunityLineItem. Use the PricebookEntryId field instead, specifying the ID of the PricebookEntry record. Check this : salesforce.com/us/developer/docs/api/Content/…
    – Ratan Paul
    Jun 29, 2016 at 12:11
  • 5
    @Ratan - why a comment? This looks like an answer to me :-) Jun 29, 2016 at 12:23
  • yes, Ratan's comment is the answer. Always insert OLI's with PricebookentryId
    – cropredy
    Jun 29, 2016 at 14:30
  • @Guy ahh was about to add anwer for became busy with other stuffs.. thanks Added as answer
    – Ratan Paul
    Jun 29, 2016 at 14:38

2 Answers 2

3

Product2Id is a read-only field available in API version 30.0 and later for OpportunityLineItem. Use the PricebookEntryId field instead, specifying the ID of the PricebookEntry record.

Check this : https://www.salesforce.com/us/developer/docs/api/Content/sforce_api_objects_opportunitylineitem.htm

4
  • can you tell me how exactly I can do it... I am not getting how to use PricebookEntryId field...because I have made an object of PricebookEntry and its giving me an error.I am have edited my code. System.DmlException: Insert failed. First exception on row 0; first error: DUPLICATE_VALUE, This price definition already exists in this price book: []
    – Anzar
    Jun 29, 2016 at 15:30
  • @Anzar check this thread salesforce.stackexchange.com/a/68641/18731
    – Ratan Paul
    Jun 29, 2016 at 15:58
  • in test class we can use Id pricebookId = Test.getStandardPricebookId(); but what about controller
    – Anzar
    Jun 29, 2016 at 16:50
  • not pricebookId but pricebookEntryId. Copy it from objOpportunityLineItem Jun 29, 2016 at 19:12
2

You can use the sObject clone() method (link to sobject documentation).

OpportunityLineItem oliClone = objOpportunityLineItem.clone(false, true, false, false);

The clone method will copy all of the fields that you have set or queried on objOpportunityLineItem (in other words, all of the fields on the object instance in memory), so that one line takes care of most of your onSave() method.

I prefer to make a deep clone, which is why the second argument to clone() in my example is set to true. Doing this means that you can alter the values of your cloned record's relationship fields without affecting the values of the relationship fields of the original record.

Having the deep clone is important if you're going to re-parent the cloned OpportunityLineItem and also update the original OpportunityLineItem.

4
  • same error is coming.
    – Anzar
    Jun 29, 2016 at 15:35
  • @Anzar It worked for me after adding PricebookEntryId to the list of fields queried for the OpportunityLineItem being cloned (Line 5 of your provided code).
    – Derek F
    Jun 29, 2016 at 15:57
  • an error is coming System.DmlException: Insert failed. First exception on row 0; first error: FIELD_INTEGRITY_EXCEPTION, field integrity exception: unknown (only one of unit price or total price may be specified): [unknown]
    – Anzar
    Jun 29, 2016 at 16:48
  • @Anzar that error is self-explanatory, and you should be able to work out what needs to be done. One solution would be to remove one of those two fields from your initial query.
    – Derek F
    Jun 29, 2016 at 17:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .