solidus_avatax_certified 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.env_example +4 -0
- data/.gitignore +16 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/GEM_VERSION +1 -0
- data/Gemfile +18 -0
- data/LICENSE +26 -0
- data/README.md +27 -0
- data/Rakefile +21 -0
- data/app/assets/javascripts/spree/backend/address_validator.js +84 -0
- data/app/assets/javascripts/spree/backend/solidus_avatax_certified.js +5 -0
- data/app/assets/javascripts/spree/backend/use_code_picker.js +51 -0
- data/app/assets/javascripts/spree/frontend/address_validator.js +87 -0
- data/app/assets/javascripts/spree/frontend/flash.js.coffee +26 -0
- data/app/assets/javascripts/spree/frontend/solidus_avatax_certified.js +4 -0
- data/app/assets/stylesheets/spree/backend/solidus_avatax_certified.css +4 -0
- data/app/assets/stylesheets/spree/frontend/solidus_avatax_certified.css +4 -0
- data/app/controllers/spree/admin/avalara_entity_use_codes_controller.rb +15 -0
- data/app/controllers/spree/admin/avatax_settings_controller.rb +82 -0
- data/app/controllers/spree/admin/users_controller_decorator.rb +11 -0
- data/app/controllers/spree/checkout_controller_decorator.rb +22 -0
- data/app/models/solidus_avatax_certified/address.rb +95 -0
- data/app/models/solidus_avatax_certified/avatax_log.rb +69 -0
- data/app/models/solidus_avatax_certified/line.rb +146 -0
- data/app/models/solidus_avatax_certified/preference_updater.rb +74 -0
- data/app/models/spree/address_decorator.rb +13 -0
- data/app/models/spree/adjustment_decorator.rb +10 -0
- data/app/models/spree/avalara_entity_use_code.rb +5 -0
- data/app/models/spree/avalara_preference.rb +72 -0
- data/app/models/spree/avalara_transaction.rb +181 -0
- data/app/models/spree/calculator/avalara_transaction.rb +86 -0
- data/app/models/spree/line_item_decorator.rb +25 -0
- data/app/models/spree/order_decorator.rb +85 -0
- data/app/models/spree/payment_decorator.rb +23 -0
- data/app/models/spree/refund_decorator.rb +30 -0
- data/app/models/spree/shipment_decorator.rb +28 -0
- data/app/models/spree/shipping_rate_decorator.rb +25 -0
- data/app/models/spree/user_decorator.rb +3 -0
- data/app/models/tax_svc.rb +143 -0
- data/app/overrides/spree/admin/shared/_configuration_menu.rb +10 -0
- data/app/overrides/spree/admin/users/sidebar.rb +8 -0
- data/app/overrides/spree/admin/users/validation_button.rb +6 -0
- data/app/views/spree/admin/avalara_entity_use_codes/_form.html.erb +27 -0
- data/app/views/spree/admin/avalara_entity_use_codes/edit.html.erb +16 -0
- data/app/views/spree/admin/avalara_entity_use_codes/index.html.erb +33 -0
- data/app/views/spree/admin/avalara_entity_use_codes/new.html.erb +17 -0
- data/app/views/spree/admin/avalara_entity_use_codes/show.html.erb +24 -0
- data/app/views/spree/admin/avatax_settings/edit.html.erb +183 -0
- data/app/views/spree/admin/avatax_settings/ping_my_service.js.erb +8 -0
- data/app/views/spree/admin/avatax_settings/show.html.erb +124 -0
- data/app/views/spree/admin/avatax_settings/validate_address.js.erb +8 -0
- data/app/views/spree/admin/users/avalara_information.html.erb +53 -0
- data/app/views/spree/checkout/_address.html.erb +35 -0
- data/app/views/spree/checkout/_address_validator_button.html.erb +3 -0
- data/bin/rails +7 -0
- data/circle.yml +17 -0
- data/config/initializers/avatax.rb +5 -0
- data/config/initializers/spree.rb +3 -0
- data/config/locales/en.yml +35 -0
- data/config/routes.rb +18 -0
- data/db/migrate/20160624154205_create_spree_avalara_transactions.rb +9 -0
- data/db/migrate/20160624154423_create_spree_avalara_entity_use_codes.rb +9 -0
- data/db/migrate/20160624155217_add_columns_to_spree_users.rb +6 -0
- data/db/migrate/20160628200504_create_spree_avalara_preferences.rb +10 -0
- data/db/migrate/20160805193512_add_vat_id_to_spree_users.rb +5 -0
- data/db/seeds.rb +1 -0
- data/lib/generators/solidus_avatax_certified/install/install_generator.rb +45 -0
- data/lib/solidus_avatax_certified/engine.rb +22 -0
- data/lib/solidus_avatax_certified/preference_seeder.rb +69 -0
- data/lib/solidus_avatax_certified/seeder.rb +117 -0
- data/lib/solidus_avatax_certified.rb +2 -0
- data/lib/tasks/load_seeds.rake +15 -0
- data/setup.md +12 -0
- data/solidus_avatax_certified.gemspec +42 -0
- data/spec/controllers/spree/admin/avalara_entity_use_codes_controller_spec.rb +53 -0
- data/spec/controllers/spree/admin/avatax_settings_controller_spec.rb +67 -0
- data/spec/factories/avalara_entity_use_code_factory.rb +6 -0
- data/spec/factories/avalara_factories.rb +76 -0
- data/spec/factories/avalara_order_factory.rb +62 -0
- data/spec/factories/avalara_preference_factory.rb +7 -0
- data/spec/factories/avalara_shipment_factory.rb +27 -0
- data/spec/factories/avalara_shipping_method_factory.rb +23 -0
- data/spec/factories/tax_rate_factory.rb +19 -0
- data/spec/features/certification_spec.rb +77 -0
- data/spec/features/checkout_spec.rb +156 -0
- data/spec/features/vat_spec.rb +153 -0
- data/spec/models/solidus_avatax_certified/address_spec.rb +80 -0
- data/spec/models/solidus_avatax_certified/avatax_log_spec.rb +97 -0
- data/spec/models/solidus_avatax_certified/line_spec.rb +100 -0
- data/spec/models/spree/address_decorator_spec.rb +44 -0
- data/spec/models/spree/adjustment_decorator_spec.rb +25 -0
- data/spec/models/spree/avalara_entity_use_code_spec.rb +5 -0
- data/spec/models/spree/avalara_preference_spec.rb +173 -0
- data/spec/models/spree/avalara_transaction_spec.rb +203 -0
- data/spec/models/spree/calculator/avalara_transaction_spec.rb +129 -0
- data/spec/models/spree/line_item_decorator_spec.rb +33 -0
- data/spec/models/spree/order_decorator_spec.rb +164 -0
- data/spec/models/spree/payment_decorator_spec.rb +117 -0
- data/spec/models/spree/refund_decorator_spec.rb +81 -0
- data/spec/models/spree/shipment_decorator_spec.rb +36 -0
- data/spec/models/spree/shipping_rate_decorator_spec.rb +17 -0
- data/spec/models/spree/user_decorator_spec.rb +5 -0
- data/spec/spec_helper.rb +81 -0
- data/spec/support/avatax_config_preferences.rb +8 -0
- data/spec/support/vcr.rb +9 -0
- data/spec/vcr/Certification/Exempt_sales_should_be_reflected_in_the_test_data_through_use_of_ExemptionNo_or_CustomerUsageType_/does_not_add_additional_tax.yml +276 -0
- data/spec/vcr/Certification/Transactions_have_been_committed_/commits_an_order.yml +336 -0
- data/spec/vcr/Certification/Transactions_have_been_voided/cancelled_/should_be_successful/returns_ResultCode_with_value_Success.yml +522 -0
- data/spec/vcr/Certification/return_orders/_commit_avatax_final/should_commit_avatax_final.yml +404 -0
- data/spec/vcr/Checkout/complete_order/has_tax_and_shipping_tax_adjustments_on_page.yml +72 -0
- data/spec/vcr/Checkout/complete_order/order_line_items_and_shipments_have_an_additional_tax_total_sum_of_0_40.yml +72 -0
- data/spec/vcr/Checkout/payment/tax_included/has_tax_and_shipping_tax_adjustments_on_page.yml +72 -0
- data/spec/vcr/Checkout/payment/tax_included/order_line_items_and_shipments_have_an_included_tax_total_sum_of_0_38.yml +72 -0
- data/spec/vcr/Checkout/payment/tax_not_included/on_payment_page/has_tax_and_shipping_tax_adjustments_on_page.yml +72 -0
- data/spec/vcr/Checkout/payment/tax_not_included/on_payment_page/order_line_items_and_shipments_and_shipments_have_an_additional_tax_total_sum_of_0_40.yml +72 -0
- data/spec/vcr/Checkout/payment/with_promotion/tax_not_included/has_adjusted_tax_amount_after_promotion_applied.yml +73 -0
- data/spec/vcr/SolidusAvataxCertified_Address/_validate/fails_when_information_is_incorrect.yml +54 -0
- data/spec/vcr/Spree_Calculator_AvalaraTransaction/_compute/when_computing_a_line_item/when_tax_is_included_in_price/should_be_equal_to_the_item_pre-tax_total_rate.yml +137 -0
- data/spec/vcr/Spree_Calculator_AvalaraTransaction/_compute/when_computing_a_line_item/when_tax_is_included_in_price/should_be_equal_to_the_previous_included_tax_total_is_order_is_at_address.yml +138 -0
- data/spec/vcr/Spree_Calculator_AvalaraTransaction/_compute/when_computing_a_line_item/when_tax_is_included_in_price/should_be_equal_to_the_previous_included_tax_total_is_order_is_at_cart.yml +137 -0
- data/spec/vcr/Spree_Calculator_AvalaraTransaction/_compute/when_computing_a_line_item/when_tax_is_not_included_in_price/should_be_equal_to_the_item_pre-tax_total_rate.yml +136 -0
- data/spec/vcr/Spree_Calculator_AvalaraTransaction/_compute/when_computing_a_line_item/when_tax_is_not_included_in_price/should_be_equal_to_the_previous_additional_tax_total_if_order_is_at_address.yml +137 -0
- data/spec/vcr/Spree_Calculator_AvalaraTransaction/_compute/when_computing_a_line_item/when_tax_is_not_included_in_price/should_be_equal_to_the_previous_additional_tax_total_if_order_is_at_cart.yml +136 -0
- data/spec/vcr/Spree_Calculator_AvalaraTransaction/_compute/when_computing_a_line_item/when_tax_is_not_included_in_price/should_be_equal_to_the_previous_tax_total_if_preference_tax_calculation_is_false.yml +136 -0
- data/spec/vcr/Spree_Calculator_AvalaraTransaction/_compute/when_computing_a_line_item/when_tax_is_not_included_in_price/when_the_line_item_is_discounted/should_be_equal_to_the_items_pre-tax_total_rate.yml +276 -0
- data/spec/vcr/Spree_Calculator_AvalaraTransaction/_compute/when_computing_a_line_item/when_tax_is_not_included_in_price/when_the_order_is_discounted/should_be_equal_to_the_items_pre-tax_total_rate.yml +206 -0
- data/spec/vcr/Spree_Calculator_AvalaraTransaction/_compute/when_given_a_shipment/computing_normal_shipment/should_be_equal_4_0.yml +141 -0
- data/spec/vcr/Spree_Calculator_AvalaraTransaction/_compute/when_given_a_shipment/when_tax_is_included_in_price/should_be_equal_to_3_85.yml +143 -0
- data/spec/vcr/Spree_Calculator_AvalaraTransaction/_compute/when_given_a_shipment/with_promotion/should_equal_3_96.yml +210 -0
- data/spec/vcr/Spree_Calculator_AvalaraTransaction/_compute/when_given_an_order/when_computing_an_order/should_raise_error.yml +136 -0
- data/spec/vcr/Spree_Order/_cancel_avalara/should_receive_cancel_order_when_cancel_avalara_is_called.yml +136 -0
- data/spec/vcr/Spree_Order/_cancel_avalara/state_machine_event_cancel/should_recieve_cancel_avalara_when_event_cancel_is_called.yml +259 -0
- data/spec/vcr/Spree_Order/_validate_ship_address/should_return_false_if_validation_failed.yml +54 -0
- data/spec/vcr/Spree_Order/_validate_ship_address/should_return_the_response_if_refuse_checkout_on_address_validation_is_disabled.yml +59 -0
- data/spec/vcr/Spree_Order/_validate_ship_address/should_return_the_response_if_validation_is_success.yml +59 -0
- data/spec/vcr/Spree_Payment/_avalara_finalize/should_update_the_amount_to_be_the_order_total.yml +136 -0
- data/spec/vcr/Spree_Payment/_cancel_avalara/committed_order/should_be_successful/ResultCode_returns_Success.yml +205 -0
- data/spec/vcr/Spree_Payment/_cancel_avalara/uncommitted_order/should_fail/ResultCode_returns_Error.yml +191 -0
- data/spec/vcr/Spree_Payment/_purchase_/receive_avalara_finalize.yml +136 -0
- data/spec/vcr/Spree_Payment/_void_transaction_/receive_cancel_avalara.yml +136 -0
- data/spec/vcr/Spree_Refund/full_refund/returns_correct_tax_calculations.yml +270 -0
- data/spec/vcr/VAT/Seller_in_EU_country_Buyer_in_another_EU_country/Seller_does_not_have_Nexus_Jurisdition_Registered/TotalTax_is_equal_to_order_included_tax_total.yml +137 -0
- data/spec/vcr/VAT/Seller_in_EU_country_Buyer_in_another_EU_country/Seller_does_not_have_Nexus_Jurisdition_Registered/origin_country_tax_is_returned.yml +138 -0
- data/spec/vcr/VAT/Seller_in_EU_country_Buyer_in_another_EU_country/Seller_does_not_have_Nexus_Jurisdition_Registered/with_BusinessIdentificationNo/origin_country_zero_rate_is_returned.yml +143 -0
- data/spec/vcr/VAT/Seller_in_EU_country_Buyer_in_another_EU_country/Seller_has_Nexus_Jurisdition_Registered/TotalTax_is_equal_to_order_included_tax_total.yml +139 -0
- data/spec/vcr/VAT/Seller_in_EU_country_Buyer_in_another_EU_country/Seller_has_Nexus_Jurisdition_Registered/destination_country_tax_is_returned.yml +139 -0
- data/spec/vcr/VAT/Seller_in_EU_country_Buyer_in_another_EU_country/Seller_has_Nexus_Jurisdition_Registered/with_BusinessIdentificationNo/origin_country_zero_rate_is_returned.yml +144 -0
- data/spec/vcr/VAT/Seller_in_EU_country_Buyer_in_same_EU_country/TotalTax_is_equal_to_order_included_tax_total.yml +137 -0
- data/spec/vcr/VAT/Seller_in_EU_country_Buyer_in_same_EU_country/tax_detail_country_equals_to_IT.yml +138 -0
- data/spec/vcr/VAT/Seller_in_EU_country_Buyer_is_outside_EU/Seller_does_not_have_Nexus_Jurisdition_registered/TotalTax_is_equal_to_order_included_tax_total.yml +137 -0
- data/spec/vcr/VAT/Seller_in_EU_country_Buyer_is_outside_EU/Seller_does_not_have_Nexus_Jurisdition_registered/tax_detail_country_equals_to_IT.yml +137 -0
- data/spec/vcr/VAT/Seller_in_EU_country_Buyer_is_outside_EU/Seller_does_not_have_Nexus_Jurisdition_registered/total_tax_is_0_since_utah_is_not_in_jurisdiction.yml +137 -0
- data/spec/vcr/VAT/Seller_in_EU_country_Buyer_is_outside_EU/Seller_does_not_have_Nexus_Jurisdition_registered/with_BusinessIdentificationNo/origin_country_zero_rate_is_returned.yml +138 -0
- data/spec/vcr/VAT/Seller_in_EU_country_Buyer_is_outside_EU/Seller_has_Nexus_Jurisdiction_Registered/TotalTax_is_equal_to_order_included_tax_total.yml +195 -0
- data/spec/vcr/VAT/Seller_in_EU_country_Buyer_is_outside_EU/Seller_has_Nexus_Jurisdiction_Registered/tax_detail_region_equals_to_AL.yml +195 -0
- data/spec/vcr/address_validation_success.yml +59 -0
- data/spec/vcr/capture_with_customer_usage_type.yml +72 -0
- data/spec/vcr/order_cancel.yml +258 -0
- data/spec/vcr/order_capture.yml +72 -0
- data/spec/vcr/order_capture_finalize.yml +141 -0
- data/spec/vcr/order_capture_with_promo.yml +73 -0
- data/spec/vcr/order_return_capture.yml +68 -0
- data/spec/vcr/tax_included_order.yml +73 -0
- metadata +581 -0
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
Spree::Order.class_eval do
|
4
|
+
|
5
|
+
has_one :avalara_transaction, dependent: :destroy
|
6
|
+
|
7
|
+
self.state_machine.before_transition :to => :canceled,
|
8
|
+
:do => :cancel_avalara,
|
9
|
+
:if => :avalara_tax_enabled?
|
10
|
+
self.state_machine.before_transition :to => :delivery,
|
11
|
+
:do => :validate_ship_address,
|
12
|
+
:if => :address_validation_enabled?
|
13
|
+
|
14
|
+
def avalara_tax_enabled?
|
15
|
+
Spree::AvalaraPreference.tax_calculation.is_true?
|
16
|
+
end
|
17
|
+
|
18
|
+
def cancel_avalara
|
19
|
+
return nil unless avalara_transaction.present?
|
20
|
+
self.avalara_transaction.cancel_order
|
21
|
+
end
|
22
|
+
|
23
|
+
def avalara_capture
|
24
|
+
logger.debug 'avalara capture'
|
25
|
+
|
26
|
+
create_avalara_transaction if avalara_transaction.nil?
|
27
|
+
line_items.reload
|
28
|
+
|
29
|
+
@rtn_tax = self.avalara_transaction.commit_avatax('SalesOrder')
|
30
|
+
|
31
|
+
logger.info_and_debug('tax amount', @rtn_tax)
|
32
|
+
@rtn_tax
|
33
|
+
end
|
34
|
+
|
35
|
+
def avalara_capture_finalize
|
36
|
+
logger.debug 'avalara capture finalize'
|
37
|
+
|
38
|
+
create_avalara_transaction if avalara_transaction.nil?
|
39
|
+
line_items.reload
|
40
|
+
|
41
|
+
@rtn_tax = avalara_transaction.commit_avatax_final('SalesInvoice')
|
42
|
+
|
43
|
+
logger.info_and_debug('tax amount', @rtn_tax)
|
44
|
+
@rtn_tax
|
45
|
+
end
|
46
|
+
|
47
|
+
def validate_ship_address
|
48
|
+
avatax_address = SolidusAvataxCertified::Address.new(self)
|
49
|
+
response = avatax_address.validate
|
50
|
+
|
51
|
+
return response if response['ResultCode'] == 'Success'
|
52
|
+
return response if !Spree::AvalaraPreference.refuse_checkout_address_validation_error.is_true?
|
53
|
+
|
54
|
+
messages = response['Messages'].each do |message|
|
55
|
+
errors.add(:address_validation_failure, message['Summary'])
|
56
|
+
end
|
57
|
+
return false
|
58
|
+
end
|
59
|
+
|
60
|
+
def avatax_cache_key
|
61
|
+
key = ['Spree::Order']
|
62
|
+
key << self.number
|
63
|
+
key << self.promo_total
|
64
|
+
key.join('-')
|
65
|
+
end
|
66
|
+
|
67
|
+
def customer_usage_type
|
68
|
+
user ? user.avalara_entity_use_code.try(:use_code) : ''
|
69
|
+
end
|
70
|
+
|
71
|
+
def stock_locations
|
72
|
+
stock_loc_ids = shipments.pluck(:stock_location_id).uniq
|
73
|
+
Spree::StockLocation.where(id: stock_loc_ids)
|
74
|
+
end
|
75
|
+
|
76
|
+
def address_validation_enabled?
|
77
|
+
return false if ship_address.nil?
|
78
|
+
|
79
|
+
ship_address.validation_enabled?
|
80
|
+
end
|
81
|
+
|
82
|
+
def logger
|
83
|
+
@logger ||= SolidusAvataxCertified::AvataxLog.new('avalara_order', 'order class', 'start order processing')
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
Spree::Payment.class_eval do
|
2
|
+
self.state_machine.before_transition to: :completed, do: :avalara_finalize
|
3
|
+
self.state_machine.after_transition to: :void, do: :cancel_avalara
|
4
|
+
|
5
|
+
def avalara_tax_enabled?
|
6
|
+
Spree::AvalaraPreference.tax_calculation.is_true?
|
7
|
+
end
|
8
|
+
|
9
|
+
def cancel_avalara
|
10
|
+
order.avalara_transaction.cancel_order unless order.avalara_transaction.nil?
|
11
|
+
end
|
12
|
+
|
13
|
+
def avalara_finalize
|
14
|
+
return unless avalara_tax_enabled?
|
15
|
+
|
16
|
+
if self.amount != order.total
|
17
|
+
self.update_attributes(amount: order.total)
|
18
|
+
order.avalara_capture_finalize
|
19
|
+
else
|
20
|
+
order.avalara_capture_finalize
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
Spree::Refund.class_eval do
|
4
|
+
has_one :avalara_transaction
|
5
|
+
after_create :avalara_capture_finalize, if: :avalara_tax_enabled?
|
6
|
+
|
7
|
+
def avalara_tax_enabled?
|
8
|
+
Spree::AvalaraPreference.tax_calculation.is_true?
|
9
|
+
end
|
10
|
+
|
11
|
+
def avalara_capture_finalize
|
12
|
+
logger.debug 'avalara capture refund avalara_capture_finalize'
|
13
|
+
begin
|
14
|
+
avalara_transaction_refund = self.payment.order.avalara_transaction
|
15
|
+
|
16
|
+
@rtn_tax = avalara_transaction_refund.commit_avatax_final('ReturnInvoice', self)
|
17
|
+
|
18
|
+
logger.info 'tax amount'
|
19
|
+
logger.debug @rtn_tax
|
20
|
+
@rtn_tax
|
21
|
+
rescue => e
|
22
|
+
logger.debug e
|
23
|
+
logger.debug 'error in avalara capture refund finalize'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def logger
|
28
|
+
@logger ||= SolidusAvataxCertified::AvataxLog.new('refund', 'refund class')
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
Spree::Shipment.class_eval do
|
2
|
+
|
3
|
+
def avatax_cache_key
|
4
|
+
key = ['Spree::Shipment']
|
5
|
+
key << self.id
|
6
|
+
key << self.cost
|
7
|
+
key << self.stock_location.try(:cache_key)
|
8
|
+
key << self.promo_total
|
9
|
+
key.join('-')
|
10
|
+
end
|
11
|
+
|
12
|
+
def avatax_line_code
|
13
|
+
'FR'
|
14
|
+
end
|
15
|
+
|
16
|
+
def shipping_method_tax_code
|
17
|
+
tax_code = shipping_method.tax_category.try(:tax_code)
|
18
|
+
if tax_code.nil?
|
19
|
+
''
|
20
|
+
else
|
21
|
+
tax_code
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def tax_category
|
26
|
+
selected_shipping_rate.try(:tax_rate).try(:tax_category) || shipping_method.try(:tax_category)
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
Spree::ShippingRate.class_eval do
|
2
|
+
def tax_rate
|
3
|
+
Spree::TaxRate.find(tax_rate_id) if tax_rate_id
|
4
|
+
end
|
5
|
+
|
6
|
+
# Solidusv1.0-v1.2 uses display_amount while newer versions use display_base_price
|
7
|
+
def display_price
|
8
|
+
price = if respond_to?(:display_amount)
|
9
|
+
display_amount
|
10
|
+
else
|
11
|
+
display_base_price
|
12
|
+
end.to_s
|
13
|
+
|
14
|
+
return price if Spree::AvalaraPreference.tax_calculation.is_true?
|
15
|
+
return price if taxes.empty? || amount == 0
|
16
|
+
|
17
|
+
tax_explanations = taxes.map(&:label).join(tax_label_separator)
|
18
|
+
|
19
|
+
Spree.t :display_price_with_explanations,
|
20
|
+
scope: 'shipping_rate.display_price',
|
21
|
+
price: price,
|
22
|
+
explanations: tax_explanations
|
23
|
+
end
|
24
|
+
alias_method :display_cost, :display_price
|
25
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'net/http'
|
3
|
+
require 'addressable/uri'
|
4
|
+
require 'base64'
|
5
|
+
require 'rest-client'
|
6
|
+
require 'logging'
|
7
|
+
|
8
|
+
# Avatax tax calculation API calls
|
9
|
+
class TaxSvc
|
10
|
+
def get_tax(request_hash)
|
11
|
+
log(__method__, request_hash)
|
12
|
+
RestClient.log = logger.logger
|
13
|
+
res = response('get', request_hash)
|
14
|
+
logger.info_and_debug('RestClient call', res)
|
15
|
+
|
16
|
+
if res['ResultCode'] != 'Success'
|
17
|
+
logger.info 'Avatax Error'
|
18
|
+
logger.debug res, 'error in Tax'
|
19
|
+
raise 'error in Tax'
|
20
|
+
else
|
21
|
+
res
|
22
|
+
end
|
23
|
+
rescue => e
|
24
|
+
logger.info 'Rest Client Error'
|
25
|
+
logger.debug e, 'error in Tax'
|
26
|
+
'error in Tax'
|
27
|
+
end
|
28
|
+
|
29
|
+
def cancel_tax(request_hash)
|
30
|
+
log(__method__, request_hash)
|
31
|
+
res = response('cancel', request_hash)['CancelTaxResult']
|
32
|
+
logger.debug res
|
33
|
+
|
34
|
+
if res['ResultCode'] != 'Success'
|
35
|
+
logger.info_and_debug("Avatax Error: Order ##{res['Messages'][0]['Details']}", res)
|
36
|
+
end
|
37
|
+
|
38
|
+
res
|
39
|
+
rescue => e
|
40
|
+
logger.debug e, 'Error in Cancel Tax'
|
41
|
+
'Error in Cancel Tax'
|
42
|
+
end
|
43
|
+
|
44
|
+
def estimate_tax(coordinates, sale_amount)
|
45
|
+
if tax_calculation_enabled?
|
46
|
+
log(__method__)
|
47
|
+
|
48
|
+
return nil if coordinates.nil?
|
49
|
+
sale_amount = 0 if sale_amount.nil?
|
50
|
+
coor = coordinates[:latitude].to_s + ',' + coordinates[:longitude].to_s
|
51
|
+
|
52
|
+
uri = URI(service_url + coor + '/get?saleamount=' + sale_amount.to_s)
|
53
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
54
|
+
http.use_ssl = true
|
55
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
56
|
+
http.open_timeout = 1
|
57
|
+
http.read_timeout = 1
|
58
|
+
|
59
|
+
res = http.get(uri.request_uri, 'Authorization' => credential, 'Content-Type' => 'application/json')
|
60
|
+
JSON.parse(res.body)
|
61
|
+
end
|
62
|
+
rescue => e
|
63
|
+
logger.debug e, 'error in Estimate Tax'
|
64
|
+
'error in Estimate Tax'
|
65
|
+
end
|
66
|
+
|
67
|
+
def ping
|
68
|
+
logger.info 'Ping Call'
|
69
|
+
estimate_tax({ latitude: '40.714623', longitude: '-74.006605' }, 0)
|
70
|
+
end
|
71
|
+
|
72
|
+
def validate_address(address)
|
73
|
+
uri = URI(address_service_url + address.to_query)
|
74
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
75
|
+
http.use_ssl = true
|
76
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
77
|
+
http.open_timeout = 1
|
78
|
+
http.read_timeout = 1
|
79
|
+
res = http.get(uri.request_uri, 'Authorization' => credential)
|
80
|
+
|
81
|
+
logger.debug res
|
82
|
+
|
83
|
+
JSON.parse(res.body)
|
84
|
+
rescue => e
|
85
|
+
"error in address validation: #{e}"
|
86
|
+
end
|
87
|
+
|
88
|
+
protected
|
89
|
+
|
90
|
+
def logger
|
91
|
+
SolidusAvataxCertified::AvataxLog.new('tax_svc', 'tax_service', 'call to tax service')
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def tax_calculation_enabled?
|
97
|
+
Spree::AvalaraPreference.tax_calculation.is_true?
|
98
|
+
end
|
99
|
+
|
100
|
+
def credential
|
101
|
+
'Basic ' + Base64.encode64(account_number + ':' + license_key)
|
102
|
+
end
|
103
|
+
|
104
|
+
def service_url
|
105
|
+
Spree::AvalaraPreference.endpoint.value + AVATAX_SERVICEPATH_TAX
|
106
|
+
end
|
107
|
+
|
108
|
+
def address_service_url
|
109
|
+
Spree::AvalaraPreference.endpoint.value + AVATAX_SERVICEPATH_ADDRESS + 'validate?'
|
110
|
+
end
|
111
|
+
|
112
|
+
def license_key
|
113
|
+
Spree::AvalaraPreference.license_key.value
|
114
|
+
end
|
115
|
+
|
116
|
+
def account_number
|
117
|
+
Spree::AvalaraPreference.account.value
|
118
|
+
end
|
119
|
+
|
120
|
+
def response(uri, request_hash)
|
121
|
+
res = RestClient::Request.execute(method: :post,
|
122
|
+
timeout: 1,
|
123
|
+
open_timeout: 1,
|
124
|
+
url: service_url + uri,
|
125
|
+
payload: JSON.generate(request_hash),
|
126
|
+
headers: {
|
127
|
+
authorization: credential,
|
128
|
+
content_type: 'application/json'
|
129
|
+
}
|
130
|
+
) do |response, request, result|
|
131
|
+
response
|
132
|
+
end
|
133
|
+
|
134
|
+
JSON.parse(res)
|
135
|
+
end
|
136
|
+
|
137
|
+
def log(method, request_hash = nil)
|
138
|
+
logger.info method.to_s + ' call'
|
139
|
+
return if request_hash.nil?
|
140
|
+
logger.debug request_hash
|
141
|
+
logger.debug JSON.generate(request_hash)
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
Deface::Override.new(
|
2
|
+
virtual_path: 'spree/admin/shared/_taxes_tabs',
|
3
|
+
name: 'add_avalara_admin_menu_links',
|
4
|
+
insert_bottom: "[data-hook='admin_settings_taxes_tabs']"
|
5
|
+
) do
|
6
|
+
<<-HTML
|
7
|
+
<%= configurations_sidebar_menu_item Spree.t(:avalara_settings), admin_avatax_settings_path %>
|
8
|
+
<%= configurations_sidebar_menu_item Spree.t(:avalara_entity_use_codes), admin_avalara_entity_use_codes_path %>
|
9
|
+
HTML
|
10
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
Deface::Override.new(
|
2
|
+
virtual_path: 'spree/admin/users/_sidebar',
|
3
|
+
name: 'add avalara information link',
|
4
|
+
insert_bottom: '[data-hook="admin_user_tab_options"]',
|
5
|
+
text: "<li>
|
6
|
+
<%= link_to 'avalara information', avalara_information_admin_user_path(@user) %>
|
7
|
+
</li>"
|
8
|
+
)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
<div class="row">
|
2
|
+
<div class="sixteen columns">
|
3
|
+
<fieldset class="no-border-bottom">
|
4
|
+
<% if @avalara_entity_use_code.errors.any? %>
|
5
|
+
<div id="error_explanation">
|
6
|
+
<h2><%= pluralize(@use_code.errors.count, "error") %> prohibited this "Use Code" from being saved:</h2>
|
7
|
+
|
8
|
+
<ul>
|
9
|
+
<% @use_code.errors.full_messages.each do |msg| %>
|
10
|
+
<li><%= msg %></li>
|
11
|
+
<% end %>
|
12
|
+
</ul>
|
13
|
+
</div>
|
14
|
+
<% end %>
|
15
|
+
|
16
|
+
<div class="field alpha eight columns">
|
17
|
+
<%= f.label :use_code %><br>
|
18
|
+
<%= f.text_field :use_code, class: 'fullwidth' %>
|
19
|
+
</div>
|
20
|
+
<div class="field omega eight columns">
|
21
|
+
<%= f.label :use_code_description %><br>
|
22
|
+
<%= f.text_field :use_code_description, class: 'fullwidth' %>
|
23
|
+
</div>
|
24
|
+
</fieldset>
|
25
|
+
</div>
|
26
|
+
|
27
|
+
</div>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<%= render 'spree/admin/shared/taxes_tabs' %>
|
2
|
+
|
3
|
+
<% content_for :page_title do %>
|
4
|
+
<%= Spree.t(:editing_avalara_entity_use_code) %>
|
5
|
+
<% end %>
|
6
|
+
|
7
|
+
<% content_for :page_actions do %>
|
8
|
+
<li><%= link_to_with_icon 'arrow-left', Spree.t(:back_to_avalara_entity_use_codes_list), admin_avalara_entity_use_codes_path, :class => 'button' %></li>
|
9
|
+
<% end %>
|
10
|
+
|
11
|
+
<%= render 'spree/shared/error_messages', :target => @avalara_entity_use_code %>
|
12
|
+
|
13
|
+
<%= form_for [:admin, @avalara_entity_use_code], :method => :put do |f| %>
|
14
|
+
<%= render :partial => 'form', :locals => { :f => f } %>
|
15
|
+
<p class="form-buttons" data-hook="buttons"><%= button Spree.t(:update) %></p>
|
16
|
+
<% end %>
|
@@ -0,0 +1,33 @@
|
|
1
|
+
<%= render 'spree/admin/shared/taxes_tabs' %>
|
2
|
+
|
3
|
+
<% content_for :page_title do %>
|
4
|
+
<%= Spree.t(:avalara_entity_use_codes) %>
|
5
|
+
<% end %>
|
6
|
+
|
7
|
+
<% content_for :page_actions do %>
|
8
|
+
<li>
|
9
|
+
<%= button_link_to Spree.t(:new_avalara_entity_use_code), new_object_url, :icon => 'plus', :id => 'admin_new_avalara_entity_use_code_link' %>
|
10
|
+
</li>
|
11
|
+
<% end %>
|
12
|
+
|
13
|
+
<table class="index" id="listing_sale_events" data-hook>
|
14
|
+
<thead>
|
15
|
+
<tr data-hook="admin_sale_events_index_headers">
|
16
|
+
<th><%= Spree.t(:use_code) %></th>
|
17
|
+
<th ><%= Spree.t(:use_code_description) %></th>
|
18
|
+
<tH data-hook="admin_sale_events_index_header_actions"></tH>
|
19
|
+
</tr>
|
20
|
+
</thead>
|
21
|
+
<tbody>
|
22
|
+
<% @avalara_entity_use_codes.each do |use_code|%>
|
23
|
+
<tr id="<%= dom_id use_code %>" data-hook="admin_sale_events_index_rows">
|
24
|
+
<td><%=link_to use_code.use_code, object_url(use_code) %></td>
|
25
|
+
<td><%=use_code.use_code_description %></td>
|
26
|
+
<td data-hook="admin_avalara_entity_use_codes_index_row_actions">
|
27
|
+
<%= link_to_edit use_code, :class => 'edit' %>
|
28
|
+
<%= link_to_delete use_code %>
|
29
|
+
</td>
|
30
|
+
</tr>
|
31
|
+
<% end %>
|
32
|
+
</tbody>
|
33
|
+
</table>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<%= render 'spree/admin/shared/taxes_tabs' %>
|
2
|
+
|
3
|
+
<% content_for :page_title do %>
|
4
|
+
<%= Spree.t(:new_avalara_entity_use_code) %>
|
5
|
+
<% end %>
|
6
|
+
|
7
|
+
<% content_for :page_actions do %>
|
8
|
+
<li><%= link_to_with_icon 'arrow-left', Spree.t(:back_to_avalara_entity_use_codes_list), admin_avalara_entity_use_codes_path, :class => 'button' %></li>
|
9
|
+
<% end %>
|
10
|
+
|
11
|
+
|
12
|
+
<%= render 'spree/shared/error_messages', :target => @avalara_entity_use_code %>
|
13
|
+
|
14
|
+
<%= form_for [:admin, @avalara_entity_use_code] , :html => { :multipart => true } do |f| %>
|
15
|
+
<%= render :partial => 'form', :locals => { :f => f } %>
|
16
|
+
<%= render :partial => 'spree/admin/shared/new_resource_links' %>
|
17
|
+
<% end %>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<%= render 'spree/admin/shared/taxes_tabs' %>
|
2
|
+
|
3
|
+
<h1><%= t(:avalara_entity_use_code) %></h1>
|
4
|
+
|
5
|
+
<table>
|
6
|
+
<tr data-hook="name">
|
7
|
+
<th><%= t(:use_code) %></th>
|
8
|
+
<td>
|
9
|
+
<%= @avalara_entity_use_code.use_code %>
|
10
|
+
</td>
|
11
|
+
</tr>
|
12
|
+
<tr data-hook="description">
|
13
|
+
<th><%= t(:description) %></th>
|
14
|
+
<td>
|
15
|
+
<%= @avalara_entity_use_code.use_code_description %>
|
16
|
+
</td>
|
17
|
+
</tr>
|
18
|
+
|
19
|
+
</table>
|
20
|
+
|
21
|
+
<p>
|
22
|
+
<%= link_to_edit @avalara_entity_use_code, :class => 'edit_avalara_entity_use_code' %> <%= t(:or) %>
|
23
|
+
<%= link_to t(:back), collection_url %>
|
24
|
+
</p>
|