spree_core 3.0.10 → 3.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (289) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/spree.js.coffee.erb +12 -3
  3. data/app/helpers/spree/base_helper.rb +4 -1
  4. data/app/helpers/spree/products_helper.rb +37 -6
  5. data/app/mailers/spree/base_mailer.rb +11 -2
  6. data/app/models/concerns/spree/adjustment_source.rb +3 -10
  7. data/app/models/concerns/spree/default_price.rb +7 -1
  8. data/app/models/concerns/spree/named_type.rb +1 -1
  9. data/app/models/concerns/spree/user_api_authentication.rb +7 -1
  10. data/app/models/concerns/spree/user_methods.rb +47 -0
  11. data/app/models/concerns/spree/user_reporting.rb +2 -2
  12. data/app/models/concerns/spree/vat_price_calculation.rb +47 -0
  13. data/app/models/spree/address.rb +8 -7
  14. data/app/models/spree/adjustable/adjuster/base.rb +25 -0
  15. data/app/models/spree/adjustable/adjuster/promotion.rb +41 -0
  16. data/app/models/spree/adjustable/adjuster/tax.rb +26 -0
  17. data/app/models/spree/adjustable/adjustments_updater.rb +22 -45
  18. data/app/models/spree/adjustment.rb +8 -10
  19. data/app/models/spree/app_configuration.rb +5 -2
  20. data/app/models/spree/base.rb +4 -0
  21. data/app/models/spree/calculator.rb +0 -5
  22. data/app/models/spree/calculator/default_tax.rb +2 -10
  23. data/app/models/spree/classification.rb +7 -3
  24. data/app/models/spree/country.rb +14 -3
  25. data/app/models/spree/credit_card.rb +21 -31
  26. data/app/models/spree/customer_return.rb +7 -15
  27. data/app/models/spree/gateway.rb +7 -6
  28. data/app/models/spree/image.rb +1 -1
  29. data/app/models/spree/inventory_unit.rb +9 -6
  30. data/app/models/spree/legacy_user.rb +1 -6
  31. data/app/models/spree/line_item.rb +69 -68
  32. data/app/models/spree/log_entry.rb +1 -4
  33. data/app/models/spree/option_type.rb +15 -6
  34. data/app/models/spree/option_type_prototype.rb +9 -0
  35. data/app/models/spree/option_value.rb +11 -3
  36. data/app/models/spree/option_value_variant.rb +6 -0
  37. data/app/models/spree/order.rb +113 -64
  38. data/app/models/spree/order/checkout.rb +8 -11
  39. data/app/models/spree/order/currency_updater.rb +1 -1
  40. data/app/models/spree/order/store_credit.rb +96 -0
  41. data/app/models/spree/order_contents.rb +6 -1
  42. data/app/models/spree/order_inventory.rb +4 -8
  43. data/app/models/spree/order_promotion.rb +6 -0
  44. data/app/models/spree/order_updater.rb +2 -7
  45. data/app/models/spree/payment.rb +46 -19
  46. data/app/models/spree/payment/gateway_options.rb +8 -4
  47. data/app/models/spree/payment_method.rb +12 -13
  48. data/app/models/spree/payment_method/store_credit.rb +130 -0
  49. data/app/models/spree/preference.rb +1 -1
  50. data/app/models/spree/price.rb +16 -6
  51. data/app/models/spree/product.rb +52 -49
  52. data/app/models/spree/product/scopes.rb +7 -2
  53. data/app/models/spree/product_option_type.rb +7 -2
  54. data/app/models/spree/product_promotion_rule.rb +9 -0
  55. data/app/models/spree/product_property.rb +8 -10
  56. data/app/models/spree/promotion.rb +19 -19
  57. data/app/models/spree/promotion/rules/product.rb +3 -1
  58. data/app/models/spree/promotion/rules/taxon.rb +2 -1
  59. data/app/models/spree/promotion/rules/user.rb +4 -4
  60. data/app/models/spree/promotion_action.rb +3 -3
  61. data/app/models/spree/promotion_category.rb +1 -1
  62. data/app/models/spree/promotion_rule_taxon.rb +9 -0
  63. data/app/models/spree/promotion_rule_user.rb +9 -0
  64. data/app/models/spree/property.rb +2 -1
  65. data/app/models/spree/property_prototype.rb +9 -0
  66. data/app/models/spree/prototype.rb +8 -3
  67. data/app/models/spree/prototype_taxon.rb +9 -0
  68. data/app/models/spree/refund.rb +10 -7
  69. data/app/models/spree/refund_reason.rb +1 -1
  70. data/app/models/spree/reimbursement.rb +12 -16
  71. data/app/models/spree/reimbursement_type/reimbursement_helpers.rb +23 -6
  72. data/app/models/spree/reimbursement_type/store_credit.rb +28 -0
  73. data/app/models/spree/return_authorization.rb +8 -13
  74. data/app/models/spree/return_authorization_reason.rb +1 -1
  75. data/app/models/spree/return_item.rb +13 -12
  76. data/app/models/spree/return_item/eligibility_validator/time_since_purchase.rb +1 -1
  77. data/app/models/spree/role.rb +3 -2
  78. data/app/models/spree/role_user.rb +6 -0
  79. data/app/models/spree/shipment.rb +18 -23
  80. data/app/models/spree/shipment_handler.rb +2 -2
  81. data/app/models/spree/shipping_category.rb +6 -3
  82. data/app/models/spree/shipping_method.rb +11 -10
  83. data/app/models/spree/shipping_method_zone.rb +6 -0
  84. data/app/models/spree/shipping_rate.rb +16 -29
  85. data/app/models/spree/state.rb +3 -2
  86. data/app/models/spree/state_change.rb +1 -1
  87. data/app/models/spree/stock/content_item.rb +10 -12
  88. data/app/models/spree/stock/coordinator.rb +13 -14
  89. data/app/models/spree/stock/estimator.rb +28 -30
  90. data/app/models/spree/stock/inventory_unit_builder.rb +1 -9
  91. data/app/models/spree/stock/packer.rb +1 -1
  92. data/app/models/spree/stock/quantifier.rb +5 -5
  93. data/app/models/spree/stock/splitter/backordered.rb +2 -2
  94. data/app/models/spree/stock_item.rb +12 -18
  95. data/app/models/spree/stock_location.rb +4 -7
  96. data/app/models/spree/stock_movement.rb +11 -9
  97. data/app/models/spree/stock_transfer.rb +11 -12
  98. data/app/models/spree/store.rb +14 -6
  99. data/app/models/spree/store_credit.rb +252 -0
  100. data/app/models/spree/store_credit_category.rb +22 -0
  101. data/app/models/spree/store_credit_event.rb +38 -0
  102. data/app/models/spree/store_credit_type.rb +6 -0
  103. data/app/models/spree/tax_category.rb +3 -8
  104. data/app/models/spree/tax_rate.rb +56 -122
  105. data/app/models/spree/taxon.rb +11 -5
  106. data/app/models/spree/tracker.rb +12 -1
  107. data/app/models/spree/validations/db_maximum_length_validator.rb +2 -1
  108. data/app/models/spree/variant.rb +82 -50
  109. data/app/models/spree/zone.rb +21 -17
  110. data/app/models/spree/zone_member.rb +6 -0
  111. data/app/validators/db_maximum_length_validator.rb +11 -0
  112. data/app/views/layouts/spree/base_mailer.html.erb +38 -781
  113. data/app/views/spree/order_mailer/_adjustment.html.erb +8 -0
  114. data/app/views/spree/order_mailer/_subtotal.html.erb +8 -0
  115. data/app/views/spree/order_mailer/_total.html.erb +8 -0
  116. data/app/views/spree/order_mailer/cancel_email.html.erb +13 -28
  117. data/app/views/spree/order_mailer/cancel_email.text.erb +1 -1
  118. data/app/views/spree/order_mailer/confirm_email.html.erb +49 -63
  119. data/app/views/spree/order_mailer/confirm_email.text.erb +1 -1
  120. data/app/views/spree/shared/_base_mailer_header.html.erb +5 -7
  121. data/app/views/spree/shared/_base_mailer_stylesheets.html.erb +777 -0
  122. data/app/views/spree/shared/_error_messages.html.erb +1 -1
  123. data/app/views/spree/shared/_mailer_line_item.html.erb +12 -0
  124. data/app/views/spree/shipment_mailer/shipped_email.html.erb +21 -14
  125. data/app/views/spree/shipment_mailer/shipped_email.text.erb +3 -3
  126. data/config/initializers/user_class_extensions.rb +7 -38
  127. data/config/locales/en.yml +113 -13
  128. data/config/routes.rb +7 -0
  129. data/db/default/spree/default_reimbursement_type.rb +1 -1
  130. data/db/default/spree/zones.rb +4 -5
  131. data/db/migrate/20150118210639_create_spree_store_credits.rb +24 -0
  132. data/db/migrate/20150118211500_create_spree_store_credit_categories.rb +8 -0
  133. data/db/migrate/20150118212051_create_spree_store_credit_events.rb +17 -0
  134. data/db/migrate/20150118212101_create_spree_store_credit_types.rb +10 -0
  135. data/db/migrate/20150314013438_add_missing_indexes.rb +25 -0
  136. data/db/migrate/20150317174308_remove_duplicated_indexes_from_multi_columns.rb +18 -0
  137. data/db/migrate/20150324104002_remove_user_index_from_spree_state_changes.rb +14 -0
  138. data/db/migrate/20150522071831_add_position_to_spree_payment_methods.rb +5 -0
  139. data/db/migrate/20150626181949_add_taxable_adjustment_total_to_line_item.rb +19 -0
  140. data/db/migrate/20150627090949_migrate_payment_methods_display.rb +12 -0
  141. data/db/migrate/20150714154102_spree_payment_method_store_credits.rb +12 -0
  142. data/db/migrate/20150726141425_rename_has_and_belongs_to_associations_to_model_names.rb +18 -0
  143. data/db/migrate/20150727191614_spree_store_credit_types.rb +11 -0
  144. data/db/migrate/20150819154308_add_discontinued_to_products_and_variants.rb +68 -0
  145. data/db/migrate/20151220072838_remove_shipping_method_id_from_spree_orders.rb +13 -0
  146. data/db/migrate/20160207191757_add_id_column_to_earlier_habtm_tables.rb +16 -0
  147. data/db/migrate/20160219165458_add_indexes.rb +14 -0
  148. data/lib/generators/spree/dummy/templates/rails/database.yml +31 -24
  149. data/lib/generators/spree/dummy/templates/rails/test.rb +2 -1
  150. data/lib/spree/core.rb +16 -0
  151. data/lib/spree/core/controller_helpers/auth.rb +1 -1
  152. data/lib/spree/core/controller_helpers/common.rb +3 -3
  153. data/lib/spree/core/controller_helpers/order.rb +6 -5
  154. data/lib/spree/core/controller_helpers/search.rb +1 -1
  155. data/lib/spree/core/controller_helpers/store.rb +29 -0
  156. data/lib/spree/core/delegate_belongs_to.rb +2 -2
  157. data/lib/spree/core/engine.rb +30 -25
  158. data/lib/spree/core/environment.rb +1 -1
  159. data/lib/spree/core/importer/order.rb +37 -40
  160. data/lib/spree/core/number_generator.rb +52 -0
  161. data/lib/spree/core/product_filters.rb +1 -1
  162. data/lib/spree/core/search/base.rb +4 -3
  163. data/lib/spree/core/version.rb +1 -1
  164. data/lib/spree/localized_number.rb +3 -1
  165. data/lib/spree/permitted_attributes.rb +5 -2
  166. data/lib/spree/testing_support/common_rake.rb +3 -3
  167. data/lib/spree/testing_support/factories.rb +3 -3
  168. data/lib/spree/testing_support/factories/address_factory.rb +1 -1
  169. data/lib/spree/testing_support/factories/country_factory.rb +2 -2
  170. data/lib/spree/testing_support/factories/order_factory.rb +2 -2
  171. data/lib/spree/testing_support/factories/payment_factory.rb +5 -0
  172. data/lib/spree/testing_support/factories/payment_method_factory.rb +8 -0
  173. data/lib/spree/testing_support/factories/promotion_rule_factory.rb +5 -0
  174. data/lib/spree/testing_support/factories/refund_factory.rb +9 -1
  175. data/lib/spree/testing_support/factories/return_authorization_factory.rb +2 -0
  176. data/lib/spree/testing_support/factories/state_factory.rb +2 -2
  177. data/lib/spree/testing_support/factories/store_credit_category_factory.rb +9 -0
  178. data/lib/spree/testing_support/factories/store_credit_event_factory.rb +8 -0
  179. data/lib/spree/testing_support/factories/store_credit_factory.rb +17 -0
  180. data/lib/spree/testing_support/factories/store_credit_type_factory.rb +11 -0
  181. data/lib/spree/testing_support/factories/user_factory.rb +1 -1
  182. data/lib/spree/testing_support/factories/zone_member_factory.rb +6 -0
  183. data/lib/spree/testing_support/microdata.rb +189 -0
  184. data/lib/tasks/core.rake +68 -0
  185. data/lib/tasks/exchanges.rake +2 -2
  186. data/spec/fixtures/microdata.html +22 -0
  187. data/spec/fixtures/microdata_itemref.html +15 -0
  188. data/spec/fixtures/microdata_no_itemscope.html +20 -0
  189. data/spec/helpers/base_helper_spec.rb +64 -1
  190. data/spec/helpers/products_helper_spec.rb +75 -3
  191. data/spec/lib/i18n_spec.rb +2 -2
  192. data/spec/lib/search/base_spec.rb +2 -2
  193. data/spec/lib/spree/core/controller_helpers/auth_spec.rb +4 -2
  194. data/spec/lib/spree/core/controller_helpers/store_spec.rb +56 -0
  195. data/spec/lib/spree/core/importer/order_spec.rb +226 -123
  196. data/spec/lib/spree/core/number_generator_spec.rb +175 -0
  197. data/spec/lib/spree/core_spec.rb +23 -0
  198. data/spec/lib/spree/localized_number_spec.rb +10 -0
  199. data/spec/mailers/order_mailer_spec.rb +11 -13
  200. data/spec/mailers/shipment_mailer_spec.rb +26 -8
  201. data/spec/mailers/test_mailer_spec.rb +15 -1
  202. data/spec/models/option_type_prototype_spec.rb +9 -0
  203. data/spec/models/spree/ability_spec.rb +6 -13
  204. data/spec/models/spree/address_spec.rb +1 -1
  205. data/spec/models/spree/adjustable/adjuster/base_spec.rb +10 -0
  206. data/spec/models/spree/adjustable/adjuster/promotion_spec.rb +211 -0
  207. data/spec/models/spree/adjustable/adjuster/tax_spec.rb +86 -0
  208. data/spec/models/spree/adjustable/adjustments_updater_spec.rb +2 -262
  209. data/spec/models/spree/adjustment_spec.rb +27 -1
  210. data/spec/models/spree/app_configuration_spec.rb +5 -2
  211. data/spec/models/spree/calculator/default_tax_spec.rb +39 -14
  212. data/spec/models/spree/concerns/user_methods_spec.rb +55 -0
  213. data/spec/models/spree/concerns/vat_price_calculation_spec.rb +66 -0
  214. data/spec/models/spree/country_spec.rb +45 -8
  215. data/spec/models/spree/credit_card_spec.rb +8 -8
  216. data/spec/models/spree/customer_return_spec.rb +4 -26
  217. data/spec/models/spree/gateway_spec.rb +7 -0
  218. data/spec/models/spree/image_spec.rb +3 -0
  219. data/spec/models/spree/inventory_unit_spec.rb +1 -18
  220. data/spec/models/spree/line_item_spec.rb +78 -18
  221. data/spec/models/spree/option_type_spec.rb +2 -2
  222. data/spec/models/spree/option_value_spec.rb +8 -3
  223. data/spec/models/spree/order/checkout_spec.rb +49 -39
  224. data/spec/models/spree/order/currency_updater_spec.rb +3 -3
  225. data/spec/models/spree/order/finalizing_spec.rb +0 -3
  226. data/spec/models/spree/order/payment_spec.rb +1 -1
  227. data/spec/models/spree/order/state_machine_spec.rb +1 -6
  228. data/spec/models/spree/order/store_credit_spec.rb +423 -0
  229. data/spec/models/spree/order/updating_spec.rb +2 -2
  230. data/spec/models/spree/order_contents_spec.rb +42 -1
  231. data/spec/models/spree/order_inventory_spec.rb +27 -17
  232. data/spec/models/spree/order_spec.rb +65 -52
  233. data/spec/models/spree/payment/gateway_options_spec.rb +10 -2
  234. data/spec/models/spree/payment/store_credit_spec.rb +60 -0
  235. data/spec/models/spree/payment_method/store_credit_spec.rb +291 -0
  236. data/spec/models/spree/payment_method_spec.rb +22 -14
  237. data/spec/models/spree/payment_spec.rb +37 -44
  238. data/spec/models/spree/price_spec.rb +86 -0
  239. data/spec/models/spree/product/scopes_spec.rb +35 -0
  240. data/spec/models/spree/product_option_type_spec.rb +6 -2
  241. data/spec/models/spree/product_promotion_rule_spec.rb +9 -0
  242. data/spec/models/spree/product_property_spec.rb +11 -0
  243. data/spec/models/spree/product_spec.rb +82 -15
  244. data/spec/models/spree/promotion/actions/create_item_adjustments_spec.rb +1 -1
  245. data/spec/models/spree/promotion/rules/user_spec.rb +8 -0
  246. data/spec/models/spree/promotion_action_spec.rb +1 -1
  247. data/spec/models/spree/promotion_rule_spec.rb +1 -1
  248. data/spec/models/spree/promotion_rule_taxon_spec.rb +9 -0
  249. data/spec/models/spree/promotion_rule_user_spec.rb +9 -0
  250. data/spec/models/spree/promotion_spec.rb +57 -36
  251. data/spec/models/spree/property_prototype_spec.rb +9 -0
  252. data/spec/models/spree/prototype_taxon_spec.rb +9 -0
  253. data/spec/models/spree/refund_reason_spec.rb +7 -0
  254. data/spec/models/spree/reimbursement_spec.rb +3 -30
  255. data/spec/models/spree/reimbursement_tax_calculator_spec.rb +17 -5
  256. data/spec/models/spree/reimbursement_type/store_credit_spec.rb +101 -0
  257. data/spec/models/spree/return_authorization_reason_spec.rb +7 -0
  258. data/spec/models/spree/return_authorization_spec.rb +2 -22
  259. data/spec/models/spree/return_item_spec.rb +50 -1
  260. data/spec/models/spree/returns_calculator_spec.rb +1 -1
  261. data/spec/models/spree/role_spec.rb +7 -0
  262. data/spec/models/spree/shipment_spec.rb +17 -17
  263. data/spec/models/spree/shipping_calculator_spec.rb +2 -2
  264. data/spec/models/spree/shipping_category_spec.rb +14 -0
  265. data/spec/models/spree/shipping_method_spec.rb +9 -2
  266. data/spec/models/spree/shipping_rate_spec.rb +40 -41
  267. data/spec/models/spree/state_spec.rb +12 -1
  268. data/spec/models/spree/stock/content_item_spec.rb +9 -0
  269. data/spec/models/spree/stock/estimator_spec.rb +56 -8
  270. data/spec/models/spree/stock/quantifier_spec.rb +61 -32
  271. data/spec/models/spree/stock_item_spec.rb +19 -1
  272. data/spec/models/spree/store_credit_event_spec.rb +101 -0
  273. data/spec/models/spree/store_credit_spec.rb +786 -0
  274. data/spec/models/spree/store_spec.rb +39 -11
  275. data/spec/models/spree/tax_category_spec.rb +6 -1
  276. data/spec/models/spree/tax_rate_spec.rb +204 -44
  277. data/spec/models/spree/user_spec.rb +105 -38
  278. data/spec/models/spree/variant_spec.rb +281 -9
  279. data/spec/models/spree/zone_member_spec.rb +38 -0
  280. data/spec/models/spree/zone_spec.rb +32 -8
  281. data/spec/spec_helper.rb +3 -0
  282. data/spec/support/concerns/{adjustment_source_spec.rb → adjustment_source.rb} +0 -0
  283. data/spec/support/concerns/{default_price_spec.rb → default_price.rb} +9 -0
  284. data/spec/validators/db_maximum_length_validator_spec.rb +22 -0
  285. data/spree_core.gemspec +5 -6
  286. metadata +99 -36
  287. data/CHANGELOG.md +0 -4
  288. data/app/models/concerns/spree/number_generator.rb +0 -39
  289. data/spec/models/spree/validations/db_maximum_length_validator_spec.rb +0 -24
