Skip to content
This repository has been archived by the owner on Dec 21, 2019. It is now read-only.

Commit

Permalink
Instead of changing price subtract discount from order total.
Browse files Browse the repository at this point in the history
This is a first step to allow us to apply discount differently to quantity
portions of the same variant. I.e. sell 3 first units for $10, the next three
for $9 and all the next for $8.
  • Loading branch information
Adam Wróbel committed Mar 3, 2011
1 parent 49190d2 commit 21caba7
Show file tree
Hide file tree
Showing 12 changed files with 155 additions and 43 deletions.
53 changes: 43 additions & 10 deletions README.md
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -33,31 +33,52 @@ Cart Contents:


Product Quantity Price Total Product Quantity Price Total
---------------------------------------------------------------- ----------------------------------------------------------------
Rails T-Shirt 1 20.99 19.99 Rails T-Shirt 1 19.99 19.99

Order details:

Volume Discount: 0.00
Subtotal: 19.99


## Example 2 ## Example 2


Cart Contents: Cart Contents:


Product Quantity Price Total Product Quantity Price Total
---------------------------------------------------------------- ----------------------------------------------------------------
Rails T-Shirt 5 18.00 90.00 Rails T-Shirt 5 19.99 99.95

Order details:

Volume Discount: -9.95 # 5 * (19.99 - 18)
Subtotal: 90.00


## Example 3 ## Example 3


Cart Contents: Cart Contents:


Product Quantity Price Total Product Quantity Price Total
---------------------------------------------------------------- ----------------------------------------------------------------
Rails T-Shirt 6 18.00 108.00 Rails T-Shirt 6 19.99 119.94

Order details:

Volume Discount: -11.94 # 6 * (19.99 - 18)
Subtotal: 108.00


## Example 4 ## Example 4


Cart Contents: Cart Contents:


Product Quantity Price Total Product Quantity Price Total
---------------------------------------------------------------- ----------------------------------------------------------------
Rails T-Shirt 20 15.00 300.00 Rails T-Shirt 20 19.99 399.80

Order details:

Volume Discount: -99.80 # 20 * (19.99 - 15)
Subtotal: 300.00





Why is it simple Why is it simple
Expand All @@ -78,6 +99,7 @@ The original extension had also some issues, such as defining overlapping
ranges. The models were unnecessarily complicated. Why `acts_as_list` if you can ranges. The models were unnecessarily complicated. Why `acts_as_list` if you can
just order volume prices by their lower quantity range end? just order volume prices by their lower quantity range end?



Volume Customers Volume Customers
================ ================


Expand Down Expand Up @@ -105,22 +127,33 @@ Assuming the same volume prices configuration as above. First order:


Product Quantity Price Total Product Quantity Price Total
---------------------------------------------------------------- ----------------------------------------------------------------
Rails T-Shirt 8 18.00 144.00 Rails T-Shirt 8 19.99 159.92

Order details:

Volume Discount: -15.92 # 8 * (19.99 - 18)
Subtotal: 144.00



Next order during the next 31 days: Next order during the next 31 days:


Product Quantity Price Total Product Quantity Price Total
---------------------------------------------------------------- ----------------------------------------------------------------
Rails T-Shirt 4 15.00 60.00 Rails T-Shirt 4 19.99 79.96

Order details:

Volume Discount: -7.96 # 4 * (19.99 - 18)
Subtotal: 72.00




Additional Notes Additional Notes
================ ================


* The volume price is applied based on the total quantity ordered for * The volume discount is calculated by applying the discount price to all
a particular variant. It does not (yet) apply different prices for the portion ordered units of a particular variant. It does not (yet) apply different
of the quantity that falls within a particular range. Although I plan to prices for the portion of the quantity that falls within a particular range.
support such option. Although I plan to support such option.


Authors Authors
======= =======
Expand Down
31 changes: 26 additions & 5 deletions app/models/line_item_decorator.rb
Original file line number Original file line Diff line number Diff line change
@@ -1,10 +1,31 @@
LineItem.class_eval do LineItem.class_eval do
before_update :check_volume_pricing before_save :check_update_volume_discount


