mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-15 23:57:48 +00:00
Merge pull request #6924 from Matt-Yorkley/adjustments-shipping-tax
[Adjustments] Shipping tax
This commit is contained in:
7
.github/workflows/build.yml
vendored
7
.github/workflows/build.yml
vendored
@@ -272,8 +272,13 @@ jobs:
|
||||
- name: Run JS tests
|
||||
run: RAILS_ENV=test bundle exec rake karma:run
|
||||
|
||||
# Migration tests need to be run in a separate task.
|
||||
# See: https://github.com/openfoodfoundation/openfoodnetwork/pull/6924#issuecomment-813056525
|
||||
- name: Run migration tests
|
||||
run: bundle exec rspec --pattern "spec/{migrations}/**/*_spec.rb"
|
||||
|
||||
- name: Run all other tests
|
||||
run: bundle exec rake ofn:specs:run:excluding_folders["models,controllers,serializers,features,lib"]
|
||||
run: bundle exec rake ofn:specs:run:excluding_folders["models,controllers,serializers,features,lib,migrations"]
|
||||
|
||||
test-the-rest:
|
||||
runs-on: ubuntu-18.04
|
||||
|
||||
@@ -79,13 +79,14 @@ module Spree
|
||||
|
||||
def load_data
|
||||
@available_zones = Zone.order(:name)
|
||||
@tax_categories = Spree::TaxCategory.order(:name)
|
||||
@calculators = ShippingMethod.calculators.sort_by(&:name)
|
||||
end
|
||||
|
||||
def permitted_resource_params
|
||||
params.require(:shipping_method).permit(
|
||||
:name, :description, :display_on, :require_ship_address, :tag_list, :calculator_type,
|
||||
distributor_ids: [],
|
||||
:tax_category_id, distributor_ids: [],
|
||||
calculator_attributes: PermittedAttributes::Calculator.attributes
|
||||
)
|
||||
end
|
||||
|
||||
@@ -14,11 +14,7 @@ module Spree
|
||||
private
|
||||
|
||||
def preferences_params
|
||||
params.require(:preferences).permit(
|
||||
:products_require_tax_category,
|
||||
:shipment_inc_vat,
|
||||
:shipping_tax_rate,
|
||||
)
|
||||
params.require(:preferences).permit(:products_require_tax_category)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -86,6 +86,7 @@ module Spree
|
||||
if @order.complete?
|
||||
@order.update_shipping_fees!
|
||||
@order.update_payment_fees!
|
||||
@order.create_tax_charge!
|
||||
end
|
||||
|
||||
respond_with(@order) do |format|
|
||||
|
||||
@@ -13,6 +13,8 @@ module Calculator
|
||||
case computable
|
||||
when Spree::Order
|
||||
compute_order(computable)
|
||||
when Spree::Shipment
|
||||
compute_shipment(computable)
|
||||
when Spree::LineItem
|
||||
compute_line_item(computable)
|
||||
end
|
||||
@@ -31,6 +33,7 @@ module Calculator
|
||||
|
||||
[
|
||||
line_items_total(order),
|
||||
shipments_total(order),
|
||||
per_item_fees_total(order, calculator),
|
||||
per_order_fees_total(order, calculator)
|
||||
].sum do |total|
|
||||
@@ -46,6 +49,12 @@ module Calculator
|
||||
matched_line_items.sum(&:total)
|
||||
end
|
||||
|
||||
def shipments_total(order)
|
||||
order.shipments.select do |shipment|
|
||||
shipment.tax_category == rate.tax_category
|
||||
end.sum(&:cost)
|
||||
end
|
||||
|
||||
# Finds relevant fees for each line_item,
|
||||
# calculates the tax on them, and returns the total tax
|
||||
def per_item_fees_total(order, calculator)
|
||||
@@ -70,17 +79,19 @@ module Calculator
|
||||
.sum { |applicator| applicator.enterprise_fee.compute_amount(order) }
|
||||
end
|
||||
|
||||
def compute_line_item(line_item)
|
||||
if line_item.tax_category == rate.tax_category
|
||||
def compute_shipment_or_line_item(item)
|
||||
if item.tax_category == rate.tax_category
|
||||
if rate.included_in_price
|
||||
deduced_total_by_rate(line_item.total, rate)
|
||||
deduced_total_by_rate(item.amount, rate)
|
||||
else
|
||||
round_to_two_places(line_item.total * rate.amount)
|
||||
round_to_two_places(item.amount * rate.amount)
|
||||
end
|
||||
else
|
||||
0
|
||||
end
|
||||
end
|
||||
alias_method :compute_shipment, :compute_shipment_or_line_item
|
||||
alias_method :compute_line_item, :compute_shipment_or_line_item
|
||||
|
||||
def round_to_two_places(amount)
|
||||
BigDecimal(amount.to_s).round(2, BigDecimal::ROUND_HALF_UP)
|
||||
|
||||
@@ -47,6 +47,8 @@ module Spree
|
||||
validates :label, presence: true
|
||||
validates :amount, numericality: true
|
||||
|
||||
after_create :update_adjustable_adjustment_total
|
||||
|
||||
state_machine :state, initial: :open do
|
||||
event :close do
|
||||
transition from: :open, to: :closed
|
||||
@@ -99,15 +101,17 @@ module Spree
|
||||
# object on the association would be in a old state and therefore the
|
||||
# adjustment calculations would not performed on proper values
|
||||
def update!(calculable = nil, force: false)
|
||||
return if immutable? && !force
|
||||
return if originator.blank?
|
||||
return amount if immutable? && !force
|
||||
|
||||
amount = originator.compute_amount(calculable || adjustable)
|
||||
if originator.present?
|
||||
amount = originator.compute_amount(calculable || adjustable)
|
||||
update_columns(
|
||||
amount: amount,
|
||||
updated_at: Time.zone.now,
|
||||
)
|
||||
end
|
||||
|
||||
update_columns(
|
||||
amount: amount,
|
||||
updated_at: Time.zone.now,
|
||||
)
|
||||
amount
|
||||
end
|
||||
|
||||
def currency
|
||||
@@ -122,11 +126,6 @@ module Spree
|
||||
state != "open"
|
||||
end
|
||||
|
||||
def set_included_tax!(rate)
|
||||
tax = amount - (amount / (1 + rate))
|
||||
set_absolute_included_tax! tax
|
||||
end
|
||||
|
||||
def set_absolute_included_tax!(tax)
|
||||
# This rubocop issue can now fixed by renaming Adjustment#update! to something else,
|
||||
# then AR's update! can be used instead of update_attributes!
|
||||
@@ -149,5 +148,11 @@ module Spree
|
||||
|
||||
originator_type.constantize.unscoped { super }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def update_adjustable_adjustment_total
|
||||
Spree::ItemAdjustments.new(adjustable).update if adjustable
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -58,7 +58,6 @@ module Spree
|
||||
preference :products_per_page, :integer, default: 12
|
||||
preference :redirect_https_to_http, :boolean, default: false
|
||||
preference :require_master_price, :boolean, default: true
|
||||
preference :shipment_inc_vat, :boolean, default: false
|
||||
# Request instructions/info for shipping
|
||||
preference :shipping_instructions, :boolean, default: false
|
||||
# Displays variant full price or difference with product price.
|
||||
@@ -118,7 +117,6 @@ module Spree
|
||||
|
||||
# Tax Preferences
|
||||
preference :products_require_tax_category, :boolean, default: false
|
||||
preference :shipping_tax_rate, :decimal, default: 0
|
||||
|
||||
# Monitoring
|
||||
preference :last_job_queue_heartbeat_at, :string, default: nil
|
||||
|
||||
42
app/models/spree/item_adjustments.rb
Normal file
42
app/models/spree/item_adjustments.rb
Normal file
@@ -0,0 +1,42 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Spree
|
||||
# Manage (recalculate) item (LineItem or Shipment) adjustments
|
||||
class ItemAdjustments
|
||||
attr_reader :item
|
||||
|
||||
delegate :adjustments, :order, to: :item
|
||||
|
||||
def initialize(item)
|
||||
@item = item
|
||||
end
|
||||
|
||||
def update
|
||||
update_adjustments if updatable_totals?
|
||||
item
|
||||
end
|
||||
|
||||
def update_adjustments
|
||||
adjustment_total = adjustments.additional.map(&:update!).compact.sum
|
||||
included_tax_total = tax_adjustments.inclusive.reload.map(&:update!).compact.sum
|
||||
additional_tax_total = tax_adjustments.additional.reload.map(&:update!).compact.sum
|
||||
|
||||
item.update_columns(
|
||||
included_tax_total: included_tax_total,
|
||||
additional_tax_total: additional_tax_total,
|
||||
adjustment_total: adjustment_total,
|
||||
updated_at: Time.zone.now
|
||||
)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def updatable_totals?
|
||||
item.persisted? && item.is_a?(Spree::Shipment)
|
||||
end
|
||||
|
||||
def tax_adjustments
|
||||
(item.respond_to?(:all_adjustments) ? item.all_adjustments : item.adjustments).tax
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -646,7 +646,7 @@ module Spree
|
||||
end
|
||||
|
||||
def shipping_tax
|
||||
shipment_adjustments.reload.shipping.sum(:included_tax)
|
||||
shipment_adjustments.reload.tax.sum(:amount)
|
||||
end
|
||||
|
||||
def enterprise_fee_tax
|
||||
|
||||
@@ -77,9 +77,9 @@ module Spree
|
||||
|
||||
before_transition to: :delivery, do: :create_proposed_shipments
|
||||
before_transition to: :delivery, do: :ensure_available_shipping_rates
|
||||
before_transition to: :payment, do: :create_tax_charge!
|
||||
|
||||
after_transition to: :complete, do: :finalize!
|
||||
after_transition to: :delivery, do: :create_tax_charge!
|
||||
after_transition to: :resumed, do: :after_resume
|
||||
after_transition to: :canceled, do: :after_cancel
|
||||
after_transition to: :payment, do: :charge_shipping_and_payment_fees!
|
||||
|
||||
@@ -15,7 +15,7 @@ module Spree
|
||||
has_many :adjustments, as: :adjustable, dependent: :destroy
|
||||
|
||||
before_create :generate_shipment_number
|
||||
after_save :ensure_correct_adjustment, :update_order
|
||||
after_save :ensure_correct_adjustment, :update_adjustments
|
||||
|
||||
attr_accessor :special_instructions
|
||||
alias_attribute :amount, :cost
|
||||
@@ -104,6 +104,10 @@ module Spree
|
||||
save!
|
||||
end
|
||||
|
||||
def tax_category
|
||||
selected_shipping_rate.try(:shipping_method).try(:tax_category)
|
||||
end
|
||||
|
||||
def refresh_rates
|
||||
return shipping_rates if shipped?
|
||||
|
||||
@@ -161,10 +165,13 @@ module Spree
|
||||
end
|
||||
|
||||
def update_amounts
|
||||
return unless fee_adjustment&.amount != cost
|
||||
|
||||
update_columns(
|
||||
cost: fee_adjustment&.amount || 0.0,
|
||||
updated_at: Time.zone.now
|
||||
)
|
||||
recalculate_adjustments
|
||||
end
|
||||
|
||||
def manifest
|
||||
@@ -276,8 +283,7 @@ module Spree
|
||||
reload # ensure adjustment is present on later saves
|
||||
end
|
||||
|
||||
update_amounts if fee_adjustment&.amount != cost
|
||||
update_adjustment_included_tax if fee_adjustment
|
||||
update_amounts
|
||||
end
|
||||
|
||||
def adjustment_label
|
||||
@@ -332,16 +338,14 @@ module Spree
|
||||
ShipmentMailer.shipped_email(id).deliver_later
|
||||
end
|
||||
|
||||
def update_adjustment_included_tax
|
||||
if Config.shipment_inc_vat && (order.distributor.nil? || order.distributor.charges_sales_tax)
|
||||
fee_adjustment.set_included_tax! Config.shipping_tax_rate
|
||||
else
|
||||
fee_adjustment.set_included_tax! 0
|
||||
end
|
||||
def update_adjustments
|
||||
return unless cost_changed? && state != 'shipped'
|
||||
|
||||
recalculate_adjustments
|
||||
end
|
||||
|
||||
def update_order
|
||||
order.reload.update!
|
||||
def recalculate_adjustments
|
||||
Spree::ItemAdjustments.new(self).update
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -23,6 +23,8 @@ module Spree
|
||||
class_name: 'Spree::Zone',
|
||||
foreign_key: 'shipping_method_id'
|
||||
|
||||
belongs_to :tax_category, class_name: 'Spree::TaxCategory'
|
||||
|
||||
validates :name, presence: true
|
||||
validate :distributor_validation
|
||||
validate :at_least_one_shipping_category
|
||||
|
||||
@@ -24,13 +24,7 @@ module Spree
|
||||
delegate :name, to: :shipping_method
|
||||
|
||||
def display_price
|
||||
price = if Spree::Config[:shipment_inc_vat]
|
||||
(1 + Spree::TaxRate.default) * cost
|
||||
else
|
||||
cost
|
||||
end
|
||||
|
||||
Spree::Money.new(price, { currency: currency })
|
||||
Spree::Money.new(cost, { currency: currency })
|
||||
end
|
||||
|
||||
alias_method :display_cost, :display_price
|
||||
|
||||
@@ -36,8 +36,7 @@ module Spree
|
||||
end
|
||||
|
||||
def self.adjust(order)
|
||||
order.adjustments.tax.destroy_all
|
||||
order.line_item_adjustments.where(originator_type: 'Spree::TaxRate').destroy_all
|
||||
order.all_adjustments.tax.destroy_all
|
||||
|
||||
match(order).each do |rate|
|
||||
rate.adjust(order)
|
||||
@@ -62,7 +61,8 @@ module Spree
|
||||
label = create_label
|
||||
if included_in_price
|
||||
if default_zone_or_zone_match? order
|
||||
order.line_items.each { |line_item| create_adjustment(label, line_item, line_item) }
|
||||
order.line_items.each { |line_item| create_adjustment(label, line_item, line_item, false, "open") }
|
||||
order.shipments.each { |shipment| create_adjustment(label, shipment, shipment, false, "open") }
|
||||
else
|
||||
amount = -1 * calculator.compute(order)
|
||||
label = Spree.t(:refund) + label
|
||||
@@ -77,7 +77,7 @@ module Spree
|
||||
)
|
||||
end
|
||||
else
|
||||
create_adjustment(label, order, order)
|
||||
create_adjustment(label, order, order, false, "open")
|
||||
end
|
||||
|
||||
order.adjustments.reload
|
||||
|
||||
@@ -20,28 +20,11 @@ class OrderTaxAdjustmentsFetcher
|
||||
attr_reader :order
|
||||
|
||||
def all
|
||||
Spree::Adjustment
|
||||
.where(order_adjustments.or(line_item_adjustments).or(shipment_adjustments))
|
||||
.order('created_at ASC')
|
||||
end
|
||||
tax_adjustments = order.all_adjustments.tax
|
||||
enterprise_fees_with_tax = order.all_adjustments.enterprise_fee.with_tax
|
||||
admin_adjustments_with_tax = order.all_adjustments.admin.with_tax
|
||||
|
||||
def order_adjustments
|
||||
table[:adjustable_id].eq(order.id)
|
||||
.and(table[:adjustable_type].eq('Spree::Order'))
|
||||
end
|
||||
|
||||
def line_item_adjustments
|
||||
table[:adjustable_id].eq_any(order.line_item_ids)
|
||||
.and(table[:adjustable_type].eq('Spree::LineItem'))
|
||||
end
|
||||
|
||||
def shipment_adjustments
|
||||
table[:order_id].eq(order.id)
|
||||
.and(table[:adjustable_type].eq('Spree::Shipment'))
|
||||
end
|
||||
|
||||
def table
|
||||
@table ||= Spree::Adjustment.arel_table
|
||||
tax_adjustments.or(enterprise_fees_with_tax).or(admin_adjustments_with_tax)
|
||||
end
|
||||
|
||||
def tax_rates_hash(adjustment)
|
||||
@@ -66,10 +49,9 @@ class OrderTaxAdjustmentsFetcher
|
||||
end
|
||||
|
||||
def no_tax_adjustments?(adjustment)
|
||||
# Enterprise Fees, Admin Adjustments, and Shipping Fees currently do not have tax adjustments.
|
||||
# Enterprise Fees and Admin Adjustments currently do not have tax adjustments.
|
||||
# The tax amount is stored in the included_tax attribute.
|
||||
adjustment.originator_type == "EnterpriseFee" ||
|
||||
adjustment.originator_type == "Spree::ShippingMethod" ||
|
||||
(adjustment.source_type.nil? && adjustment.originator_type.nil?)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -43,9 +43,15 @@
|
||||
= f.hidden_field :tag_list, "ng-value" => "shippingMethod.tag_list"
|
||||
%tags-with-translation#something{ object: "shippingMethod", 'find-tags' => 'findTags(query)' }
|
||||
|
||||
|
||||
|
||||
= render partial: 'spree/admin/shared/calculator_fields', locals: { f: f }
|
||||
|
||||
%fieldset.tax_categories.no-border-bottom
|
||||
%legend{align: "center"}= t('.tax_category')
|
||||
= f.field_container :tax_categories do
|
||||
= f.select :tax_category_id, @tax_categories.map { |tc| [tc.name, tc.id] }, {}, :class => "select2 fullwidth"
|
||||
= error_message_on :shipping_method, :tax_category_id
|
||||
|
||||
%fieldset.categories.no-border-bottom
|
||||
%legend{align: "center"}= t('.categories')
|
||||
= f.field_container :categories do
|
||||
@@ -56,7 +62,7 @@
|
||||
%br/
|
||||
= error_message_on :shipping_method, :shipping_category_id
|
||||
|
||||
|
||||
|
||||
%fieldset.no-border-bottom
|
||||
%legend{align: "center"}= t('.zones')
|
||||
= f.field_container :zones do
|
||||
|
||||
@@ -10,14 +10,5 @@
|
||||
= check_box_tag 'preferences[products_require_tax_category]', '1', Spree::Config[:products_require_tax_category]
|
||||
= label_tag nil, t(:products_require_tax_category)
|
||||
|
||||
.field.align-center{"data-hook" => "shipment_vat"}
|
||||
= hidden_field_tag 'preferences[shipment_inc_vat]', '0'
|
||||
= check_box_tag 'preferences[shipment_inc_vat]', '1', Spree::Config[:shipment_inc_vat]
|
||||
= label_tag nil, t(:shipment_inc_vat)
|
||||
|
||||
.field.align-center{ "data-hook" => "shipping_tax_rate" }
|
||||
= number_field_tag "preferences[shipping_tax_rate]", Spree::Config[:shipping_tax_rate].to_f, in: 0.0..1.0, step: 0.01
|
||||
= label_tag nil, t(:shipping_tax_rate)
|
||||
|
||||
.form-buttons{"data-hook" => "buttons"}
|
||||
= button t(:update), 'icon-refresh'
|
||||
|
||||
@@ -3526,6 +3526,7 @@ See the %{link} to find out more about %{sitename}'s features and to start using
|
||||
back_to_shipping_methods_list: "Back To Shipping Methods List"
|
||||
form:
|
||||
categories: "Categories"
|
||||
tax_category: "Tax Category"
|
||||
zones: "Zones"
|
||||
both: "Both Checkout and Back office"
|
||||
back_end: "Back office only"
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
class AddTaxCategoryIdToShippingMethods < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :spree_shipping_methods, :tax_category_id, :integer
|
||||
end
|
||||
end
|
||||
14
db/migrate/20210207131247_add_tax_totals_to_shipment.rb
Normal file
14
db/migrate/20210207131247_add_tax_totals_to_shipment.rb
Normal file
@@ -0,0 +1,14 @@
|
||||
class AddTaxTotalsToShipment < ActiveRecord::Migration
|
||||
def up
|
||||
add_column :spree_shipments, :included_tax_total, :decimal,
|
||||
precision: 10, scale: 2, null: false, default: 0.0
|
||||
|
||||
add_column :spree_shipments, :additional_tax_total, :decimal,
|
||||
precision: 10, scale: 2, null: false, default: 0.0
|
||||
end
|
||||
|
||||
def down
|
||||
remove_column :spree_shipments, :included_tax_total
|
||||
remove_column :spree_shipments, :additional_tax_total
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,31 @@
|
||||
class AddAdjustmentTotalToShipment < ActiveRecord::Migration
|
||||
def up
|
||||
add_column :spree_shipments, :adjustment_total, :decimal,
|
||||
precision: 10, scale: 2, null: false, default: 0.0
|
||||
|
||||
populate_adjustment_totals
|
||||
end
|
||||
|
||||
def down
|
||||
remove_column :spree_shipments, :adjustment_total
|
||||
end
|
||||
|
||||
def populate_adjustment_totals
|
||||
# Populates the new `adjustment_total` field in the spree_shipments table. Sets the value
|
||||
# to the shipment's (shipping fee) adjustment amount.
|
||||
|
||||
adjustment_totals_sql = <<-SQL
|
||||
UPDATE spree_shipments
|
||||
SET adjustment_total = shipping_adjustment.fee_amount
|
||||
FROM (
|
||||
SELECT spree_adjustments.source_id AS shipment_id, spree_adjustments.amount AS fee_amount
|
||||
FROM spree_adjustments
|
||||
WHERE spree_adjustments.source_type = 'Spree::Shipment'
|
||||
AND spree_adjustments.amount <> 0
|
||||
) shipping_adjustment
|
||||
WHERE spree_shipments.id = shipping_adjustment.shipment_id
|
||||
SQL
|
||||
|
||||
ActiveRecord::Base.connection.execute(adjustment_totals_sql)
|
||||
end
|
||||
end
|
||||
164
db/migrate/20210224190247_migrate_shipping_taxes.rb
Normal file
164
db/migrate/20210224190247_migrate_shipping_taxes.rb
Normal file
@@ -0,0 +1,164 @@
|
||||
class MigrateShippingTaxes < ActiveRecord::Migration
|
||||
class Spree::Preference < ActiveRecord::Base; end
|
||||
class Spree::TaxCategory < ActiveRecord::Base
|
||||
has_many :tax_rates, class_name: "Spree::TaxRate", inverse_of: :tax_category
|
||||
end
|
||||
class Spree::Order < ActiveRecord::Base
|
||||
has_many :adjustments, as: :adjustable
|
||||
belongs_to :bill_address, foreign_key: :bill_address_id, class_name: 'Spree::Address'
|
||||
belongs_to :ship_address, foreign_key: :ship_address_id, class_name: 'Spree::Address'
|
||||
|
||||
def tax_zone
|
||||
Spree::Zone.match(tax_address) || Spree::Zone.default_tax
|
||||
end
|
||||
|
||||
def tax_address
|
||||
Spree::Config[:tax_using_ship_address] ? ship_address : bill_address
|
||||
end
|
||||
end
|
||||
class Spree::Address < ActiveRecord::Base; end
|
||||
class Spree::Shipment < ActiveRecord::Base
|
||||
has_many :adjustments, as: :adjustable
|
||||
end
|
||||
class Spree::ShippingMethod < ActiveRecord::Base; end
|
||||
class Spree::Zone < ActiveRecord::Base
|
||||
has_many :zone_members, dependent: :destroy, class_name: "Spree::ZoneMember", inverse_of: :zone
|
||||
has_many :tax_rates, class_name: "Spree::TaxRate", inverse_of: :zone
|
||||
|
||||
def self.match(address)
|
||||
return unless (matches = includes(:zone_members).
|
||||
order('zone_members_count', 'created_at').
|
||||
select { |zone| zone.include? address })
|
||||
|
||||
['state', 'country'].each do |zone_kind|
|
||||
if (match = matches.detect { |zone| zone_kind == zone.kind })
|
||||
return match
|
||||
end
|
||||
end
|
||||
matches.first
|
||||
end
|
||||
|
||||
def kind
|
||||
return unless zone_members.any? && zone_members.none? { |member| member.try(:zoneable_type).nil? }
|
||||
|
||||
zone_members.last.zoneable_type.demodulize.underscore
|
||||
end
|
||||
|
||||
def include?(address)
|
||||
return false unless address
|
||||
|
||||
zone_members.any? do |zone_member|
|
||||
case zone_member.zoneable_type
|
||||
when 'Spree::Country'
|
||||
zone_member.zoneable_id == address.country_id
|
||||
when 'Spree::State'
|
||||
zone_member.zoneable_id == address.state_id
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
class Spree::ZoneMember < ActiveRecord::Base
|
||||
belongs_to :zone, class_name: 'Spree::Zone', inverse_of: :zone_members
|
||||
belongs_to :zoneable, polymorphic: true
|
||||
end
|
||||
class Spree::TaxRate < ActiveRecord::Base
|
||||
belongs_to :zone, class_name: "Spree::Zone", inverse_of: :tax_rates
|
||||
belongs_to :tax_category, class_name: "Spree::TaxCategory", inverse_of: :tax_rates
|
||||
has_one :calculator, class_name: "Spree::Calculator", as: :calculable, dependent: :destroy
|
||||
accepts_nested_attributes_for :calculator
|
||||
end
|
||||
class Spree::Adjustment < ActiveRecord::Base
|
||||
belongs_to :adjustable, polymorphic: true
|
||||
belongs_to :originator, polymorphic: true
|
||||
belongs_to :source, polymorphic: true
|
||||
belongs_to :order, class_name: "Spree::Order"
|
||||
|
||||
scope :shipping, -> { where(originator_type: 'Spree::ShippingMethod') }
|
||||
end
|
||||
|
||||
def up
|
||||
return unless instance_uses_shipping_tax?
|
||||
|
||||
create_shipping_tax_rates
|
||||
assign_to_shipping_methods
|
||||
migrate_tax_amounts_to_adjustments
|
||||
end
|
||||
|
||||
def instance_uses_shipping_tax?
|
||||
Spree::Preference.find_by(key: '/spree/app_configuration/shipment_inc_vat')&.value || false
|
||||
end
|
||||
|
||||
def instance_shipping_tax_rate
|
||||
Spree::Preference.find_by(key: '/spree/app_configuration/shipping_tax_rate')&.value || 0.0
|
||||
end
|
||||
|
||||
def shipping_tax_category
|
||||
@shipping_tax_category ||= Spree::TaxCategory.create(name: I18n.t(:shipping))
|
||||
end
|
||||
|
||||
def create_shipping_tax_rates
|
||||
# Create a shipping tax rate for each zone, set to current default rate
|
||||
Spree::Zone.all.each do |tax_zone|
|
||||
Spree::TaxRate.create!(
|
||||
name: shipping_rate_label(tax_zone),
|
||||
zone: tax_zone,
|
||||
tax_category: shipping_tax_category,
|
||||
amount: instance_shipping_tax_rate,
|
||||
included_in_price: true,
|
||||
calculator: Calculator::DefaultTax.new
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def assign_to_shipping_methods
|
||||
# Assign the new default shipping tax category to all existing shipping methods
|
||||
Spree::ShippingMethod.update_all(tax_category_id: shipping_tax_category.id)
|
||||
end
|
||||
|
||||
def migrate_tax_amounts_to_adjustments
|
||||
shipping_tax_rates = Spree::TaxRate.where(tax_category: shipping_tax_category).to_a
|
||||
|
||||
# Migrate all shipping tax amounts from shipment field to tax adjustments
|
||||
Spree::Adjustment.shipping.where("included_tax <> 0").includes(:source, :order).find_each do |shipping_fee|
|
||||
shipment = shipping_fee.source
|
||||
order = shipping_fee.order
|
||||
next if order.nil?
|
||||
|
||||
tax_rate = shipping_tax_rates.detect{ |rate| rate.zone == order.tax_zone }
|
||||
|
||||
# Move all tax totals to adjustments
|
||||
Spree::Adjustment.create!(
|
||||
label: tax_adjustment_label(tax_rate),
|
||||
amount: shipping_fee.included_tax,
|
||||
included: true,
|
||||
order_id: order.id,
|
||||
state: "closed",
|
||||
adjustable_type: "Spree::Shipment",
|
||||
adjustable_id: shipment.id,
|
||||
source_type: "Spree::Shipment",
|
||||
source_id: shipment.id,
|
||||
originator_type: "Spree::TaxRate",
|
||||
originator_id: tax_rate.id
|
||||
)
|
||||
|
||||
# Update shipment included tax total
|
||||
shipment.update_columns(
|
||||
included_tax_total: shipping_fee.included_tax
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def shipping_rate_label(zone)
|
||||
I18n.t(:shipping) + " - #{zone.name.chomp('_VAT')}"
|
||||
end
|
||||
|
||||
def tax_adjustment_label(tax_rate)
|
||||
label = ""
|
||||
label << tax_rate.name
|
||||
label << " #{tax_rate.amount * 100}%"
|
||||
label << " (#{I18n.t('models.tax_rate.included_in_price')})"
|
||||
label
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,5 @@
|
||||
class AddIndexOnShippingMethodsTaxCategory < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
add_index :spree_shipping_methods, :tax_category_id
|
||||
end
|
||||
end
|
||||
@@ -10,7 +10,7 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20210320003951) do
|
||||
ActiveRecord::Schema.define(version: 20210329123820) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
@@ -778,6 +778,9 @@ ActiveRecord::Schema.define(version: 20210320003951) do
|
||||
t.datetime "updated_at", null: false
|
||||
t.string "state", limit: 255
|
||||
t.integer "stock_location_id"
|
||||
t.decimal "included_tax_total", precision: 10, scale: 2, default: "0.0", null: false
|
||||
t.decimal "additional_tax_total", precision: 10, scale: 2, default: "0.0", null: false
|
||||
t.decimal "adjustment_total", precision: 10, scale: 2, default: "0.0", null: false
|
||||
t.index ["number"], name: "index_shipments_on_number", using: :btree
|
||||
t.index ["order_id"], name: "index_spree_shipments_on_order_id", unique: true, using: :btree
|
||||
end
|
||||
@@ -807,6 +810,8 @@ ActiveRecord::Schema.define(version: 20210320003951) do
|
||||
t.boolean "require_ship_address", default: true
|
||||
t.text "description"
|
||||
t.string "tracking_url", limit: 255
|
||||
t.integer "tax_category_id"
|
||||
t.index ["tax_category_id"], name: "index_spree_shipping_methods_on_tax_category_id", using: :btree
|
||||
end
|
||||
|
||||
create_table "spree_shipping_methods_zones", id: false, force: :cascade do |t|
|
||||
|
||||
@@ -61,7 +61,7 @@ module OrderManagement
|
||||
order.additional_tax_total = all_adjustments.tax.additional.sum(:amount)
|
||||
order.included_tax_total = order.line_item_adjustments.tax.inclusive.sum(:amount) +
|
||||
all_adjustments.enterprise_fee.sum(:included_tax) +
|
||||
all_adjustments.shipping.sum(:included_tax) +
|
||||
order.shipment_adjustments.tax.inclusive.sum(:amount) +
|
||||
adjustments.admin.sum(:included_tax)
|
||||
end
|
||||
|
||||
@@ -122,7 +122,7 @@ module OrderManagement
|
||||
end
|
||||
|
||||
def update_all_adjustments
|
||||
order.adjustments.reload.each(&:update!)
|
||||
order.all_adjustments.reload.each(&:update!)
|
||||
end
|
||||
|
||||
def before_save_hook
|
||||
|
||||
@@ -32,6 +32,7 @@ module OrderManagement
|
||||
allow(order).to receive_message_chain(:all_adjustments, :tax, :additional, :sum).and_return(20)
|
||||
allow(order).to receive_message_chain(:all_adjustments, :enterprise_fee, :sum).and_return(10)
|
||||
allow(order).to receive_message_chain(:all_adjustments, :shipping, :sum).and_return(5)
|
||||
allow(order).to receive_message_chain(:shipment_adjustments, :tax, :inclusive, :sum).and_return(5)
|
||||
allow(order).to receive_message_chain(:adjustments, :admin, :sum).and_return(2)
|
||||
|
||||
updater.update_adjustment_total
|
||||
|
||||
@@ -102,13 +102,5 @@ module OpenFoodNetwork
|
||||
def tax_included_in(line_item)
|
||||
line_item.adjustments.tax.inclusive.sum(:amount)
|
||||
end
|
||||
|
||||
def shipment_inc_vat
|
||||
Spree::Config.shipment_inc_vat
|
||||
end
|
||||
|
||||
def shipping_tax_rate
|
||||
Spree::Config.shipping_tax_rate
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -204,7 +204,7 @@ module OpenFoodNetwork
|
||||
end
|
||||
|
||||
def tax_on_shipping_s(order)
|
||||
tax_on_shipping = order.all_adjustments.shipping.sum(:included_tax) > 0
|
||||
tax_on_shipping = order.shipments.sum("additional_tax_total + included_tax_total").positive?
|
||||
tax_on_shipping ? I18n.t(:report_header_gst_on_income) : I18n.t(:report_header_gst_free_income)
|
||||
end
|
||||
|
||||
|
||||
@@ -27,18 +27,12 @@ module Spree
|
||||
# calculator as applied to the given calculable (Order, LineItems[], Shipment, etc.)
|
||||
# By default the adjustment will not be considered mandatory
|
||||
def create_adjustment(label, target, calculable, mandatory = false, state = "closed")
|
||||
# Adjustment calculations done on Spree::Shipment objects MUST
|
||||
# be done on their to_package'd variants instead
|
||||
# It's only the package that contains the correct information.
|
||||
# See https://github.com/spree/spree_active_shipping/pull/96 et. al
|
||||
old_calculable = calculable
|
||||
calculable = calculable.to_package if calculable.is_a?(Spree::Shipment)
|
||||
amount = compute_amount(calculable)
|
||||
return if amount.zero? && !mandatory
|
||||
|
||||
adjustment_attributes = {
|
||||
amount: amount,
|
||||
source: old_calculable,
|
||||
source: calculable,
|
||||
originator: self,
|
||||
order: order_object_for(target),
|
||||
label: label,
|
||||
|
||||
@@ -103,22 +103,36 @@ describe LineItemsController, type: :controller do
|
||||
end
|
||||
|
||||
context "on a completed order with shipping and payment fees" do
|
||||
let(:zone) { create(:zone_with_member) }
|
||||
let(:shipping_tax_rate) do
|
||||
create(:tax_rate, included_in_price: true,
|
||||
calculator: Calculator::DefaultTax.new,
|
||||
amount: 0.25,
|
||||
zone: zone)
|
||||
end
|
||||
let(:shipping_tax_category) { create(:tax_category, tax_rates: [shipping_tax_rate]) }
|
||||
let(:shipping_fee) { 3 }
|
||||
let(:payment_fee) { 5 }
|
||||
let(:distributor_with_taxes) { create(:distributor_enterprise_with_tax) }
|
||||
let(:order) { create(:completed_order_with_fees, distributor: distributor_with_taxes, shipping_fee: shipping_fee, payment_fee: payment_fee) }
|
||||
let(:order) {
|
||||
create(:completed_order_with_fees, distributor: distributor_with_taxes,
|
||||
shipping_fee: shipping_fee, payment_fee: payment_fee,
|
||||
shipping_tax_category: shipping_tax_category)
|
||||
}
|
||||
|
||||
before do
|
||||
Spree::Config.shipment_inc_vat = true
|
||||
Spree::Config.shipping_tax_rate = 0.25
|
||||
allow(order).to receive(:tax_zone) { zone }
|
||||
order.reload
|
||||
order.create_tax_charge!
|
||||
end
|
||||
|
||||
it "updates the fees" do
|
||||
# Sanity check fees
|
||||
item_num = order.line_items.length
|
||||
initial_fees = item_num * (shipping_fee + payment_fee)
|
||||
expect(order.adjustment_total).to eq initial_fees
|
||||
expect(order.shipments.last.fee_adjustment.included_tax).to eq 1.2
|
||||
|
||||
expect(order.shipment.adjustments.tax.count).to eq 1
|
||||
expect(order.shipment.included_tax_total).to eq 1.2
|
||||
|
||||
# Delete the item
|
||||
item = order.line_items.first
|
||||
@@ -130,9 +144,9 @@ describe LineItemsController, type: :controller do
|
||||
order.reload
|
||||
order.shipment.reload
|
||||
expect(order.adjustment_total).to eq initial_fees - shipping_fee - payment_fee
|
||||
expect(order.shipments.last.fee_adjustment.amount).to eq shipping_fee
|
||||
expect(order.shipment.adjustment_total).to eq shipping_fee
|
||||
expect(order.payments.first.adjustment.amount).to eq payment_fee
|
||||
expect(order.shipments.last.fee_adjustment.included_tax).to eq 0.6
|
||||
expect(order.shipment.included_tax_total).to eq 0.6
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ describe Spree::Admin::OrdersController, type: :controller do
|
||||
adjustable: order,
|
||||
label: "invalid adjustment",
|
||||
eligible: false,
|
||||
order: order,
|
||||
amount: 0
|
||||
)
|
||||
|
||||
|
||||
@@ -4,15 +4,7 @@ require 'spec_helper'
|
||||
|
||||
describe Spree::Admin::TaxSettingsController, type: :controller do
|
||||
describe "#update" do
|
||||
let(:params) {
|
||||
{
|
||||
preferences: {
|
||||
products_require_tax_category: "1",
|
||||
shipment_inc_vat: "0",
|
||||
shipping_tax_rate: "0.1",
|
||||
}
|
||||
}
|
||||
}
|
||||
let(:params) { { preferences: { products_require_tax_category: "1" } } }
|
||||
|
||||
before do
|
||||
allow(controller).to receive(:spree_current_user) { create(:admin_user) }
|
||||
@@ -21,19 +13,7 @@ describe Spree::Admin::TaxSettingsController, type: :controller do
|
||||
it "changes Tax settings" do
|
||||
expect {
|
||||
spree_post :update, params
|
||||
}.to change {
|
||||
[
|
||||
Spree::Config[:products_require_tax_category],
|
||||
Spree::Config[:shipment_inc_vat],
|
||||
Spree::Config[:shipping_tax_rate],
|
||||
]
|
||||
}.to(
|
||||
[
|
||||
true,
|
||||
false,
|
||||
0.1,
|
||||
]
|
||||
)
|
||||
}.to change { Spree::Config[:products_require_tax_category] }.to(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -265,7 +265,12 @@ describe Spree::OrdersController, type: :controller do
|
||||
describe "removing items from a completed order" do
|
||||
context "with shipping and transaction fees" do
|
||||
let(:distributor) { create(:distributor_enterprise, charges_sales_tax: true, allow_order_changes: true) }
|
||||
let(:order) { create(:completed_order_with_fees, distributor: distributor, shipping_fee: shipping_fee, payment_fee: payment_fee) }
|
||||
let(:shipping_tax_rate) { create(:tax_rate, amount: 0.25, included_in_price: true, zone: create(:zone_with_member)) }
|
||||
let(:shipping_tax_category) { create(:tax_category, tax_rates: [shipping_tax_rate]) }
|
||||
let(:order) {
|
||||
create(:completed_order_with_fees, distributor: distributor, shipping_fee: shipping_fee,
|
||||
payment_fee: payment_fee, shipping_tax_category: shipping_tax_category)
|
||||
}
|
||||
let(:line_item1) { order.line_items.first }
|
||||
let(:line_item2) { order.line_items.second }
|
||||
let(:shipping_fee) { 3 }
|
||||
@@ -274,14 +279,16 @@ describe Spree::OrdersController, type: :controller do
|
||||
let(:expected_fees) { item_num * (shipping_fee + payment_fee) }
|
||||
|
||||
before do
|
||||
allow(Spree::Config).to receive(:shipment_inc_vat) { true }
|
||||
allow(Spree::Config).to receive(:shipping_tax_rate) { 0.25 }
|
||||
allow(order).to receive(:tax_zone) { shipping_tax_rate.zone }
|
||||
order.reload
|
||||
order.create_tax_charge!
|
||||
|
||||
# Sanity check the fees
|
||||
expect(order.all_adjustments.length).to eq 2
|
||||
expect(order.all_adjustments.length).to eq 3
|
||||
expect(item_num).to eq 2
|
||||
expect(order.adjustment_total).to eq expected_fees
|
||||
expect(order.shipment.fee_adjustment.included_tax).to eq 1.2
|
||||
expect(order.shipment.adjustments.tax.first.amount).to eq 1.2
|
||||
expect(order.shipment.included_tax_total).to eq 1.2
|
||||
|
||||
allow(subject).to receive(:spree_current_user) { order.user }
|
||||
allow(subject).to receive(:order_to_update) { order }
|
||||
@@ -296,7 +303,8 @@ describe Spree::OrdersController, type: :controller do
|
||||
|
||||
expect(order.reload.line_items.count).to eq 1
|
||||
expect(order.adjustment_total).to eq(1 * (shipping_fee + payment_fee))
|
||||
expect(order.shipment.fee_adjustment.included_tax).to eq 0.6
|
||||
expect(order.shipment.adjustments.tax.first.amount).to eq 0.6
|
||||
expect(order.shipment.included_tax_total).to eq 0.6
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -25,4 +25,6 @@ FactoryBot.define do
|
||||
c.save!
|
||||
}
|
||||
end
|
||||
|
||||
factory :default_tax_calculator, class: Calculator::DefaultTax
|
||||
end
|
||||
|
||||
@@ -196,6 +196,7 @@ FactoryBot.define do
|
||||
transient do
|
||||
payment_fee { 5 }
|
||||
shipping_fee { 3 }
|
||||
shipping_tax_category { nil }
|
||||
end
|
||||
|
||||
ship_address { create(:address) }
|
||||
@@ -214,7 +215,8 @@ FactoryBot.define do
|
||||
state: 'checkout')
|
||||
|
||||
create(:shipping_method_with, :shipping_fee, shipping_fee: evaluator.shipping_fee,
|
||||
distributors: [order.distributor])
|
||||
distributors: [order.distributor],
|
||||
tax_category: evaluator.shipping_tax_category)
|
||||
|
||||
order.reload
|
||||
while !order.completed? do break unless order.next! end
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
FactoryBot.define do
|
||||
factory :tax_rate, class: Spree::TaxRate do
|
||||
zone
|
||||
amount { 100.00 }
|
||||
amount { 0.1 }
|
||||
tax_category
|
||||
association(:calculator, factory: :default_tax_calculator, strategy: :build)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -166,7 +166,9 @@ feature '
|
||||
let(:distributor2) { create(:distributor_enterprise, with_payment_and_shipping: true, charges_sales_tax: true) }
|
||||
let(:user1) { create(:user, enterprises: [distributor1]) }
|
||||
let(:user2) { create(:user, enterprises: [distributor2]) }
|
||||
let!(:shipping_method) { create(:shipping_method_with, :expensive_name, distributors: [distributor1]) }
|
||||
let(:shipping_tax_rate) { create(:tax_rate, amount: 0.20, included_in_price: true, zone: zone) }
|
||||
let(:shipping_tax_category) { create(:tax_category, tax_rates: [shipping_tax_rate]) }
|
||||
let!(:shipping_method) { create(:shipping_method_with, :expensive_name, distributors: [distributor1], tax_category: shipping_tax_category) }
|
||||
let(:enterprise_fee) { create(:enterprise_fee, enterprise: user1.enterprises.first, tax_category: product2.tax_category, calculator: Calculator::FlatRate.new(preferred_amount: 120.0)) }
|
||||
let(:order_cycle) { create(:simple_order_cycle, coordinator: distributor1, coordinator_fees: [enterprise_fee], distributors: [distributor1], variants: [product1.master]) }
|
||||
|
||||
@@ -180,12 +182,12 @@ feature '
|
||||
let!(:line_item2) { create(:line_item, variant: product2.master, price: 500.15, quantity: 3, order: order1) }
|
||||
|
||||
before do
|
||||
allow(Spree::Config).to receive(:shipment_inc_vat) { true }
|
||||
allow(Spree::Config).to receive(:shipping_tax_rate) { 0.2 }
|
||||
|
||||
order1.reload
|
||||
2.times { order1.next }
|
||||
order1.select_shipping_method shipping_method.id
|
||||
order1.reload.recreate_all_fees!
|
||||
order1.create_tax_charge!
|
||||
order1.update!
|
||||
order1.finalize!
|
||||
|
||||
login_as_admin_and_visit spree.admin_reports_path
|
||||
@@ -385,16 +387,11 @@ feature '
|
||||
let(:product1) { create(:taxed_product, zone: zone, price: 12.54, tax_rate_amount: 0, sku: 'sku1') }
|
||||
let(:product2) { create(:taxed_product, zone: zone, price: 500.15, tax_rate_amount: 0.2, sku: 'sku2') }
|
||||
|
||||
before do
|
||||
allow(Spree::Config).to receive(:shipment_inc_vat) { true }
|
||||
allow(Spree::Config).to receive(:shipping_tax_rate) { 0.1 }
|
||||
end
|
||||
|
||||
describe "with adjustments" do
|
||||
let!(:line_item1) { create(:line_item, variant: product1.master, price: 12.54, quantity: 1, order: order1) }
|
||||
let!(:line_item2) { create(:line_item, variant: product2.master, price: 500.15, quantity: 3, order: order1) }
|
||||
|
||||
let!(:adj_shipping) { create(:adjustment, order: order1, adjustable: order1, label: "Shipping", originator: shipping_method, amount: 100.55, included_tax: 10.06) }
|
||||
let!(:adj_shipping) { create(:adjustment, order: order1, adjustable: order1, label: "Shipping", originator: shipping_method, amount: 100.55) }
|
||||
let!(:adj_fee1) { create(:adjustment, order: order1, adjustable: order1, originator: enterprise_fee1, label: "Enterprise fee untaxed", amount: 10, included_tax: 0) }
|
||||
let!(:adj_fee2) { create(:adjustment, order: order1, adjustable: order1, originator: enterprise_fee2, label: "Enterprise fee taxed", amount: 20, included_tax: 2) }
|
||||
let!(:adj_manual1) { create(:adjustment, order: order1, adjustable: order1, originator: nil, source: nil, label: "Manual adjustment", amount: 30, included_tax: 0) }
|
||||
@@ -402,8 +399,8 @@ feature '
|
||||
|
||||
before do
|
||||
order1.update_attribute :email, 'customer@email.com'
|
||||
order1.shipment.update_columns(included_tax_total: 10.06)
|
||||
Timecop.travel(Time.zone.local(2015, 4, 25, 14, 0, 0)) { order1.finalize! }
|
||||
|
||||
login_as_admin_and_visit spree.admin_reports_path
|
||||
|
||||
click_link 'Xero Invoices'
|
||||
|
||||
@@ -8,11 +8,7 @@ feature 'Account and Billing Settings' do
|
||||
|
||||
describe "updating" do
|
||||
before do
|
||||
Spree::Config.set(
|
||||
products_require_tax_category: false,
|
||||
shipment_inc_vat: false,
|
||||
shipping_tax_rate: 0
|
||||
)
|
||||
Spree::Config.set(products_require_tax_category: false)
|
||||
end
|
||||
|
||||
context "as an admin user" do
|
||||
@@ -21,22 +17,16 @@ feature 'Account and Billing Settings' do
|
||||
click_link "Tax Settings"
|
||||
|
||||
expect(page).to have_unchecked_field 'preferences_products_require_tax_category'
|
||||
expect(page).to have_unchecked_field 'preferences_shipment_inc_vat'
|
||||
expect(page).to have_field 'preferences_shipping_tax_rate'
|
||||
end
|
||||
|
||||
it "attributes can be changed" do
|
||||
login_as_admin_and_visit spree.edit_admin_tax_settings_path
|
||||
|
||||
check 'preferences_products_require_tax_category'
|
||||
check 'preferences_shipment_inc_vat'
|
||||
fill_in 'preferences_shipping_tax_rate', with: '0.12'
|
||||
|
||||
click_button "Update"
|
||||
|
||||
expect(Spree::Config.products_require_tax_category).to be true
|
||||
expect(Spree::Config.shipment_inc_vat).to be true
|
||||
expect(Spree::Config.shipping_tax_rate).to eq 0.12
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -17,9 +17,15 @@ feature "As a consumer I want to check out my cart", js: true do
|
||||
let(:product) { create(:taxed_product, supplier: supplier, price: 10, zone: zone, tax_rate_amount: 0.1) }
|
||||
let(:variant) { product.variants.first }
|
||||
let(:order) { create(:order, order_cycle: order_cycle, distributor: distributor, bill_address_id: nil, ship_address_id: nil) }
|
||||
let(:shipping_tax_rate) { create(:tax_rate, amount: 0.25, zone: zone, included_in_price: true) }
|
||||
let(:shipping_tax_category) { create(:tax_category, tax_rates: [shipping_tax_rate]) }
|
||||
|
||||
let(:free_shipping) { create(:shipping_method, require_ship_address: true, name: "Frogs", description: "yellow", calculator: Calculator::FlatRate.new(preferred_amount: 0.00)) }
|
||||
let(:shipping_with_fee) { create(:shipping_method, require_ship_address: false, name: "Donkeys", description: "blue", calculator: Calculator::FlatRate.new(preferred_amount: 4.56)) }
|
||||
let(:shipping_with_fee) {
|
||||
create(:shipping_method, require_ship_address: false, tax_category: shipping_tax_category,
|
||||
name: "Donkeys", description: "blue",
|
||||
calculator: Calculator::FlatRate.new(preferred_amount: 4.56))
|
||||
}
|
||||
let(:tagged_shipping) { create(:shipping_method, require_ship_address: false, name: "Local", tag_list: "local") }
|
||||
let!(:check_without_fee) { create(:payment_method, distributors: [distributor], name: "Roger rabbit", type: "Spree::PaymentMethod::Check") }
|
||||
let!(:check_with_fee) { create(:payment_method, distributors: [distributor], calculator: Calculator::FlatRate.new(preferred_amount: 5.67)) }
|
||||
@@ -32,9 +38,6 @@ feature "As a consumer I want to check out my cart", js: true do
|
||||
end
|
||||
|
||||
before do
|
||||
Spree::Config.shipment_inc_vat = true
|
||||
Spree::Config.shipping_tax_rate = 0.25
|
||||
|
||||
add_enterprise_fee enterprise_fee
|
||||
set_order order
|
||||
add_product_to_cart order, product
|
||||
|
||||
89
spec/migrations/migrate_shipping_taxes_spec.rb
Normal file
89
spec/migrations/migrate_shipping_taxes_spec.rb
Normal file
@@ -0,0 +1,89 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
require_relative '../../db/migrate/20210224190247_migrate_shipping_taxes'
|
||||
|
||||
describe MigrateShippingTaxes do
|
||||
let(:migration) { MigrateShippingTaxes.new }
|
||||
|
||||
describe '#shipping_tax_category' do
|
||||
it "creates a new shipping tax category" do
|
||||
migration.shipping_tax_category
|
||||
|
||||
expect(Spree::TaxCategory.last.name).to eq I18n.t(:shipping)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#create_shipping_tax_rates' do
|
||||
let!(:zone1) { create(:zone_with_member) }
|
||||
let!(:zone2) { create(:zone_with_member) }
|
||||
|
||||
before do
|
||||
allow(migration).to receive(:instance_shipping_tax_rate) { 0.25 }
|
||||
end
|
||||
|
||||
it "creates a shipping tax rate for each zone" do
|
||||
migration.create_shipping_tax_rates
|
||||
|
||||
tax_rates = Spree::TaxRate.all
|
||||
|
||||
expect(tax_rates.count).to eq 2
|
||||
expect(tax_rates.map(&:zone_id).uniq.sort).to eq [zone1.id, zone2.id]
|
||||
expect(tax_rates.map(&:amount).uniq).to eq [0.25]
|
||||
end
|
||||
end
|
||||
|
||||
describe '#assign_to_shipping_methods' do
|
||||
let!(:shipping_method1) { create(:shipping_method) }
|
||||
let!(:shipping_method2) { create(:shipping_method) }
|
||||
let(:shipping_tax_category) { create(:tax_category) }
|
||||
|
||||
before do
|
||||
allow(migration).to receive(:shipping_tax_category) { shipping_tax_category }
|
||||
end
|
||||
|
||||
it "assigns the new shipping tax category to all shipping methods" do
|
||||
migration.assign_to_shipping_methods
|
||||
|
||||
expect(shipping_method1.reload.tax_category).to eq shipping_tax_category
|
||||
expect(shipping_method2.reload.tax_category).to eq shipping_tax_category
|
||||
end
|
||||
end
|
||||
|
||||
describe '#migrate_tax_amounts_to_adjustments' do
|
||||
let!(:zone) { create(:zone_with_member) }
|
||||
let!(:shipping_tax_category) { create(:tax_category) }
|
||||
let!(:shipping_tax_rate) {
|
||||
create(:tax_rate, zone: zone, tax_category: shipping_tax_category, name: "Shipping Tax Rate")
|
||||
}
|
||||
let(:order) { create(:completed_order_with_fees) }
|
||||
let(:shipment) { order.shipment }
|
||||
|
||||
before do
|
||||
shipment.adjustments.first.update_columns(included_tax: 0.23)
|
||||
allow(order).to receive(:tax_zone) { zone }
|
||||
allow(migration).to receive(:shipping_tax_category) { shipping_tax_category }
|
||||
end
|
||||
|
||||
it "migrates the shipment's tax to a tax adjustment" do
|
||||
expect(shipment.adjustments.first.included_tax).to eq 0.23
|
||||
expect(shipment.included_tax_total).to be_zero
|
||||
expect(shipment.adjustments.tax.count).to be_zero
|
||||
|
||||
migration.migrate_tax_amounts_to_adjustments
|
||||
|
||||
expect(shipment.reload.included_tax_total).to eq 0.23
|
||||
expect(shipment.adjustments.tax.count).to eq 1
|
||||
|
||||
shipping_tax_adjustment = shipment.adjustments.tax.first
|
||||
|
||||
expect(shipping_tax_adjustment.amount).to eq 0.23
|
||||
expect(shipping_tax_adjustment.originator).to eq shipping_tax_rate
|
||||
expect(shipping_tax_adjustment.source).to eq shipment
|
||||
expect(shipping_tax_adjustment.adjustable).to eq shipment
|
||||
expect(shipping_tax_adjustment.order_id).to eq order.id
|
||||
expect(shipping_tax_adjustment.included).to eq true
|
||||
expect(shipping_tax_adjustment.state).to eq "closed"
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -197,11 +197,17 @@ module Spree
|
||||
end
|
||||
|
||||
describe "Shipment adjustments" do
|
||||
let(:zone) { create(:zone_with_member) }
|
||||
let(:inclusive_tax) { true }
|
||||
let(:tax_rate) {
|
||||
create(:tax_rate, included_in_price: inclusive_tax, zone: zone, amount: 0.25)
|
||||
}
|
||||
let(:tax_category) { create(:tax_category, name: "Shipping", tax_rates: [tax_rate] ) }
|
||||
let(:hub) { create(:distributor_enterprise, charges_sales_tax: true) }
|
||||
let(:order) { create(:order, distributor: hub) }
|
||||
let(:line_item) { create(:line_item, order: order) }
|
||||
|
||||
let(:shipping_method) { create(:shipping_method_with, :flat_rate) }
|
||||
let(:shipping_method) { create(:shipping_method_with, :flat_rate, tax_category: tax_category) }
|
||||
let(:shipment) { create(:shipment_with, :shipping_method, shipping_method: shipping_method, order: order) }
|
||||
|
||||
describe "the shipping charge" do
|
||||
@@ -212,54 +218,114 @@ module Spree
|
||||
end
|
||||
end
|
||||
|
||||
describe "when tax on shipping is disabled" do
|
||||
context "with tax" do
|
||||
before do
|
||||
allow(Config).to receive(:shipment_inc_vat).and_return(false)
|
||||
allow(order).to receive(:tax_zone) { zone }
|
||||
end
|
||||
|
||||
it "records 0% tax on shipment adjustments" do
|
||||
allow(Config).to receive(:shipping_tax_rate).and_return(0)
|
||||
order.shipments = [shipment]
|
||||
context "when the shipment has an inclusive tax rate" do
|
||||
it "calculates the shipment tax from the tax rate" do
|
||||
order.shipments = [shipment]
|
||||
order.create_tax_charge!
|
||||
order.update_totals
|
||||
|
||||
expect(order.shipment_adjustments.first.included_tax).to eq(0)
|
||||
# Finding the tax included in an amount that's already inclusive of tax:
|
||||
# total - ( total / (1 + rate) )
|
||||
# 50 - ( 50 / (1 + 0.25) )
|
||||
# = 10
|
||||
expect(order.shipment_adjustments.tax.first.amount).to eq(10)
|
||||
expect(order.shipment_adjustments.tax.first.included).to eq true
|
||||
|
||||
expect(shipment.reload.cost).to eq(50)
|
||||
expect(shipment.included_tax_total).to eq(10)
|
||||
expect(shipment.additional_tax_total).to eq(0)
|
||||
|
||||
expect(order.included_tax_total).to eq(10)
|
||||
expect(order.additional_tax_total).to eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
it "records 0% tax on shipments when a rate is set but shipment_inc_vat is false" do
|
||||
allow(Config).to receive(:shipping_tax_rate).and_return(0.25)
|
||||
order.shipments = [shipment]
|
||||
context "when the shipment has an added tax rate" do
|
||||
let(:inclusive_tax) { false }
|
||||
|
||||
expect(order.shipment_adjustments.first.included_tax).to eq(0)
|
||||
end
|
||||
end
|
||||
# Current behaviour. Will be replaced by the pending test below
|
||||
it "records the tax on the order's adjustments" do
|
||||
order.shipments = [shipment]
|
||||
order.create_tax_charge!
|
||||
order.update_totals
|
||||
|
||||
describe "when tax on shipping is enabled" do
|
||||
before do
|
||||
allow(Config).to receive(:shipment_inc_vat).and_return(true)
|
||||
expect(order.shipment_adjustments.tax.count).to be_zero
|
||||
|
||||
# Finding the added tax for an amount:
|
||||
# total * rate
|
||||
# 50 * 0.25
|
||||
# = 12.5
|
||||
expect(order.adjustments.tax.first.amount).to eq(12.50)
|
||||
expect(order.adjustments.tax.first.included).to eq false
|
||||
|
||||
expect(shipment.reload.cost).to eq(50)
|
||||
expect(shipment.included_tax_total).to eq(0)
|
||||
expect(shipment.additional_tax_total).to eq(0)
|
||||
|
||||
expect(order.included_tax_total).to eq(0)
|
||||
expect(order.additional_tax_total).to eq(12.50)
|
||||
end
|
||||
|
||||
xit "records the tax on the shipment's adjustments" do
|
||||
order.shipments = [shipment]
|
||||
order.create_tax_charge!
|
||||
order.update_totals
|
||||
|
||||
# Finding the added tax for an amount:
|
||||
# total * rate
|
||||
# 50 * 0.25
|
||||
# = 12.5
|
||||
expect(order.shipment_adjustments.tax.first.amount).to eq(12.50)
|
||||
expect(order.shipment_adjustments.tax.first.included).to eq false
|
||||
|
||||
expect(shipment.reload.cost).to eq(50)
|
||||
expect(shipment.included_tax_total).to eq(0)
|
||||
expect(shipment.additional_tax_total).to eq(12.50)
|
||||
|
||||
expect(order.included_tax_total).to eq(0)
|
||||
expect(order.additional_tax_total).to eq(12.50)
|
||||
end
|
||||
end
|
||||
|
||||
it "takes the shipment adjustment tax included from the system setting" do
|
||||
allow(Config).to receive(:shipping_tax_rate).and_return(0.25)
|
||||
order.shipments = [shipment]
|
||||
context "when the distributor does not charge sales tax" do
|
||||
it "records 0% tax on shipments" do
|
||||
order.distributor.update! charges_sales_tax: false
|
||||
order.shipments = [shipment]
|
||||
order.create_tax_charge!
|
||||
order.update_totals
|
||||
|
||||
# Finding the tax included in an amount that's already inclusive of tax:
|
||||
# total - ( total / (1 + rate) )
|
||||
# 50 - ( 50 / (1 + 0.25) )
|
||||
# = 10
|
||||
expect(order.shipment_adjustments.first.included_tax).to eq(10.00)
|
||||
expect(order.shipment_adjustments.tax.count).to be_zero
|
||||
|
||||
expect(shipment.reload.cost).to eq(50)
|
||||
expect(shipment.included_tax_total).to eq(0)
|
||||
expect(shipment.additional_tax_total).to eq(0)
|
||||
|
||||
expect(order.included_tax_total).to eq(0)
|
||||
expect(order.additional_tax_total).to eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
it "records 0% tax on shipments when shipping_tax_rate is not set" do
|
||||
allow(Config).to receive(:shipping_tax_rate).and_return(0)
|
||||
order.shipments = [shipment]
|
||||
context "when the shipment has no applicable tax rate" do
|
||||
it "records 0% tax on shipments" do
|
||||
allow(shipment).to receive(:tax_category) { nil }
|
||||
order.shipments = [shipment]
|
||||
order.create_tax_charge!
|
||||
order.update_totals
|
||||
|
||||
expect(order.shipment_adjustments.first.included_tax).to eq(0)
|
||||
end
|
||||
expect(order.shipment_adjustments.tax.count).to be_zero
|
||||
|
||||
it "records 0% tax on shipments when the distributor does not charge sales tax" do
|
||||
order.distributor.update! charges_sales_tax: false
|
||||
order.shipments = [shipment]
|
||||
expect(shipment.reload.cost).to eq(50)
|
||||
expect(shipment.included_tax_total).to eq(0)
|
||||
expect(shipment.additional_tax_total).to eq(0)
|
||||
|
||||
expect(order.shipment_adjustments.first.included_tax).to eq(0)
|
||||
expect(order.included_tax_total).to eq(0)
|
||||
expect(order.additional_tax_total).to eq(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -417,15 +483,6 @@ module Spree
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "setting the included tax by tax rate" do
|
||||
let(:adjustment) { Adjustment.new label: 'foo', amount: 50 }
|
||||
|
||||
it "sets it, rounding to two decimal places" do
|
||||
adjustment.set_included_tax! 0.25
|
||||
expect(adjustment.included_tax).to eq(10.00)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "extends LocalizedNumber" do
|
||||
|
||||
@@ -32,7 +32,7 @@ describe Spree::Gateway::StripeSCA, type: :model do
|
||||
stub_request(:get, "https://api.stripe.com/v1/payment_intents/12345").
|
||||
to_return(status: 200, body: payment_authorised)
|
||||
stub_request(:post, "https://api.stripe.com/v1/payment_intents/12345/capture").
|
||||
with(body: {"amount_to_capture" => "10.0"}).
|
||||
with(body: {"amount_to_capture" => order.total}).
|
||||
to_return(status: 200, body: capture_successful)
|
||||
|
||||
response = subject.purchase(order.total, credit_card, gateway_options)
|
||||
|
||||
@@ -48,24 +48,15 @@ describe Spree::Order do
|
||||
end
|
||||
end
|
||||
|
||||
context "when current state is address" do
|
||||
before do
|
||||
allow(order).to receive(:ensure_available_shipping_rates)
|
||||
order.state = "address"
|
||||
end
|
||||
|
||||
it "adjusts tax rates when transitioning to delivery" do
|
||||
# Once because the record is being saved
|
||||
# Twice because it is transitioning to the delivery state
|
||||
expect(Spree::TaxRate).to receive(:adjust).twice
|
||||
order.next!
|
||||
end
|
||||
end
|
||||
|
||||
context "when current state is delivery" do
|
||||
before do
|
||||
allow(order).to receive(:ensure_available_shipping_rates)
|
||||
order.state = "delivery"
|
||||
allow(order).to receive_messages total: 10.0
|
||||
end
|
||||
|
||||
it "adjusts tax rates when transitioning to payment" do
|
||||
expect(Spree::TaxRate).to receive(:adjust)
|
||||
order.next!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -636,16 +636,19 @@ describe Spree::Order do
|
||||
|
||||
describe "getting the shipping tax" do
|
||||
let(:order) { create(:order) }
|
||||
let(:shipping_method) { create(:shipping_method_with, :flat_rate) }
|
||||
let(:shipping_tax_rate) { create(:tax_rate, amount: 0.25, included_in_price: true, zone: create(:zone_with_member)) }
|
||||
let(:shipping_tax_category) { create(:tax_category, tax_rates: [shipping_tax_rate]) }
|
||||
let!(:shipping_method) { create(:shipping_method_with, :flat_rate, tax_category: shipping_tax_category) }
|
||||
|
||||
context "with a taxed shipment" do
|
||||
before do
|
||||
allow(Spree::Config).to receive(:shipment_inc_vat).and_return(true)
|
||||
allow(Spree::Config).to receive(:shipping_tax_rate).and_return(0.25)
|
||||
end
|
||||
|
||||
let!(:shipment) { create(:shipment_with, :shipping_method, shipping_method: shipping_method, order: order) }
|
||||
|
||||
before do
|
||||
allow(order).to receive(:tax_zone) { shipping_tax_rate.zone }
|
||||
order.reload
|
||||
order.create_tax_charge!
|
||||
end
|
||||
|
||||
it "returns the shipping tax" do
|
||||
expect(order.shipping_tax).to eq(10)
|
||||
end
|
||||
@@ -677,11 +680,7 @@ describe Spree::Order do
|
||||
end
|
||||
|
||||
describe "getting the total tax" do
|
||||
before do
|
||||
allow(Spree::Config).to receive(:shipment_inc_vat).and_return(true)
|
||||
allow(Spree::Config).to receive(:shipping_tax_rate).and_return(0.25)
|
||||
end
|
||||
|
||||
let(:shipping_tax_rate) { create(:tax_rate, amount: 0.25) }
|
||||
let(:order) { create(:order) }
|
||||
let(:shipping_method) { create(:shipping_method_with, :flat_rate) }
|
||||
let!(:shipment) do
|
||||
@@ -690,15 +689,10 @@ describe Spree::Order do
|
||||
let(:enterprise_fee) { create(:enterprise_fee) }
|
||||
|
||||
before do
|
||||
create(
|
||||
:adjustment,
|
||||
order: order,
|
||||
adjustable: order,
|
||||
originator: enterprise_fee,
|
||||
label: "EF",
|
||||
amount: 123,
|
||||
included_tax: 2
|
||||
)
|
||||
create(:adjustment, adjustable: order, originator: enterprise_fee, label: "EF", amount: 123,
|
||||
included_tax: 2, order: order)
|
||||
create(:adjustment, adjustable: shipment, source: shipment, originator: shipping_tax_rate,
|
||||
amount: 10, order: order, state: "closed")
|
||||
order.update!
|
||||
end
|
||||
|
||||
@@ -1043,22 +1037,30 @@ describe Spree::Order do
|
||||
|
||||
describe "a completed order with shipping and transaction fees" do
|
||||
let(:distributor) { create(:distributor_enterprise_with_tax) }
|
||||
let(:order) { create(:completed_order_with_fees, distributor: distributor, shipping_fee: shipping_fee, payment_fee: payment_fee) }
|
||||
let(:zone) { create(:zone_with_member) }
|
||||
let(:shipping_tax_rate) { create(:tax_rate, amount: 0.25, included_in_price: true, zone: zone) }
|
||||
let(:shipping_tax_category) { create(:tax_category, tax_rates: [shipping_tax_rate]) }
|
||||
let(:order) {
|
||||
create(:completed_order_with_fees, distributor: distributor, shipping_fee: shipping_fee,
|
||||
payment_fee: payment_fee,
|
||||
shipping_tax_category: shipping_tax_category)
|
||||
}
|
||||
let(:shipping_fee) { 3 }
|
||||
let(:payment_fee) { 5 }
|
||||
let(:item_num) { order.line_items.length }
|
||||
let(:expected_fees) { item_num * (shipping_fee + payment_fee) }
|
||||
|
||||
before do
|
||||
Spree::Config.shipment_inc_vat = true
|
||||
Spree::Config.shipping_tax_rate = 0.25
|
||||
order.reload
|
||||
order.create_tax_charge!
|
||||
|
||||
# Sanity check the fees
|
||||
expect(order.all_adjustments.length).to eq 2
|
||||
expect(order.shipment_adjustments.length).to eq 1
|
||||
expect(order.all_adjustments.length).to eq 3
|
||||
expect(order.shipment_adjustments.length).to eq 2
|
||||
expect(item_num).to eq 2
|
||||
expect(order.adjustment_total).to eq expected_fees
|
||||
expect(order.shipment.fee_adjustment.included_tax).to eq 1.2
|
||||
expect(order.shipment.adjustments.tax.inclusive.sum(:amount)).to eq 1.2
|
||||
expect(order.shipment.included_tax_total).to eq 1.2
|
||||
end
|
||||
|
||||
context "removing line_items" do
|
||||
@@ -1067,7 +1069,8 @@ describe Spree::Order do
|
||||
order.save
|
||||
|
||||
expect(order.adjustment_total).to eq expected_fees - shipping_fee - payment_fee
|
||||
expect(order.shipment.fee_adjustment.included_tax).to eq 0.6
|
||||
expect(order.shipment.adjustments.tax.inclusive.sum(:amount)).to eq 0.6
|
||||
expect(order.shipment.included_tax_total).to eq 0.6
|
||||
end
|
||||
|
||||
context "when finalized fee adjustments exist on the order" do
|
||||
@@ -1086,7 +1089,8 @@ describe Spree::Order do
|
||||
# Check if fees got updated
|
||||
order.reload
|
||||
expect(order.adjustment_total).to eq expected_fees
|
||||
expect(order.shipment.fee_adjustment.included_tax).to eq 1.2
|
||||
expect(order.shipment.adjustments.tax.inclusive.sum(:amount)).to eq 1.2
|
||||
expect(order.shipment.included_tax_total).to eq 1.2
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1099,7 +1103,8 @@ describe Spree::Order do
|
||||
order.save
|
||||
|
||||
expect(order.adjustment_total).to eq expected_fees - (item_num * shipping_fee)
|
||||
expect(order.shipment.fee_adjustment.included_tax).to eq 0
|
||||
expect(order.shipment.adjustments.tax.inclusive.sum(:amount)).to eq 0
|
||||
expect(order.shipment.included_tax_total).to eq 0
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -423,13 +423,6 @@ describe Spree::Shipment do
|
||||
end
|
||||
end
|
||||
|
||||
context "update_order" do
|
||||
it "should update order" do
|
||||
expect(order).to receive_message_chain(:reload, :update!)
|
||||
shipment.__send__(:update_order)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#update_amounts" do
|
||||
it "persists the shipping cost from the shipping fee adjustment" do
|
||||
allow(shipment).to receive(:fee_adjustment) { double(:adjustment, amount: 10) }
|
||||
@@ -442,7 +435,7 @@ describe Spree::Shipment do
|
||||
context "after_save" do
|
||||
it "should run correct callbacks" do
|
||||
expect(shipment).to receive(:ensure_correct_adjustment)
|
||||
expect(shipment).to receive(:update_order)
|
||||
expect(shipment).to receive(:update_adjustments)
|
||||
shipment.run_callbacks(:save)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -10,21 +10,10 @@ describe Spree::ShippingRate do
|
||||
shipping_method: shipping_method,
|
||||
cost: 10.55)
|
||||
}
|
||||
before { allow(Spree::TaxRate).to receive_messages(default: 0.05) }
|
||||
|
||||
context "#display_price" do
|
||||
context "when shipment includes VAT" do
|
||||
before { Spree::Config[:shipment_inc_vat] = true }
|
||||
it "displays the correct price" do
|
||||
expect(shipping_rate.display_price.to_s).to eq "$11.08" # $10.55 * 1.05 == $11.08
|
||||
end
|
||||
end
|
||||
|
||||
context "when shipment does not include VAT" do
|
||||
before { Spree::Config[:shipment_inc_vat] = false }
|
||||
it "displays the correct price" do
|
||||
expect(shipping_rate.display_price.to_s).to eq "$10.55"
|
||||
end
|
||||
it "displays the shipping price" do
|
||||
expect(shipping_rate.display_price.to_s).to eq "$10.55"
|
||||
end
|
||||
|
||||
context "when the currency is JPY" do
|
||||
|
||||
@@ -16,7 +16,7 @@ describe "checking out an order that initially fails", type: :request do
|
||||
let!(:shipment) { create(:shipment_with, :shipping_method, shipping_method: shipping_method) }
|
||||
let!(:order) { create(:order, shipments: [shipment], distributor: shop, order_cycle: order_cycle) }
|
||||
let(:params) do
|
||||
{ format: :json, order: {
|
||||
{ order: {
|
||||
shipping_method_id: shipping_method.id,
|
||||
payments_attributes: [{ payment_method_id: payment_method.id }],
|
||||
bill_address_attributes: address.attributes.slice("firstname", "lastname", "address1", "address2", "phone", "city", "zipcode", "state_id", "country_id"),
|
||||
@@ -46,7 +46,7 @@ describe "checking out an order that initially fails", type: :request do
|
||||
end
|
||||
|
||||
it "clears shipments and payments before rendering the checkout" do
|
||||
put update_checkout_path, params
|
||||
put update_checkout_path, params: params, as: :json
|
||||
|
||||
# Checking out a BogusGateway without a source fails at :payment
|
||||
# Shipments and payments should then be cleared before rendering checkout
|
||||
@@ -62,7 +62,8 @@ describe "checking out an order that initially fails", type: :request do
|
||||
|
||||
# Use a check payment method, which should work
|
||||
params[:order][:payments_attributes][0][:payment_method_id] = check_payment_method.id
|
||||
put update_checkout_path, params
|
||||
|
||||
put update_checkout_path, params: params, as: :json
|
||||
|
||||
expect(response.status).to be 200
|
||||
order.reload
|
||||
|
||||
@@ -66,14 +66,9 @@ describe OrderTaxAdjustmentsFetcher do
|
||||
distributor: coordinator
|
||||
)
|
||||
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) do
|
||||
create(:shipping_method, calculator: Calculator::FlatRate.new(preferred_amount: 46.0))
|
||||
create(:shipping_method, calculator: Calculator::FlatRate.new(preferred_amount: 46.0),
|
||||
tax_category: tax_category15)
|
||||
end
|
||||
let!(:shipment) do
|
||||
create(:shipment_with, :shipping_method, shipping_method: shipping_method, order: order)
|
||||
|
||||
Reference in New Issue
Block a user