@@ -30,20 +30,48 @@ describe Spree::Store, :type => :model do
30
30
  end
31
31
  end
32
32
 
33
- describe ".default" do
34
- let!(:store) { create(:store) }
35
- let!(:store_2) { create(:store, default: true) }
33
+ describe '.default' do
34
+ context 'when a default store is already present' do
35
+ let!(:store) { create(:store) }
36
+ let!(:store_2) { create(:store, default: true) }
36
37
 
37
- it "should ensure there is a default if one doesn't exist yet" do
38
- expect(store_2.default).to be true
39
- end
38
+ it 'should return the already existing default store' do
39
+ expect(Spree::Store.default).to eq(store_2)
40
+ end
41
+
42
+ it "should ensure there is a default if one doesn't exist yet" do
43
+ expect(store_2.default).to be true
44
+ end
45
+
46
+ it 'should ensure there is only one default' do
47
+ [store, store_2].each(&:reload)
40
48
 
41
- it "should ensure there is only one default" do
42
- [store, store_2].each(&:reload)
49
+ expect(Spree::Store.where(default: true).count).to eq(1)
50
+ expect(store_2.default).to be true
51
+ expect(store.default).not_to be true
52
+ end
53
+
54
+ context 'when store is not saved' do
55
+ before do
56
+ store.default = true
57
+ store.code = nil
58
+ store.save
59
+ end
60
+
61
+ it 'ensure old default location still default' do
62
+ [store, store_2].each(&:reload)
63
+ expect(store.default).to be false
64
+ expect(store_2.default).to be true
65
+ end
66
+ end
67
+ end
43
68
 
