Calculate fee breakdown

This commit is contained in:
Rohan Mitchell
2014-07-31 10:09:46 +10:00
parent 45fd479ade
commit 8c41a6c909
5 changed files with 54 additions and 11 deletions

View File

@@ -48,6 +48,10 @@ Spree::Variant.class_eval do
OpenFoodNetwork::EnterpriseFeeCalculator.new(distributor, order_cycle).fees_for self
end
def fees_by_type_for(distributor, order_cycle)
OpenFoodNetwork::EnterpriseFeeCalculator.new(distributor, order_cycle).fees_by_type_for self
end
# Copied and modified from Spree::Variant
def options_text

View File

@@ -7,13 +7,10 @@ class Api::VariantSerializer < ActiveModel::Serializer
end
def base_price
1.00
object.price
end
def fees
{admin: 1.23, sales: 4.56, packing: 7.89, transport: 0.12}
object.fees_by_type_for(options[:current_distributor], options[:current_order_cycle])
end
end
# price_without_fees / price

View File

@@ -10,14 +10,19 @@ module OpenFoodNetwork
def fees_for(variant)
per_item_enterprise_fee_applicators_for(variant).sum do |applicator|
# Spree's Calculator interface accepts Orders or LineItems,
# so we meet that interface with a struct.
# Amount is faked, this is a method on LineItem
line_item = OpenStruct.new variant: variant, quantity: 1, amount: variant.price
applicator.enterprise_fee.compute_amount(line_item)
calculate_fee_for variant, applicator
end
end
def fees_by_type_for(variant)
per_item_enterprise_fee_applicators_for(variant).inject({}) do |fees, applicator|
fees[applicator.enterprise_fee.fee_type.to_sym] ||= 0
fees[applicator.enterprise_fee.fee_type.to_sym] += calculate_fee_for variant, applicator
fees
end
end
def create_line_item_adjustments_for(line_item)
variant = line_item.variant
@distributor = line_item.order.distributor
@@ -40,6 +45,14 @@ module OpenFoodNetwork
private
def calculate_fee_for(variant, applicator)
# Spree's Calculator interface accepts Orders or LineItems,
# so we meet that interface with a struct.
# Amount is faked, this is a method on LineItem
line_item = OpenStruct.new variant: variant, quantity: 1, amount: variant.price
applicator.enterprise_fee.compute_amount(line_item)
end
def per_item_enterprise_fee_applicators_for(variant)
fees = []

View File

@@ -8,7 +8,7 @@ module OpenFoodNetwork
let(:order_cycle) { create(:simple_order_cycle) }
let(:product) { create(:simple_product, price: 10.00) }
describe "calculating fees for a variant via a particular distribution" do
describe "calculating fees for a variant" do
it "sums all the per-item fees for the variant in the specified hub + order cycle" do
enterprise_fee1 = create(:enterprise_fee, amount: 20)
enterprise_fee2 = create(:enterprise_fee, amount: 3)
@@ -32,6 +32,21 @@ module OpenFoodNetwork
end
end
describe "calculating fees by type" do
let!(:ef_admin) { create(:enterprise_fee, fee_type: 'admin', amount: 1.23) }
let!(:ef_sales) { create(:enterprise_fee, fee_type: 'sales', amount: 4.56) }
let!(:ef_packing) { create(:enterprise_fee, fee_type: 'packing', amount: 7.89) }
let!(:ef_transport) { create(:enterprise_fee, fee_type: 'transport', amount: 0.12) }
let!(:exchange) { create(:exchange, order_cycle: order_cycle,
sender: coordinator, receiver: distributor, incoming: false,
enterprise_fees: [ef_admin, ef_sales, ef_packing, ef_transport],
variants: [product.master]) }
it "returns a breakdown of fees" do
EnterpriseFeeCalculator.new(distributor, order_cycle).fees_by_type_for(product.master).should == {admin: 1.23, sales: 4.56, packing: 7.89, transport: 0.12}
end
end
describe "creating adjustments" do
let(:order) { create(:order, distributor: distributor, order_cycle: order_cycle) }
let!(:line_item) { create(:line_item, order: order, variant: product.master) }

View File

@@ -94,6 +94,20 @@ module Spree
end
describe "calculating fees broken down by fee type" do
it "delegates to EnterpriseFeeCalculator" do
distributor = double(:distributor)
order_cycle = double(:order_cycle)
variant = Variant.new
fees = double(:fees)
OpenFoodNetwork::EnterpriseFeeCalculator.any_instance.should_receive(:fees_by_type_for).with(variant) { fees }
variant.fees_by_type_for(distributor, order_cycle).should == fees
end
end
context "when the product has variants" do
let!(:product) { create(:simple_product) }
let!(:variant) { create(:variant, product: product) }