diff options
-rw-r--r-- | lib/super_good/solidus_taxjar/tax_calculator.rb | 48 | ||||
-rw-r--r-- | spec/super_good/solidus_taxjar/tax_calculator_spec.rb | 89 |
2 files changed, 121 insertions, 16 deletions
diff --git a/lib/super_good/solidus_taxjar/tax_calculator.rb b/lib/super_good/solidus_taxjar/tax_calculator.rb index e2a398e..e498da0 100644 --- a/lib/super_good/solidus_taxjar/tax_calculator.rb +++ b/lib/super_good/solidus_taxjar/tax_calculator.rb @@ -1,28 +1,60 @@ module SuperGood module SolidusTaxJar class TaxCalculator - def initialize(order) + def self.default_api + ::SuperGood::SolidusTaxJar::API.new + end + + def initialize(order, api: self.class.default_api) @order = order + @api = api end def calculate + return no_tax if order.tax_address.empty? + return no_tax unless taxjar_breakdown + Spree::Tax::OrderTax.new( order_id: order.id, - line_item_taxes: line_item_rates, - shipment_taxes: shipment_rates + line_item_taxes: line_item_taxes, + shipment_taxes: [] ) end private - attr_reader :order + attr_reader :order, :api + + def line_item_taxes + taxjar_breakdown.line_items.map do |line_item| + Spree::Tax::ItemTax.new( + item_id: line_item.id.to_i, + label: "Sales Tax", + tax_rate: tax_rate, + amount: line_item.tax_collectable, + included_in_price: false + ) + end + end + + def taxjar_breakdown + @taxjar_breakdown ||= taxjar_tax.breakdown + end + + def taxjar_tax + @taxjar_taxes ||= api.tax_for(order) + end - def line_item_rates - [] + def no_tax + Spree::Tax::OrderTax.new( + order_id: order.id, + line_item_taxes: [], + shipment_taxes: [] + ) end - def shipment_rates - [] + def tax_rate + Spree::TaxRate.find_by(name: "Sales Tax") end end end diff --git a/spec/super_good/solidus_taxjar/tax_calculator_spec.rb b/spec/super_good/solidus_taxjar/tax_calculator_spec.rb index eaf810c..02140da 100644 --- a/spec/super_good/solidus_taxjar/tax_calculator_spec.rb +++ b/spec/super_good/solidus_taxjar/tax_calculator_spec.rb @@ -1,21 +1,94 @@ require 'spec_helper' -RSpec.describe SuperGood::SolidusTaxJar::TaxCalculator do +RSpec.describe ::SuperGood::SolidusTaxJar::TaxCalculator do describe "#calculate" do subject { calculator.calculate } - let(:calculator) { described_class.new(order) } + let(:calculator) { described_class.new(order, api: dummy_api) } + + let(:dummy_api) do + instance_double ::SuperGood::SolidusTaxJar::API + end let(:order) do - Spree::Order.new( - id: 10 + ::Spree::Order.new( + id: 10, + store: store, + ship_address: address + ) + end + + let(:store) do + ::Spree::Store.new( + name: "Default Store", + url: "https://store.example.com", + code: "store", + mail_from_address: "contact@example.com", + cart_tax_country_iso: "US" ) end - it "returns the taxes" do - expect(subject.order_id).to eq order.id - expect(subject.line_item_taxes).to be_empty - expect(subject.shipment_taxes).to be_empty + context "when the order has an empty tax address" do + let(:address) { nil } + + it "returns no taxes" do + expect(subject.order_id).to eq order.id + expect(subject.shipment_taxes).to be_empty + expect(subject.line_item_taxes).to be_empty + end + end + + context "when the order has a non-empty tax address" do + let(:address) { ::Spree::Address.new(first_name: "Ronnie James") } + + before do + allow(dummy_api).to receive(:tax_for).with(order).and_return( + instance_double(::Taxjar::Tax, breakdown: breakdown) + ) + end + + context "and there is a breakdown" do + let!(:tax_rate) do + ::Spree::TaxRate.create!( + name: "Sales Tax", + amount: 0.5, + calculator: ::Spree::Calculator.new + ) + end + + let(:breakdown) do + instance_double ::Taxjar::Breakdown, line_items: [taxjar_line_item] + end + + let(:taxjar_line_item) do + instance_double ::Taxjar::BreakdownLineItem, id: "33", tax_collectable: 6.66 + end + + it "returns the taxes" do + expect(subject.order_id).to eq order.id + expect(subject.shipment_taxes).to be_empty + expect(subject.line_item_taxes.length).to eq 1 + + item_tax = subject.line_item_taxes.first + aggregate_failures do + expect(item_tax.item_id).to eq 33 + expect(item_tax.label).to eq "Sales Tax" + expect(item_tax.tax_rate).to eq tax_rate + expect(item_tax.amount).to eq 6.66 + expect(item_tax.included_in_price).to eq false + end + end + end + + context "and there is not a breakdown" do + let(:breakdown) { nil } + + it "returns no taxes" do + expect(subject.order_id).to eq order.id + expect(subject.shipment_taxes).to be_empty + expect(subject.line_item_taxes).to be_empty + end + end end end end |