44
- expect(Spree::Store.where(default: true).count).to eq(1)
45
- expect(store_2.default).to be true
46
- expect(store.default).not_to be true
69
+ context 'when a default store is not present' do
70
+ it 'should build a new default store' do
71
+ expect(Spree::Store.default.class).to eq(Spree::Store)
72
+ expect(Spree::Store.default.persisted?).to eq(false)
73
+ expect(Spree::Store.default.default).to be(true)
74
+ end
47
75
  end
48
76
  end
49
77
 
@@ -1,6 +1,11 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Spree::TaxCategory, :type => :model do
3
+ describe Spree::TaxCategory, type: :model do
4
+ describe 'Validations' do
5
+ it { is_expected.to validate_presence_of(:name) }
6
+ it { is_expected.to validate_uniqueness_of(:name).scoped_to(:deleted_at).case_insensitive.allow_blank }
7
+ end
8
+
4
9
  context 'default tax category' do
5
10
  let(:tax_category) { create(:tax_category) }
6
11
  let(:new_tax_category) { create(:tax_category) }
@@ -98,11 +98,8 @@ describe Spree::TaxRate, :type => :model do
98
98
  context "when the order has the same tax zone" do
99
99
  before do
100
100
  allow(order).to receive_messages :tax_zone => @zone
