Simple Volume Pricing is an extension to Spree (a complete open source commerce solution for Ruby on Rails) that allows order quantity to determine the price for a particular product variant. For instance the variant's starting price might be $19.99, but $18 if customer orders 5 or more units or $15 if customer orders 20 or more.
Each VolumePrice contains the following values:
- Variant: Each VolumePrice is associated with a Variant, which is used to link products to particular prices.
- Starting Quantity: The minimum quantity for which this VolumePrice applies. If there is a VolumePrice with higher starting quantity that still applies to this order, it will be used instead.
- Price: The price of the variant if the line item quantity is big enough for this VolumePrice to apply.
Variant objects get a new boolean property
progressive_volume_discount
to select between two available discount
strategies.
Product objects get a boolean property
variants_use_master_discount
that controls whether the volume is calculated
per product or separately for each of it's variants.
If you want to see the extension's UI there are screenshots available.
Currently I do not release this extension as a gem. To use it add this to your Gemfile:
gem "spree_simple_volume_pricing", :git => "https://github.com/amw/spree-simple-volume-pricing.git", :tag => "v3.0.0"
By default volume discount is configured and calculated separately for all variants. There is a per-product preference that you can use if you want it to be calculated based on the sum of product's variants in the cart. This implies that the starting price and volume prices that were set for particular variants will be ignored and, instead, the product's own pricing scheme will be used.
This extension supports two discount strategies. Uniform volume discount selects one VolumePrice based on ordered quantity and applies it to all ordered units. Progressive volume discount applies different VolumePrices to different portions of the item's quantity. This means that you can charge i.e. $15 for the first three units in the cart, $13 for the next five and $10 for all additional.
Some people find progressive volume discount easier to configure. With prices applied uniformly your customers often end up in situations when it's cheaper to buy X + Y units than just X (a substantial price drop can neglect an added quantity).
Rails T-Shirt variant has a price of $19.99. Consider the following examples of volume prices:
Variant Starting Quantity Price
---------------------------------------------
Rails T-Shirt 5 18.00
Rails T-Shirt 20 15.00
Cart Contents:
Product Quantity Price Total
----------------------------------------------------------------
Rails T-Shirt 1 19.99 19.99
Order details:
Subtotal: 19.99
Cart Contents:
Product Quantity Price Total
----------------------------------------------------------------
Rails T-Shirt 5 19.99 99.95
Order details:
Volume Discount: -9.95 # 5 * (19.99 - 18.00)
Subtotal: 90.00 # 5 * 18.00
Cart Contents:
Product Quantity Price Total
----------------------------------------------------------------
Rails T-Shirt 6 19.99 119.94
Order details:
Volume Discount: -11.94 # 6 * (19.99 - 18.00)
Subtotal: 108.00 # 6 * 18.00
Cart Contents:
Product Quantity Price Total
----------------------------------------------------------------
Rails T-Shirt 20 19.99 399.80
Order details:
Volume Discount: -99.80 # 20 * (19.99 - 15.00)
Subtotal: 300.00 # 20 * 15.00
Given the same volume prices configuration as in uniform discount examples.
Cart Contents:
Product Quantity Price Total
----------------------------------------------------------------
Rails T-Shirt 6 19.99 119.94
Order details:
Volume Discount: -3.98
Subtotal: 115.96 # 4 * 19.99 + 2 * 18.00
Cart Contents:
Product Quantity Price Total
----------------------------------------------------------------
Rails T-Shirt 25 19.99 499.75
Order details:
Volume Discount: -59.79
Subtotal: 439.96 # 4 * 19.99 + 15 * 18.00 + 6 * 15.00
This extension is called Simple to differentiate it from another volume pricing extension created and maintained by the Spree Core team at RailsDog.
Simple Volume Pricing is simple to use, but gives you the same level of control. It doesn't require you to define ranges, assign them a human readable description or arrange them in order manually. You just slice the quantity continuum with points (starting quantity) between 1 and infinity. The volume price with highest starting quantity is automatically open ended. If you need to end that range just add another point with the variant's original price.
The original extension had also some issues, such as defining overlapping
ranges. The models were unnecessarily complicated. Why acts_as_list
if you can
just order volume prices by their lower quantity range end?
By default volume prices are calculated based only on the quantity of the
current order. But your business might want to allow customers to buy huge
volumes over a number of smaller orders. If you want to include quantities from
customer's past orders in volume price calculation you can overwrite
Order::variant_starting_quantity(variant)
method. By default it returns 0.
If you want to calculate customer's volume discount based on his order history from last 31 days just add this to your site's code:
Order.class_eval do
def variants_starting_quantity *variant_ids
orders = Order.complete.by_customer(self.email).between(self.created_at - 1.month + 1.day, self.created_at + 1.day)
orders.map do |o|
o.line_items.select do |li|
variant_ids.include? li.variant_id
end.map(&:quantity).sum
end.sum
end
end
Assuming the same volume prices configuration as above and uniform volume discount strategy. First order:
Product Quantity Price Total
----------------------------------------------------------------
Rails T-Shirt 8 19.99 159.92
Order details:
Volume Discount: -15.92 # 8 * (19.99 - 18.00)
Subtotal: 144.00 # 8 * 18.00
Next order during the next 31 days:
Product Quantity Price Total
----------------------------------------------------------------
Rails T-Shirt 4 19.99 79.96
Order details:
Volume Discount: -7.96 # 4 * (19.99 - 18.00)
Subtotal: 72.00 # 4 * 18.00
This extension is based on spree-volume-pricing extension. It was rewritten by Adam Wróbel of Flux Inc, but there are some bits by the original authors in the initial commit.