Thursday, July 05, 2018

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


No comments:

Post a Comment