mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-27 01:43:22 +00:00
Extract application of enterprise fees as adjustments into its own class
This commit is contained in:
@@ -35,6 +35,10 @@ class Exchange < ActiveRecord::Base
|
||||
receiver == order_cycle.coordinator
|
||||
end
|
||||
|
||||
def role
|
||||
incoming? ? 'supplier' : 'distributor'
|
||||
end
|
||||
|
||||
def to_h(core=false)
|
||||
h = attributes.merge({ 'variant_ids' => variant_ids.sort, 'enterprise_fee_ids' => enterprise_fee_ids.sort })
|
||||
h.reject! { |k| %w(id order_cycle_id created_at updated_at).include? k } if core
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
require 'open_food_network/enterprise_fee_applicator'
|
||||
|
||||
class OrderCycle < ActiveRecord::Base
|
||||
belongs_to :coordinator, :class_name => 'Enterprise'
|
||||
has_and_belongs_to_many :coordinator_fees, :class_name => 'EnterpriseFee', :join_table => 'coordinator_fees'
|
||||
@@ -144,12 +146,12 @@ class OrderCycle < ActiveRecord::Base
|
||||
|
||||
# -- Fees
|
||||
def fees_for(variant, distributor)
|
||||
enterprise_fees_for(variant, distributor).sum do |fee|
|
||||
enterprise_fees_for(variant, distributor).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)
|
||||
fee[:enterprise_fee].compute_amount(line_item)
|
||||
applicator.enterprise_fee.compute_amount(line_item)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -157,7 +159,7 @@ class OrderCycle < ActiveRecord::Base
|
||||
variant = line_item.variant
|
||||
distributor = line_item.order.distributor
|
||||
|
||||
enterprise_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 { |applicator| applicator.create_line_item_adjustment(line_item) }
|
||||
end
|
||||
|
||||
private
|
||||
@@ -168,31 +170,17 @@ class OrderCycle < ActiveRecord::Base
|
||||
|
||||
exchanges_carrying(variant, distributor).each do |exchange|
|
||||
exchange.enterprise_fees.each do |enterprise_fee|
|
||||
role = exchange.incoming? ? 'supplier' : 'distributor'
|
||||
fees << {enterprise_fee: enterprise_fee,
|
||||
label: adjustment_label_for(variant, enterprise_fee, role),
|
||||
role: role}
|
||||
fees << OpenFoodNetwork::EnterpriseFeeApplicator.new(enterprise_fee, variant, exchange.role)
|
||||
end
|
||||
end
|
||||
|
||||
coordinator_fees.each do |enterprise_fee|
|
||||
fees << {enterprise_fee: enterprise_fee,
|
||||
label: adjustment_label_for(variant, enterprise_fee, 'coordinator'),
|
||||
role: 'coordinator'}
|
||||
fees << OpenFoodNetwork::EnterpriseFeeApplicator.new(enterprise_fee, variant, 'coordinator')
|
||||
end
|
||||
|
||||
fees
|
||||
end
|
||||
|
||||
def create_adjustment_for_fee(line_item, enterprise_fee, label, role)
|
||||
a = enterprise_fee.create_locked_adjustment(label, line_item.order, line_item, true)
|
||||
AdjustmentMetadata.create! adjustment: a, enterprise: enterprise_fee.enterprise, fee_name: enterprise_fee.name, fee_type: enterprise_fee.fee_type, enterprise_role: role
|
||||
end
|
||||
|
||||
def adjustment_label_for(variant, enterprise_fee, role)
|
||||
"#{variant.product.name} - #{enterprise_fee.fee_type} fee by #{role} #{enterprise_fee.enterprise.name}"
|
||||
end
|
||||
|
||||
def exchanges_carrying(variant, distributor)
|
||||
exchanges.to_enterprises([coordinator, distributor]).with_variant(variant)
|
||||
end
|
||||
|
||||
16
lib/open_food_network/enterprise_fee_applicator.rb
Normal file
16
lib/open_food_network/enterprise_fee_applicator.rb
Normal file
@@ -0,0 +1,16 @@
|
||||
module OpenFoodNetwork
|
||||
class EnterpriseFeeApplicator < Struct.new(:enterprise_fee, :variant, :role)
|
||||
def create_line_item_adjustment(line_item)
|
||||
a = enterprise_fee.create_locked_adjustment(adjustment_label, line_item.order, line_item, true)
|
||||
AdjustmentMetadata.create! adjustment: a, enterprise: enterprise_fee.enterprise, fee_name: enterprise_fee.name, fee_type: enterprise_fee.fee_type, enterprise_role: role
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
def adjustment_label
|
||||
"#{variant.product.name} - #{enterprise_fee.fee_type} fee by #{role} #{enterprise_fee.enterprise.name}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
37
spec/lib/open_food_network/enterprise_fee_applicator_spec.rb
Normal file
37
spec/lib/open_food_network/enterprise_fee_applicator_spec.rb
Normal file
@@ -0,0 +1,37 @@
|
||||
require 'open_food_network/enterprise_fee_applicator'
|
||||
|
||||
module OpenFoodNetwork
|
||||
describe EnterpriseFeeApplicator do
|
||||
it "creates an adjustment for a line item" do
|
||||
line_item = create(:line_item)
|
||||
enterprise_fee = create(:enterprise_fee)
|
||||
product = create(:simple_product)
|
||||
|
||||
efa = EnterpriseFeeApplicator.new enterprise_fee, product.master, 'role'
|
||||
efa.stub(:adjustment_label) { 'label' }
|
||||
efa.create_line_item_adjustment line_item
|
||||
|
||||
adjustment = Spree::Adjustment.last
|
||||
adjustment.label.should == 'label'
|
||||
adjustment.adjustable.should == line_item.order
|
||||
adjustment.source.should == line_item
|
||||
adjustment.originator.should == enterprise_fee
|
||||
adjustment.should be_mandatory
|
||||
|
||||
md = adjustment.metadata
|
||||
md.enterprise.should == enterprise_fee.enterprise
|
||||
md.fee_name.should == enterprise_fee.name
|
||||
md.fee_type.should == enterprise_fee.fee_type
|
||||
md.enterprise_role.should == 'role'
|
||||
end
|
||||
|
||||
it "makes adjustment labels" do
|
||||
variant = double(:variant, product: double(:product, name: 'Bananas'))
|
||||
enterprise_fee = double(:enterprise_fee, fee_type: 'packing', enterprise: double(:enterprise, name: 'Ballantyne'))
|
||||
|
||||
efa = EnterpriseFeeApplicator.new enterprise_fee, variant, 'distributor'
|
||||
|
||||
efa.send(:adjustment_label).should == "Bananas - packing fee by distributor Ballantyne"
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -62,6 +62,20 @@ describe Exchange do
|
||||
end
|
||||
end
|
||||
|
||||
describe "reporting its role" do
|
||||
it "returns 'supplier' when it is an incoming exchange" do
|
||||
e = Exchange.new
|
||||
e.stub(:incoming?) { true }
|
||||
e.role.should == 'supplier'
|
||||
end
|
||||
|
||||
it "returns 'distributor' when it is an outgoing exchange" do
|
||||
e = Exchange.new
|
||||
e.stub(:incoming?) { false }
|
||||
e.role.should == 'distributor'
|
||||
end
|
||||
end
|
||||
|
||||
describe "scopes" do
|
||||
let(:supplier) { create(:supplier_enterprise) }
|
||||
let(:coordinator) { create(:distributor_enterprise) }
|
||||
|
||||
@@ -348,9 +348,9 @@ describe OrderCycle do
|
||||
let(:line_item) { double(:line_item, variant: variant, order: order) }
|
||||
|
||||
it "creates adjustment for each fee" do
|
||||
fee = {enterprise_fee: 'ef', label: 'label', role: 'role'}
|
||||
oc.should_receive(:enterprise_fees_for).with(variant, distributor) { [fee] }
|
||||
oc.should_receive(:create_adjustment_for_fee).with(line_item, 'ef', 'label', 'role')
|
||||
applicator = double(:enterprise_fee_applicator)
|
||||
applicator.should_receive(:create_line_item_adjustment).with(line_item)
|
||||
oc.should_receive(:enterprise_fees_for).with(variant, distributor) { [applicator] }
|
||||
|
||||
oc.send(:create_adjustments_for, line_item)
|
||||
end
|
||||
@@ -360,44 +360,16 @@ describe OrderCycle do
|
||||
ef1 = double(:enterprise_fee)
|
||||
ef2 = double(:enterprise_fee)
|
||||
ef3 = double(:enterprise_fee)
|
||||
incoming_exchange = double(:exchange, enterprise_fees: [ef1], incoming?: true)
|
||||
outgoing_exchange = double(:exchange, enterprise_fees: [ef2], incoming?: false)
|
||||
incoming_exchange = double(:exchange, enterprise_fees: [ef1], role: 'supplier')
|
||||
outgoing_exchange = double(:exchange, enterprise_fees: [ef2], role: 'distributor')
|
||||
|
||||
oc.stub(:exchanges_carrying) { [incoming_exchange, outgoing_exchange] }
|
||||
oc.stub(:coordinator_fees) { [ef3] }
|
||||
oc.stub(:adjustment_label_for) { 'label' }
|
||||
|
||||
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'}]
|
||||
end
|
||||
|
||||
it "creates an adjustment for a fee" do
|
||||
line_item = create(:line_item)
|
||||
enterprise_fee = create(:enterprise_fee)
|
||||
|
||||
oc.send(:create_adjustment_for_fee, line_item, enterprise_fee, 'label', 'role')
|
||||
|
||||
adjustment = Spree::Adjustment.last
|
||||
adjustment.label.should == 'label'
|
||||
adjustment.adjustable.should == line_item.order
|
||||
adjustment.source.should == line_item
|
||||
adjustment.originator.should == enterprise_fee
|
||||
adjustment.should be_mandatory
|
||||
|
||||
md = adjustment.metadata
|
||||
md.enterprise.should == enterprise_fee.enterprise
|
||||
md.fee_name.should == enterprise_fee.name
|
||||
md.fee_type.should == enterprise_fee.fee_type
|
||||
md.enterprise_role.should == 'role'
|
||||
end
|
||||
|
||||
it "makes adjustment labels" do
|
||||
variant = double(:variant, product: double(:product, name: 'Bananas'))
|
||||
enterprise_fee = double(:enterprise_fee, fee_type: 'packing', enterprise: double(:enterprise, name: 'Ballantyne'))
|
||||
|
||||
oc.send(:adjustment_label_for, variant, enterprise_fee, 'distributor').should == "Bananas - packing fee by distributor Ballantyne"
|
||||
[OpenFoodNetwork::EnterpriseFeeApplicator.new(ef1, line_item.variant, 'supplier'),
|
||||
OpenFoodNetwork::EnterpriseFeeApplicator.new(ef2, line_item.variant, 'distributor'),
|
||||
OpenFoodNetwork::EnterpriseFeeApplicator.new(ef3, line_item.variant, 'coordinator')]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user