solidus_avatax_certified 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (165) hide show
  1. checksums.yaml +7 -0
  2. data/.env_example +4 -0
  3. data/.gitignore +16 -0
  4. data/.rspec +3 -0
  5. data/.ruby-version +1 -0
  6. data/GEM_VERSION +1 -0
  7. data/Gemfile +18 -0
  8. data/LICENSE +26 -0
  9. data/README.md +27 -0
  10. data/Rakefile +21 -0
  11. data/app/assets/javascripts/spree/backend/address_validator.js +84 -0
  12. data/app/assets/javascripts/spree/backend/solidus_avatax_certified.js +5 -0
  13. data/app/assets/javascripts/spree/backend/use_code_picker.js +51 -0
  14. data/app/assets/javascripts/spree/frontend/address_validator.js +87 -0
  15. data/app/assets/javascripts/spree/frontend/flash.js.coffee +26 -0
  16. data/app/assets/javascripts/spree/frontend/solidus_avatax_certified.js +4 -0
  17. data/app/assets/stylesheets/spree/backend/solidus_avatax_certified.css +4 -0
  18. data/app/assets/stylesheets/spree/frontend/solidus_avatax_certified.css +4 -0
  19. data/app/controllers/spree/admin/avalara_entity_use_codes_controller.rb +15 -0
  20. data/app/controllers/spree/admin/avatax_settings_controller.rb +82 -0
  21. data/app/controllers/spree/admin/users_controller_decorator.rb +11 -0
  22. data/app/controllers/spree/checkout_controller_decorator.rb +22 -0
  23. data/app/models/solidus_avatax_certified/address.rb +95 -0
  24. data/app/models/solidus_avatax_certified/avatax_log.rb +69 -0
  25. data/app/models/solidus_avatax_certified/line.rb +146 -0
  26. data/app/models/solidus_avatax_certified/preference_updater.rb +74 -0
  27. data/app/models/spree/address_decorator.rb +13 -0
  28. data/app/models/spree/adjustment_decorator.rb +10 -0
  29. data/app/models/spree/avalara_entity_use_code.rb +5 -0
  30. data/app/models/spree/avalara_preference.rb +72 -0
  31. data/app/models/spree/avalara_transaction.rb +181 -0
  32. data/app/models/spree/calculator/avalara_transaction.rb +86 -0
  33. data/app/models/spree/line_item_decorator.rb +25 -0
  34. data/app/models/spree/order_decorator.rb +85 -0
  35. data/app/models/spree/payment_decorator.rb +23 -0
  36. data/app/models/spree/refund_decorator.rb +30 -0
  37. data/app/models/spree/shipment_decorator.rb +28 -0
  38. data/app/models/spree/shipping_rate_decorator.rb +25 -0
  39. data/app/models/spree/user_decorator.rb +3 -0
  40. data/app/models/tax_svc.rb +143 -0
  41. data/app/overrides/spree/admin/shared/_configuration_menu.rb +10 -0
  42. data/app/overrides/spree/admin/users/sidebar.rb +8 -0
  43. data/app/overrides/spree/admin/users/validation_button.rb +6 -0
  44. data/app/views/spree/admin/avalara_entity_use_codes/_form.html.erb +27 -0
  45. data/app/views/spree/admin/avalara_entity_use_codes/edit.html.erb +16 -0
  46. data/app/views/spree/admin/avalara_entity_use_codes/index.html.erb +33 -0
  47. data/app/views/spree/admin/avalara_entity_use_codes/new.html.erb +17 -0
  48. data/app/views/spree/admin/avalara_entity_use_codes/show.html.erb +24 -0
  49. data/app/views/spree/admin/avatax_settings/edit.html.erb +183 -0
  50. data/app/views/spree/admin/avatax_settings/ping_my_service.js.erb +8 -0
  51. data/app/views/spree/admin/avatax_settings/show.html.erb +124 -0
  52. data/app/views/spree/admin/avatax_settings/validate_address.js.erb +8 -0
  53. data/app/views/spree/admin/users/avalara_information.html.erb +53 -0
  54. data/app/views/spree/checkout/_address.html.erb +35 -0
  55. data/app/views/spree/checkout/_address_validator_button.html.erb +3 -0
  56. data/bin/rails +7 -0
  57. data/circle.yml +17 -0
  58. data/config/initializers/avatax.rb +5 -0
  59. data/config/initializers/spree.rb +3 -0
  60. data/config/locales/en.yml +35 -0
  61. data/config/routes.rb +18 -0
  62. data/db/migrate/20160624154205_create_spree_avalara_transactions.rb +9 -0
  63. data/db/migrate/20160624154423_create_spree_avalara_entity_use_codes.rb +9 -0
  64. data/db/migrate/20160624155217_add_columns_to_spree_users.rb +6 -0
  65. data/db/migrate/20160628200504_create_spree_avalara_preferences.rb +10 -0
  66. data/db/migrate/20160805193512_add_vat_id_to_spree_users.rb +5 -0
  67. data/db/seeds.rb +1 -0
  68. data/lib/generators/solidus_avatax_certified/install/install_generator.rb +45 -0
  69. data/lib/solidus_avatax_certified/engine.rb +22 -0
  70. data/lib/solidus_avatax_certified/preference_seeder.rb +69 -0
  71. data/lib/solidus_avatax_certified/seeder.rb +117 -0
  72. data/lib/solidus_avatax_certified.rb +2 -0
  73. data/lib/tasks/load_seeds.rake +15 -0
  74. data/setup.md +12 -0
  75. data/solidus_avatax_certified.gemspec +42 -0
  76. data/spec/controllers/spree/admin/avalara_entity_use_codes_controller_spec.rb +53 -0
  77. data/spec/controllers/spree/admin/avatax_settings_controller_spec.rb +67 -0
  78. data/spec/factories/avalara_entity_use_code_factory.rb +6 -0
  79. data/spec/factories/avalara_factories.rb +76 -0
  80. data/spec/factories/avalara_order_factory.rb +62 -0
  81. data/spec/factories/avalara_preference_factory.rb +7 -0
  82. data/spec/factories/avalara_shipment_factory.rb +27 -0
  83. data/spec/factories/avalara_shipping_method_factory.rb +23 -0
  84. data/spec/factories/tax_rate_factory.rb +19 -0
  85. data/spec/features/certification_spec.rb +77 -0
  86. data/spec/features/checkout_spec.rb +156 -0
  87. data/spec/features/vat_spec.rb +153 -0
  88. data/spec/models/solidus_avatax_certified/address_spec.rb +80 -0
  89. data/spec/models/solidus_avatax_certified/avatax_log_spec.rb +97 -0
  90. data/spec/models/solidus_avatax_certified/line_spec.rb +100 -0
  91. data/spec/models/spree/address_decorator_spec.rb +44 -0
  92. data/spec/models/spree/adjustment_decorator_spec.rb +25 -0
  93. data/spec/models/spree/avalara_entity_use_code_spec.rb +5 -0
  94. data/spec/models/spree/avalara_preference_spec.rb +173 -0
  95. data/spec/models/spree/avalara_transaction_spec.rb +203 -0
  96. data/spec/models/spree/calculator/avalara_transaction_spec.rb +129 -0
  97. data/spec/models/spree/line_item_decorator_spec.rb +33 -0
  98. data/spec/models/spree/order_decorator_spec.rb +164 -0
  99. data/spec/models/spree/payment_decorator_spec.rb +117 -0
  100. data/spec/models/spree/refund_decorator_spec.rb +81 -0
  101. data/spec/models/spree/shipment_decorator_spec.rb +36 -0
  102. data/spec/models/spree/shipping_rate_decorator_spec.rb +17 -0
  103. data/spec/models/spree/user_decorator_spec.rb +5 -0
  104. data/spec/spec_helper.rb +81 -0
  105. data/spec/support/avatax_config_preferences.rb +8 -0
  106. data/spec/support/vcr.rb +9 -0
  107. 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
  108. data/spec/vcr/Certification/Transactions_have_been_committed_/commits_an_order.yml +336 -0
  109. data/spec/vcr/Certification/Transactions_have_been_voided/cancelled_/should_be_successful/returns_ResultCode_with_value_Success.yml +522 -0
  110. data/spec/vcr/Certification/return_orders/_commit_avatax_final/should_commit_avatax_final.yml +404 -0
  111. data/spec/vcr/Checkout/complete_order/has_tax_and_shipping_tax_adjustments_on_page.yml +72 -0
  112. data/spec/vcr/Checkout/complete_order/order_line_items_and_shipments_have_an_additional_tax_total_sum_of_0_40.yml +72 -0
  113. data/spec/vcr/Checkout/payment/tax_included/has_tax_and_shipping_tax_adjustments_on_page.yml +72 -0
  114. data/spec/vcr/Checkout/payment/tax_included/order_line_items_and_shipments_have_an_included_tax_total_sum_of_0_38.yml +72 -0
  115. data/spec/vcr/Checkout/payment/tax_not_included/on_payment_page/has_tax_and_shipping_tax_adjustments_on_page.yml +72 -0
  116. 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
  117. data/spec/vcr/Checkout/payment/with_promotion/tax_not_included/has_adjusted_tax_amount_after_promotion_applied.yml +73 -0
  118. data/spec/vcr/SolidusAvataxCertified_Address/_validate/fails_when_information_is_incorrect.yml +54 -0
  119. 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
  120. 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
  121. 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
  122. 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
  123. 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
  124. 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
  125. 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
  126. 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
  127. 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
  128. data/spec/vcr/Spree_Calculator_AvalaraTransaction/_compute/when_given_a_shipment/computing_normal_shipment/should_be_equal_4_0.yml +141 -0
  129. 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
  130. data/spec/vcr/Spree_Calculator_AvalaraTransaction/_compute/when_given_a_shipment/with_promotion/should_equal_3_96.yml +210 -0
  131. data/spec/vcr/Spree_Calculator_AvalaraTransaction/_compute/when_given_an_order/when_computing_an_order/should_raise_error.yml +136 -0
  132. data/spec/vcr/Spree_Order/_cancel_avalara/should_receive_cancel_order_when_cancel_avalara_is_called.yml +136 -0
  133. data/spec/vcr/Spree_Order/_cancel_avalara/state_machine_event_cancel/should_recieve_cancel_avalara_when_event_cancel_is_called.yml +259 -0
  134. data/spec/vcr/Spree_Order/_validate_ship_address/should_return_false_if_validation_failed.yml +54 -0
  135. data/spec/vcr/Spree_Order/_validate_ship_address/should_return_the_response_if_refuse_checkout_on_address_validation_is_disabled.yml +59 -0
  136. data/spec/vcr/Spree_Order/_validate_ship_address/should_return_the_response_if_validation_is_success.yml +59 -0
  137. data/spec/vcr/Spree_Payment/_avalara_finalize/should_update_the_amount_to_be_the_order_total.yml +136 -0
  138. data/spec/vcr/Spree_Payment/_cancel_avalara/committed_order/should_be_successful/ResultCode_returns_Success.yml +205 -0
  139. data/spec/vcr/Spree_Payment/_cancel_avalara/uncommitted_order/should_fail/ResultCode_returns_Error.yml +191 -0
  140. data/spec/vcr/Spree_Payment/_purchase_/receive_avalara_finalize.yml +136 -0
  141. data/spec/vcr/Spree_Payment/_void_transaction_/receive_cancel_avalara.yml +136 -0
  142. data/spec/vcr/Spree_Refund/full_refund/returns_correct_tax_calculations.yml +270 -0
  143. 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
  144. 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
  145. 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
  146. 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
  147. 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
  148. 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
  149. data/spec/vcr/VAT/Seller_in_EU_country_Buyer_in_same_EU_country/TotalTax_is_equal_to_order_included_tax_total.yml +137 -0
  150. data/spec/vcr/VAT/Seller_in_EU_country_Buyer_in_same_EU_country/tax_detail_country_equals_to_IT.yml +138 -0
  151. 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
  152. 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
  153. 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
  154. 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
  155. 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
  156. 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
  157. data/spec/vcr/address_validation_success.yml +59 -0
  158. data/spec/vcr/capture_with_customer_usage_type.yml +72 -0
  159. data/spec/vcr/order_cancel.yml +258 -0
  160. data/spec/vcr/order_capture.yml +72 -0
  161. data/spec/vcr/order_capture_finalize.yml +141 -0
  162. data/spec/vcr/order_capture_with_promo.yml +73 -0
  163. data/spec/vcr/order_return_capture.yml +68 -0
  164. data/spec/vcr/tax_included_order.yml +73 -0
  165. 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,3 @@
1
+ Spree.user_class.class_eval do
2
+ belongs_to :avalara_entity_use_code
3
+ 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,6 @@
1
+ Deface::Override.new(
2
+ virtual_path: 'spree/admin/users/_addresses_form',
3
+ name: 'add validator button',
4
+ insert_bottom: '[data-hook="ship_address_wrapper"]',
5
+ text: "<a href='#'' class='button address_validator' style='float: right;'>Validate Ship Address</a>"
6
+ )
@@ -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' %> &nbsp;
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>