-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add DistributedAmount calculator for line item adjustments
This calculator allows us to use order level promotions ("Save $50 on your order") and spread that $50 over all of the line items. This calculator shoots logic off to another class to handle the calculations. Each line item needs to call out to the DistributedAmountsHandler separately which is annoying but each line item needs to be aware of the order as a whole. The calculator spreads the discount amount among each of the line items relative to their price. This means that more expensive items will receive a greater share of the discount.
- Loading branch information
1 parent
f3d600e
commit 4b00354
Showing
5 changed files
with
115 additions
and
1 deletion.
There are no files selected for viewing
54 changes: 54 additions & 0 deletions
54
backend/app/views/spree/admin/promotions/calculators/weighted_rate/_fields.html.erb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
<%= fields_for "#{prefix}[calculator_attributes]", calculator do |f| %> | ||
<%= f.label :preferred_amount %> | ||
<%= render "spree/admin/shared/number_with_currency", f: f, amount_attr: :preferred_amount, currency_attr: :preferred_currency %> | ||
<% end %> | ||
|
||
<div class="field"> | ||
<p> | ||
<%= admin_hint( | ||
calculator.model_name.human, | ||
""" | ||
<p> | ||
This amount will distributed to line items weighted relative to their | ||
price. More expensive line items will receive a greater share of the | ||
adjustment. | ||
</p> | ||
<p> | ||
For example, with three line items and a preferred amount of $15 we | ||
would end up with the following distribution: | ||
</p> | ||
<table> | ||
<thead> | ||
<tr> | ||
<th></th> | ||
<th>Price</th> | ||
<th>Weighted Adj.</th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
<tr> | ||
<td>Socks</td> | ||
<td>$5</td> | ||
<td>-$1.5</td> | ||
</tr> | ||
<tr> | ||
<td>Shoes</td> | ||
<td>$30</td> | ||
<td>-$9</td> | ||
</tr> | ||
<tr> | ||
<td>Slippers</td> | ||
<td>$15</td> | ||
<td>-$4.5</td> | ||
</tr> | ||
</tbody> | ||
</table> | ||
""" | ||
) %> | ||
|
||
This amount will be the <strong>total</strong> discount spread amongst all | ||
of the line items. | ||
</p> | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
require_dependency 'spree/calculator' | ||
|
||
# This is a calculator for line item adjustment actions. It accepts a line item | ||
# and calculates its weighted adjustment amount based on the value of the | ||
# preferred amount and the price of the other line items. More expensive line | ||
# items will receive a greater share of the preferred amount. | ||
|
||
module Spree | ||
class Calculator::DistributedAmount < Calculator | ||
preference :amount, :decimal, default: 0 | ||
preference :currency, :string, default: -> { Spree::Config[:currency] } | ||
|
||
def compute_line_item(line_item) | ||
if line_item && preferred_currency.casecmp(line_item.currency).zero? | ||
Spree::DistributedAmountsHandler.new( | ||
line_item, | ||
preferred_amount | ||
).amount | ||
else | ||
0 | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
32 changes: 32 additions & 0 deletions
32
core/spec/models/spree/calculator/distributed_amount_spec.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
require 'spec_helper' | ||
require 'shared_examples/calculator_shared_examples' | ||
|
||
describe Spree::Calculator::DistributedAmount, type: :model do | ||
describe "#compute_line_item" do | ||
subject { calculator.compute_line_item(order.line_items.first) } | ||
|
||
let(:calculator) { Spree::Calculator::DistributedAmount.new } | ||
|
||
let(:order) do | ||
FactoryGirl.create( | ||
:order_with_line_items, | ||
line_items_attributes: [{ price: 50 }, { price: 50 }, { price: 50 }] | ||
) | ||
end | ||
|
||
before do | ||
calculator.preferred_amount = 15 | ||
calculator.preferred_currency = currency | ||
end | ||
|
||
context "when the order currency matches the store's currency" do | ||
let(:currency) { "USD" } | ||
it { is_expected.to eq 5 } | ||
end | ||
|
||
context "when the order currency does not match the store's currency" do | ||
let(:currency) { "CAD" } | ||
it { is_expected.to eq 0 } | ||
end | ||
end | ||
end |