From 9989b76b7dd6f96e978db9668a2ab7062b8a0821 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Fri, 6 May 2016 16:42:28 +1000 Subject: [PATCH] Integrate from Spree fork: Calculators work against LineItems --- .../flat_percent_item_total_decorator.rb | 9 +++++++++ .../spree/calculator/flexi_rate_decorator.rb | 19 +++++++++++++++++++ .../spree/calculator/per_item_decorator.rb | 15 +++++++++++++++ app/models/spree/calculator_decorator.rb | 18 ++++++++++++++++++ .../flat_percent_item_total_spec.rb | 10 ++++++++++ .../spree/calculator/flexi_rate_spec.rb | 17 +++++++++++++++++ spec/models/spree/calculator/per_item_spec.rb | 12 ++++++++++++ .../spree/calculator/price_sack_spec.rb | 17 +++++++++++++++++ 8 files changed, 117 insertions(+) create mode 100644 app/models/spree/calculator/flat_percent_item_total_decorator.rb create mode 100644 app/models/spree/calculator/flexi_rate_decorator.rb create mode 100644 app/models/spree/calculator/per_item_decorator.rb create mode 100644 app/models/spree/calculator_decorator.rb create mode 100644 spec/models/spree/calculator/flat_percent_item_total_spec.rb create mode 100644 spec/models/spree/calculator/flexi_rate_spec.rb create mode 100644 spec/models/spree/calculator/per_item_spec.rb create mode 100644 spec/models/spree/calculator/price_sack_spec.rb diff --git a/app/models/spree/calculator/flat_percent_item_total_decorator.rb b/app/models/spree/calculator/flat_percent_item_total_decorator.rb new file mode 100644 index 0000000000..9012261dab --- /dev/null +++ b/app/models/spree/calculator/flat_percent_item_total_decorator.rb @@ -0,0 +1,9 @@ +module Spree + Calculator::FlatPercentItemTotal.class_eval do + def compute(object) + item_total = line_items_for(object).map(&:amount).sum + value = item_total * BigDecimal(self.preferred_flat_percent.to_s) / 100.0 + (value * 100).round.to_f / 100 + end + end +end diff --git a/app/models/spree/calculator/flexi_rate_decorator.rb b/app/models/spree/calculator/flexi_rate_decorator.rb new file mode 100644 index 0000000000..c4ef6183c2 --- /dev/null +++ b/app/models/spree/calculator/flexi_rate_decorator.rb @@ -0,0 +1,19 @@ +module Spree + Calculator::FlexiRate.class_eval do + def compute(object) + sum = 0 + max = self.preferred_max_items.to_i + items_count = line_items_for(object).map(&:quantity).sum + items_count.times do |i| + # check max value to avoid divide by 0 errors + if (max == 0 && i == 0) || (max > 0) && (i % max == 0) + sum += self.preferred_first_item.to_f + else + sum += self.preferred_additional_item.to_f + end + end + + sum + end + end +end diff --git a/app/models/spree/calculator/per_item_decorator.rb b/app/models/spree/calculator/per_item_decorator.rb new file mode 100644 index 0000000000..ebaaf6fc1c --- /dev/null +++ b/app/models/spree/calculator/per_item_decorator.rb @@ -0,0 +1,15 @@ +module Spree + Calculator::PerItem.class_eval do + def compute(object=nil) + return 0 if object.nil? + self.preferred_amount * line_items_for(object).reduce(0) do |sum, value| + if matching_products.blank? || matching_products.include?(value.product) + value_to_add = value.quantity + else + value_to_add = 0 + end + sum + value_to_add + end + end + end +end diff --git a/app/models/spree/calculator_decorator.rb b/app/models/spree/calculator_decorator.rb new file mode 100644 index 0000000000..f8be4d00ef --- /dev/null +++ b/app/models/spree/calculator_decorator.rb @@ -0,0 +1,18 @@ +module Spree + Calculator.class_eval do + + + private + + # Given an object which might be an Order or a LineItem (amongst + # others), return a collection of line items. + def line_items_for(object) + if object.respond_to? :line_items + object.line_items + else + [object] + end + end + + end +end diff --git a/spec/models/spree/calculator/flat_percent_item_total_spec.rb b/spec/models/spree/calculator/flat_percent_item_total_spec.rb new file mode 100644 index 0000000000..02b6e5d1ae --- /dev/null +++ b/spec/models/spree/calculator/flat_percent_item_total_spec.rb @@ -0,0 +1,10 @@ + describe Spree::Calculator::FlatPercentItemTotal do + let(:calculator) { Spree::Calculator::FlatPercentItemTotal.new } + let(:line_item) { mock_model(Spree::LineItem, amount: 10) } + + before { calculator.stub :preferred_flat_percent => 10 } + + it "should compute amount correctly for a single line item" do + calculator.compute(line_item).should == 1.0 + end +end diff --git a/spec/models/spree/calculator/flexi_rate_spec.rb b/spec/models/spree/calculator/flexi_rate_spec.rb new file mode 100644 index 0000000000..a242429dca --- /dev/null +++ b/spec/models/spree/calculator/flexi_rate_spec.rb @@ -0,0 +1,17 @@ +require 'spec_helper' + +describe Spree::Calculator::FlexiRate do + let(:calculator) { Spree::Calculator::FlexiRate.new } + let(:line_item) { mock_model(Spree::LineItem, amount: 10, quantity: 4) } + + describe "computing for a single line item" do + it "returns the first item rate" do + calculator.stub preferred_first_item: 1.0 + calculator.compute(line_item).round(2).should == 1.0 + end + end + + it "allows creation of new object with all the attributes" do + Spree::Calculator::FlexiRate.new(preferred_first_item: 1, preferred_additional_item: 1, preferred_max_items: 1) + end +end diff --git a/spec/models/spree/calculator/per_item_spec.rb b/spec/models/spree/calculator/per_item_spec.rb new file mode 100644 index 0000000000..09c2fb02f6 --- /dev/null +++ b/spec/models/spree/calculator/per_item_spec.rb @@ -0,0 +1,12 @@ +require 'spec_helper' + +describe Spree::Calculator::PerItem do + let(:calculator) { Spree::Calculator::PerItem.new(preferred_amount: 10) } + let(:shipping_calculable) { double(:calculable) } + let(:line_item) { double(:line_item, quantity: 5, product: double(:product)) } + + it "correctly calculates on a single line item object" do + calculator.stub(calculable: shipping_calculable) + calculator.compute(line_item).to_f.should == 50 # 5 x 10 + end +end diff --git a/spec/models/spree/calculator/price_sack_spec.rb b/spec/models/spree/calculator/price_sack_spec.rb new file mode 100644 index 0000000000..b34771c720 --- /dev/null +++ b/spec/models/spree/calculator/price_sack_spec.rb @@ -0,0 +1,17 @@ +require 'spec_helper' + +describe Spree::Calculator::PriceSack do + let(:calculator) do + calculator = Spree::Calculator::PriceSack.new + calculator.preferred_minimal_amount = 5 + calculator.preferred_normal_amount = 10 + calculator.preferred_discount_amount = 1 + calculator + end + + let(:line_item) { stub_model(Spree::LineItem, price: 1, quantity: 2) } + + it "computes with a line item object" do + calculator.compute(line_item) + end +end