101
- allow(order).to receive_messages :tax_address => tax_address
102
101
  end
103
102
 
104
- let(:tax_address) { stub_model(Spree::Address) }
105
-
106
103
  context "when the tax is not a VAT" do
107
104
  it { is_expected.to eq([rate]) }
108
105
  end
@@ -116,41 +113,21 @@ describe Spree::TaxRate, :type => :model do
116
113
  context "when the order has a different tax zone" do
117
114
  before do
118
115
  allow(order).to receive_messages :tax_zone => create(:zone, :name => "Other Zone")
119
- allow(order).to receive_messages :tax_address => tax_address
120
116
  end
121
117
 
122
- context "when the order has a tax_address" do
123
- let(:tax_address) { stub_model(Spree::Address) }
124
-
125
- context "when the tax is a VAT" do
126
- let(:included_in_price) { true }
127
- # The rate should match in this instance because:
128
- # 1) It's the default rate (and as such, a negative adjustment should apply)
129
- it { is_expected.to eq([rate]) }
130
- end
131
-
132
- context "when the tax is not VAT" do
133
- it "returns no tax rate" do
134
- expect(subject).to be_empty
135
- end
118
+ context "when the tax is a VAT" do
119
+ let(:included_in_price) { true }
120
+ # The rate should NOT match in this instance because:
121
+ # The order has a different tax zone, and the price is
122
+ # henceforth a net price and will not change.
123
+ it 'return no tax rate' do
124
+ expect(subject).to be_empty
136
125
  end
