Use OrderTaxAdjustmentsFetcher service

This commit is contained in:
François Turbelin
2020-06-09 11:03:11 +02:00
parent c729f64fcf
commit 9abe41f6cb
7 changed files with 102 additions and 86 deletions

View File

@@ -44,7 +44,7 @@ module CheckoutHelper
end end
def display_checkout_taxes_hash(order) def display_checkout_taxes_hash(order)
order.tax_adjustment_totals.each_with_object({}) do |(tax_rate, tax_amount), hash| OrderTaxAdjustmentsFetcher.new(order).totals.each_with_object({}) do |(tax_rate, tax_amount), hash|
hash[number_to_percentage(tax_rate.amount * 100, precision: 1)] = Spree::Money.new tax_amount, currency: order.currency hash[number_to_percentage(tax_rate.amount * 100, precision: 1)] = Spree::Money.new tax_amount, currency: order.currency
end end
end end

View File

@@ -18,7 +18,7 @@ module Spree
where(originator_type: 'Spree::TaxRate', adjustable_type: 'Spree::LineItem') where(originator_type: 'Spree::TaxRate', adjustable_type: 'Spree::LineItem')
} }
scope :with_tax, -> { where('spree_adjustments.included_tax > 0') } scope :with_tax, -> { where('spree_adjustments.included_tax <> 0') }
scope :without_tax, -> { where('spree_adjustments.included_tax = 0') } scope :without_tax, -> { where('spree_adjustments.included_tax = 0') }
scope :payment_fee, -> { where(AdjustmentScopes::PAYMENT_FEE_SCOPE) } scope :payment_fee, -> { where(AdjustmentScopes::PAYMENT_FEE_SCOPE) }
scope :shipping, -> { where(AdjustmentScopes::SHIPPING_SCOPE) } scope :shipping, -> { where(AdjustmentScopes::SHIPPING_SCOPE) }

View File

@@ -312,24 +312,6 @@ Spree::Order.class_eval do
(adjustments + price_adjustments).sum(&:included_tax) (adjustments + price_adjustments).sum(&:included_tax)
end end
def tax_adjustments
adjustments + price_adjustments
end
def tax_adjustment_totals
tax_adjustments.each_with_object({}) do |adjustment, hash|
# No need of dealing with a missing Tax Rate if no tax setup
next if adjustment.included_tax.zero?
tax_rates = TaxRateFinder.tax_rates_of(adjustment)
tax_rates_hash = Hash[tax_rates.collect do |tax_rate|
tax_amount = tax_rates.one? ? adjustment.included_tax : tax_rate.compute_tax(adjustment.amount)
[tax_rate, tax_amount]
end]
hash.update(tax_rates_hash) { |_tax_rate, amount1, amount2| amount1 + amount2 }
end
end
def has_taxes_included def has_taxes_included
!line_items.with_tax.empty? !line_items.with_tax.empty?
end end

View File

@@ -0,0 +1,28 @@
# This class will be used to get Tax Adjustments related to an order,
# and proceed basic calcultation over them.
class OrderTaxAdjustmentsFetcher
def initialize(order)
@order = order
end
def totals
all.each_with_object({}) do |adjustment, hash|
tax_rates = TaxRateFinder.tax_rates_of(adjustment)
tax_rates_hash = Hash[tax_rates.collect do |tax_rate|
tax_amount = tax_rates.one? ? adjustment.included_tax : tax_rate.compute_tax(adjustment.amount)
[tax_rate, tax_amount]
end]
hash.update(tax_rates_hash) { |_tax_rate, amount1, amount2| amount1 + amount2 }
end
end
private
attr_reader :order
def all
order.adjustments.with_tax +
order.line_items.includes(:adjustments).map { |li| li.adjustments.with_tax }.flatten
end
end

View File

@@ -49,8 +49,9 @@ module OpenFoodNetwork
when "tax_rates" when "tax_rates"
orders.map do |order| orders.map do |order|
[order.number, order.total - order.total_tax] + [order.number, order.total - order.total_tax] +
relevant_rates.map { |rate| order.tax_adjustment_totals.fetch(rate, 0) } + relevant_rates.map { |rate|
[order.total_tax, order.total] OrderTaxAdjustmentsFetcher.new(order).totals.fetch(rate, 0)
} + [order.total_tax, order.total]
end end
else else
orders.map do |order| orders.map do |order|

View File

