Skip to main content

Pricebook, Pricebook Entry and Product : Adding custom pricebook in Salesforce

Lately I worked on these object a lot and learned a lot of new things.

Some issues that we face around these object :
  • Some exceptions during data upload  such as :
    • FIELD_INTEGRITY_EXCEPTION .Message :field integrity exception: PricebookEntryId, unknown (versions 3.0 and higher must specify pricebook entry id, others must specify product id)
    • No Standard Price defined
  • Not able to retrieve standard price in test class


Understand the relationship of these object


Ignore Opportunity and Opportunity Line Item- these two object are using Price Book entry .Image credit to ForceTalk forum

PriceBook

  • Pricebook object store a list of products and services for sale.
  • A pricebook can be used in one or more different opportunities.
  • A pricebook has one or more different price entries.
  • Pricebook can be divided into type which are :
    •  Standard Price Book which is the master list of all the products and their default standard price.
    • Custom Price Book is separate list of product with custom price - called list price.


Product2

  • Product object is a catalogue of items or services for sales.
  • A product may contain one or more different sets of prices (PriceBookEntry).

PriceBookEntry

  • PricebookEntry object is a product entry in a pricebook.
  • This object allows products to be linked to standard price book or custom price book.
  • One price book entry is linked to only one product.
  • One price book entry can only appear in one pricebook.
  • One price book entry can be used in multiple line items. This also further creates flexibility for users to set their own prices.

Rules for Data Upload

  • PriceBookentry is junction object that connect Product and PriceBook so the order will be like this :
    • Insert PriceBook
    • Insert Product
    • Insert PriceBookEntry with PricebookId and Product Id

Scenario 1 : I am not able to insert PriceBookEntry for custom PriceBook.

We already have custom PriceBook and Product data inserted but we not able to insert PriceBookEntry to link these two objects

Reason : In order to insert PriceBookEntry for custom PriceBook , those Products must be added to Standard PriceBook first because Standard PriceBook is considered as master price. 

Refer knowledge articles here : 

Scenario 2 : Standard Price is not querable and insertable in test class

Well nothing I can do much because this how it works currently. But I can give some advice :

If the code contains SOQL on Pricebook make sure it get surrounded with try and catch. Add Test.isRunningTest() checking in the code and assign Standard Price Book.
If you have custom price you may want get an idea how to handle catch based on code below

 catch (Exception e){
   if(Test.isRunningTest()){
      List<Pricebook2>  listPB= [ select Id ,Name , IsStandard from Pricebook2 where Name ='Custom'  LIMIT 1];
      mapPriceBook.put('Standard',Test.getStandardPricebookId() );
      mapPriceBook.put('Custom',listPB[0].Id);
    
   }
 }

Also avoid retrieve and using PriceBook object but use Id.

Example of code that you want to avoid.Note that there is no way for you to get away with Test class exception because you only can use Test.getStandardPriceBookId() , not the whole object in test class.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
List<Pricebook2> listPB = [select Id ,Name , IsStandard from Pricebook2 where IsStandard = True OR  Name ='Custom'  LIMIT 2];

static  Map<String,Pricebook2> mapPriceBook =new Map<String,Pricebook2> ();

for(Pricebook2 pb : listPB){

if(pb.IsStandard){
  mapPriceBook.put('Standard',pb); //this will not get over the test class
}
else if(pb.Name =='Custom'){
 mapPriceBook.put('Custom',pb);
}

One way to be safe is using Id.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
List<Pricebook2> listPB = [select Id ,Name , IsStandard from Pricebook2 where IsStandard = True OR  Name ='Custom'  LIMIT 2];

static  Map<String,Id> mapPriceBook =new Map<String,Id> ();
             
             for(Pricebook2 pb : listPB){
             
               if(pb.IsStandard){
                  mapPriceBook.put('Standard',pb.Id);
               }
               else if(pb.Name =='Custom'){
                 mapPriceBook.put('Custom',pb.Id);
               }

I think that's all I can think today. I believe you also got some of tips and trick to get over exception related to these objects. Please let me know how you do that?

References


Comments

Popular posts from this blog

Search Solution Basics

When is it a good time to create a customized search solution? You're developing an external knowledge base for user support. You're in the mood for a fun Friday night. The sales reps just started using the Sales Cloud in Lightning Experience. You want to put your company branding in the search bar. What differentiates SOSL from SOQL? Syntax SOSL searches the search index instead of the org database. SOSL searches more efficiently when you don't know in which object the data resides. All of the above. SOSL works with: REST only SOAP only REST, SOAP, and Apex SOQL only What does a search for a single object look like in SOSL? FIND {cloud} RETURNING Account FIND in ACCOUNT RETURNING "cloud" FIND "cloud" in ACCOUNT FIND (cloud) RIGHT NOW! What does a search for multiple objects look like in SOSL? FIND {sneakers} RETURNING ALL ARTICLES FIND {sneakers} in ALL OBJECTS FIND {sneakers} RETURNING Product2, Content

Process Builder is not fired when field update is called from Approval Process

Scenario In Final Approvals section ; in Approval Process we have field update to update Status field. In Process Builder , we have some action that need to be done when Status field is updated in Approval Process.However this process builder is not fired. Solution To handle this, in Field Update in Approval Process , check Re-evaluated Workflow Rules after Field Change as picture below. What happen if field updated from Approval Process. Workflow - does not fires untill Re-evaluate workflow checkbox is ticked on your field update Process Builder - does not fires untill Re-evaluate workflow checkbox is ticked on your field update Trigger - will fire if conditions are matched This is explained in article here  . Field Updates That Re-evaluate Workflow Rules If  Re-evaluate Workflow Rules After Field Change  is enabled for a field update action, Salesforce  re-evaluates all workflow rules on the object if the field update results in a change to the value of the fi

Tips and Tricks : Test class for Invocable method

Issue : I got 100% coverage in my sandbox but when run validation for deployment it returns 0% coverage It turn out that in my sandbox, I am depending on Process Builder to Invocable Apex class, as long I manipulate test data that fire Process Builder it will call Invocable class. This is not useful when deploying it to Production although it gets deployed together with Process Builder. The correct way is to direct call Invocable method inside test class itself. Example of class : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 global class MyCustomObject_StatusUpdate_Util { @InvocableMethod ( label = ' Update Quote Status ' ) public static void updateQuote ( Request [] requests ) { Set < Id > setOppId = new Set < Id >(); List < SBQQ__Quote__c > listQuoteToUpdate = new List < SBQQ__Quote__c >(); for ( Request request : requests ) {