You need to sign in to do that
Don't have an account?

Problem with TotalPrice in OpportunityLineItem
Hi everybody,
I have a problem with updating Opportunity Products. User can change the Discount, the Quantity and the Sales Price (in special cases only). The Total Price shall be calculated by the system and displayed at the VF page. In some cases Discount can be set to 100%. If so, I detected the issue that the Sales Price (OpportunityLineItem.UnitPrice, so I call it UnitPrice in the following description) is set to null by the system during the Update.
In Forum Threads and in the Documentation of the OpportunityLineItem Object I read that UnitPrice and TotalPrice must not be set both during an Update. That’s why I force the TotalPrice to be null before I update a record which is selected from the database before. Indead, this solves the problem. The UnitPrice is stored into the database as expected and TotalPrice is calculated to 0.0 which is correct. Unfortunately the next update in exactly the same manner is failing. I get an exception that the TotalPrice must not be null…
I narrowed down the behavior with a simple test class in a developer edition. There are no custom fields, no triggers and no validation rules for the object OpportunityLineItem.
Here is the code of my test class mixed with the corresponding Debug information picked out from Apex Test Runner window in the IDE (Eclipse).
static testMethod void myUnitTest() { // insert a dummy Product with PricebookEntries then check that they were created Product2 pr1 = new Product2(Name='Unit Test Product PR1 Dummy'); insert pr1; //Get the PriceBook PriceBook2 pb=[Select Name, IsStandard, IsActive, Id From Pricebook2 Where IsStandard=true Limit 1]; PricebookEntry pe1 = New PriceBookEntry(Product2Id=pr1.Id,PriceBook2Id=pb.Id,unitPrice=444.0,isactive=true); insert pe1; Account ac1 = new Account(Name='Unit Test Parent'); insert ac1; Opportunity op1 = new Opportunity(Name = 'Unit Test Parent', StageName='Prospecting', CloseDate=System.today().addDays(1), AccountId=ac1.Id); insert op1; Opportunity op1s = [SELECT ID FROM Opportunity WHERE Id=:op1.Id]; //check calculation Prices OpportunityLineItem ol1 = new OpportunityLineItem(OpportunityId=op1.Id, UnitPrice=123.00, Quantity=1,Description=null, Discount=100, PricebookEntryId=pe1.Id); System.debug(LoggingLevel.INFO, '**********Before Insert Id=null ListPrice= ' +ol1.ListPrice+' UnitPrice=' + ol1.UnitPrice+' Discount='+ol1.Discount+' TotalPrice='+ol1.TotalPrice);
14:17:14.598 (1598203000)|USER_DEBUG|[27]|INFO|**********Before Insert Id=null ListPrice= null UnitPrice=123.00 Discount=100 TotalPrice=null
insert ol1; OpportunityLineItem ol2=[Select o.UnitPrice, o.TotalPrice, o.Quantity, o.PricebookEntryId, o.ListPrice, o.Id, o.Discount From OpportunityLineItem o where o.id=:ol1.Id]; System.debug(LoggingLevel.INFO, '**********After Insert Id='+ol2.Id+ ' ListPrice= '+ol2.ListPrice+' UnitPrice=' + ol2.UnitPrice+ ' Discount='+ol2.Discount+' TotalPrice='+ol2.TotalPrice);
14:17:14.688 (1688622000)|USER_DEBUG|[34]|INFO|**********After Insert Id=00kG000000HBCU9IAP ListPrice= 444.00 UnitPrice=123.00 Discount=100.00 TotalPrice=0.00
OKAY
Update ol2; OpportunityLineItem ol3=[Select o.UnitPrice, o.TotalPrice, o.Quantity, o.PricebookEntryId, o.ListPrice, o.Id, o.Discount From OpportunityLineItem o where o.id=:ol2.Id]; System.debug(LoggingLevel.INFO, '**********After Update ' +ol3.Id+'ListPrice= '+ol3.ListPrice+ ' UnitPrice=' + ol3.UnitPrice+' Discount='+ol3.Discount+' TotalPrice=' +ol3.TotalPrice);
14:17:14.739 (1739783000)|USER_DEBUG|[42]|INFO|**********After Update 00kG000000HBCU9IAPListPrice= 444.00 UnitPrice=null Discount=100.00 TotalPrice=0.00
Problem: UnitPrice is set to null. Trying to hide this by setting TotalPrice to null:
//Try to set TotalPrice to null because it's 0.0 after update ol2.TotalPrice=null; Update ol2; ol3=[Select o.UnitPrice, o.TotalPrice, o.Quantity, o.PricebookEntryId, o.ListPrice,o.Id, o.Discount From OpportunityLineItem o where o.id=:ol2.Id]; System.debug(LoggingLevel.INFO, '**********After Update with TotalPrice set to null ' +ol3.Id+'ListPrice= '+ol3.ListPrice+ ' UnitPrice=' + ol3.UnitPrice+' Discount='+ol3.Discount+' TotalPrice=' +ol3.TotalPrice);
14:17:14.790 (1790286000)|USER_DEBUG|[50]|INFO|**********After Update with TotalPrice set to null 00kG000000HBCU9IAPListPrice= 444.00 UnitPrice=123.00 Discount=100.00 TotalPrice=0.00
OKAY! But what if user updates a second time:
//Try to set TotalPrice to null again because it's 0.0 after update ol2.TotalPrice=null; Update ol2; ol3=[Select o.UnitPrice, o.TotalPrice, o.Quantity, o.PricebookEntryId, o.ListPrice,o.Id, o.Discount From OpportunityLineItem o where o.id=:ol2.Id]; System.debug(LoggingLevel.INFO, '**********After 2. Update with TotalPrice set to null ' +ol3.Id+'ListPrice= '+ol3.ListPrice+ ' UnitPrice=' + ol3.UnitPrice+' Discount='+ol3.Discount+' TotalPrice=' +ol3.TotalPrice); } }
14:17:15.099 (2099067000)|FATAL_ERROR|System.DmlException: Update failed. First exception on row 0 with id 00kG000000HBCU9IAP; first error: FIELD_INTEGRITY_EXCEPTION, field integrity exception: TotalPrice (total price must be specified): [TotalPrice]
Why can't I update the same record twice with TotalPrice set to null? Maybe I'm wrong with anything...
Any explainings for this behavior? I urgently need an idea how to solve this trouble. Seems to be the same problem in Winter’12 and Spring ’12.
Thanks in advance,
Elke
From what I remember when playing around with these fields, updating one also updates the other.
So when you're setting TotalPrice to null, it's doing a lot of other work that you're probably not anticipating.
In your first call, you're not setting TotalPrice to null, you're just not assigning it. Why don't you do that in your second call? What is the point of setting it to null explicitly?
My application does following (not exciting things, a very common workflow): Selecting all OpportunityLineItems for an Opportunity from the database, display at a VF Page. If a user is changing something (e.g. Discount or Quantity) this OpportunityLineItem has to be updated. Since this record has been already inserted and selected again, the field TotalPrice is filled with a value (in case of 100% Discount it's filled with 0.0). Updating this record with this TotalPrice, Unitprice and all other fields results in setting UnitPrice to null during the Save. That's why I tried to set TotalPrice to null before updating - at least it shall be calculated once again during the Save based on the actual field values...
Tried one thing more today: created a new OpportunityLineItem record, filled all my sected values in it but without assigning a TotalPrice as you suggested. In this case I have the problem again with the UnitPrice is set to null:
results in following:
07:46:37.168 (1168081000)|USER_DEBUG|[34]|INFO|**********After Insert Id=00kG000000HBEdYIAX ListPrice= 444.00 UnitPrice=123.00 Discount=100.00 TotalPrice=0.00
07:46:37.169 (1169129000)|USER_DEBUG|[40]|INFO|**********Before Insert of Record Copy Id=00kG000000HBEdYIAX ListPrice= null UnitPrice=123.00 Discount=100.00 TotalPrice=null
07:46:37.216 (1216018000)|USER_DEBUG|[48]|INFO|**********After Upsert Record Copy 00kG000000HBEdYIAXListPrice= 444.00 UnitPrice=null Discount=100.00 TotalPrice=0.00
Any help is highly appreciated, thanks.
Elke
Hmmm, yeah...that does seem fairly straightforward, but complicated by how Salesforce updates the OpportunityLineItem object automatically. I'd say that your best bet is to look at the actions that Salesforce takes, play around with it a bit, and you should get a handle on what actions produce which results.
http://www.salesforce.com/us/developer/docs/api/Content/sforce_api_objects_opportunitylineitem.htm
@Elke,
Did you ever resolve this? I am running to a similar issue, the user creates quote line item with a 100% discount.
when the record sync's back to the opportunity, the Total Price field shows as 0.00, and the Sales Price (unit Price) is blank. If the user tries to update the OLI they get a UNIT PRICE CANNOT BE BLANK error.
I'm curious if you ever found a solution as well.