diff --git a/app/models/order_cycle.rb b/app/models/order_cycle.rb index 99a3ff7406..39fed33674 100644 --- a/app/models/order_cycle.rb +++ b/app/models/order_cycle.rb @@ -143,18 +143,27 @@ class OrderCycle < ActiveRecord::Base # -- Fees + def fees_for(variant, distributor) + enterprise_fees_for(variant, distributor).sum do |fee| + # Spree's Calculator interface accepts Orders or LineItems, + # so we meet that interface with a struct. + line_item = OpenStruct.new variant: variant, quantity: 1 + fee[:enterprise_fee].compute_amount(line_item) + end + end + def create_adjustments_for(line_item) variant = line_item.variant distributor = line_item.order.distributor - fees_for(variant, distributor).each { |fee| create_adjustment_for_fee line_item, fee[:enterprise_fee], fee[:label], fee[:role] } + enterprise_fees_for(variant, distributor).each { |fee| create_adjustment_for_fee line_item, fee[:enterprise_fee], fee[:label], fee[:role] } end private # -- Fees - def fees_for(variant, distributor) + def enterprise_fees_for(variant, distributor) fees = [] exchanges_carrying(variant, distributor).each do |exchange| diff --git a/app/models/spree/variant_decorator.rb b/app/models/spree/variant_decorator.rb index e3850d5c78..8150ce6529 100644 --- a/app/models/spree/variant_decorator.rb +++ b/app/models/spree/variant_decorator.rb @@ -12,6 +12,18 @@ Spree::Variant.class_eval do after_save :update_units + def price_with_fees(distributor, order_cycle) + price + fees_for(distributor, order_cycle) + end + + # TODO: This method seems a little redundant. Though perhaps a useful interface. + # Consider removing. + def fees_for(distributor, order_cycle) + order_cycle.fees_for(self, distributor) + end + + + # Copied and modified from Spree::Variant def options_text values = self.option_values.joins(:option_type).order("#{Spree::OptionType.table_name}.position asc") diff --git a/spec/models/order_cycle_spec.rb b/spec/models/order_cycle_spec.rb index 512298fc51..d5ee190efa 100644 --- a/spec/models/order_cycle_spec.rb +++ b/spec/models/order_cycle_spec.rb @@ -309,6 +309,22 @@ describe OrderCycle do end end + describe "calculating fees for a variant via a particular distributor" do + it "sums all the fees for the variant in the specified hub + order cycle" do + coordinator = create(:distributor_enterprise) + distributor = create(:distributor_enterprise) + order_cycle = create(:simple_order_cycle) + enterprise_fee1 = create(:enterprise_fee, amount: 20) + enterprise_fee2 = create(:enterprise_fee, amount: 3) + product = create(:simple_product) + + create(:exchange, order_cycle: order_cycle, sender: coordinator, receiver: distributor, + enterprise_fees: [enterprise_fee1, enterprise_fee2], variants: [product.master]) + + order_cycle.fees_for(product.master, distributor).should == 23 + end + end + describe "creating adjustments for a line item" do let(:oc) { OrderCycle.new } let(:variant) { double(:variant) } @@ -318,7 +334,7 @@ describe OrderCycle do it "creates adjustment for each fee" do fee = {enterprise_fee: 'ef', label: 'label', role: 'role'} - oc.should_receive(:fees_for).with(variant, distributor) { [fee] } + oc.should_receive(:enterprise_fees_for).with(variant, distributor) { [fee] } oc.should_receive(:create_adjustment_for_fee).with(line_item, 'ef', 'label', 'role') oc.send(:create_adjustments_for, line_item) @@ -335,7 +351,7 @@ describe OrderCycle do oc.stub(:coordinator_fees) { [ef3] } oc.stub(:adjustment_label_for) { 'label' } - oc.send(:fees_for, line_item.variant, distributor).should == + oc.send(:enterprise_fees_for, line_item.variant, distributor).should == [{enterprise_fee: ef1, label: 'label', role: 'supplier'}, {enterprise_fee: ef2, label: 'label', role: 'distributor'}, {enterprise_fee: ef3, label: 'label', role: 'coordinator'}] diff --git a/spec/models/spree/variant_spec.rb b/spec/models/spree/variant_spec.rb index 2075912afc..930ba631ad 100644 --- a/spec/models/spree/variant_spec.rb +++ b/spec/models/spree/variant_spec.rb @@ -2,6 +2,30 @@ require 'spec_helper' module Spree describe Variant do + describe "calculating the price with enterprise fees" do + it "returns the price plus the fees" do + distributor = double(:distributor) + order_cycle = double(:order_cycle) + + variant = Variant.new price: 100 + variant.should_receive(:fees_for).with(distributor, order_cycle) { 23 } + variant.price_with_fees(distributor, order_cycle).should == 123 + end + end + + + describe "calculating the fees" do + it "delegates to order cycle" do + distributor = double(:distributor) + order_cycle = double(:order_cycle) + variant = Variant.new + + order_cycle.should_receive(:fees_for).with(variant, distributor) { 23 } + variant.fees_for(distributor, order_cycle).should == 23 + end + end + + context "when the product has variants" do let!(:product) { create(:simple_product) } let!(:variant) { create(:variant, product: product) }