Charge order cycle fees

This commit is contained in:
Rohan Mitchell
2013-08-19 09:27:18 +10:00
parent dfd1a89975
commit e15e9a1476
4 changed files with 177 additions and 2 deletions

View File

@@ -58,4 +58,54 @@ class OrderCycle < ActiveRecord::Base
end
# -- Fees
def ensure_correct_adjustments_for(line_item)
EnterpriseFee.clear_all_adjustments_for line_item
create_adjustments_for line_item
end
private
# -- Fees
def create_adjustments_for(line_item)
fees_for(line_item).each { |fee| create_adjustment_for_fee line_item, fee[:enterprise_fee], fee[:label], fee[:role] }
end
def fees_for(line_item)
fees = []
# If there are multiple distributors with this variant, won't this mean that we get a fee charged for each of them?
# We just want the one matching line_item.order.distributor
exchanges_carrying(line_item.variant).each do |exchange|
exchange.enterprise_fees.each do |enterprise_fee|
role = exchange.incoming? ? 'supplier' : 'distributor'
fees << {enterprise_fee: enterprise_fee,
label: adjustment_label_for(line_item, enterprise_fee, role),
role: role}
end
end
coordinator_fees.each do |enterprise_fee|
fees << {enterprise_fee: enterprise_fee,
label: adjustment_label_for(line_item, enterprise_fee, 'coordinator'),
role: 'coordinator'}
end
fees
end
def create_adjustment_for_fee(line_item, enterprise_fee, label, role)
a = enterprise_fee.create_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(line_item, enterprise_fee, role)
"#{line_item.variant.product.name} - #{enterprise_fee.fee_type} fee by #{role} #{enterprise_fee.enterprise.name}"
end
def exchanges_carrying(variant)
exchanges.with_variant(variant)
end
end

View File

@@ -55,8 +55,13 @@ Spree::Order.class_eval do
def update_distribution_charge!
line_items.each do |line_item|
pd = product_distribution_for line_item
pd.ensure_correct_adjustment_for line_item if pd
if provided_by_order_cycle? line_item
order_cycle.ensure_correct_adjustments_for line_item
else
pd = product_distribution_for line_item
pd.ensure_correct_adjustment_for line_item if pd
end
end
end
@@ -96,6 +101,11 @@ Spree::Order.class_eval do
end
end
def provided_by_order_cycle?(line_item)
order_cycle_variants = order_cycle.andand.variants || []
order_cycle_variants.include? line_item.variant
end
def product_distribution_for(line_item)
line_item.variant.product.product_distribution_for self.distributor
end

View File

@@ -140,4 +140,77 @@ describe OrderCycle do
@oc.products.sort.should == [@p0, @p1, @p2]
end
end
describe "ensuring that a line item has the correct adjustment" do
let(:oc) { OrderCycle.new }
let(:line_item) { double(:line_item) }
it "clears all enterprise fee adjustments on the line item" do
EnterpriseFee.should_receive(:clear_all_adjustments_for).with(line_item)
oc.stub(:create_adjustments_for)
oc.ensure_correct_adjustments_for line_item
end
it "creates an adjustment on the line item" do
EnterpriseFee.stub(:clear_all_adjustments_for)
oc.should_receive(:create_adjustments_for).with(line_item)
oc.ensure_correct_adjustments_for line_item
end
end
describe "creating adjustments for a line item" do
let(:oc) { OrderCycle.new }
let(:line_item) { double(:line_item, variant: 123) }
it "creates adjustment for each fee" do
fee = {enterprise_fee: 'ef', label: 'label', role: 'role'}
oc.stub(:fees_for) { [fee] }
oc.should_receive(:create_adjustment_for_fee).with(line_item, 'ef', 'label', 'role')
oc.send(:create_adjustments_for, line_item)
end
it "finds fees for a line item" 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)
oc.stub(:exchanges_carrying) { [incoming_exchange, outgoing_exchange] }
oc.stub(:coordinator_fees) { [ef3] }
oc.stub(:adjustment_label_for) { 'label' }
oc.send(:fees_for, line_item).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
line_item = double(:line_item, 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, line_item, enterprise_fee, 'distributor').should == "Bananas - packing fee by distributor Ballantyne"
end
end
end

View File

@@ -21,6 +21,7 @@ describe Spree::Order do
it "ensures the correct adjustment(s) are created for the product distribution" do
line_item = double(:line_item)
subject.stub(:line_items) { [line_item] }
subject.stub(:provided_by_order_cycle?) { false }
product_distribution = double(:product_distribution)
product_distribution.should_receive(:ensure_correct_adjustment_for).with(line_item)
@@ -32,12 +33,53 @@ describe Spree::Order do
it "skips line items that don't have a product distribution" do
line_item = double(:line_item)
subject.stub(:line_items) { [line_item] }
subject.stub(:provided_by_order_cycle?) { false }
subject.stub(:product_distribution_for) { nil }
subject.send(:update_distribution_charge!)
end
it "ensures the correct adjustment(s) are created for order cycles" do
line_item = double(:line_item)
subject.stub(:line_items) { [line_item] }
subject.stub(:provided_by_order_cycle?) { true }
order_cycle = double(:order_cycle)
order_cycle.should_receive(:ensure_correct_adjustments_for).with(line_item)
subject.stub(:order_cycle) { order_cycle }
subject.send(:update_distribution_charge!)
end
describe "looking up whether a line item can be provided by an order cycle" do
it "returns true when the variant is provided" do
v = double(:variant)
line_item = double(:line_item, variant: v)
order_cycle = double(:order_cycle, variants: [v])
subject.stub(:order_cycle) { order_cycle }
subject.send(:provided_by_order_cycle?, line_item).should be_true
end
it "returns false otherwise" do
v = double(:variant)
line_item = double(:line_item, variant: v)
order_cycle = double(:order_cycle, variants: [])
subject.stub(:order_cycle) { order_cycle }
subject.send(:provided_by_order_cycle?, line_item).should be_false
end
it "returns false when there is no order cycle" do
v = double(:variant)
line_item = double(:line_item, variant: v)
subject.stub(:order_cycle) { nil }
subject.send(:provided_by_order_cycle?, line_item).should be_false
end
end
it "looks up product distribution enterprise fees for a line item" do
product = double(:product)
variant = double(:variant, product: product)