137
126
  end
138
127
 
139
- context "when the order does not have a tax_address" do
140
- let(:tax_address) { nil}
141
-
142
- context "when the tax is a VAT" do
143
- let(:included_in_price) { true }
144
- # The rate should match in this instance because:
145
- # 1) The order has no tax address by this stage
146
- # 2) With no tax address, it has no tax zone
147
- # 3) Therefore, we assume the default tax zone
148
- # 4) This default zone has a default tax rate.
149
- it { is_expected.to eq([rate]) }
150
- end
151
-
152
- context "when the tax is not a VAT" do
153
- it { is_expected.to be_empty }
128
+ context "when the tax is not VAT" do
129
+ it "returns no tax rate" do
130
+ expect(subject).to be_empty
154
131
  end
155
132
  end
156
133
  end
@@ -158,7 +135,7 @@ describe Spree::TaxRate, :type => :model do
158
135
  end
159
136
  end
160
137
 
161
- context ".adjust" do
138
+ describe ".adjust" do
162
139
  let(:order) { stub_model(Spree::Order) }
163
140
  let(:tax_category_1) { stub_model(Spree::TaxCategory) }
164
141
  let(:tax_category_2) { stub_model(Spree::TaxCategory) }
@@ -201,9 +178,187 @@ describe Spree::TaxRate, :type => :model do
201
178
  Spree::TaxRate.adjust(order, shipments)
202
179
  end
203
180
  end
