mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-09 23:06:06 +00:00
Calculate fee breakdown
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = []
|
||||
|
||||
|
||||
@@ -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) }
|
||||
|
||||
@@ -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) }
|
||||
|
||||
Reference in New Issue
Block a user