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,77 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Certification", :vcr do
4
+ let!(:avalara_order) { create(:avalara_order) }
5
+ let(:unique_ship_address) { create(:address, firstname: 'Jimmie', lastname: 'Johnson', address1: '3366 Speedway Blvd', city: 'Lincoln', state_name: 'Alabama', zipcode: 35096) }
6
+ let!(:order) { create(:order_with_line_items, state: 'delivery', user: nil, ship_address: unique_ship_address, email: 'acreilly3@gmail.com') }
7
+ let(:use_code) { create(:avalara_entity_use_code) }
8
+
9
+ context 'Transactions have been voided/cancelled.' do
10
+ let!(:completed_order) { create(:completed_avalara_order) }
11
+
12
+ describe 'should be successful' do
13
+ it 'returns ResultCode with value Success' do
14
+ response = completed_order.cancel_avalara
15
+ expect(response["ResultCode"]).to eq("Success")
16
+ end
17
+ end
18
+ end
19
+
20
+ context 'Transactions have been committed.' do
21
+ it 'commits an order' do
22
+ res = order.avalara_capture_finalize
23
+
24
+ expect(res['ResultCode']).to eq('Success')
25
+ end
26
+ end
27
+
28
+ context 'Exempt sales should be reflected in the test data through use of ExemptionNo or CustomerUsageType.' do
29
+ before do
30
+ avalara_order.user.update_attributes(avalara_entity_use_code: use_code)
31
+ end
32
+
33
+ it 'does not add additional tax' do
34
+ expect(avalara_order.avalara_transaction.commit_avatax('SalesInvoice')['TotalTax']).to eq('0')
35
+ end
36
+ end
37
+
38
+ context 'return orders' do
39
+ let(:refund_reason) { create(:refund_reason) }
40
+ let(:reimbursement) { create(:reimbursement) }
41
+ let(:order) { reimbursement.order }
42
+ let(:refund) { build(:refund, payment: order.payments.first, amount: BigDecimal.new(10), reason: refund_reason, transaction_id: nil, reimbursement: reimbursement) }
43
+
44
+ before do
45
+ order.update_attributes(completed_at: 2.days.ago)
46
+ order.avalara_capture_finalize
47
+ order.reload
48
+ end
49
+
50
+ describe '#commit_avatax_final' do
51
+ it 'should commit avatax final' do
52
+ response = order.avalara_transaction.commit_avatax_final('ReturnInvoice', refund)
53
+
54
+ expect(response).to be_kind_of(Hash)
55
+ expect(response['ResultCode']).to eq('Success')
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+
62
+ #### Certification Requirements to pass ####
63
+
64
+ # Transactions have been voided/cancelled.
65
+ # Transactions have been committed.
66
+ # Test transactions had meaningful document codes.
67
+ # Test transactions had meaningful customer code values.
68
+ # Transactions with more than one line item were tested.
69
+ # Exempt sales should be reflected in the test data through use of ExemptionNo or CustomerUsageType.
70
+ # Returns were tested with negative amounts and TaxDate overrides.
71
+ # Quantites should always represent positive values.
72
+ # Multiple quantity lines were tested.
73
+ # Shipping charges were reflected in the test data as separate line items.
74
+ # Multiple item codes were tested.
75
+ # Multiple descriptions were tested.
76
+ # Multiple tax codes were tested.
77
+ # A variety of addresses were used for testing.
@@ -0,0 +1,156 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Checkout", :vcr, type: :feature, inaccessible: true do
4
+ let(:product) { Spree::Product.first }
5
+ let!(:order) { create(:avalara_order, state: 'cart', shipment_cost: 10) }
6
+ let!(:user) { order.user }
7
+
8
+ before do
9
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(:current_order => order)
10
+ allow_any_instance_of(Spree::CheckoutController).to receive_messages(:try_spree_current_user => user)
11
+ end
12
+
13
+ context 'address' do
14
+ before do
15
+ visit_address
16
+ end
17
+
18
+ it 'has no tax adjustments on page' do
19
+ expect(page).not_to have_content('Tax')
20
+ expect(page).not_to have_content('Shipping Tax')
21
+ end
22
+ end
23
+
24
+ context 'delivery', js: true do
25
+ before do
26
+ visit_delivery
27
+ end
28
+
29
+ it 'has no tax adjustments on page' do
30
+ expect(page).not_to have_content('Tax')
31
+ expect(page).not_to have_content('Shipping Tax')
32
+ end
33
+ end
34
+
35
+ context 'payment', js: true do
36
+ before do
37
+ visit_delivery
38
+ end
39
+
40
+ context 'tax not included' do
41
+ before do
42
+ click_button 'Save and Continue'
43
+ end
44
+
45
+ context 'on payment page' do
46
+ it 'has tax and shipping tax adjustments on page' do
47
+ expect(page).to have_content('Tax')
48
+ expect(page).to have_content('Shipping Tax')
49
+ expect(page).to have_content('$0.40', count: 2)
50
+ end
51
+
52
+ it 'order line_items and shipments and shipments have an additional_tax_total sum of 0.40' do
53
+ expect(order.line_items.sum(:additional_tax_total).to_f).to eq(0.40)
54
+ expect(order.shipments.sum(:additional_tax_total).to_f).to eq(0.40)
55
+ expect(order.all_adjustments.tax.count).to eq(2)
56
+ end
57
+ end
58
+ end
59
+
60
+ context 'tax included' do
61
+ before do
62
+ Spree::TaxRate.update_all(included_in_price: true)
63
+ order.reload
64
+ click_button 'Save and Continue'
65
+ end
66
+
67
+ it 'has tax and shipping tax adjustments on page' do
68
+ expect(page).to have_content('Tax (Included in Price)')
69
+ expect(page).to have_content('Shipping Tax (Included in Price)')
70
+ expect(page).to have_content('$0.38', count: 2)
71
+ end
72
+
73
+ it 'order line_items and shipments have an included_tax_total sum of 0.38' do
74
+ expect(order.line_items.sum(:included_tax_total).to_f).to eq(0.38)
75
+ expect(order.shipments.sum(:included_tax_total).to_f).to eq(0.38)
76
+ expect(order.all_adjustments.tax.count).to eq(2)
77
+ end
78
+ end
79
+
80
+ context 'with promotion' do
81
+
82
+ context 'tax not included' do
83
+ let(:promotion) { create(:promotion, :with_line_item_adjustment, adjustment_rate: 5) }
84
+
85
+ before do
86
+ order.line_items.each do |li|
87
+ create(:adjustment, order: order, source: promotion.promotion_actions.first, adjustable: li)
88
+ end
89
+ order.update!
90
+ order.reload
91
+ click_button 'Save and Continue'
92
+ end
93
+
94
+ it 'has adjusted tax amount after promotion applied' do
95
+ expect(page).to have_content('-$5.00')
96
+ expect(order.line_items.sum(:additional_tax_total).to_f).to eq(0.2)
97
+ expect(page).to have_content('$0.2')
98
+ end
99
+ end
100
+ end
101
+ end
102
+
103
+ context 'complete order', js: true do
104
+ let(:payment_method) { create(:credit_card_payment_method) }
105
+ let!(:credit_card) do
106
+ create(:credit_card, user_id: order.user.id, payment_method: payment_method, gateway_customer_profile_id: "BGS-WEFWF")
107
+ end
108
+ before do
109
+ allow(order).to receive_messages(:available_payment_methods => [ payment_method ])
110
+ visit_delivery
111
+ click_button 'Save and Continue'
112
+ click_button "Save and Continue"
113
+ click_button "Place Order"
114
+ end
115
+
116
+ it 'has tax and shipping tax adjustments on page' do
117
+ expect(page).to have_content('Tax')
118
+ expect(page).to have_content('Shipping Tax')
119
+ expect(page).to have_content('$0.40', count: 2)
120
+ end
121
+
122
+ it 'order line_items and shipments have an additional_tax_total sum of 0.40' do
123
+ expect(order.line_items.sum(:additional_tax_total).to_f).to eq(0.40)
124
+ expect(order.shipments.sum(:additional_tax_total).to_f).to eq(0.40)
125
+ expect(order.all_adjustments.tax.count).to eq(2)
126
+ end
127
+ end
128
+
129
+
130
+ def fill_in_address
131
+ address = "order_bill_address_attributes"
132
+ fill_in "#{address}_firstname", with: "Ryan"
133
+ fill_in "#{address}_lastname", with: "Bigg"
134
+ fill_in "#{address}_address1", with: "915 S Jackson St"
135
+ fill_in "#{address}_city", with: "Montgomery"
136
+ select "United States of America", from: "#{address}_country_id"
137
+ select "Alabama", from: "#{address}_state_id"
138
+ fill_in "#{address}_zipcode", with: "36104"
139
+ fill_in "#{address}_phone", with: "(555) 555-5555"
140
+ end
141
+
142
+ def visit_address
143
+ order.all_adjustments.destroy_all
144
+ order.line_items.update_all(additional_tax_total: 0.0)
145
+ order.shipments.update_all(additional_tax_total: 0.0)
146
+ visit spree.checkout_state_path(:address)
147
+ end
148
+
149
+ def visit_delivery
150
+ VCR.use_cassette('address_validation_success') do
151
+ visit_address
152
+ fill_in_address
153
+ click_button 'Save and Continue'
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,153 @@
1
+ require 'spec_helper'
2
+
3
+ describe "VAT", :vcr do
4
+ let!(:it) { create(:country, iso: 'IT', name: 'Italy') }
5
+ let!(:nl) { create(:country, iso: 'NL', name: 'Netherlands') }
6
+ let!(:fr) { create(:country, iso: 'FR', name: 'France') }
7
+ let!(:cr) { create(:country, iso: 'CR', name: 'Costa Rica') }
8
+ let!(:us) { Spree::Country.find_by(iso: 'US') }
9
+
10
+ let(:it_address) { create(:address, address1: '34 Borgo degli Albizi', city: 'Florence', zipcode: '50122', country: it, state_name: '') }
11
+ let(:res) { avalara_order.avalara_capture }
12
+
13
+ context 'Seller in EU country; Buyer in same EU country' do
14
+ let!(:avalara_order) { create(:avalara_order, tax_included: true, ship_address: it_address, state: 'address') }
15
+ before { prep_avalara_order }
16
+
17
+ it 'TotalTax is equal to order included_tax_total' do
18
+ expect(avalara_order.included_tax_total.to_f).to eq(res['TotalTax'].to_f)
19
+ end
20
+
21
+ it 'tax detail country equals to IT' do
22
+ tax_detail_country = res['TaxLines'][0]['TaxDetails'][0]['Country']
23
+
24
+ expect(tax_detail_country).to eq('IT')
25
+ end
26
+ end
27
+
28
+ context 'Seller in EU country, Buyer is outside EU' do
29
+
30
+ context 'Seller does not have Nexus Jurisdition registered' do
31
+ let(:cr_address) { create(:address, address1: '350 Av Central', city: 'Tamarindo', zipcode: '50309', state_name: '', country: cr) }
32
+ let!(:avalara_order) { create(:avalara_order, tax_included: true, state: 'address', ship_address: cr_address) }
33
+
34
+ let(:res) { avalara_order.avalara_capture }
35
+ before { prep_avalara_order }
36
+
37
+ it 'tax detail country equals to IT' do
38
+ tax_detail_country = res['TaxLines'][0]['TaxDetails'][0]['Country']
39
+
40
+ expect(tax_detail_country).to eq('IT')
41
+ end
42
+
43
+ it 'TotalTax is equal to order included_tax_total' do
44
+ expect(avalara_order.included_tax_total.to_f).to eq(res['TotalTax'].to_f)
45
+ end
46
+
47
+ it 'total tax is 0 since utah is not in jurisdiction' do
48
+ expect(res['TotalTax'].to_f).to eq(0)
49
+ end
50
+
51
+ context 'with BusinessIdentificationNo' do
52
+ before do
53
+ avalara_order.user.update_attributes(vat_id: '123456789')
54
+ end
55
+
56
+ it 'origin country zero rate is returned' do
57
+ tax_detail_country = res['TaxLines'][0]['TaxDetails'][0]['Country']
58
+
59
+ expect(tax_detail_country).to eq('IT')
60
+ expect(res['TotalTax']).to eq('0')
61
+ end
62
+ end
63
+ end
64
+
65
+ context 'Seller has Nexus Jurisdiction Registered' do
66
+ let!(:avalara_order) { create(:avalara_order, tax_included: true, state: 'address') }
67
+ before { prep_avalara_order }
68
+
69
+ it 'tax detail region equals to AL' do
70
+ tax_detail_region = res['TaxLines'][0]['TaxDetails'][0]['Region']
71
+
72
+ expect(tax_detail_region).to eq('AL')
73
+ end
74
+
75
+ it 'TotalTax is equal to order included_tax_total' do
76
+ expect(avalara_order.included_tax_total.to_f).to eq(res['TotalTax'].to_f)
77
+ end
78
+ end
79
+ end
80
+
81
+ context 'Seller in EU country, Buyer in another EU country' do
82
+
83
+ context 'Seller has Nexus Jurisdition Registered' do
84
+ let(:nl_address) { create(:address, address1: '89 Nieuwendijk', city: 'Amsterdam', zipcode: '1012 MC', country: nl, state_name: '') }
85
+ let!(:avalara_order) { create(:avalara_order, tax_included: true, state: 'address', ship_address: nl_address) }
86
+ before { prep_avalara_order }
87
+
88
+ it 'destination country tax is returned' do
89
+ tax_detail_country = res['TaxLines'][0]['TaxDetails'][0]['Country']
90
+
91
+ expect(tax_detail_country).to eq('NL')
92
+ end
93
+
94
+ it 'TotalTax is equal to order included_tax_total' do
95
+ expect(avalara_order.included_tax_total.to_f).to eq(res['TotalTax'].to_f)
96
+ end
97
+
98
+ context 'with BusinessIdentificationNo' do
99
+ before do
100
+ avalara_order.user.update_attributes(vat_id: '123456789')
101
+ end
102
+
103
+ it 'origin country zero rate is returned' do
104
+ tax_detail_country = res['TaxLines'][0]['TaxDetails'][0]['Country']
105
+
106
+ expect(tax_detail_country).to eq('IT')
107
+ expect(res['TotalTax']).to eq('0')
108
+ end
109
+ end
110
+ end
111
+
112
+ context 'Seller does not have Nexus Jurisdition Registered' do
113
+ let(:fr_address) { create(:address, address1: '8 Boulevard du Palais', city: 'Paris', zipcode: '75001', country: fr, state_name: '') }
114
+ let!(:avalara_order) { create(:avalara_order, tax_included: true, state: 'address', ship_address: fr_address) }
115
+ before { prep_avalara_order }
116
+
117
+ it 'origin country tax is returned' do
118
+ tax_detail_country = res['TaxLines'][0]['TaxDetails'][0]['Country']
119
+ expect(tax_detail_country).to eq('IT')
120
+ end
121
+
122
+ it 'TotalTax is equal to order included_tax_total' do
123
+ expect(avalara_order.included_tax_total.to_f).to eq(res['TotalTax'].to_f)
124
+ end
125
+
126
+ context 'with BusinessIdentificationNo' do
127
+ before do
128
+ avalara_order.user.update_attributes(vat_id: '123456789')
129
+ end
130
+
131
+ it 'origin country zero rate is returned' do
132
+ tax_detail_country = res['TaxLines'][0]['TaxDetails'][0]['Country']
133
+
134
+ expect(tax_detail_country).to eq('IT')
135
+ expect(res['TotalTax']).to eq('0')
136
+ end
137
+ end
138
+ end
139
+ end
140
+
141
+
142
+ def set_seller_location
143
+ Spree::AvalaraPreference.origin_address.update_attributes(value: "{\"Address1\":\"34 Borgo degli Albizi\",\"Address2\":\"\",\"City\":\"Florence\",\"Region\":\"\",\"Zip5\":\"50122\",\"Zip4\":\"\",\"Country\":\"IT\"}")
144
+ Spree::StockLocation.update_all(address1: '150 Piccadilly', city: 'Florence', country_id: it.id)
145
+ end
146
+
147
+ def prep_avalara_order
148
+ set_seller_location
149
+ avalara_order.reload
150
+ avalara_order.next!
151
+ end
152
+ end
153
+
@@ -0,0 +1,80 @@
1
+ require 'spec_helper'
2
+
3
+ describe SolidusAvataxCertified::Address, :type => :model do
4
+ let(:address){ build(:address, city: 'Tuscaloosa', address1: '220 Paul W Bryant Dr') }
5
+ let(:order) { build(:order_with_line_items, ship_address: address) }
6
+
7
+ before do
8
+ Spree::AvalaraPreference.address_validation.update_attributes(value: 'true')
9
+ end
10
+
11
+ let(:address_lines) { SolidusAvataxCertified::Address.new(order) }
12
+
13
+ describe '#initialize' do
14
+ it 'should have order' do
15
+ expect(address_lines.order).to eq(order)
16
+ end
17
+ it 'should have addresses be an array' do
18
+ expect(address_lines.addresses).to be_kind_of(Array)
19
+ end
20
+ end
21
+
22
+ describe '#build_addresses' do
23
+ it 'receives origin_address' do
24
+ expect(address_lines).to receive(:origin_address)
25
+ address_lines.build_addresses
26
+ end
27
+ it 'receives order_ship_address' do
28
+ expect(address_lines).to receive(:order_ship_address)
29
+ address_lines.build_addresses
30
+ end
31
+ it 'receives origin_ship_addresses' do
32
+ expect(address_lines).to receive(:origin_ship_addresses)
33
+ address_lines.build_addresses
34
+ end
35
+ end
36
+
37
+ describe '#origin_address' do
38
+ it 'returns an array' do
39
+ expect(address_lines.origin_address).to be_kind_of(Array)
40
+ end
41
+
42
+ it 'has the origin address return a hash' do
43
+ expect(address_lines.origin_address[0]).to be_kind_of(Hash)
44
+ end
45
+ end
46
+
47
+ describe '#order_ship_address' do
48
+ it 'returns an array' do
49
+ expect(address_lines.order_ship_address).to be_kind_of(Array)
50
+ end
51
+
52
+ it 'has the origin address return a hash' do
53
+ expect(address_lines.order_ship_address[0]).to be_kind_of(Hash)
54
+ end
55
+ end
56
+
57
+ describe '#validate', :vcr do
58
+ subject do
59
+ VCR.use_cassette('address_validation_success') do
60
+ address_lines.validate
61
+ end
62
+ end
63
+
64
+ it "validates address with success" do
65
+ expect(subject["ResultCode"]).to eq("Success")
66
+ end
67
+
68
+ it "does not validate when config settings are false" do
69
+ Spree::AvalaraPreference.address_validation.update_attributes(value: 'false')
70
+
71
+ expect(subject).to eq("Address validation disabled")
72
+ end
73
+
74
+ it 'fails when information is incorrect' do
75
+ order.ship_address.update_attributes(city: nil)
76
+
77
+ expect(address_lines.validate['ResultCode']).to eq('Error')
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,97 @@
1
+ require 'spec_helper'
2
+
3
+ describe SolidusAvataxCertified::AvataxLog, :type => :model do
4
+ let(:logger) { SolidusAvataxCertified::AvataxLog.new('test_log', 'test_file.rb', 'test info') }
5
+
6
+
7
+ before do
8
+ Spree::AvalaraPreference.log_to_stdout.update_attributes(value: 'false')
9
+ end
10
+
11
+ describe '#enabled?' do
12
+ it 'returns a boolean value' do
13
+ Spree::AvalaraPreference.log.update_attributes(value: 'true')
14
+
15
+ expect(logger.enabled?).to be_truthy
16
+ end
17
+ end
18
+
19
+ describe '#progname' do
20
+ it 'sets the logger progname' do
21
+ Spree::AvalaraPreference.log_to_stdout.update_attributes(value: 'false')
22
+ Spree::AvalaraPreference.log.update_attributes(value: 'true')
23
+ logger = SolidusAvataxCertified::AvataxLog.new('test_log', 'test_file.rb', 'test info')
24
+
25
+ expect{ logger.progname('changed') }.to change{ logger.progname }.from('test_file').to('changed')
26
+ end
27
+
28
+ it 'returns nil if logger is not enabled' do
29
+ Spree::AvalaraPreference.log.update_attributes(value: 'false')
30
+
31
+ expect(logger.progname('this_wont_change')).to be_nil
32
+ end
33
+ end
34
+
35
+ describe '#info' do
36
+ it 'logs info with given message' do
37
+ logger = SolidusAvataxCertified::AvataxLog.new('test_log', 'test_file.rb', 'test info')
38
+
39
+ expect(logger.logger).to receive(:info).with('[AVATAX] Hyah!')
40
+ logger.info('Hyah!')
41
+ end
42
+
43
+ it 'returns nil if logger is not enabled' do
44
+ Spree::AvalaraPreference.log.update_attributes(value: 'false')
45
+
46
+ expect(logger.info('this_wont_change')).to be_nil
47
+ end
48
+ end
49
+
50
+ describe '#info_and_debug' do
51
+ it 'recieves info and debug messages' do
52
+ logger = SolidusAvataxCertified::AvataxLog.new('test_log', 'test_file.rb', 'test info')
53
+
54
+ expect(logger.logger).to receive(:info).with('[AVATAX] Hyah!')
55
+ expect(logger.logger).to receive(:debug).with("[AVATAX] [\"Heuh!\"]")
56
+
57
+ logger.info_and_debug('Hyah!', ['Heuh!'])
58
+ end
59
+
60
+ it 'returns nil if logger is not enabled' do
61
+ Spree::AvalaraPreference.log.update_attributes(value: 'false')
62
+
63
+ expect(logger.info_and_debug('Hyah!', ['Heuh!'])).to be_nil
64
+ end
65
+ end
66
+
67
+ describe '#debug' do
68
+ it 'receives debug with message' do
69
+ logger = SolidusAvataxCertified::AvataxLog.new('test_log', 'test_file.rb', 'test info')
70
+
71
+ expect(logger.logger).to receive(:debug).with("[AVATAX] [\"Heuh!\"]")
72
+
73
+ logger.debug(['Heuh!'])
74
+ end
75
+
76
+ it 'returns nil if logger is not enabled' do
77
+ Spree::AvalaraPreference.log.update_attributes(value: 'false')
78
+
79
+ expect(logger.debug(['Heuh!'])).to be_nil
80
+ end
81
+ end
82
+
83
+ describe '#error' do
84
+ it 'logs error with given message' do
85
+ logger = SolidusAvataxCertified::AvataxLog.new('test_log', 'test_file.rb', 'test error')
86
+
87
+ expect(logger.logger).to receive(:error).with('[AVATAX] Hyah!')
88
+ logger.error('Hyah!')
89
+ end
90
+
91
+ it 'returns nil if logger is not enabled' do
92
+ Spree::AvalaraPreference.log.update_attributes(value: 'false')
93
+
94
+ expect(logger.error('this_wont_change')).to be_nil
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,100 @@
1
+ require 'spec_helper'
2
+
3
+ describe SolidusAvataxCertified::Line, :type => :model do
4
+ let(:included_in_price) { false }
5
+ let(:order) { create(:avalara_order, line_items_count: 2, tax_included: included_in_price) }
6
+ let(:shipped_order) { create(:shipped_order) }
7
+ let(:sales_lines) { SolidusAvataxCertified::Line.new(order, 'SalesOrder') }
8
+
9
+ describe '#initialize' do
10
+ it 'should have order' do
11
+ expect(sales_lines.order).to eq(order)
12
+ end
13
+ it 'should have lines be an array' do
14
+ expect(sales_lines.lines).to be_kind_of(Array)
15
+ end
16
+ it 'lines should be a length of 3' do
17
+ expect(sales_lines.lines.length).to eq(3)
18
+ end
19
+ end
20
+
21
+ context 'sales order' do
22
+ describe '#build_lines' do
23
+ it 'receives method item_lines_array' do
24
+ expect(sales_lines).to receive(:item_lines_array)
25
+ sales_lines.build_lines
26
+ end
27
+ it 'receives method shipment_lines_array' do
28
+ expect(sales_lines).to receive(:shipment_lines_array)
29
+ sales_lines.build_lines
30
+ end
31
+ end
32
+
33
+ describe '#item_lines_array' do
34
+ it 'returns an Array' do
35
+ expect(sales_lines.item_lines_array).to be_kind_of(Array)
36
+ end
37
+ end
38
+
39
+ describe '#shipment_lines_array' do
40
+ it 'returns an Array' do
41
+ expect(sales_lines.shipment_lines_array).to be_kind_of(Array)
42
+ end
43
+ it 'should have a length of 1' do
44
+ expect(sales_lines.shipment_lines_array.length).to eq(1)
45
+ end
46
+ end
47
+
48
+ describe '#item_line' do
49
+ it 'returns a Hash' do
50
+ expect(sales_lines.item_line(order.line_items.first)).to be_kind_of(Hash)
51
+ end
52
+ end
53
+ describe '#shipment_line' do
54
+ it 'returns a Hash' do
55
+ expect(sales_lines.shipment_line(order.shipments.first)).to be_kind_of(Hash)
56
+ end
57
+ end
58
+ end
59
+
60
+ context 'return invoice' do
61
+ let(:authorization) { generate(:refund_transaction_id) }
62
+ let(:payment_amount) { 10*2 }
63
+ let(:payment_method) { build(:credit_card_payment_method) }
64
+ let(:payment) { build(:payment, amount: payment_amount, payment_method: payment_method, order: order) }
65
+ let(:refund_reason) { build(:refund_reason) }
66
+ let(:gateway_response) {
67
+ ActiveMerchant::Billing::Response.new(
68
+ gateway_response_success,
69
+ gateway_response_message,
70
+ gateway_response_params,
71
+ gateway_response_options
72
+ )
73
+ }
74
+ let(:gateway_response_success) { true }
75
+ let(:gateway_response_message) { '' }
76
+ let(:gateway_response_params) { {} }
77
+ let(:gateway_response_options) { {} }
78
+
79
+ let(:refund) {Spree::Refund.new(payment: payment, amount: BigDecimal.new(10), reason: refund_reason, transaction_id: nil)}
80
+ let(:shipped_order) { build(:shipped_order) }
81
+ let(:return_lines) { SolidusAvataxCertified::Line.new(shipped_order, 'ReturnOrder', refund) }
82
+
83
+ describe 'build_lines' do
84
+ it 'receives method refund_lines' do
85
+ expect(return_lines).to receive(:refund_lines)
86
+ return_lines.build_lines
87
+ end
88
+ end
89
+ describe '#refund_line' do
90
+ it 'returns an Hash' do
91
+ expect(return_lines.refund_line).to be_kind_of(Hash)
92
+ end
93
+ end
94
+ describe '#refund_line' do
95
+ it 'returns an Array' do
96
+ expect(return_lines.refund_lines).to be_kind_of(Array)
97
+ end
98
+ end
99
+ end
100
+ end