diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..452ebb3 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,7 @@ +version: 2 +updates: +- package-ecosystem: bundler + directory: "/" + schedule: + interval: daily + open-pull-requests-limit: 10 diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..ac1f502 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,58 @@ +os: linux +dist: bionic + +addons: + apt: + sources: + - google-chrome + packages: + - google-chrome-stable + +services: + - mysql + - postgresql + +language: ruby + +rvm: + - 2.7 + - 3.0 + +env: + - DB=mysql + - DB=postgres + +gemfile: + - gemfiles/spree_3_2.gemfile + - gemfiles/spree_3_3.gemfile + - gemfiles/spree_3_4.gemfile + - gemfiles/spree_3_7.gemfile + - gemfiles/spree_4.gemfile + - gemfiles/spree_master.gemfile + +jobs: + allow_failures: + - gemfile: gemfiles/spree_master.gemfile + exclude: + - rvm: 3.0 + gemfile: gemfiles/spree_3_2.gemfile + - rvm: 3.0 + gemfile: gemfiles/spree_3_3.gemfile + - rvm: 3.0 + gemfile: gemfiles/spree_3_4.gemfile + - rvm: 3.0 + gemfile: gemfiles/spree_3_7.gemfile + +before_install: + - mysql -u root -e "GRANT ALL ON *.* TO 'travis'@'%';" + +before_script: + - CHROME_MAIN_VERSION=`google-chrome-stable --version | sed -E 's/(^Google Chrome |\.[0-9]+ )//g'` + - CHROMEDRIVER_VERSION=`curl -s "https://chromedriver.storage.googleapis.com/LATEST_RELEASE_$CHROME_MAIN_VERSION"` + - curl "https://chromedriver.storage.googleapis.com/${CHROMEDRIVER_VERSION}/chromedriver_linux64.zip" -O + - unzip chromedriver_linux64.zip -d ~/bin + - nvm install 14 + +script: + - bundle exec rake test_app + - bundle exec rake spec diff --git a/Appraisals b/Appraisals new file mode 100644 index 0000000..2e990ae --- /dev/null +++ b/Appraisals @@ -0,0 +1,24 @@ +appraise "spree-3-2" do + gem 'spree', '~> 3.2.0' +end + +appraise "spree-3-3" do + gem 'spree', '~> 3.3.0' +end + +appraise "spree-3-4" do + gem 'spree', '~> 3.4.0' +end + +appraise "spree-3-7" do + gem 'spree', '~> 3.7.0' +end + +appraise 'spree-4' do + gem 'spree', '~> 4.2' + gem 'rails-controller-testing' +end + +appraise "spree-master" do + gem 'spree', github: 'spree/spree', branch: 'master' +end diff --git a/Gemfile b/Gemfile index 4b365d4..e5940dd 100644 --- a/Gemfile +++ b/Gemfile @@ -1,9 +1,5 @@ source 'https://rubygems.org' -gem 'spree', github: 'spree/spree', branch: '3-2-stable' -# Provides basic authentication functionality for testing parts of your engine -gem 'spree_auth_devise', github: 'spree/spree_auth_devise', branch: 'master' - group :test do gem 'rails-controller-testing' gem 'byebug' diff --git a/README.md b/README.md index bc83b9d..0590330 100644 --- a/README.md +++ b/README.md @@ -15,23 +15,21 @@ Spree::Taxjar is a sales tax extension for Spree using [SmartCalcs by TaxJar](ht 1. Add this extension to your Gemfile with this line: - ```ruby - gem 'spree_taxjar', github: 'vinsol-spree-contrib/spree_taxjar', branch: - ``` - - *The `branch` option is important:* it must match the version of Spree you're using. For example, use `3-1-stable` if you're using Spree `3-1-stable` or any `3.1.x` version. + ```ruby + gem 'spree_taxjar', github: 'spree-contrib/spree_taxjar' + ``` 2. Install the gem using Bundler: - ```ruby - bundle install - ``` + ```ruby + bundle install + ``` 3. Copy & run migrations - ```ruby - bundle exec rails g spree_taxjar:install - ``` + ```ruby + bundle exec rails g spree_taxjar:install + ``` 4. Restart your server @@ -42,6 +40,7 @@ Spree::Taxjar is a sales tax extension for Spree using [SmartCalcs by TaxJar](ht - Check the `TAXJAR ENABLED` checkbox - Optionally, check `TAXJAR DEBUG ENABLED` for debugging issues - Not recommended for production use unless debugging production issues + - Update tax rates to Spree/Taxjar calculator. ## Developing / Debugging Extension @@ -75,6 +74,11 @@ bundle bundle exec rake ``` +## See It In Action + + ## Credits [![vinsol.com: Ruby on Rails, iOS and Android developers](http://vinsol.com/vin_logo.png "Ruby on Rails, iOS and Android developers")](http://vinsol.com) diff --git a/app/controllers/spree/admin/taxjar_settings_controller.rb b/app/controllers/spree/admin/taxjar_settings_controller.rb index 6963bee..1045b43 100644 --- a/app/controllers/spree/admin/taxjar_settings_controller.rb +++ b/app/controllers/spree/admin/taxjar_settings_controller.rb @@ -2,13 +2,14 @@ module Spree module Admin class TaxjarSettingsController < Spree::Admin::BaseController def edit - @preferences_api = [:taxjar_api_key, :taxjar_enabled, :taxjar_debug_enabled] + @preferences_api = %i[taxjar_api_key taxjar_enabled taxjar_debug_enabled taxjar_sandbox_environment_enabled] end def update Spree::Config[:taxjar_api_key] = params[:taxjar_api_key] Spree::Config[:taxjar_enabled] = params[:taxjar_enabled] Spree::Config[:taxjar_debug_enabled] = params[:taxjar_debug_enabled] + Spree::Config[:taxjar_sandbox_environment_enabled] = params[:taxjar_sandbox_environment_enabled] flash[:success] = Spree.t(:taxjar_settings_updated) redirect_to edit_admin_taxjar_settings_path diff --git a/app/helpers/taxjar_helper.rb b/app/helpers/taxjar_helper.rb index 0c679ea..363765a 100644 --- a/app/helpers/taxjar_helper.rb +++ b/app/helpers/taxjar_helper.rb @@ -13,21 +13,16 @@ def context class TaxjarLog attr_reader :logger - def initialize(path_name, file_name, log_info = nil, schedule = "weekly") - @logger ||= Logger.new("#{Rails.root}/log/#{path_name}.log", schedule) + def initialize(logdev) + @logger ||= Logger.new(logdev) @logger.formatter = Pretty.new - progname(file_name.split("/").last.chomp(".rb")) - info(log_info) unless log_info.nil? + @logger.progname = 'spree_taxjar extension' end def logger_enabled? Spree::Config[:taxjar_debug_enabled] end - def progname(progname = nil) - progname.nil? ? logger.progname : logger.progname = progname - end - def info(log_info = nil) if logger_enabled? logger.info log_info unless log_info.nil? diff --git a/app/models/concerns/spree_taxjar/taxable.rb b/app/models/concerns/spree_taxjar/taxable.rb new file mode 100644 index 0000000..4f3f2a3 --- /dev/null +++ b/app/models/concerns/spree_taxjar/taxable.rb @@ -0,0 +1,12 @@ +module SpreeTaxjar + module Taxable + extend ActiveSupport::Concern + + private + + def taxjar_applicable?(order) + ::Spree::TaxRate.match(order.tax_zone).any? { |rate| rate.calculator_type == "Spree::Calculator::TaxjarCalculator" } + end + end +end + diff --git a/app/models/concerns/taxable.rb b/app/models/concerns/taxable.rb deleted file mode 100644 index b6f0ef0..0000000 --- a/app/models/concerns/taxable.rb +++ /dev/null @@ -1,8 +0,0 @@ -module Taxable - extend ActiveSupport::Concern - - private - def taxjar_applicable?(order) - Spree::TaxRate.match(order.tax_zone).any? { |rate| rate.calculator_type == "Spree::Calculator::TaxjarCalculator" } - end -end diff --git a/app/models/spree/calculator/taxjar_calculator.rb b/app/models/spree/calculator/taxjar_calculator.rb index e0ca5ac..06a390d 100644 --- a/app/models/spree/calculator/taxjar_calculator.rb +++ b/app/models/spree/calculator/taxjar_calculator.rb @@ -83,7 +83,7 @@ def cache_response(taxjar_response, order, address, item = nil) ## better to use Rails.cache.fetch for order and wrapping lookup based on line_item id res = nil taxjar_response.breakdown.line_items.each do |line_item| - item_from_db = Spree::LineItem.find_by(id: line_item.id) + item_from_db = Spree::LineItem.includes(:adjustments).find_by(id: line_item.id) if item && item_from_db.id == item.id res = line_item.tax_collectable end @@ -94,9 +94,9 @@ def cache_response(taxjar_response, order, address, item = nil) def cache_key(order, item, address) if item.is_a?(Spree::LineItem) - ['Spree::LineItem', order.id, item.id, address.state.id, address.zipcode, item.amount, :amount_to_collect] + [Spree::LineItem.to_s, order.id, item.id, address.state_id, address.zipcode, item.taxable_amount, :amount_to_collect] else - ['Spree::Shipment', order.id, item.id, address.state.id, address.zipcode, item.cost, :amount_to_collect] + [Spree::Shipment.to_s, order.id, item.id, address.state_id, address.zipcode, item.cost, item.adjustments.select { |adjustment| adjustment.source_type != Spree::TaxRate.to_s }.map(&:amount).sum.to_f, :amount_to_collect] end end end diff --git a/app/models/spree/order_decorator.rb b/app/models/spree/order_decorator.rb deleted file mode 100644 index 086107c..0000000 --- a/app/models/spree/order_decorator.rb +++ /dev/null @@ -1,23 +0,0 @@ -Spree::Order.class_eval do - include Taxable - - state_machine.after_transition to: :complete, do: :capture_taxjar - state_machine.after_transition to: :canceled, do: :delete_taxjar_transaction - state_machine.after_transition to: :resumed, from: :canceled, do: :capture_taxjar - - private - - def delete_taxjar_transaction - return unless Spree::Config[:taxjar_enabled] - return unless taxjar_applicable?(self) - client = Spree::Taxjar.new(self) - client.delete_transaction_for_order - end - - def capture_taxjar - return unless Spree::Config[:taxjar_enabled] - return unless taxjar_applicable?(self) - client = Spree::Taxjar.new(self) - client.create_transaction_for_order - end -end diff --git a/app/models/spree/reimbursment_decorator.rb b/app/models/spree/reimbursment_decorator.rb deleted file mode 100644 index a8d2d26..0000000 --- a/app/models/spree/reimbursment_decorator.rb +++ /dev/null @@ -1,13 +0,0 @@ -Spree::Reimbursement.class_eval do - include Taxable - - state_machine = self.state_machines[:reimbursement_status] - state_machine.after_transition to: [:reimbursed], do: :remove_tax_for_returned_items - - def remove_tax_for_returned_items - return unless Spree::Config[:taxjar_enabled] - return unless taxjar_applicable?(order) - client = Spree::Taxjar.new(order, self) - client.create_refund_transaction_for_order - end -end diff --git a/app/models/spree/taxjar.rb b/app/models/spree/taxjar.rb index c9dc746..0628f7a 100644 --- a/app/models/spree/taxjar.rb +++ b/app/models/spree/taxjar.rb @@ -6,7 +6,7 @@ def initialize(order = nil, reimbursement = nil, shipment = nil) @order = order @shipment = shipment @reimbursement = reimbursement - @client = ::Taxjar::Client.new(api_key: Spree::Config[:taxjar_api_key]) + @client = ::Taxjar::Client.new(client_params) end def create_refund_transaction_for_order @@ -55,6 +55,8 @@ def calculate_tax_for_shipment end def has_nexus? + return false if tax_address.blank? + nexus_regions = @client.nexus_regions SpreeTaxjar::Logger.log(__method__, { order: {id: @order.id, number: @order.number}, @@ -86,19 +88,19 @@ def nexus_states(nexus_regions) end def tax_address_country_iso - tax_address.country.iso + tax_address.country&.iso end def tax_address_state_abbr - tax_address.state.abbr + tax_address.state&.abbr end def tax_address_city - tax_address.city + tax_address&.city end def tax_address_zip - tax_address.zipcode + tax_address&.zipcode end def tax_address @@ -108,7 +110,7 @@ def tax_address def tax_params { amount: @order.item_total, - shipping: @order.shipment_total, + shipping: @order.shipment_total + adjustments_total(@order.shipment_adjustments), to_state: tax_address_state_abbr, to_zip: tax_address_zip, line_items: taxable_line_items_params @@ -120,15 +122,17 @@ def taxable_line_items_params { id: item.id, quantity: item.quantity, - unit_price: item.price, - discount: item.promo_total, + unit_price: item.taxable_amount / item.quantity, product_tax_code: item.tax_category.try(:tax_code) } end end def reimbursement_present? - @client.list_refunds(from_transaction_date: Date.today - 1, to_transaction_date: Date.today + 1).include?(@reimbursement.number) + @client.list_refunds( + from_transaction_date: (Date.today - 1).strftime('%Y/%m/%d'), + to_transaction_date: (Date.today + 1).strftime('%Y/%m/%d') + ).include?(@reimbursement.number) end def group_by_line_items @@ -141,7 +145,7 @@ def return_items_params { quantity: return_items.length, product_identifier: item.variant.sku, - description: ActionView::Base.full_sanitizer.sanitize(item.variant.description).truncate(150), + description: ActionView::Base.full_sanitizer.sanitize(item.variant.description).try(:truncate, 150), unit_price: item.pre_tax_amount, product_tax_code: item.variant.tax_category.try(:tax_code) } @@ -164,8 +168,8 @@ def transaction_parameters address_params.merge({ transaction_id: @order.number, transaction_date: @order.completed_at.as_json, - amount: @order.item_total + @order.shipment_total, - shipping: @order.shipment_total, + amount: @order.total - @order.tax_total, + shipping: @order.shipment_total + adjustments_total(@order.shipment_adjustments), sales_tax: @order.additional_tax_total, line_items: line_item_params }) @@ -183,23 +187,44 @@ def address_params def shipment_tax_params address_params.merge({ amount: 0, - shipping: @shipment.cost + shipping: @shipment.cost + adjustments_total(@shipment.adjustments) }) end def line_item_params @order.line_items.map do |item| + unit_price = item.taxable_amount / item.quantity { quantity: item.quantity, product_identifier: item.sku, description: ActionView::Base.full_sanitizer.sanitize(item.description).try(:truncate, 150), - unit_price: item.price, + unit_price: unit_price, sales_tax: item.additional_tax_total, - discount: item.promo_total, + discount: discount_weightage(item, unit_price), product_tax_code: item.tax_category.try(:tax_code) } end end + def discount_weightage(item, unit_price) + return 0 if @order.item_total.zero? + weightage = @order.adjustments.sum(:amount) / (@order.item_total) + - weightage * unit_price + end + + def adjustments_total(adjustments) + adjustments.select { |adjustment| adjustment.source_type != Spree::TaxRate.to_s }.map(&:amount).sum.to_f + end + + def client_params + { + api_key: Spree::Config[:taxjar_api_key], + api_url: api_url + } + end + + def api_url + Spree::Config[:taxjar_sandbox_environment_enabled] ? ::Taxjar::API::Request::SANDBOX_API_URL : ::Taxjar::API::Request::DEFAULT_API_URL + end end end diff --git a/app/models/spree_taxjar/spree/order_decorator.rb b/app/models/spree_taxjar/spree/order_decorator.rb new file mode 100644 index 0000000..0c0906c --- /dev/null +++ b/app/models/spree_taxjar/spree/order_decorator.rb @@ -0,0 +1,31 @@ +module SpreeTaxjar + module Spree + module OrderDecorator + def self.prepended(base) + base.include Taxable + + base.state_machine.after_transition to: :complete, do: :capture_taxjar + base.state_machine.after_transition to: :canceled, do: :delete_taxjar_transaction + base.state_machine.after_transition to: :resumed, from: :canceled, do: :capture_taxjar + end + + private + + def delete_taxjar_transaction + return unless ::Spree::Config[:taxjar_enabled] + return unless taxjar_applicable?(self) + client = ::Spree::Taxjar.new(self) + client.delete_transaction_for_order + end + + def capture_taxjar + return unless ::Spree::Config[:taxjar_enabled] + return unless taxjar_applicable?(self) + client = ::Spree::Taxjar.new(self) + client.create_transaction_for_order + end + end + end +end + +Spree::Order.prepend(SpreeTaxjar::Spree::OrderDecorator) \ No newline at end of file diff --git a/app/models/spree_taxjar/spree/reimbursement_decorator.rb b/app/models/spree_taxjar/spree/reimbursement_decorator.rb new file mode 100644 index 0000000..c178ade --- /dev/null +++ b/app/models/spree_taxjar/spree/reimbursement_decorator.rb @@ -0,0 +1,21 @@ +module SpreeTaxjar + module Spree + module ReimbursementDecorator + def self.prepended(base) + base.include Taxable + + state_machine = base.state_machines[:reimbursement_status] + state_machine.after_transition to: [:reimbursed], do: :remove_tax_for_returned_items + end + + def remove_tax_for_returned_items + return unless ::Spree::Config[:taxjar_enabled] + return unless taxjar_applicable?(order) + client = ::Spree::Taxjar.new(order, self) + client.create_refund_transaction_for_order + end + end + end +end + +Spree::Reimbursement.prepend(SpreeTaxjar::Spree::ReimbursementDecorator) \ No newline at end of file diff --git a/app/overrides/spree/admin/shared/sub_menu/_configuration.rb b/app/overrides/spree/admin/shared/sub_menu/_configuration.rb index 401bcd0..210e477 100644 --- a/app/overrides/spree/admin/shared/sub_menu/_configuration.rb +++ b/app/overrides/spree/admin/shared/sub_menu/_configuration.rb @@ -2,5 +2,5 @@ virtual_path: "spree/admin/shared/sub_menu/_configuration", name: "add_taxjar_admin_menu_link", insert_bottom: "[data-hook='admin_configurations_sidebar_menu']", - text: "<%= configurations_sidebar_menu_item 'Taxjar Settings', edit_admin_taxjar_settings_path %>" + text: "<%= configurations_sidebar_menu_item 'Taxjar Settings', edit_admin_taxjar_settings_path if can? :manage, Spree::Config %>" ) diff --git a/app/views/spree/admin/taxjar_settings/edit.html.erb b/app/views/spree/admin/taxjar_settings/edit.html.erb index c736e4a..85ae093 100644 --- a/app/views/spree/admin/taxjar_settings/edit.html.erb +++ b/app/views/spree/admin/taxjar_settings/edit.html.erb @@ -1,28 +1,31 @@ <%= render 'spree/admin/shared/sub_menu/configuration' %> - <% content_for :page_title do %> <%= Spree.t(:taxjar_settings) %> <% end %> - <%= form_tag admin_taxjar_settings_path, method: :put do %>
<% @preferences_api.each do |key| %> -
+
+ <% if Spree::Config.preference_type(key) == :boolean %> +
+ <%= label_tag key do %> + <%= hidden_field_tag(key, 0, id: "#{key}_hidden") %> + <%= check_box_tag(key, 1, Spree::Config[key]) %> + <%= Spree.t(key) %> + <%end%> +
+ <% else %> <%= label_tag key %> <%= preference_field_tag(key, Spree::Config[key], type: Spree::Config.preference_type(key)) %> -
+ <% end %> +
<% end %>
- -
- <%= button Spree.t('actions.update'), 'refresh' %> - <%= Spree.t(:or) %> - <%= button_link_to Spree.t('actions.cancel'), admin_orders_url, icon: 'delete' %> -
+ <%= render partial: 'spree/admin/shared/edit_resource_links', locals: {collection_url: admin_orders_url} %>
<% end %> diff --git a/app/models/spree/app_configuration_decorator.rb b/config/initializers/app_configuration.rb similarity index 60% rename from app/models/spree/app_configuration_decorator.rb rename to config/initializers/app_configuration.rb index 4601ba2..3c5a2bb 100644 --- a/app/models/spree/app_configuration_decorator.rb +++ b/config/initializers/app_configuration.rb @@ -2,4 +2,6 @@ preference :taxjar_api_key, :string preference :taxjar_enabled, :boolean, default: false preference :taxjar_debug_enabled, :boolean, default: false + preference :taxjar_sandbox_environment_enabled, :boolean, default: false + preference :taxjar_timeout, :float, default: 2.0 end diff --git a/config/initializers/logger.rb b/config/initializers/logger.rb index 56fb741..aad5a12 100644 --- a/config/initializers/logger.rb +++ b/config/initializers/logger.rb @@ -1,2 +1,2 @@ -SpreeTaxjar::Logger = TaxjarHelper::TaxjarLog.new("spree_taxjar", "taxjar_calculator") +SpreeTaxjar::Logger = TaxjarHelper::TaxjarLog.new(STDOUT) SpreeTaxjar::Logger.logger.extend(ActiveSupport::Logger.broadcast(Rails.logger)) diff --git a/gemfiles/spree_3_2.gemfile b/gemfiles/spree_3_2.gemfile new file mode 100644 index 0000000..4fa2f1c --- /dev/null +++ b/gemfiles/spree_3_2.gemfile @@ -0,0 +1,12 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gem "spree", "~> 3.2.0" + +group :test do + gem "rails-controller-testing" + gem "byebug" +end + +gemspec path: "../" diff --git a/gemfiles/spree_3_3.gemfile b/gemfiles/spree_3_3.gemfile new file mode 100644 index 0000000..26905f1 --- /dev/null +++ b/gemfiles/spree_3_3.gemfile @@ -0,0 +1,12 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gem "spree", "~> 3.3.0" + +group :test do + gem "rails-controller-testing" + gem "byebug" +end + +gemspec path: "../" diff --git a/gemfiles/spree_3_4.gemfile b/gemfiles/spree_3_4.gemfile new file mode 100644 index 0000000..d90f7e2 --- /dev/null +++ b/gemfiles/spree_3_4.gemfile @@ -0,0 +1,12 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gem "spree", "~> 3.4.0" + +group :test do + gem "rails-controller-testing" + gem "byebug" +end + +gemspec path: "../" diff --git a/gemfiles/spree_3_7.gemfile b/gemfiles/spree_3_7.gemfile new file mode 100644 index 0000000..623d785 --- /dev/null +++ b/gemfiles/spree_3_7.gemfile @@ -0,0 +1,12 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gem "spree", "~> 3.7.0" + +group :test do + gem "rails-controller-testing" + gem "byebug" +end + +gemspec path: "../" diff --git a/gemfiles/spree_4.gemfile b/gemfiles/spree_4.gemfile new file mode 100644 index 0000000..aaf6252 --- /dev/null +++ b/gemfiles/spree_4.gemfile @@ -0,0 +1,13 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gem "spree", "~> 4.2" +gem "rails-controller-testing" + +group :test do + gem "rails-controller-testing" + gem "byebug" +end + +gemspec path: "../" diff --git a/gemfiles/spree_master.gemfile b/gemfiles/spree_master.gemfile new file mode 100644 index 0000000..8d1047c --- /dev/null +++ b/gemfiles/spree_master.gemfile @@ -0,0 +1,12 @@ +# This file was generated by Appraisal + +source "https://rubygems.org" + +gem "spree", github: "spree/spree", branch: "master" + +group :test do + gem "rails-controller-testing" + gem "byebug" +end + +gemspec path: "../" diff --git a/lib/spree_taxjar.rb b/lib/spree_taxjar.rb index e78b548..4f4b22e 100644 --- a/lib/spree_taxjar.rb +++ b/lib/spree_taxjar.rb @@ -1,2 +1,3 @@ require 'spree_core' require 'spree_taxjar/engine' +require 'deface' diff --git a/lib/spree_taxjar/engine.rb b/lib/spree_taxjar/engine.rb index db8c9fa..cfc166e 100644 --- a/lib/spree_taxjar/engine.rb +++ b/lib/spree_taxjar/engine.rb @@ -17,6 +17,10 @@ def self.activate Dir.glob(File.join(File.dirname(__FILE__), '../../app/**/*_decorator*.rb')) do |c| Rails.configuration.cache_classes ? require(c) : load(c) end + + Dir.glob(File.join(File.dirname(__FILE__), '../../lib/taxjar/**/*_decorator*.rb')) do |c| + Rails.application.config.cache_classes ? require(c) : load(c) + end end initializer 'spree.register.calculators' do |app| diff --git a/lib/spree_taxjar/factories.rb b/lib/spree_taxjar/factories.rb deleted file mode 100644 index bc50ea8..0000000 --- a/lib/spree_taxjar/factories.rb +++ /dev/null @@ -1,6 +0,0 @@ -FactoryGirl.define do - # Define your Spree extensions Factories within this file to enable applications, and other extensions to use and override them. - # - # Example adding this to your spec_helper will load these Factories for use: - # require 'spree_taxjar/factories' -end diff --git a/lib/taxjar/api/request_decorator.rb b/lib/taxjar/api/request_decorator.rb new file mode 100644 index 0000000..46cdae8 --- /dev/null +++ b/lib/taxjar/api/request_decorator.rb @@ -0,0 +1,15 @@ +module Taxjar + module API + module RequestDecorator + def set_http_timeout + @http_timeout = {} + + %i[connect write read].each do |method| + @http_timeout[method] = @options[:timeout] || ::Spree::Config[:taxjar_timeout] + end + end + end + end +end + +Taxjar::API::Request.prepend Taxjar::API::RequestDecorator diff --git a/spec/controllers/spree/admin/taxjar_settings_controller_spec.rb b/spec/controllers/spree/admin/taxjar_settings_controller_spec.rb index 8d08275..8b0825a 100644 --- a/spec/controllers/spree/admin/taxjar_settings_controller_spec.rb +++ b/spec/controllers/spree/admin/taxjar_settings_controller_spec.rb @@ -21,7 +21,7 @@ def send_request end it "assigns @preferences_api" do - expect(assigns[:preferences_api]).to eq([:taxjar_api_key, :taxjar_enabled, :taxjar_debug_enabled]) + expect(assigns[:preferences_api]).to eq([:taxjar_api_key, :taxjar_enabled, :taxjar_debug_enabled, :taxjar_sandbox_environment_enabled]) end it "renders edit template" do diff --git a/spec/models/concerns/taxable_spec.rb b/spec/models/concerns/spree_taxjar/taxable_spec.rb similarity index 71% rename from spec/models/concerns/taxable_spec.rb rename to spec/models/concerns/spree_taxjar/taxable_spec.rb index 4ac64da..c1c6b66 100644 --- a/spec/models/concerns/taxable_spec.rb +++ b/spec/models/concerns/spree_taxjar/taxable_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -describe Taxable do +describe SpreeTaxjar::Taxable do let(:order) { create(:order) } let(:tax_category) { create(:tax_category) } let(:country) { create(:country) } @@ -9,11 +9,17 @@ describe '#taxjar_applicable?' do context 'when TaxRate matches tax_zone' do before do - @zone = create(:zone, :name => "Country Zone", :default_tax => false, :zone_members => []) - @zone.zone_members.create(:zoneable => country) + Spree::Config[:tax_using_ship_address] = false + @zone = create( + :zone, + name: "Country Zone", + default_tax: false, + zone_members: [], + states: [order.bill_address.country.states.first] + ) + @zone.zone_members.create(:zoneable => order.bill_address.country) @rate = Spree::TaxRate.create(amount: 1, zone: @zone, tax_category: tax_category, calculator: calculator) - allow(order).to receive_messages :tax_zone => @zone end it 'should return true' do diff --git a/spec/models/spree/calculator/taxjar_calculator_spec.rb b/spec/models/spree/calculator/taxjar_calculator_spec.rb index 67b595f..5c6cf63 100644 --- a/spec/models/spree/calculator/taxjar_calculator_spec.rb +++ b/spec/models/spree/calculator/taxjar_calculator_spec.rb @@ -14,7 +14,7 @@ let!(:rate) { create(:tax_rate, tax_category: tax_category, amount: 0.05, included_in_price: included_in_price) } let(:included_in_price) { false } let!(:calculator) { Spree::Calculator::TaxjarCalculator.new(calculable: rate) } - let!(:order) { create(:order,ship_address_id: ship_address.id) } + let!(:order) { create(:order,ship_address: ship_address) } let!(:line_item) { create(:line_item, price: 10, quantity: 3, order_id: order.id) } let!(:line_item_exempt) { create(:line_item, price: 10, quantity: 3, order_id: order.id) } let!(:shipment) { create(:shipment, cost: 10, order: order) } diff --git a/spec/models/spree/order_decorator_spec.rb b/spec/models/spree/order_decorator_spec.rb index 267b1f4..709280a 100644 --- a/spec/models/spree/order_decorator_spec.rb +++ b/spec/models/spree/order_decorator_spec.rb @@ -7,7 +7,7 @@ describe 'Constants' do it 'should include Taxable' do - expect(Spree::Order.include?(Taxable)).to eq true + expect(Spree::Order.include?(SpreeTaxjar::Taxable)).to eq true end end diff --git a/spec/models/spree/reimbursment_decorator_spec.rb b/spec/models/spree/reimbursment_decorator_spec.rb index cc2cd02..64bc002 100644 --- a/spec/models/spree/reimbursment_decorator_spec.rb +++ b/spec/models/spree/reimbursment_decorator_spec.rb @@ -7,7 +7,7 @@ describe 'Constants' do it 'should include Taxable' do - expect(Spree::Order.include?(Taxable)).to eq true + expect(Spree::Order.include?(SpreeTaxjar::Taxable)).to eq true end end diff --git a/spec/models/spree/taxjar_spec.rb b/spec/models/spree/taxjar_spec.rb index a6694f2..468149e 100644 --- a/spec/models/spree/taxjar_spec.rb +++ b/spec/models/spree/taxjar_spec.rb @@ -8,11 +8,11 @@ let!(:zone) { create(:zone, name: "Country Zone", default_tax: true, zone_members: []) } let!(:ship_address) { create(:ship_address, city: "Adrian", zipcode: "79001", state: state) } let!(:tax_category) { create(:tax_category, tax_rates: []) } - let!(:order) { create(:order,ship_address_id: ship_address.id) } + let!(:order) { create(:order, ship_address: ship_address) } let!(:line_item) { create(:line_item, price: 10, quantity: 3, order_id: order.id) } let!(:state_al) { create(:state, country: country, abbr: "AL") } let!(:ship_address_al) { create(:ship_address, city: "Adrian", zipcode: "79001", state: state_al) } - let!(:order_al) { create(:order,ship_address_id: ship_address_al.id) } + let!(:order_al) { create(:order,ship_address: ship_address_al) } let!(:line_item_al) { create(:line_item, price: 10, quantity: 3, order_id: order_al.id) } let!(:shipment_al) { create(:shipment, cost: 10, order: order_al) } let!(:taxjar_api_key) { Spree::Config[:taxjar_api_key] = '04d828b7374896d7867b03289ea20957' } @@ -55,7 +55,7 @@ context 'When reimbursement is not present' do before :each do Spree::Config[:taxjar_api_key] = '04d828b7374896d7867b03289ea20957' - allow(::Taxjar::Client).to receive(:new).with(api_key: Spree::Config[:taxjar_api_key]).and_return(client) + allow(::Taxjar::Client).to receive(:new).with(api_key: Spree::Config[:taxjar_api_key], api_url: ::Taxjar::API::Request::DEFAULT_API_URL).and_return(client) end let(:spree_taxjar) { Spree::Taxjar.new(order) } @@ -88,7 +88,7 @@ context 'when has_nexus? returns true' do before do - allow(::Taxjar::Client).to receive(:new).with(api_key: Spree::Config[:taxjar_api_key]).and_return(client) + allow(::Taxjar::Client).to receive(:new).with(api_key: Spree::Config[:taxjar_api_key], api_url: ::Taxjar::API::Request::DEFAULT_API_URL).and_return(client) allow(spree_taxjar).to receive(:has_nexus?).and_return(true) allow(client).to receive(:create_order).and_return(true) end @@ -160,7 +160,7 @@ context 'When reimbursement is present' do let(:spree_taxjar) { Spree::Taxjar.new(order, reimbursement) } before do - allow(::Taxjar::Client).to receive(:new).with(api_key: Spree::Config[:taxjar_api_key]).and_return(client) + allow(::Taxjar::Client).to receive(:new).with(api_key: Spree::Config[:taxjar_api_key], api_url: ::Taxjar::API::Request::DEFAULT_API_URL).and_return(client) end describe '#create_refund_transaction_for_order' do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 32dffe3..eafcb30 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,100 +1,16 @@ -# Run Coverage report -require 'simplecov' -SimpleCov.start do - add_filter 'spec/dummy' - add_group 'Controllers', 'app/controllers' - add_group 'Helpers', 'app/helpers' - add_group 'Mailers', 'app/mailers' - add_group 'Models', 'app/models' - add_group 'Views', 'app/views' - add_group 'Libraries', 'lib' -end - # Configure Rails Environment ENV['RAILS_ENV'] = 'test' -require File.expand_path('../dummy/config/environment.rb', __FILE__) +require File.expand_path('../dummy/config/environment.rb', __FILE__) +require 'spree_dev_tools/rspec/spec_helper' require 'shoulda-matchers' include Shoulda::Matchers::Independent -require 'rspec/rails' -require 'database_cleaner' -require 'ffaker' -require 'rspec/active_model/mocks' require 'vcr' # Requires supporting ruby files with custom matchers and macros, etc, # in spec/support/ and its subdirectories. -Dir[File.join(File.dirname(__FILE__), 'support/**/*.rb')].each { |f| require f } - -# Requires factories and other useful helpers defined in spree_core. -require 'spree/testing_support/authorization_helpers' -require 'spree/testing_support/capybara_ext' -require 'spree/testing_support/controller_requests' -require 'spree/testing_support/factories' -require 'spree/testing_support/url_helpers' - -# Requires factories defined in lib/spree_taxjar/factories.rb -require 'spree_taxjar/factories' - -RSpec.configure do |config| - config.include FactoryGirl::Syntax::Methods - - # Infer an example group's spec type from the file location. - config.infer_spec_type_from_file_location! - - # == URL Helpers - # - # Allows access to Spree's routes in specs: - # - # visit spree.admin_path - # current_path.should eql(spree.products_path) - config.include Spree::TestingSupport::UrlHelpers - - # == Requests support - # - # Adds convenient methods to request Spree's controllers - # spree_get :index - config.include Spree::TestingSupport::ControllerRequests, type: :controller - - # == Mock Framework - # - # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line: - # - # config.mock_with :mocha - # config.mock_with :flexmock - # config.mock_with :rr - config.mock_with :rspec - config.color = true - - # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures - config.fixture_path = "#{::Rails.root}/spec/fixtures" - - # Capybara javascript drivers require transactional fixtures set to false, and we use DatabaseCleaner - # to cleanup after each test instead. Without transactional fixtures set to false the records created - # to setup a test will be unavailable to the browser, which runs under a separate server instance. - config.use_transactional_fixtures = false - - # Ensure Suite is set to use transactions for speed. - config.before :suite do - DatabaseCleaner.strategy = :transaction - DatabaseCleaner.clean_with :truncation - end - - # Before each spec check if it is a Javascript test and switch between using database transactions or not where necessary. - config.before :each do - DatabaseCleaner.strategy = RSpec.current_example.metadata[:js] ? :truncation : :transaction - DatabaseCleaner.start - end - - # After each spec clean the database. - config.after :each do - DatabaseCleaner.clean - end - - config.fail_fast = ENV['FAIL_FAST'] || false - config.order = "random" -end +Dir[File.join(File.dirname(__FILE__), 'support/**/*.rb')].sort.each { |f| require f } VCR.configure do |c| c.cassette_library_dir = 'spec/fixtures/vcr_cassettes' diff --git a/spree_taxjar.gemspec b/spree_taxjar.gemspec index f623f83..68897bb 100644 --- a/spree_taxjar.gemspec +++ b/spree_taxjar.gemspec @@ -2,7 +2,7 @@ Gem::Specification.new do |s| s.platform = Gem::Platform::RUBY s.name = 'spree_taxjar' - s.version = '3.2.0' + s.version = '4.2.0' s.summary = 'Spree extension to calculate sales tax in states of USA' s.description = 'Spree extension for providing TaxJar services in USA' s.required_ruby_version = '>= 2.1.0' @@ -14,21 +14,14 @@ Gem::Specification.new do |s| s.require_path = 'lib' s.requirements << 'none' - s.add_dependency('spree_core', '~> 3.2.0') - s.add_dependency 'taxjar-ruby', '~> 1.5' + spree_version = '>= 3.2.0' + + s.add_dependency 'spree_backend', spree_version + s.add_dependency 'taxjar-ruby', '>= 2.6', '< 3.1' + s.add_dependency 'deface', '~> 1.0' - s.add_development_dependency 'capybara', '~> 2.6' - s.add_development_dependency 'coffee-rails', '~> 4.2.1' - s.add_development_dependency 'database_cleaner', '~> 1.5.3' - s.add_development_dependency 'factory_girl', '~> 4.5' - s.add_development_dependency 'ffaker', '~> 2.2.0' - s.add_development_dependency 'rspec-rails', '~> 3.4' - s.add_development_dependency 'sass-rails', '~> 5.0.0' - s.add_development_dependency 'selenium-webdriver', '~> 2.53.4' - s.add_development_dependency 'simplecov', '~> 0.12.0' - s.add_development_dependency 'sqlite3', '~> 1.3.11' s.add_development_dependency 'shoulda-matchers' - s.add_development_dependency 'rspec-activemodel-mocks' + s.add_development_dependency 'spree_dev_tools' s.add_development_dependency 'vcr' s.add_development_dependency 'webmock' end