181
+
182
+ context "for MOSS taxation in Europe" do
183
+ let(:germany) { create :country, name: "Germany" }
184
+ let(:india) { create :country, name: "India" }
185
+ let(:france) { create :country, name: "France" }
186
+ let(:france_zone) { create :zone_with_country, name: "France Zone" }
187
+ let(:germany_zone) { create :zone_with_country, name: "Germany Zone", default_tax: true }
188
+ let(:india_zone) { create :zone_with_country, name: "India" }
189
+ let(:moss_category) { Spree::TaxCategory.create(name: "Digital Goods") }
190
+ let(:normal_category) { Spree::TaxCategory.create(name: "Analogue Goods") }
191
+ let(:eu_zone) { create(:zone, name: "EU") }
192
+
193
+ let!(:german_vat) do
194
+ Spree::TaxRate.create(
195
+ name: "German VAT",
196
+ amount: 0.19,
197
+ calculator: Spree::Calculator::DefaultTax.create,
198
+ tax_category: moss_category,
199
+ zone: germany_zone,
200
+ included_in_price: true
201
+ )
202
+ end
203
+ let!(:french_vat) do
204
+ Spree::TaxRate.create(
205
+ name: "French VAT",
206
+ amount: 0.25,
207
+ calculator: Spree::Calculator::DefaultTax.create,
208
+ tax_category: moss_category,
209
+ zone: france_zone,
210
+ included_in_price: true
211
+ )
212
+ end
213
+ let!(:eu_vat) do
214
+ Spree::TaxRate.create(
215
+ name: "EU_VAT",
216
+ amount: 0.19,
217
+ calculator: Spree::Calculator::DefaultTax.create,
218
+ tax_category: normal_category,
219
+ zone: eu_zone,
220
+ included_in_price: true
221
+ )
222
+ end
223
+
224
+ let(:download) { create(:product, tax_category: moss_category, price: 100) }
225
+ let(:tshirt) { create(:product, tax_category: normal_category, price: 100) }
226
+ let(:order) { Spree::Order.create }
227
+
228
+ before do
229
+ germany_zone.zone_members.create(zoneable: germany)
230
+ france_zone.zone_members.create(zoneable: france)
231
+ india_zone.zone_members.create(zoneable: india)
232
+ eu_zone.zone_members.create(zoneable: germany)
233
+ eu_zone.zone_members.create(zoneable: france)
234
+ end
235
+
236
+ context "a download" do
237
+ before do
238
+ order.contents.add(download.master, 1)
239
+ end
240
+
241
+ it "without an adress costs 100 euros including tax" do
242
+ Spree::TaxRate.adjust(order, order.line_items)
243
+ order.update_with_updater!
244
+ expect(order.display_total).to eq(Spree::Money.new(100))
245
+ expect(order.included_tax_total).to eq(15.97)
246
+ end
247
+
248
+ it "to germany costs 100 euros including tax" do
249
+ allow(order).to receive(:tax_zone).and_return(germany_zone)
250
+ Spree::TaxRate.adjust(order, order.line_items)
251
+ order.update_with_updater!
252
+ expect(order.display_total).to eq(Spree::Money.new(100))
253
+ expect(order.included_tax_total).to eq(15.97)
254
+ end
255
+
256
+ it "to france costs more including tax" do
257
+ allow(order).to receive(:tax_zone).and_return(france_zone)
258
+ order.update_line_item_prices!
259
+ Spree::TaxRate.adjust(order, order.line_items)
260
+ order.update_with_updater!
261
+ expect(order.display_total).to eq(Spree::Money.new(105.04))
262
+ expect(order.included_tax_total).to eq(21.01)
263
+ expect(order.additional_tax_total).to eq(0)
264
+ end
265
+
266
+ it "to somewhere else costs the net amount" do
267
+ allow(order).to receive(:tax_zone).and_return(india_zone)
268
+ order.update_line_item_prices!
269
+ Spree::TaxRate.adjust(order, order.line_items)
270
+ order.update_with_updater!
271
+ expect(order.included_tax_total).to eq(0)
272
+ expect(order.included_tax_total).to eq(0)
273
+ expect(order.display_total).to eq(Spree::Money.new(84.03))
274
+ end
275
+ end
276
+
277
+ context "a t-shirt" do
278
+ before do
279
+ order.contents.add(tshirt.master, 1)
280
+ end
281
+
282
+ it "to germany costs 100 euros including tax" do
283
+ allow(order).to receive(:tax_zone).and_return(germany_zone)
284
+ Spree::TaxRate.adjust(order, order.line_items)
285
+ order.update_with_updater!
286
+ expect(order.display_total).to eq(Spree::Money.new(100))
287
+ expect(order.included_tax_total).to eq(15.97)
288
+ end
289
+
290
+ it "to france costs 100 euros including tax" do
291
+ allow(order).to receive(:tax_zone).and_return(france_zone)
292
+ order.update_line_item_prices!
293
+ Spree::TaxRate.adjust(order, order.line_items)
294
+ order.update_with_updater!
295
+ expect(order.display_total).to eq(Spree::Money.new(100.00))
296
+ expect(order.included_tax_total).to eq(15.97)
297
+ expect(order.additional_tax_total).to eq(0)
298
+ end
299
+
300
+ it "to somewhere else costs the net amount" do
301
+ allow(order).to receive(:tax_zone).and_return(india_zone)
302
+ order.update_line_item_prices!
303
+ Spree::TaxRate.adjust(order, order.line_items)
304
+ order.update_with_updater!
305
+ expect(order.included_tax_total).to eq(0)
306
+ expect(order.display_total).to eq(Spree::Money.new(84.03))
307
+ end
308
+ end
309
+ end
204
310
  end
205
311
 
206
- context "#adjust" do
312
+ describe ".included_tax_amount_for" do
313
+ let!(:order) { create :order_with_line_items }
314
+ let!(:included_tax_rate) do
315
+ create :tax_rate,
316
+ included_in_price: true,
317
+ tax_category: order.line_items.first.tax_category,
318
+ zone: order.tax_zone,
319
+ amount: 0.4
320
+ end
321
+
322
+ let!(:other_included_tax_rate) do
323
+ create :tax_rate,
324
+ included_in_price: true,
325
+ tax_category: order.line_items.first.tax_category,
326
+ zone: order.tax_zone,
327
+ amount: 0.05
328
+ end
329
+
330
+ let!(:additional_tax_rate) do
331
+ create :tax_rate,
332
+ included_in_price: false,
333
+ tax_category: order.line_items.first.tax_category,
334
+ zone: order.tax_zone,
335
+ amount: 0.2
336
+ end
337
+
338
+ let!(:included_tax_rate_from_somewhere_else) do
339
+ create :tax_rate,
340
+ included_in_price: true,
341
+ tax_category: order.line_items.first.tax_category,
342
+ zone: create(:zone_with_country),
343
+ amount: 0.1
344
+ end
345
+ let(:price_options) do
346
+ {
347
+ tax_zone: order.tax_zone,
348
+ tax_category: line_item.tax_category
349
+ }
350
+ end
351
+
352
+
353
+ let(:line_item) { order.line_items.first }
354
+ subject(:included_tax_amount) { Spree::TaxRate.included_tax_amount_for(price_options) }
355
+
356
+ it 'will only get me tax amounts from tax_rates that match' do
357
+ expect(subject).to eq(included_tax_rate.amount + other_included_tax_rate.amount)
358
+ end
359
+ end
360
+
361
+ describe "#adjust" do
207
362
  before do
208
363
  @country = create(:country)
209
364
  @zone = create(:zone, :name => "Country Zone", :default_tax => true, :zone_members => [])
@@ -254,7 +409,7 @@ describe Spree::TaxRate, :type => :model do
254
409
  context "when zone is contained by default tax zone" do
255
410
  it "should create two adjustments, one for each tax rate" do
256
411
  Spree::TaxRate.adjust(@order, @order.line_items)
257
- expect(line_item.adjustments.count).to eq(1)
412
+ expect(line_item.adjustments.count).to eq(2)
258
413
  end
259
414
 
260
415
  it "should not create a tax refund" do
@@ -265,11 +420,16 @@ describe Spree::TaxRate, :type => :model do
265
420
 
266
421
  context "when order's zone is neither the default zone, or included in the default zone, but matches the rate's zone" do
267
422
  before do
