We have a client who wants to synchronize products between Salesforce and his ERP solution (Sage Office Line).

In Sage it is possible to have many graduated prices (in German we say "Staffelpreise") per product which are selected according to the amount. Say you can buy 1 iPad for $800, if you buy more than 5 iPads you get it for $750 or more than 100 iPads you pay $735 each. Very simple logic.

What the client has now for the example above, are 3 products in SF, where in the ERP is only 1. And fancy Names in SF like e. g.

  • iPad (1-5 pcs.)
  • iPad (6-99 pcs.)
  • iPad (100+ pcs.)

Now in Salesforce we have the well known Product2, Pricebook2, PricebookEntry structure and an old-school UI on opportunity for LineItems, which has as to my knowledge no bulk-price mechanisms out-of-the-box.

I see the following alternatives:

a.1) Custom Object+UI

I think a good design would be to create BulkPrice__c custom object for that purpose. The logic to fetch the relevant bulk price I would put in a custom UI (not in a trigger) to provide better UX. The data structure is very simple, the UI-replacement is more effort. Because stuff like schedules is not required, the UI can be simplified.

a.2) Custom Object+Trigger Like a.1) but use a Trigger instead a custom UI. Downside is a poorer UX due to wrong price display during addition of new products and possible interference with manual price tweaking by users.

b) keep it as-it-is

Bad data-mode with redundant products. More effort with integration-mapping. No effort for UI/Objects.

c) hacked UI (not recommended)

like a) but neither custom UI nor Trigger. Instead use just about 10 evil lines of injected javascript code to update the price. Obviously it may break later. Obviously we can't recommend it. But as always a nasty temptation...

d) Concatenate bulk prices in a text field (failed)

Populate a long textarea with bulk prices. Let the user manually copy+paste the according price. It's like c) with the hack replaced by humans. Update: this approach reders practically worthless, since a custom field in the "Add Product" or "Update all" Standard UI can only be displayed from OpportunityLineItem and not from PricebookEntry or Product2.


My question is, if there is any best practice for this scenario or if anyone of you would propose a different (better/simpler) approach?

2 Answers 2


I did the following:

  1. One Product2 record with a list price (PBE) corresponding to qty = 1
  2. A custom object called Tier__c which had a label, a min qty and a max qty
  3. A junction custom object between Product2 and Tier__c called Product_Tier_Discount__c. This had cross object formula fields for the productCode, tier__c.minQty__c, tier__c.,maxQty__c, and one new field - discount__c

All of the above was used by a VF quoting "module" where the results were then stashed in the OpportunityLineItem, with suitably adjusted unitprice based on qty entered.

If not using quoting, you could use the trigger approach on OpportunityLineItem to adjust the unitPrice based on quantity

The advantage to the above data model was it allowed the tier structure to be reused across multiple SKUs (Product2). It also allows reporting on discounts offered against the base list price for qty 1 - you could even store in OLI the base discounted price in case it is further discounted by the sales rep

If you have lots of these, a custom VF solution to manage becomes important; I seem to recall I built a CSV uploader utility to assist.


Something I have done for a customer before is similar to your scenario whereby I kept the concept of 1 product with a standard price (in your case ipad = $800). Against the product I had a series of custom records (range price) which held a lower quantity, upper quantity and price which relates to your 6-99=$750, 100+=$735. Custom VF was written to admin the ranges.

Upon adding an Opportunity Product line entry the sales price would be left as the standard price.

Using a trigger I'd work out the product range to use, find the correct sales price and update the OpportunityLineItem accordingly.

Worked ok for them!

  • Thx. The more I think about it, I come also back towards the trigger.
    – Uwe Heim
    Feb 19, 2015 at 14:36

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .