Salesforce Pricing Enhancements

The Salesforce Summer ’14 release is right around the corner.  This article details two new features related to products and pricing: creating PricebookEntry records in unit tests and PricebookEntry custom fields.  Visit the Summer ’14 Release page for general information about the release.

SeeAllData=true Not Needed For PricebookEntry

PricebookEntry records can now be created in unit tests without using the @isTest(SeeAllData=true) annotation. This is a huge win for the best practice of isolating test data from org data. A PricebookEntry cannot be inserted unless there is a standard PricebookEntry already.  If it is attempted, a DmlException will be generated with an error message “FIELD_INTEGRITY_EXCEPTION, No standard price defined for this product”.  Prior to Summer ’14, the only way to create a standard PricebookEntry was to use the SeeAllData=true annotation, query for the standard pricebook to get its Id, and then set the PricebookEntry’s Pricebook2Id field to the standard Id. The method Test.getStandardPricebookId() is new in Summer ’14 and can be used to get the standard pricebook Id.  From now on, PricebookEntry records should be created in unit tests using this method to get the standard pricebook Id.  The method is available for classes that are in previous API versions, as well, if you wish to refactor.  If your code uses a single mechanism such as a TestUtils class to set up the data for unit tests, you can just modify it to start using the Test.getStandardPricebookId() and then change the unit test methods to no longer specify SeeAllData=true. Here is an example of how the new method can be used in data set up for a unit test.  The example has a contrived unit test that creates products, standard prices, and non-standard prices.  A TestUtils class does the work of creating the records for the unit test.  Note the use of the Test.getStandardPricebookId() method to create the standard PricebookEntry records.

PricebookEntry Custom Fields

The PricebookEntry object now supports custom fields. This is a huge win for data migration and integration or just general data loading, because an external Id field can be added to the PricebookEntry.  Once added, systems that integrate with Salesforce to set prices can just specify the external Id in their updating process. The release notes describe a possible use case for custom fields on PricebookEntry as having start and end effective date fields.  Entries in the pricebook could then be set to be valid during a certain time period.  It would be up to the functionality using the PricebookEntry to enforce the validity via code or a validation rule. Be sure to understand what it isn’t before implementing it.  Since a pricebook can only have one entry per product you cannot set up any pricing in advance for existing entries.  For example, you cannot preload all special weekly sale prices for a subset of products, with start dates in the future.  Doing so would require the same product to be in a pricebook more than once.  Likewise, you could not have multiple prices in the same pricebook at the same time (i.e., overlapping sales).  However, if your pricing is driven by integration the dates could be updated through the integration at the appropriate times, now that external Ids are supported.  Overall, support for custom fields on PricebookEntry is a huge win and there are many uses cases that can now be supported easily. In addition to custom fields, validation rules page layouts, field sets, and search layouts are available for customization.

Determining the Standard PricebookEntries in Code Under Test

The Id of the standard pricebook is available in the unit tests, but the actual record is not.  If you have code that needs to get all of the standard PricebookEntry records, you might consider something like

The problem is that in the unit test context the standard pricebook record is not available, so no record is returned from the “Pricebook2.” reference and the WHERE clause always evaluates to false and nothing is returned.  You could change your code to detect if Test.isRunningTest() and branch based on that. Something like the following.  But, that’s icky.

A better solution is to add a checkbox formula field to the PricebookEntry called something like “Is Standard”.  The value should be {!Pricebook2.IsStandard}.  Your query to get all standard PricebookEntry records would then change to the following, which works in unit tests as well as normal execution contexts.

Try It Out

The ability to create PricebookEntry records without SeeAllData=true and custom fields on PricebookEntry records are valuable new features.  If you are interested in trying the out now you can sign up for a Summer ’14 prerelease org. The release notes can be viewed in their HTML format (responsive design / mobile  friendly!) and downloaded as a PDF.

2 thoughts on “Salesforce Pricing Enhancements

Leave a Reply

Your email address will not be published. Required fields are marked *