268
- # With no zone members, this zone will not contain anything
269
- # Previously:
270
- # Zone.stub_chain :default_tax, :contains? => false
271
- @zone.zone_members.delete_all
423
+ new_rate = Spree::TaxRate.create(
424
+ amount: 0.2,
425
+ included_in_price: true,
426
+ calculator: Spree::Calculator::DefaultTax.create,
427
+ tax_category: @category,
428
+ zone: create(:zone_with_country)
429
+ )
430
+ allow(@order).to receive(:tax_zone).and_return(new_rate.zone)
272
431
  end
432
+
273
433
  it "should create an adjustment" do
274
434
  Spree::TaxRate.adjust(@order, @order.line_items)
275
435
  expect(line_item.adjustments.charge.count).to eq(1)
@@ -296,9 +456,9 @@ describe Spree::TaxRate, :type => :model do
296
456
  expect(line_item.adjustments.charge.count).to eq(0)
297
457
  end
298
458
 
299
- it "should create a tax refund for each tax rate" do
459
+ it "should not create a tax refund for each tax rate" do
300
460
  Spree::TaxRate.adjust(@order, @order.line_items)
301
- expect(line_item.adjustments.credit.count).to eq(1)
461
+ expect(line_item.adjustments.credit.count).to eq(0)
302
462
  end
303
463
  end
304
464
 
@@ -320,7 +480,7 @@ describe Spree::TaxRate, :type => :model do
320
480
  end
321
481
 
322
482
  it "should not delete adjustments for complete order when taxrate is deleted" do
323
- @order.update_column :completed_at, Time.now
483
+ @order.update_column :completed_at, Time.current
324
484
  @rate1.destroy!
325
485
  @rate2.destroy!
326
486
  expect(line_item.adjustments.count).to eq(2)
@@ -373,7 +533,7 @@ describe Spree::TaxRate, :type => :model do
373
533
 
374
534
  it "price adjustments should be accurate" do
375
535
  included_tax = @order.line_item_adjustments.sum(:amount)
376
- expect(@price_before_taxes + included_tax).to eq(line_item.price)
536
+ expect(@price_before_taxes + included_tax).to eq(line_item.total)
377
537
  end
378
538
  end
379
539
  end
@@ -1,40 +1,40 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Spree::LegacyUser, :type => :model do
3
+ describe Spree::LegacyUser, type: :model do
4
4
  # Regression test for #2844 + #3346
5
- context "#last_incomplete_order" do
5
+ context '#last_incomplete_order' do
6
6
  let!(:user) { create(:user) }
7
7
  let!(:order) { create(:order, bill_address: create(:address), ship_address: create(:address)) }
8
8
 
9
- let!(:order_1) { create(:order, :created_at => 1.day.ago, :user => user, :created_by => user) }
10
- let!(:order_2) { create(:order, :user => user, :created_by => user) }
11
- let!(:order_3) { create(:order, :user => user, :created_by => create(:user)) }
9
+ let!(:order_1) { create(:order, created_at: 1.day.ago, user: user, created_by: user) }
10
+ let!(:order_2) { create(:order, user: user, created_by: user) }
11
+ let!(:order_3) { create(:order, user: user, created_by: create(:user)) }
12
12
 
13
- it "returns correct order" do
13
+ it 'returns correct order' do
14
14
  expect(user.last_incomplete_spree_order).to eq order_3
15
15
  end
16
16
 
17
- context "persists order address" do
18
- it "copies over order addresses" do
19
- expect {
17
+ context 'persists order address' do
18
+ it 'copies over order addresses' do
19
+ expect do
20
20
  user.persist_order_address(order)
21
- }.to change { Spree::Address.count }.by(2)
21
+ end.to change { Spree::Address.count }.by(2)
22
22
 
23
23
  expect(user.bill_address).to eq order.bill_address
24
24
  expect(user.ship_address).to eq order.ship_address
25
25
  end
26
26
 
27
- it "doesnt create new addresses if user has already" do
27
+ it 'doesnt create new addresses if user has already' do
28
28
  user.update_column(:bill_address_id, create(:address))
29
29
  user.update_column(:ship_address_id, create(:address))
30
30
  user.reload
31
31
 
32
- expect {
32
+ expect do
33
33
  user.persist_order_address(order)
34
- }.not_to change { Spree::Address.count }
34
+ end.not_to change { Spree::Address.count }
35
35
  end
36
36
 
37
- it "set both bill and ship address id on subject" do
37
+ it 'set both bill and ship address id on subject' do
38
38
  user.persist_order_address(order)
39
39
 
40
40
  expect(user.bill_address_id).not_to be_blank
@@ -42,17 +42,17 @@ describe Spree::LegacyUser, :type => :model do
42
42
  end
43
43
  end
44
44
 
45
- context "payment source" do
45
+ context 'payment source' do
46
46
  let(:payment_method) { create(:credit_card_payment_method) }
47
47
  let!(:cc) do
48
48
  create(:credit_card, user_id: user.id, payment_method: payment_method, gateway_customer_profile_id: "2342343")
49
49
  end
50
50
 
51
- it "has payment sources" do
51
+ it 'has payment sources' do
52
52
  expect(user.payment_sources.first.gateway_customer_profile_id).not_to be_empty
53
53
  end
54
54
 
55
- it "drops payment source" do
55
+ it 'drops payment source' do
56
56
  user.drop_payment_source cc
57
57
  expect(cc.gateway_customer_profile_id).to be_nil
58
58
  end
@@ -60,14 +60,14 @@ describe Spree::LegacyUser, :type => :model do
60
60
  end
61
61
  end
62
62
 
63
- describe Spree.user_class, :type => :model do
64
- context "reporting" do
65
- let(:order_value) { BigDecimal.new("80.94") }
63
+ describe Spree.user_class, type: :model do
64
+ context 'reporting' do
65
+ let(:order_value) { BigDecimal.new('80.94') }
66
66
  let(:order_count) { 4 }
67
67
  let(:orders) { Array.new(order_count, double(total: order_value)) }
68
68
 
69
69
  before do
70
- allow(orders).to receive(:pluck).with(:total).and_return(orders.map(&:total))
70
+ allow(orders).to receive(:sum).with(:total).and_return(orders.sum(&:total))
71
71
  allow(orders).to receive(:count).and_return(orders.length)
72
72
  end
73
73
 
@@ -75,56 +75,123 @@ describe Spree.user_class, :type => :model do
75
75
  allow(subject).to receive(:orders).and_return(double(complete: orders))
76
76
  end
77
77
 
78
- describe "#lifetime_value" do
79
- context "with orders" do
78
+ describe '#lifetime_value' do
79
+ context 'with orders' do
80
80
  before { load_orders }
81
81
  it "returns the total of completed orders for the user" do
82
82
  expect(subject.lifetime_value).to eq (order_count * order_value)
83
83
  end
84
84
  end
85
- context "without orders" do
86
- it "returns 0.00" do
85
+ context 'without orders' do
86
+ it 'returns 0.00' do
87
87
  expect(subject.lifetime_value).to eq BigDecimal("0.00")
88
88
  end
89
89
  end
90
90
  end
91
91
 
92
- describe "#display_lifetime_value" do
93
- it "returns a Spree::Money version of lifetime_value" do
94
- value = BigDecimal("500.05")
92
+ describe '#display_lifetime_value' do
93
+ it 'returns a Spree::Money version of lifetime_value' do
94
+ value = BigDecimal('500.05')
95
95
  allow(subject).to receive(:lifetime_value).and_return(value)
96
96
  expect(subject.display_lifetime_value).to eq Spree::Money.new(value)
97
97
  end
98
98
  end
99
99
 
100
- describe "#order_count" do
100
+ describe '#order_count' do
101
101
  before { load_orders }
102
- it "returns the count of completed orders for the user" do
102
+ it 'returns the count of completed orders for the user' do
103
103
  expect(subject.order_count).to eq BigDecimal(order_count)
104
104
  end
105
105
  end
106
106
 
107
- describe "#average_order_value" do
108
- context "with orders" do
107
+ describe '#average_order_value' do
108
+ context 'with orders' do
109
109
  before { load_orders }
110
- it "returns the average completed order price for the user" do
110
+ it 'returns the average completed order price for the user' do
111
111
  expect(subject.average_order_value).to eq order_value
112
112
  end
113
113
  end
114
- context "without orders" do
115
- it "returns 0.00" do
116
- expect(subject.average_order_value).to eq BigDecimal("0.00")
114
+ context 'without orders' do
115
+ it 'returns 0.00' do
116
+ expect(subject.average_order_value).to eq BigDecimal('0.00')
117
117
  end
118
118
  end
119
119
  end
120
120
 
121
121
  describe "#display_average_order_value" do
122
122
  before { load_orders }
123
- it "returns a Spree::Money version of average_order_value" do
124
- value = BigDecimal("500.05")
123
+ it 'returns a Spree::Money version of average_order_value' do
124
+ value = BigDecimal('500.05')
125
125
  allow(subject).to receive(:average_order_value).and_return(value)
126
126
  expect(subject.display_average_order_value).to eq Spree::Money.new(value)
127
127
  end
128
128
  end
129
129
  end
130
+
131
+ describe '#total_available_store_credit' do
132
+ context 'user does not have any associated store credits' do
133
+ subject { create(:user) }
134
+
135
+ it 'returns 0' do
136
+ expect(subject.total_available_store_credit).to be_zero
137
+ end
138
+ end
139
+
140
+ context 'user has several associated store credits' do
141
+ let(:user) { create(:user) }
142
+ let(:amount) { 120.25 }
143
+ let(:additional_amount) { 55.75 }
144
+ let(:store_credit) { create(:store_credit, user: user, amount: amount, amount_used: 0.0) }
145
+ let!(:additional_store_credit) { create(:store_credit, user: user, amount: additional_amount, amount_used: 0.0) }
146
+
147
+ subject { store_credit.user }
148
+
149
+ context 'part of the store credit has been used' do
150
+ let(:amount_used) { 35.00 }
151
+
152
+ before { store_credit.update_attributes(amount_used: amount_used) }
153
+
154
+ context 'part of the store credit has been authorized' do
155
+ let(:authorized_amount) { 10 }
156
+
157
+ before { additional_store_credit.update_attributes(amount_authorized: authorized_amount) }
158
+
159
+ it 'returns sum of amounts minus used amount and authorized amount' do
160
+ available_store_credit = amount + additional_amount - amount_used - authorized_amount
161
+ expect(subject.total_available_store_credit.to_f).to eq available_store_credit
162
+ end
163
+ end
164
+
165
+ context 'there are no authorized amounts on any of the store credits' do
166
+ it 'returns sum of amounts minus used amount' do
167
+ expect(subject.total_available_store_credit.to_f).to eq (amount + additional_amount - amount_used)
168
+ end
169
+ end
170
+ end
171
+
172
+ context 'store credits have never been used' do
173
+ context 'part of the store credit has been authorized' do
174
+ let(:authorized_amount) { 10 }
175
+
176
+ before { additional_store_credit.update_attributes(amount_authorized: authorized_amount) }
177
+
178
+ it 'returns sum of amounts minus authorized amount' do
179
+ expect(subject.total_available_store_credit.to_f).to eq (amount + additional_amount - authorized_amount)
180
+ end
181
+ end
182
+
183
+ context 'there are no authorized amounts on any of the store credits' do
184
+ it 'returns sum of amounts' do
185
+ expect(subject.total_available_store_credit.to_f).to eq (amount + additional_amount)
186
+ end
187
+ end
188
+ end
189
+
190
+ context 'all store credits have never been used or authorized' do
191
+ it 'returns sum of amounts' do
192
+ expect(subject.total_available_store_credit.to_f).to eq (amount + additional_amount)
193
+ end
194
+ end
195
+ end
196
+ end
130
197
  end