solidus_avatax_certified 1.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.
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>