private def update_volume_discount updated_order = nil
def check_volume_pricing self.volume_discount = 0
if changed? && changes.keys.include?("quantity")
self.price = variant.volume_price quantity, order return if self.quantity < 1 || variant.volume_prices.empty?

self.order = updated_order if updated_order
total_quantity = self.quantity + order.variant_starting_quantity(variant)
final_price = default_price = self.price

variant.volume_prices.each do |vp|
break if vp.starting_quantity > total_quantity
final_price = vp.price
end end

self.volume_discount = self.quantity * (final_price - default_price)
end

def amount_with_volume_discount
update_volume_discount
amount_without_volume_discount + self.volume_discount
end
alias_method_chain :amount, :volume_discount

private
def check_update_volume_discount
update_volume_discount if price_changed? || quantity_changed?
end end
end end
24 changes: 9 additions & 15 deletions app/models/order_decorator.rb
Original file line number Original file line Diff line number Diff line change
@@ -1,11 +1,7 @@
Order.class_eval do Order.class_eval do
def add_variant_with_volume_prices variant, quantity = 1 def volume_discount
current_item = add_variant_without_volume_prices variant, quantity line_items.map(&:volume_discount).sum
current_item.price = variant.volume_price current_item.quantity, self
raise ActiveRecord::RollBack unless current_item.save
update!
end end
alias_method_chain :add_variant, :volume_prices


# By default volume price is calculated based only on quantity of the current # By default volume price is calculated based only on quantity of the current
# order. If you want to have "Volume Customers" - people who purchase at # order. If you want to have "Volume Customers" - people who purchase at
Expand All @@ -19,14 +15,12 @@ def variant_starting_quantity variant
end end


# This is required for Volume Customers # This is required for Volume Customers
# It updates line items prices when user logs in # It updates item_total when user logs in
def recalculate_prices_on_user_association def update_totals_on_user_association
if user_id_changed? || email_changed? return unless user_id_changed? || email_changed?
line_items.each do |li|
li.price = li.variant.volume_price li.quantity, self line_items.each {|li| li.update_volume_discount self}
li.save update_totals
end
end
end end
before_save :recalculate_prices_on_user_association before_save :update_totals_on_user_association
end end
12 changes: 0 additions & 12 deletions app/models/variant_decorator.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -9,18 +9,6 @@


after_create :copy_master_volume_prices after_create :copy_master_volume_prices


# calculates the price based on quantity
def volume_price quantity, order = nil
quantity += order.variant_starting_quantity self if order

price = self.price
volume_prices.each do |vp|
break if vp.starting_quantity > quantity
price = vp.price
end
price
end

def blank_volume_price attributes def blank_volume_price attributes
attributes['starting_quantity'].blank? && attributes['price'].blank? attributes['starting_quantity'].blank? && attributes['price'].blank?
end end
Expand Down
17 changes: 17 additions & 0 deletions app/views/order_mailer/cancel_email.text.erb
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,17 @@
Dear Customer,

Your order has been CANCELED. Please retain this cancellation information for your records.

============================================================
Order Summary [CANCELED]
============================================================
<% for item in @order.line_items %>
<%=item.variant.sku %> <%=item.variant.product.name%> <%= variant_options(item.variant) %> (<%=item.quantity%>) @ <%= number_to_currency item.price %> = <%= number_to_currency(item.price * item.quantity) %>
<% end %>
============================================================
Volume Discount: <%= number_to_currency @order.volume_discount %>
Subtotal: <%= number_to_currency @order.item_total %>
<% @order.adjustments.each do |adjustment| %>
<%= "#{adjustment.label}: #{number_to_currency adjustment.amount}"%>
<% end %>
Order Total: <%= number_to_currency @order.total %>
20 changes: 20 additions & 0 deletions app/views/order_mailer/confirm_email.text.erb
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,20 @@
Dear Customer,

