[SalesForce] Is It Impossible To Upsert OpportunityLineItem

I would love to be able to upsert records to automate some data creation for a forecasting module, specifically Opportunity and OpportunityLineItem records. But I am becoming convinced that it is not possible to do so.


When I try with the PricebookEntryId field specified on records I know don't exist yet, I still get this error:

Unable to create/update fields: PricebookEntryId. Please check the security settings of this field and verify that it is read/write for your profile or permission set.

However, if I remove it, I obviously get:

System.DmlException: Upsert failed. First exception on row 0; first error: FIELD_INTEGRITY_EXCEPTION, field integrity exception: PricebookEntryId, unknown (versions 3.0 and higher must specify pricebook entry id, others must specify product id): [PricebookEntryId, unknown]


Seems like I'm stuck between a rock and a hard place. The way I see it, my only options are to:

  • Delete every forecasting OpportunityLineItem in the system before running the calculation
  • Query all the existing records before doing my upsert, then either:
    • Separate the insert/update, and remove PricebookEntryId for existing records
    • Use a Map to store existing records, and never add them to the insert collection

None of these approaches are ideal. They add a lot of complexity for what seems like a simple roadblock. Is it really impossible to upsert the OpportunityLineItem object?

Best Answer

I've done it before by not setting the PricebookEntryId field and setting it in a Before Insert trigger (you may need to ensure this is the first code the inserted OrderLineItem recs encounter!)

The updates work because you're not setting the field and the inserts work because you set the field in a Before Insert trigger.

Here's a ridiculous example, but you could pass through enough info in custom field(s) in order to work out the correct PriceBookEntryId.

trigger MyOLITrigger on OpportunityLineItem (before insert){
    if (Trigger.IsBefore && Trigger.IsInsert)
    {
        for (OpportunityLineItem oli : Trigger.New)
        {
            if (oli.PriceBookEntryId==null){
                oli.PriceBookEntryId = '01u58000001adHDAAY';
            }
        }
    }
}
Related Topic