spree_avatax_official 1.9.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.claude/settings.local.json +8 -0
- data/.env-sample +3 -3
- data/.gem_release.yml +2 -0
- data/.github/workflows/ci.yml +80 -0
- data/.gitignore +1 -0
- data/Gemfile +12 -6
- data/README.md +1 -1
- data/app/assets/images/integration_icons/avalara-logo.png +0 -0
- data/app/controllers/spree/admin/avalara_entity_use_codes_controller.rb +11 -47
- data/app/controllers/spree/admin/avatax_customer_settings_controller.rb +43 -0
- data/app/controllers/spree_avatax_official/admin/base_controller_decorator.rb +11 -0
- data/app/helpers/spree_avatax_official/avalara_integration_helper.rb +10 -0
- data/app/helpers/spree_avatax_official/tax_adjustment_label_helper.rb +5 -3
- data/app/models/spree/integrations/avalara.rb +61 -0
- data/app/models/spree_avatax_official/calculator/avatax_transaction_calculator.rb +0 -3
- data/app/models/spree_avatax_official/configuration.rb +0 -1
- data/app/models/spree_avatax_official/entity_use_code.rb +5 -4
- data/app/models/spree_avatax_official/spree/address_decorator.rb +2 -8
- data/app/models/spree_avatax_official/spree/line_item_decorator.rb +1 -7
- data/app/models/spree_avatax_official/spree/order_decorator.rb +35 -13
- data/app/models/spree_avatax_official/spree/refund_decorator.rb +2 -2
- data/app/models/spree_avatax_official/spree/shipment_decorator.rb +8 -1
- data/app/models/spree_avatax_official/spree/user_decorator.rb +1 -1
- data/app/models/spree_avatax_official/transaction.rb +3 -2
- data/app/presenters/spree_avatax_official/item_presenter.rb +16 -10
- data/app/presenters/spree_avatax_official/transactions/amount_refund_presenter.rb +35 -0
- data/app/presenters/spree_avatax_official/transactions/create_presenter.rb +31 -27
- data/app/services/spree_avatax_official/address/validate.rb +13 -4
- data/app/services/spree_avatax_official/base.rb +12 -12
- data/app/services/spree_avatax_official/create_tax_adjustments_service.rb +5 -5
- data/app/services/spree_avatax_official/generate_transaction_cache_key_service.rb +16 -6
- data/app/services/spree_avatax_official/get_tax_service.rb +1 -1
- data/app/services/spree_avatax_official/transactions/adjust_service.rb +1 -1
- data/app/services/spree_avatax_official/transactions/amount_refund_service.rb +31 -0
- data/app/services/spree_avatax_official/transactions/create_service.rb +2 -2
- data/app/services/spree_avatax_official/transactions/full_refund_service.rb +1 -1
- data/app/services/spree_avatax_official/transactions/get_by_code_service.rb +1 -1
- data/app/services/spree_avatax_official/transactions/partial_refund_service.rb +1 -1
- data/app/services/spree_avatax_official/transactions/refund_service.rb +15 -5
- data/app/services/spree_avatax_official/transactions/void_service.rb +1 -1
- data/app/views/spree/admin/avalara_entity_use_codes/_form.html.erb +5 -18
- data/app/views/spree/admin/avalara_entity_use_codes/edit.html.erb +1 -12
- data/app/views/spree/admin/avalara_entity_use_codes/index.html.erb +6 -28
- data/app/views/spree/admin/avalara_entity_use_codes/new.html.erb +1 -12
- data/app/views/spree/admin/avatax_customer_settings/_form.html.erb +18 -0
- data/app/views/spree/admin/avatax_customer_settings/edit.html.erb +3 -0
- data/app/views/spree/admin/integrations/forms/_avalara.html.erb +33 -0
- data/app/views/spree/admin/shared/_avatax_customer_settings_link.html.erb +12 -0
- data/config/initializers/spree_avatax_official_navigation.rb +42 -0
- data/config/initializers/spree_permitted_attributes.rb +1 -1
- data/config/locales/en.yml +27 -22
- data/config/routes.rb +3 -9
- data/db/migrate/20190118155953_add_exemption_number_to_spree_users.rb +1 -1
- data/db/migrate/20190118160653_create_spree_avalara_entity_use_codes.rb +1 -1
- data/db/migrate/20190118161318_add_avalara_entity_use_code_reference_to_users.rb +1 -1
- data/db/migrate/20190118162345_add_vat_id_to_spree_users.rb +1 -1
- data/db/migrate/20190122154119_create_spree_avatax_official_transactions.rb +1 -1
- data/db/migrate/20190201123706_add_tax_code_to_spree_tax_categories.rb +1 -1
- data/db/migrate/20190208130136_add_avatax_company_code_to_spree_stores.rb +1 -1
- data/db/migrate/20190225145808_add_uuid_to_spree_line_items_and_spree_shipments.rb +1 -1
- data/db/migrate/20191001085458_remove_spree_avalara_entity_use_codes_table.rb +1 -1
- data/db/migrate/20191001092353_create_spree_avatax_official_entity_use_codes_table.rb +5 -6
- data/lib/generators/spree_avatax_official/install/templates/config/initializers/spree_avatax_official.rb +16 -9
- data/lib/spree_avatax_official/configuration.rb +7 -16
- data/lib/spree_avatax_official/engine.rb +1 -2
- data/lib/spree_avatax_official/factories.rb +2 -8
- data/lib/spree_avatax_official/seeder.rb +1 -1
- data/lib/spree_avatax_official/testing_support/factories/avalara_integration.rb +13 -0
- data/lib/spree_avatax_official/version.rb +1 -1
- data/lib/spree_avatax_official.rb +2 -3
- data/spec/controllers/spree/admin/avalara_entity_use_codes_controller_spec.rb +64 -0
- data/spec/controllers/spree/admin/avatax_customer_settings_controller_spec.rb +57 -0
- data/spec/factories/spree_avatax_official/avalara_entity_use_code_factory.rb +3 -1
- data/spec/helpers/spree_avatax_official/tax_adjustment_label_helper_spec.rb +13 -14
- data/spec/models/spree/integrations/avalara_spec.rb +75 -0
- data/spec/models/spree/line_item_spec.rb +0 -65
- data/spec/models/spree/order_spec.rb +36 -28
- data/spec/models/spree/shipment_spec.rb +33 -0
- data/spec/models/spree_avatax_official/spree/refund_decorator_spec.rb +4 -7
- data/spec/presenters/spree_avatax_official/address_presenter_spec.rb +11 -2
- data/spec/presenters/spree_avatax_official/item_presenter_spec.rb +32 -8
- data/spec/presenters/spree_avatax_official/transactions/amount_refund_presenter_spec.rb +44 -0
- data/spec/presenters/spree_avatax_official/transactions/create_presenter_spec.rb +39 -19
- data/spec/presenters/spree_avatax_official/transactions/partial_refund_presenter_spec.rb +17 -18
- data/spec/services/spree_avatax_official/address/validate_spec.rb +44 -2
- data/spec/services/spree_avatax_official/create_tax_adjustments_service_spec.rb +105 -179
- data/spec/services/spree_avatax_official/generate_transaction_cache_key_service_spec.rb +45 -1
- data/spec/services/spree_avatax_official/get_tax_service_spec.rb +11 -3
- data/spec/services/spree_avatax_official/transactions/adjust_service_spec.rb +13 -3
- data/spec/services/spree_avatax_official/transactions/amount_refund_service_spec.rb +55 -0
- data/spec/services/spree_avatax_official/transactions/create_service_spec.rb +77 -71
- data/spec/services/spree_avatax_official/transactions/find_order_transaction_service_spec.rb +1 -1
- data/spec/services/spree_avatax_official/transactions/full_refund_service_spec.rb +7 -3
- data/spec/services/spree_avatax_official/transactions/get_by_code_service_spec.rb +1 -1
- data/spec/services/spree_avatax_official/transactions/partial_refund_service_spec.rb +6 -4
- data/spec/services/spree_avatax_official/transactions/refund_service_spec.rb +88 -10
- data/spec/services/spree_avatax_official/transactions/void_service_spec.rb +13 -2
- data/spec/spec_helper.rb +14 -26
- data/spec/support/avatax.rb +0 -10
- data/spec/support/factory_bot.rb +4 -0
- data/spec/support/integration_helper.rb +16 -0
- data/spec/support/tax_inclusive_helper.rb +29 -0
- data/spec/support/vcr.rb +3 -13
- data/spec/vcr/SpreeAvataxOfficial_Transactions_FindOrderTransactionService/_call/with_Spree_Order/when_order_does_NOT_have_a_SalesInvoice_transaction/when_transaction_exists_in_avatax/returns_success_and_creates_a_new_SalesInvoice_transaction.yml +2 -47
- data/spec/vcr/spree/integrations/avalara/can_connect/authenticated.yml +65 -0
- data/spec/vcr/spree/integrations/avalara/can_connect/unauthenticated.yml +65 -0
- data/spec/vcr/spree_avatax_official/address/validate_failure.yml +48 -12
- data/spec/vcr/spree_avatax_official/address/validate_success.yml +123 -9
- data/spec/vcr/spree_avatax_official/address/zipcode_failure.yml +45 -9
- data/spec/vcr/spree_avatax_official/create_tax_adjustments/californian_stock_location.yml +242 -20
- data/spec/vcr/spree_avatax_official/create_tax_adjustments/completed_order_line_item_update.yml +156 -25
- data/spec/vcr/spree_avatax_official/create_tax_adjustments/order_adjustment_promotion.yml +360 -22
- data/spec/vcr/spree_avatax_official/create_tax_adjustments/shipment_adjustment_promotion.yml +335 -20
- data/spec/vcr/spree_avatax_official/create_tax_adjustments/simple_completed_order.yml +341 -22
- data/spec/vcr/spree_avatax_official/create_tax_adjustments/tax_address_not_persisted.yml +110 -0
- data/spec/vcr/spree_avatax_official/create_tax_adjustments/tax_excluded/line_item_adjustment_promotion.yml +362 -22
- data/spec/vcr/spree_avatax_official/create_tax_adjustments/tax_excluded/line_item_and_shipment.yml +242 -20
- data/spec/vcr/spree_avatax_official/create_tax_adjustments/tax_excluded/multiple_line_items_multiple_quantity.yml +165 -23
- data/spec/vcr/spree_avatax_official/create_tax_adjustments/tax_included/line_item_adjustment_promotion.yml +362 -22
- data/spec/vcr/spree_avatax_official/create_tax_adjustments/tax_included/line_item_and_shipment.yml +245 -23
- data/spec/vcr/spree_avatax_official/create_tax_adjustments/tax_included/multiple_line_items_multiple_quantity.yml +165 -23
- data/spec/vcr/spree_avatax_official/create_tax_adjustments/with_incorrect_address.yml +119 -31
- data/spec/vcr/spree_avatax_official/get_tax/error.yml +48 -14
- data/spec/vcr/spree_avatax_official/get_tax/sucsess.yml +62 -21
- data/spec/vcr/spree_avatax_official/spree/shipment/selected_shipping_rate_change.yml +189 -0
- data/spec/vcr/spree_avatax_official/spree/shipment/selected_shipping_rate_change_completed.yml +96 -0
- data/spec/vcr/spree_avatax_official/transactions/adjust/failure.yml +107 -36
- data/spec/vcr/spree_avatax_official/transactions/adjust/invoice_order_success.yml +117 -54
- data/spec/vcr/spree_avatax_official/transactions/create/complete_order_success.yml +152 -23
- data/spec/vcr/spree_avatax_official/transactions/create/gst/canada_to_canada.yml +241 -18
- data/spec/vcr/spree_avatax_official/transactions/create/gst/canada_to_us.yml +154 -21
- data/spec/vcr/spree_avatax_official/transactions/create/gst/us_to_canada.yml +255 -19
- data/spec/vcr/spree_avatax_official/transactions/create/invoice_order_success.yml +150 -21
- data/spec/vcr/spree_avatax_official/transactions/create/sales_order_success.yml +150 -21
- data/spec/vcr/spree_avatax_official/transactions/create/timeout.yml +144 -15
- data/spec/vcr/spree_avatax_official/transactions/create/vat/europe_to_europe.yml +245 -18
- data/spec/vcr/spree_avatax_official/transactions/create/vat/europe_to_us.yml +153 -20
- data/spec/vcr/spree_avatax_official/transactions/create/vat/us_to_europe.yml +247 -19
- data/spec/vcr/spree_avatax_official/transactions/refund/amount_refund_success.yml +196 -0
- data/spec/vcr/spree_avatax_official/transactions/refund/full_refund_success.yml +121 -49
- data/spec/vcr/spree_avatax_official/transactions/refund/partial_refund_success.yml +57 -23
- data/spec/vcr/spree_avatax_official/transactions/refund/partial_refund_with_refund_success.yml +57 -23
- data/spec/vcr/spree_avatax_official/transactions/void/success.yml +117 -45
- data/spec/vcr/spree_order/california_order.yml +66 -28
- data/spec/vcr/spree_order/complete_order.yml +236 -23
- data/spec/vcr/spree_order/complete_order_no_transaction.yml +96 -0
- data/spec/vcr/spree_order/order_transition_to_completed.yml +58 -74
- data/spec/vcr/spree_order/order_with_line_item_adjustment.yml +151 -19
- data/spec/vcr/spree_order/order_with_order_adjustment.yml +151 -19
- data/spec/vcr/spree_order/simple_order_with_single_line_item_and_shipment.yml +60 -21
- data/spec/zeitwerk_spec.rb +9 -0
- data/spree_avatax_official.gemspec +4 -5
- metadata +58 -73
- data/.circleci/config.yml +0 -115
- data/app/controllers/spree/admin/avatax_pings_controller.rb +0 -19
- data/app/controllers/spree/admin/avatax_settings_controller.rb +0 -26
- data/app/controllers/spree/admin/users_controller_decorator.rb +0 -27
- data/app/overrides/spree/admin/shared/sub_menu/_configuration.rb +0 -10
- data/app/overrides/spree/admin/sidebar.rb +0 -14
- data/app/services/spree_avatax_official/settings/update_service.rb +0 -36
- data/app/services/spree_avatax_official/utilities/ping_service.rb +0 -9
- data/app/views/spree/admin/avatax_settings/edit.html.erb +0 -99
- data/app/views/spree/admin/users/avalara_information.html.erb +0 -39
- data/app/views/spree/admin/zones/_form.html.erb +0 -58
- data/db/migrate/20190329071439_add_included_in_price_to_spree_zones.rb +0 -5
- data/spec/features/admin/edit_avatax_settings_spec.rb +0 -11
- data/spec/features/admin/update_avatax_settings_spec.rb +0 -200
- data/spec/features/spree/admin/avalara_entity_use_codes_controller_spec.rb +0 -71
- data/spec/features/spree/admin/users_controller_spec.rb +0 -34
- data/spec/services/spree_avatax_official/settings/update_service_spec.rb +0 -131
- data/spec/services/spree_avatax_official/utilities/ping_service_spec.rb +0 -35
- data/spec/support/capybara.rb +0 -21
- data/spec/support/database_cleaner.rb +0 -25
- data/spec/vcr/spree_avatax_official/create_tax_adjustments/tax_excluded/single_line_item.yml +0 -55
- data/spec/vcr/spree_avatax_official/create_tax_adjustments/tax_included/single_line_item.yml +0 -55
- data/spec/vcr/spree_avatax_official/utilities/ping.yml +0 -41
- data/spec/vcr/spree_avatax_official/utilities/ping_unauthorized.yml +0 -42
- data/spec/vcr/spree_line_item/update_tax_charge/decrease_quantity.yml +0 -55
- data/spec/vcr/spree_line_item/update_tax_charge/increase_quantity.yml +0 -55
- data/spec/vcr/spree_order/simple_order_with_single_line_item.yml +0 -55
- data/spec/vcr/spree_order/update_tax_charge/create_line_item.yml +0 -55
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: dbc764902a265aa63189cd4bd388a9d527c6dde67864a039519978c868adf4de
|
|
4
|
+
data.tar.gz: 9c3fca8394ddbd9b8191a97ca939a2ac0c3ac76945e15ed47b096001b5d1ae1b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3fef2a3753c92f98eee99edf803d4796487427b41a58d842e1c81d6925cbc60d4c072d6f71f845c6ac2ca7a3553831432f58aade0a83b7d5cd4b45ae11933b2b
|
|
7
|
+
data.tar.gz: 75e78335343ca45ff5c1b178e8db0baf5a3dc52d57bc5652b4cad96425299425a374b3602845682fae6af02bd17b109b554c2600cdd71ec65032484e84c5643a
|
data/.env-sample
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
AVATAX_ENDPOINT=https://sandbox-rest.avatax.com
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
AVATAX_COMPANY_CODE=
|
|
2
|
+
AVATAX_ACCOUNT_NUMBER=
|
|
3
|
+
AVATAX_LICENSE_KEY=
|
|
4
|
+
AVATAX_COMPANY_CODE=test1
|
data/.gem_release.yml
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [master]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
tests_postgres:
|
|
11
|
+
name: Tests (PostgreSQL)
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
services:
|
|
14
|
+
postgres:
|
|
15
|
+
image: postgres:16
|
|
16
|
+
env:
|
|
17
|
+
POSTGRES_USER: postgres
|
|
18
|
+
POSTGRES_PASSWORD: postgres
|
|
19
|
+
ports:
|
|
20
|
+
- 5432:5432
|
|
21
|
+
options: >-
|
|
22
|
+
--health-cmd pg_isready
|
|
23
|
+
--health-interval 10s
|
|
24
|
+
--health-timeout 5s
|
|
25
|
+
--health-retries 5
|
|
26
|
+
env:
|
|
27
|
+
DB: postgres
|
|
28
|
+
DB_HOST: localhost
|
|
29
|
+
DB_USERNAME: postgres
|
|
30
|
+
DB_PASSWORD: postgres
|
|
31
|
+
BUNDLE_JOBS: 4
|
|
32
|
+
BUNDLE_RETRY: 3
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@v4
|
|
35
|
+
- name: Install libvips
|
|
36
|
+
run: sudo apt-get update && sudo apt-get install -y libvips
|
|
37
|
+
- name: Set up Ruby
|
|
38
|
+
uses: ruby/setup-ruby@v1
|
|
39
|
+
with:
|
|
40
|
+
ruby-version: '4.0'
|
|
41
|
+
bundler-cache: true
|
|
42
|
+
- name: Create test app
|
|
43
|
+
run: bundle exec rake test_app
|
|
44
|
+
- name: Run tests
|
|
45
|
+
run: bundle exec rspec --format documentation
|
|
46
|
+
|
|
47
|
+
tests_mysql:
|
|
48
|
+
name: Tests (MySQL)
|
|
49
|
+
runs-on: ubuntu-latest
|
|
50
|
+
services:
|
|
51
|
+
mysql:
|
|
52
|
+
image: mysql:8.0
|
|
53
|
+
env:
|
|
54
|
+
MYSQL_ALLOW_EMPTY_PASSWORD: yes
|
|
55
|
+
ports:
|
|
56
|
+
- 3306:3306
|
|
57
|
+
options: >-
|
|
58
|
+
--health-cmd "mysqladmin ping -h 127.0.0.1"
|
|
59
|
+
--health-interval 10s
|
|
60
|
+
--health-timeout 5s
|
|
61
|
+
--health-retries 5
|
|
62
|
+
env:
|
|
63
|
+
DB: mysql
|
|
64
|
+
DB_HOST: 127.0.0.1
|
|
65
|
+
DB_USERNAME: root
|
|
66
|
+
BUNDLE_JOBS: 4
|
|
67
|
+
BUNDLE_RETRY: 3
|
|
68
|
+
steps:
|
|
69
|
+
- uses: actions/checkout@v4
|
|
70
|
+
- name: Install libvips
|
|
71
|
+
run: sudo apt-get update && sudo apt-get install -y libvips
|
|
72
|
+
- name: Set up Ruby
|
|
73
|
+
uses: ruby/setup-ruby@v1
|
|
74
|
+
with:
|
|
75
|
+
ruby-version: '4.0'
|
|
76
|
+
bundler-cache: true
|
|
77
|
+
- name: Create test app
|
|
78
|
+
run: bundle exec rake test_app
|
|
79
|
+
- name: Run tests
|
|
80
|
+
run: bundle exec rspec --format documentation
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
|
@@ -6,20 +6,26 @@ git_source(:github) do |repo_name|
|
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
gem 'rails-controller-testing'
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
|
|
10
|
+
spree_opts = if ENV['SPREE_PATH']
|
|
11
|
+
{ 'path': ENV['SPREE_PATH'] }
|
|
12
|
+
else
|
|
13
|
+
{ 'github': 'spree/spree', 'branch': 'main', 'glob': 'spree/**/*.gemspec' }
|
|
14
|
+
end
|
|
15
|
+
gem 'spree', spree_opts
|
|
16
|
+
gem 'spree_core', spree_opts
|
|
17
|
+
gem 'spree_admin', spree_opts
|
|
18
|
+
|
|
13
19
|
|
|
14
20
|
if ENV['DB'] == 'mysql'
|
|
15
21
|
gem 'mysql2'
|
|
16
22
|
elsif ENV['DB'] == 'postgres'
|
|
17
23
|
gem 'pg'
|
|
18
24
|
else
|
|
19
|
-
gem 'sqlite3'
|
|
25
|
+
gem 'sqlite3'
|
|
20
26
|
end
|
|
21
27
|
|
|
22
|
-
gem '
|
|
28
|
+
gem 'propshaft'
|
|
23
29
|
gem 'pry'
|
|
24
30
|
|
|
25
31
|
gemspec
|
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Spree Avalara AvaTax official extension
|
|
2
2
|
|
|
3
|
-
[](https://github.com/spree/spree_avatax_official/actions/workflows/ci.yml)
|
|
4
4
|
|
|
5
5
|
The new officially supported Avalara AvaTax extension for [Spree Commerce](https://spreecommerce.org/) using [Avalara REST API v2](https://developer.avalara.com/api-reference/avatax/rest/v2/).
|
|
6
6
|
* [Introduction](#introduction)
|
|
Binary file
|
|
@@ -1,60 +1,24 @@
|
|
|
1
1
|
module Spree
|
|
2
2
|
module Admin
|
|
3
|
-
class AvalaraEntityUseCodesController <
|
|
4
|
-
|
|
3
|
+
class AvalaraEntityUseCodesController < ResourceController
|
|
4
|
+
include Spree::Admin::SettingsConcern
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
@use_codes = SpreeAvataxOfficial::EntityUseCode.all.order(code: :asc)
|
|
8
|
-
respond_with(@use_codes)
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def new
|
|
12
|
-
@use_code = SpreeAvataxOfficial::EntityUseCode.new
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def edit; end
|
|
16
|
-
|
|
17
|
-
def update
|
|
18
|
-
if @use_code.update(entity_use_codes_params)
|
|
19
|
-
redirect_to admin_avalara_entity_use_codes_path, success: Spree.t('spree_avatax_official.entity_use_code_updated')
|
|
20
|
-
else
|
|
21
|
-
redirect_to edit_admin_avalara_entity_use_code_path(@use_code), error: @use_code.errors.full_messages.to_sentence
|
|
22
|
-
end
|
|
23
|
-
end
|
|
6
|
+
private
|
|
24
7
|
|
|
25
|
-
def
|
|
26
|
-
|
|
27
|
-
if @use_code.save
|
|
28
|
-
redirect_to admin_avalara_entity_use_codes_path, success: Spree.t('spree_avatax_official.entity_use_code_created')
|
|
29
|
-
else
|
|
30
|
-
redirect_to new_admin_avalara_entity_use_code_path, error: @use_code.errors.full_messages.to_sentence
|
|
31
|
-
end
|
|
8
|
+
def model_class
|
|
9
|
+
SpreeAvataxOfficial::EntityUseCode
|
|
32
10
|
end
|
|
33
11
|
|
|
34
|
-
def
|
|
35
|
-
|
|
36
|
-
flash[:success] = Spree.t('spree_avatax_official.entity_use_code_removed')
|
|
37
|
-
else
|
|
38
|
-
flash[:error] = @use_code.errors.full_messages.to_sentence
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
respond_with(@use_code) do |format|
|
|
42
|
-
format.html { redirect_to admin_avalara_entity_use_codes_path }
|
|
43
|
-
format.js { render_js_for_destroy }
|
|
44
|
-
end
|
|
12
|
+
def permitted_resource_params
|
|
13
|
+
params.require(:avalara_entity_use_code).permit(:code, :name, :description)
|
|
45
14
|
end
|
|
46
15
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
def load_use_code
|
|
50
|
-
@use_code ||= SpreeAvataxOfficial::EntityUseCode.find(params[:id])
|
|
51
|
-
rescue ActiveRecord::RecordNotFound => e
|
|
52
|
-
flash[:error] = e.message
|
|
53
|
-
redirect_to admin_avalara_entity_use_codes_path
|
|
16
|
+
def collection_url(options = {})
|
|
17
|
+
spree.admin_avalara_entity_use_codes_url(options)
|
|
54
18
|
end
|
|
55
19
|
|
|
56
|
-
def
|
|
57
|
-
|
|
20
|
+
def new_object_url(options = {})
|
|
21
|
+
spree.new_admin_avalara_entity_use_code_url(options)
|
|
58
22
|
end
|
|
59
23
|
end
|
|
60
24
|
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Admin
|
|
3
|
+
class AvataxCustomerSettingsController < Spree::Admin::BaseController
|
|
4
|
+
helper_method :object_url
|
|
5
|
+
|
|
6
|
+
before_action :load_user
|
|
7
|
+
before_action :load_entity_use_codes, only: %i[edit update]
|
|
8
|
+
|
|
9
|
+
def edit; end
|
|
10
|
+
|
|
11
|
+
def update
|
|
12
|
+
if @user.update(permitted_resource_params)
|
|
13
|
+
flash[:success] = flash_message_for(@user, :successfully_updated)
|
|
14
|
+
redirect_to spree.admin_user_path(@user), status: :see_other
|
|
15
|
+
else
|
|
16
|
+
render :edit, status: :unprocessable_entity
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def load_user
|
|
23
|
+
@user = Spree.user_class.find_by_prefix_id!(params[:user_id])
|
|
24
|
+
authorize! :update, @user
|
|
25
|
+
|
|
26
|
+
@object = @user
|
|
27
|
+
@resource = Spree::Admin::Resource.new(controller_path, controller_name, nil)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def object_url
|
|
31
|
+
spree.admin_user_avatax_customer_settings_path(@user)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def load_entity_use_codes
|
|
35
|
+
@entity_use_codes = SpreeAvataxOfficial::EntityUseCode.order(:code)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def permitted_resource_params
|
|
39
|
+
params.require(:avatax_customer_setting).permit(:avatax_entity_use_code_id, :exemption_number, :vat_id)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module SpreeAvataxOfficial
|
|
2
|
+
module Admin
|
|
3
|
+
module BaseControllerDecorator
|
|
4
|
+
def self.prepended(base)
|
|
5
|
+
base.helper SpreeAvataxOfficial::AvalaraIntegrationHelper
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
::Spree::Admin::BaseController.prepend(::SpreeAvataxOfficial::Admin::BaseControllerDecorator) if defined?(::Spree::Admin::BaseController)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
module SpreeAvataxOfficial
|
|
2
|
+
module AvalaraIntegrationHelper
|
|
3
|
+
def avalara_endpoint_options
|
|
4
|
+
[
|
|
5
|
+
[::Spree.t('spree_avatax_official.endpoint_sandbox'), ::Spree::Integrations::Avalara::SANDBOX_ENDPOINT],
|
|
6
|
+
[::Spree.t('spree_avatax_official.endpoint_production'), ::Spree::Integrations::Avalara::PRODUCTION_ENDPOINT]
|
|
7
|
+
]
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -10,7 +10,8 @@ module SpreeAvataxOfficial
|
|
|
10
10
|
|
|
11
11
|
format_adjustment_label(
|
|
12
12
|
::Spree.t("spree_avatax_official.create_tax_adjustments.#{item_class}_tax_adjustment_default_label", included_label: included_label(item)),
|
|
13
|
-
rate
|
|
13
|
+
rate,
|
|
14
|
+
item.order
|
|
14
15
|
)
|
|
15
16
|
end
|
|
16
17
|
|
|
@@ -18,13 +19,14 @@ module SpreeAvataxOfficial
|
|
|
18
19
|
item.included_in_price ? 'Included ' : ''
|
|
19
20
|
end
|
|
20
21
|
|
|
21
|
-
def format_adjustment_label(adjustment_default_label, rate)
|
|
22
|
+
def format_adjustment_label(adjustment_default_label, rate, order)
|
|
22
23
|
rate_in_percents = number_to_percentage(
|
|
23
24
|
rate * 100.0,
|
|
24
25
|
precision: PRECISION_OF_PERCENT_VALUE,
|
|
25
26
|
strip_insignificant_zeros: STRIP_INSIGNIFICANT_ZEROS
|
|
26
27
|
)
|
|
27
|
-
|
|
28
|
+
show_rate = order.avalara_integration&.preferred_show_rate_in_label || false
|
|
29
|
+
show_rate ? "#{adjustment_default_label} (#{rate_in_percents})" : adjustment_default_label
|
|
28
30
|
end
|
|
29
31
|
end
|
|
30
32
|
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Integrations
|
|
3
|
+
class Avalara < Spree::Integration
|
|
4
|
+
SANDBOX_ENDPOINT = 'https://sandbox-rest.avatax.com'.freeze
|
|
5
|
+
PRODUCTION_ENDPOINT = 'https://rest.avatax.com'.freeze
|
|
6
|
+
|
|
7
|
+
preference :account_number, :string
|
|
8
|
+
preference :license_key, :password
|
|
9
|
+
preference :endpoint, :string, default: SANDBOX_ENDPOINT
|
|
10
|
+
preference :company_code, :string
|
|
11
|
+
|
|
12
|
+
preference :address_validation_enabled, :boolean, default: false
|
|
13
|
+
preference :commit_transaction_enabled, :boolean, default: true
|
|
14
|
+
preference :show_rate_in_label, :boolean, default: false
|
|
15
|
+
|
|
16
|
+
validates :preferred_account_number, :preferred_license_key, :preferred_company_code, presence: true
|
|
17
|
+
|
|
18
|
+
def self.integration_group
|
|
19
|
+
'tax'
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.icon_path
|
|
23
|
+
'integration_icons/avalara-logo.png'
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def can_connect?
|
|
27
|
+
response = avatax_client.ping
|
|
28
|
+
body = response.respond_to?(:body) ? response.body : response
|
|
29
|
+
|
|
30
|
+
return true if body.is_a?(Hash) && body['authenticated']
|
|
31
|
+
|
|
32
|
+
@connection_error_message =
|
|
33
|
+
if body.is_a?(Hash) && body.key?('authenticated')
|
|
34
|
+
'Invalid credentials'
|
|
35
|
+
elsif body.is_a?(Hash) && body['error'].is_a?(Hash)
|
|
36
|
+
body['error']['message'].presence || 'Could not connect to AvaTax'
|
|
37
|
+
else
|
|
38
|
+
'Could not connect to AvaTax'
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
false
|
|
42
|
+
rescue StandardError => e
|
|
43
|
+
@connection_error_message = e.message
|
|
44
|
+
false
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def avatax_client
|
|
48
|
+
AvaTax::Client.new(
|
|
49
|
+
app_name: SpreeAvataxOfficial::Base::APP_NAME,
|
|
50
|
+
app_version: SpreeAvataxOfficial::Base::APP_VERSION,
|
|
51
|
+
connection_options: SpreeAvataxOfficial::Base::CONNECTION_OPTIONS,
|
|
52
|
+
logger: SpreeAvataxOfficial::Config.log,
|
|
53
|
+
faraday_response: true,
|
|
54
|
+
endpoint: preferred_endpoint,
|
|
55
|
+
username: preferred_account_number,
|
|
56
|
+
password: preferred_license_key
|
|
57
|
+
)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -9,9 +9,6 @@ module SpreeAvataxOfficial
|
|
|
9
9
|
raise 'Tax adjustments should be calculated on line item or shipment level'
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
# Following lines require this recalculation:
|
|
13
|
-
# https://github.com/spree/spree/blob/master/core/app/models/spree/adjustment.rb#L104
|
|
14
|
-
# https://github.com/spree/spree/blob/master/core/app/models/spree/line_item.rb#L159
|
|
15
12
|
def compute_line_item(line_item)
|
|
16
13
|
line_item.adjustments.tax.sum(:amount)
|
|
17
14
|
end
|
|
@@ -3,7 +3,6 @@ module SpreeAvataxOfficial
|
|
|
3
3
|
preference :address_validation_enabled, :boolean, default: false
|
|
4
4
|
preference :company_code, :string, default: ''
|
|
5
5
|
preference :enabled, :boolean, default: false
|
|
6
|
-
preference :ship_from_address, :hash, default: {}
|
|
7
6
|
preference :log, :boolean, default: true
|
|
8
7
|
preference :log_to_stdout, :boolean, default: false
|
|
9
8
|
preference :log_file_name, :string, default: 'avatax.log'
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
module SpreeAvataxOfficial
|
|
2
|
-
class EntityUseCode < ::Spree
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
class EntityUseCode < ::Spree.base_class
|
|
3
|
+
self.whitelisted_ransackable_attributes = %w[code name description]
|
|
4
|
+
|
|
5
|
+
validates :code, presence: true, uniqueness: { scope: spree_base_uniqueness_scope }
|
|
6
|
+
validates :name, presence: true, uniqueness: { scope: spree_base_uniqueness_scope }
|
|
6
7
|
end
|
|
7
8
|
end
|
|
@@ -2,20 +2,14 @@ module SpreeAvataxOfficial
|
|
|
2
2
|
module Spree
|
|
3
3
|
module AddressDecorator
|
|
4
4
|
def self.prepended(base)
|
|
5
|
-
base.
|
|
5
|
+
base.after_commit :recalculate_avatax_taxes, on: %i[update]
|
|
6
6
|
base.const_set 'OBSERVABLE_FIELDS', %w[address1 address2 city zipcode state_id country_id].freeze
|
|
7
7
|
end
|
|
8
8
|
|
|
9
9
|
private
|
|
10
10
|
|
|
11
11
|
def recalculate_avatax_taxes
|
|
12
|
-
return
|
|
13
|
-
|
|
14
|
-
observed_fields_changed = self.class::OBSERVABLE_FIELDS & changed
|
|
15
|
-
|
|
16
|
-
yield # around_save requires yield to perform save operation
|
|
17
|
-
|
|
18
|
-
return unless observed_fields_changed.any? && persisted?
|
|
12
|
+
return unless (self.class::OBSERVABLE_FIELDS & saved_changes.keys).any?
|
|
19
13
|
|
|
20
14
|
address_sym = ::Spree::Config.tax_using_ship_address ? :ship_address : :bill_address
|
|
21
15
|
order = ::Spree::Order.incomplete.find_by(address_sym => self)
|
|
@@ -8,13 +8,7 @@ module SpreeAvataxOfficial
|
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def included_in_price
|
|
11
|
-
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def update_tax_charge
|
|
15
|
-
return super unless SpreeAvataxOfficial::Config.enabled
|
|
16
|
-
|
|
17
|
-
SpreeAvataxOfficial::CreateTaxAdjustmentsService.call(order: order)
|
|
11
|
+
order.market&.tax_inclusive || false
|
|
18
12
|
end
|
|
19
13
|
|
|
20
14
|
def avatax_tax_code
|
|
@@ -13,6 +13,17 @@ module SpreeAvataxOfficial
|
|
|
13
13
|
base.state_machine.before_transition to: :delivery, do: :validate_tax_address, if: :address_validation_enabled?
|
|
14
14
|
base.state_machine.after_transition to: :canceled, do: :void_in_avatax
|
|
15
15
|
base.state_machine.after_transition to: :complete, do: :commit_in_avatax
|
|
16
|
+
|
|
17
|
+
# Recalculate when the order's address changes (selecting an existing address from the address book).
|
|
18
|
+
base.after_update :recalculate_avatax_taxes_on_address_change
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def avalara_integration
|
|
22
|
+
store&.integrations&.active&.find_by(type: 'Spree::Integrations::Avalara')
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def avatax_enabled?
|
|
26
|
+
avalara_integration.present?
|
|
16
27
|
end
|
|
17
28
|
|
|
18
29
|
def taxable_items
|
|
@@ -20,17 +31,17 @@ module SpreeAvataxOfficial
|
|
|
20
31
|
end
|
|
21
32
|
|
|
22
33
|
def avatax_tax_calculation_required?
|
|
23
|
-
tax_address&.persisted?
|
|
34
|
+
return false unless tax_address&.persisted?
|
|
35
|
+
return false unless line_items.any?
|
|
36
|
+
return false if delivery_required? && shipments.empty?
|
|
37
|
+
|
|
38
|
+
true
|
|
24
39
|
end
|
|
25
40
|
|
|
26
41
|
def avatax_discount_amount
|
|
27
42
|
adjustments.promotion.eligible.sum(:amount).abs
|
|
28
43
|
end
|
|
29
44
|
|
|
30
|
-
def avatax_ship_from_address
|
|
31
|
-
SpreeAvataxOfficial::Config.ship_from_address
|
|
32
|
-
end
|
|
33
|
-
|
|
34
45
|
def line_items_discounted_in_avatax?
|
|
35
46
|
adjustments.promotion.eligible.any?
|
|
36
47
|
end
|
|
@@ -39,14 +50,16 @@ module SpreeAvataxOfficial
|
|
|
39
50
|
::Spree::Config.tax_using_ship_address ? :ship_address : :bill_address
|
|
40
51
|
end
|
|
41
52
|
|
|
53
|
+
# We need to override this so the default Spree tax calculation is not triggered.
|
|
54
|
+
# The actual tax calculation by Avalara is done in #recalculate_avatax_taxes
|
|
42
55
|
def create_tax_charge!
|
|
43
|
-
return
|
|
56
|
+
return if avatax_enabled?
|
|
44
57
|
|
|
45
|
-
|
|
58
|
+
super
|
|
46
59
|
end
|
|
47
60
|
|
|
48
61
|
def recalculate_avatax_taxes
|
|
49
|
-
return unless
|
|
62
|
+
return unless avatax_enabled?
|
|
50
63
|
|
|
51
64
|
SpreeAvataxOfficial::CreateTaxAdjustmentsService.call(order: self)
|
|
52
65
|
update_totals
|
|
@@ -55,12 +68,14 @@ module SpreeAvataxOfficial
|
|
|
55
68
|
|
|
56
69
|
def validate_tax_address
|
|
57
70
|
response = SpreeAvataxOfficial::Address::Validate.call(
|
|
58
|
-
address: tax_address
|
|
71
|
+
address: tax_address,
|
|
72
|
+
order: self
|
|
59
73
|
)
|
|
60
74
|
|
|
61
75
|
return if response.success?
|
|
62
76
|
|
|
63
|
-
|
|
77
|
+
messages = response.value&.body&.dig('messages')
|
|
78
|
+
error_message = messages.present? ? messages.map { |message| message['summary'] }.join('. ') : 'Address validation failed'
|
|
64
79
|
|
|
65
80
|
errors.add(:base, error_message)
|
|
66
81
|
|
|
@@ -68,19 +83,26 @@ module SpreeAvataxOfficial
|
|
|
68
83
|
end
|
|
69
84
|
|
|
70
85
|
def address_validation_enabled?
|
|
71
|
-
|
|
86
|
+
avalara_integration&.preferred_address_validation_enabled || false
|
|
72
87
|
end
|
|
73
88
|
|
|
74
89
|
private
|
|
75
90
|
|
|
91
|
+
def recalculate_avatax_taxes_on_address_change
|
|
92
|
+
return unless avatax_enabled?
|
|
93
|
+
return unless (%w[ship_address_id bill_address_id] & saved_changes.keys).any?
|
|
94
|
+
|
|
95
|
+
recalculate_avatax_taxes
|
|
96
|
+
end
|
|
97
|
+
|
|
76
98
|
def commit_in_avatax
|
|
77
|
-
return unless
|
|
99
|
+
return unless avatax_enabled? && avalara_integration.preferred_commit_transaction_enabled
|
|
78
100
|
|
|
79
101
|
SpreeAvataxOfficial::Transactions::CreateService.call(order: self)
|
|
80
102
|
end
|
|
81
103
|
|
|
82
104
|
def void_in_avatax
|
|
83
|
-
return unless
|
|
105
|
+
return unless avatax_enabled?
|
|
84
106
|
|
|
85
107
|
SpreeAvataxOfficial::Transactions::VoidService.call(order: self)
|
|
86
108
|
end
|
|
@@ -5,13 +5,13 @@ module SpreeAvataxOfficial
|
|
|
5
5
|
base.after_create :refund_in_avatax
|
|
6
6
|
|
|
7
7
|
base.delegate :order, to: :payment
|
|
8
|
-
base.delegate :
|
|
8
|
+
base.delegate :number, to: :order, prefix: true
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
private
|
|
12
12
|
|
|
13
13
|
def refund_in_avatax
|
|
14
|
-
return unless
|
|
14
|
+
return unless order.avatax_enabled? && order.avalara_integration.preferred_commit_transaction_enabled
|
|
15
15
|
|
|
16
16
|
SpreeAvataxOfficial::Transactions::RefundService.call(refundable: self)
|
|
17
17
|
end
|
|
@@ -8,7 +8,7 @@ module SpreeAvataxOfficial
|
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def included_in_price
|
|
11
|
-
|
|
11
|
+
order.market&.tax_inclusive || false
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def tax_category
|
|
@@ -18,6 +18,13 @@ module SpreeAvataxOfficial
|
|
|
18
18
|
def avatax_tax_code
|
|
19
19
|
tax_category.try(:tax_code).presence || ::Spree::TaxCategory::DEFAULT_TAX_CODES['Shipment']
|
|
20
20
|
end
|
|
21
|
+
|
|
22
|
+
def selected_shipping_rate_id=(id)
|
|
23
|
+
super
|
|
24
|
+
return if order.nil? || order.completed?
|
|
25
|
+
|
|
26
|
+
order.recalculate_avatax_taxes
|
|
27
|
+
end
|
|
21
28
|
end
|
|
22
29
|
end
|
|
23
30
|
end
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
module SpreeAvataxOfficial
|
|
2
|
-
class Transaction <
|
|
2
|
+
class Transaction < ::Spree.base_class
|
|
3
3
|
SALES_ORDER = 'SalesOrder'.freeze
|
|
4
4
|
SALES_INVOICE = 'SalesInvoice'.freeze
|
|
5
5
|
RETURN_INVOICE = 'ReturnInvoice'.freeze
|
|
@@ -12,8 +12,9 @@ module SpreeAvataxOfficial
|
|
|
12
12
|
|
|
13
13
|
belongs_to :order, class_name: 'Spree::Order'
|
|
14
14
|
|
|
15
|
+
validates :code, presence: true, uniqueness: { scope: spree_base_uniqueness_scope }
|
|
16
|
+
|
|
15
17
|
with_options presence: true do
|
|
16
|
-
validates :code, uniqueness: true
|
|
17
18
|
validates :order
|
|
18
19
|
validates :transaction_type
|
|
19
20
|
end
|