Please review and retain the following order information for your records.

============================================================
Order Summary
============================================================
<% for item in @order.line_items %>
<%=item.variant.sku %> <%=item.variant.product.name%> <%= variant_options(item.variant) %> (<%=item.quantity%>) @ <%= number_to_currency item.price %> = <%= number_to_currency(item.price * item.quantity) %>
<% end %>
============================================================
Volume Discount: <%= number_to_currency @order.volume_discount %>
Subtotal: <%= number_to_currency @order.item_total %>
<% @order.adjustments.each do |adjustment| %>
<%= "#{adjustment.label}: #{number_to_currency adjustment.amount}"%>
<% end %>
Order Total: <%= number_to_currency @order.total %>


Thank you for your business.
18 changes: 18 additions & 0 deletions app/views/orders/_cart_volume_discount.html.erb
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,18 @@
<% if @order.volume_discount != 0.0 %>
<style>
#cart-volume-discount {
float: right;
width: 30%;
text-align: left;
}
div#subtotal {
clear: both;
width: 30%;
}
</style>
<div id="cart-volume-discount">
<h3>
<%= t 'volume_discount' %>: <%= format_price @order.volume_discount %>
</h3>
</div>
<% end %>
8 changes: 8 additions & 0 deletions app/views/shared/_order_details_volume_discount.html.erb
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,8 @@
<% if @order.volume_discount != 0.0 %>
<tbody id='volume-discount'>
<tr class="total" id="volume-discount-row">
<td colspan="3"><b><%= t('volume_discount') %>:</b></td>
<td class="total"><span><%= number_to_currency @order.volume_discount %></span></td>
</tr>
</tbody>
<% end %>
1 change: 1 addition & 0 deletions config/locales/en.yml
Original file line number Original file line Diff line number Diff line change
@@ -1,5 +1,6 @@
en: en:
volume_pricing: Volume Pricing volume_pricing: Volume Pricing
volume_prices: Volume Prices volume_prices: Volume Prices
volume_discount: Volume Discount
starting_from: Starting from starting_from: Starting from
add_volume_price: Add Volume Price add_volume_price: Add Volume Price
10 changes: 10 additions & 0 deletions db/migrate/20110302170148_add_volume_discount_to_line_items.rb
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,10 @@
class AddVolumeDiscountToLineItems < ActiveRecord::Migration
def self.up
add_column :line_items, :volume_discount, :decimal,
:precision => 8, :scale => 2, :null => false, :default => 0
end

def self.down
remove_column :line_items, :volume_discount
end
end
2 changes: 2 additions & 0 deletions lib/volume_pricing_hooks.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ class VolumePricingHooks < Spree::ThemeSupport::HookListener
insert_after :admin_product_tabs, :partial => "admin/shared/vp_product_tab" insert_after :admin_product_tabs, :partial => "admin/shared/vp_product_tab"
insert_after :admin_variant_edit_form, :partial => "admin/variants/volume_prices" insert_after :admin_variant_edit_form, :partial => "admin/variants/volume_prices"
replace :product_price, :partial => "products/volume_prices" replace :product_price, :partial => "products/volume_prices"
insert_after :cart_items, :partial => "orders/cart_volume_discount"
insert_before :order_details_subtotal, :partial => "shared/order_details_volume_discount"
end end
2 changes: 1 addition & 1 deletion spree_simple_volume_pricing.gemspec
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Gem::Specification.new do |s| Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY s.platform = Gem::Platform::RUBY
s.name = 'spree_simple_volume_pricing' s.name = 'spree_simple_volume_pricing'
s.version = '1.0.0' s.version = '2.0.0'
s.summary = 'Adds volume pricing capabilities to Spree' s.summary = 'Adds volume pricing capabilities to Spree'


s.author = 'Adam Wróbel' s.author = 'Adam Wróbel'
Expand Down

0 comments on commit 21caba7

Please sign in to comment.