@@ -287,70 +287,6 @@ describe Spree::Order do
end end
end end
describe "getting a hash of all taxes" do
let(:zone) { create(:zone_with_member) }
let(:coordinator) { create(:distributor_enterprise, charges_sales_tax: true) }
let(:tax_rate10) { create(:tax_rate, included_in_price: true, calculator: Spree::Calculator::DefaultTax.new, amount: 0.1, zone: zone) }
let(:tax_rate15) { create(:tax_rate, included_in_price: true, calculator: Spree::Calculator::DefaultTax.new, amount: 0.15, zone: zone) }
let(:tax_rate20) { create(:tax_rate, included_in_price: true, calculator: Spree::Calculator::DefaultTax.new, amount: 0.2, zone: zone) }
let(:tax_rate25) { create(:tax_rate, included_in_price: true, calculator: Spree::Calculator::DefaultTax.new, amount: 0.25, zone: zone) }
let(:tax_category10) { create(:tax_category, tax_rates: [tax_rate10]) }
let(:tax_category15) { create(:tax_category, tax_rates: [tax_rate15]) }
let(:tax_category20) { create(:tax_category, tax_rates: [tax_rate20]) }
let(:tax_category25) { create(:tax_category, tax_rates: [tax_rate25]) }
let(:variant) { create(:variant, product: create(:product, tax_category: tax_category10)) }
let(:enterprise_fee) { create(:enterprise_fee, enterprise: coordinator, tax_category: tax_category20, calculator: Spree::Calculator::FlatRate.new(preferred_amount: 48.0)) }
let(:additional_adjustment) { create(:adjustment, amount: 50.0, included_tax: tax_rate25.compute_tax(50.0)) }
let(:order_cycle) { create(:simple_order_cycle, coordinator: coordinator, coordinator_fees: [enterprise_fee], distributors: [coordinator], variants: [variant]) }
let(:line_item) { create(:line_item, variant: variant, price: 44.0) }
let(:order) do
create(
:order,
line_items: [line_item],
bill_address: create(:address),
order_cycle: order_cycle,
distributor: coordinator,
adjustments: [additional_adjustment]
)
end
before do
allow(Spree::Config).to receive(:shipment_inc_vat).and_return(true)
allow(Spree::Config).to receive(:shipping_tax_rate).and_return(tax_rate15.amount)
end
let(:shipping_method) { create(:shipping_method, calculator: Spree::Calculator::FlatRate.new(preferred_amount: 46.0)) }
let!(:shipment) { create(:shipment_with, :shipping_method, shipping_method: shipping_method, order: order) }
before do
order.create_tax_charge!
order.update_distribution_charge!
end
it "returns a hash with all 3 taxes" do
expect(order.tax_adjustment_totals.size).to eq(4)
end
it "contains tax on line_item" do
expect(order.tax_adjustment_totals[tax_rate10]).to eq(4.0)
end
it "contains tax on shipping_fee" do
expect(order.tax_adjustment_totals[tax_rate15]).to eq(6.0)
end
it "contains tax on enterprise_fee" do
expect(order.tax_adjustment_totals[tax_rate20]).to eq(8.0)
end
it "contains tax on order adjustment" do
expect(order.tax_adjustment_totals[tax_rate25]).to eq(10.0)
end
end
describe "setting the distributor" do describe "setting the distributor" do
it "sets the distributor when no order cycle is set" do it "sets the distributor when no order cycle is set" do
d = create(:distributor_enterprise) d = create(:distributor_enterprise)

View File

@@ -0,0 +1,69 @@
require "spec_helper"
describe OrderTaxAdjustmentsFetcher do
describe "#totals" do
let(:zone) { create(:zone_with_member) }
let(:coordinator) { create(:distributor_enterprise, charges_sales_tax: true) }
let(:tax_rate10) { create(:tax_rate, included_in_price: true, calculator: Spree::Calculator::DefaultTax.new, amount: 0.1, zone: zone) }
let(:tax_rate15) { create(:tax_rate, included_in_price: true, calculator: Spree::Calculator::DefaultTax.new, amount: 0.15, zone: zone) }
let(:tax_rate20) { create(:tax_rate, included_in_price: true, calculator: Spree::Calculator::DefaultTax.new, amount: 0.2, zone: zone) }
let(:tax_rate25) { create(:tax_rate, included_in_price: true, calculator: Spree::Calculator::DefaultTax.new, amount: 0.25, zone: zone) }
let(:tax_category10) { create(:tax_category, tax_rates: [tax_rate10]) }
let(:tax_category15) { create(:tax_category, tax_rates: [tax_rate15]) }
let(:tax_category20) { create(:tax_category, tax_rates: [tax_rate20]) }
let(:tax_category25) { create(:tax_category, tax_rates: [tax_rate25]) }
let(:variant) { create(:variant, product: create(:product, tax_category: tax_category10)) }
let(:enterprise_fee) { create(:enterprise_fee, enterprise: coordinator, tax_category: tax_category20, calculator: Spree::Calculator::FlatRate.new(preferred_amount: 48.0)) }
let(:additional_adjustment) { create(:adjustment, amount: 50.0, included_tax: tax_rate25.compute_tax(50.0)) }
let(:order_cycle) { create(:simple_order_cycle, coordinator: coordinator, coordinator_fees: [enterprise_fee], distributors: [coordinator], variants: [variant]) }
let(:line_item) { create(:line_item, variant: variant, price: 44.0) }
let(:order) do
create(
:order,
line_items: [line_item],
bill_address: create(:address),
order_cycle: order_cycle,
distributor: coordinator,
adjustments: [additional_adjustment]
)
end
before do
allow(Spree::Config).to receive(:shipment_inc_vat).and_return(true)
allow(Spree::Config).to receive(:shipping_tax_rate).and_return(tax_rate15.amount)
end
let(:shipping_method) { create(:shipping_method, calculator: Spree::Calculator::FlatRate.new(preferred_amount: 46.0)) }
let!(:shipment) { create(:shipment_with, :shipping_method, shipping_method: shipping_method, order: order) }
before do
order.create_tax_charge!
order.update_distribution_charge!
end
subject { OrderTaxAdjustmentsFetcher.new(order).totals }
it "returns a hash with all 3 taxes" do
expect(subject.size).to eq(4)
end
it "contains tax on line_item" do
expect(subject[tax_rate10]).to eq(4.0)
end
it "contains tax on shipping_fee" do
expect(subject[tax_rate15]).to eq(6.0)
end
it "contains tax on enterprise_fee" do
expect(subject[tax_rate20]).to eq(8.0)
end
it "contains tax on order adjustment" do
expect(subject[tax_rate25]).to eq(10.0)
end
end
end