solidus_core 2.1.1 → 2.2.0.beta1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of solidus_core might be problematic. Click here for more details.

Files changed (145) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +0 -1
  3. data/app/assets/config/solidus_core_manifest.js +1 -0
  4. data/app/assets/javascripts/spree.js.erb +72 -0
  5. data/app/helpers/spree/store_helper.rb +5 -0
  6. data/app/jobs/spree/promotion_code_batch_job.rb +24 -0
  7. data/app/mailers/spree/promotion_code_batch_mailer.rb +13 -0
  8. data/app/models/concerns/spree/calculated_adjustments.rb +1 -1
  9. data/app/models/concerns/spree/ordered_property_value_list.rb +2 -2
  10. data/app/models/concerns/spree/user_address_book.rb +4 -4
  11. data/app/models/concerns/spree/user_methods.rb +7 -0
  12. data/app/models/concerns/spree/user_payment_source.rb +12 -5
  13. data/app/models/spree/address.rb +14 -3
  14. data/app/models/spree/adjustment.rb +13 -1
  15. data/app/models/spree/app_configuration.rb +0 -19
  16. data/app/models/spree/base.rb +2 -0
  17. data/app/models/spree/credit_card.rb +34 -43
  18. data/app/models/spree/gateway/bogus.rb +1 -1
  19. data/app/models/spree/gateway.rb +6 -4
  20. data/app/models/spree/inventory_unit.rb +3 -2
  21. data/app/models/spree/order/checkout.rb +187 -273
  22. data/app/models/spree/order.rb +137 -71
  23. data/app/models/spree/order_contents.rb +1 -1
  24. data/app/models/spree/order_inventory.rb +11 -11
  25. data/app/models/spree/order_promotion.rb +2 -0
  26. data/app/models/spree/order_update_attributes.rb +1 -8
  27. data/app/models/spree/order_updater.rb +67 -63
  28. data/app/models/spree/payment.rb +0 -1
  29. data/app/models/spree/payment_create.rb +27 -7
  30. data/app/models/spree/payment_method/store_credit.rb +3 -3
  31. data/app/models/spree/payment_method.rb +4 -1
  32. data/app/models/spree/payment_source.rb +45 -0
  33. data/app/models/spree/product/scopes.rb +24 -24
  34. data/app/models/spree/product.rb +4 -4
  35. data/app/models/spree/promotion.rb +2 -0
  36. data/app/models/spree/promotion_code/batch_builder.rb +63 -0
  37. data/app/models/spree/promotion_code.rb +1 -0
  38. data/app/models/spree/promotion_code_batch.rb +25 -0
  39. data/app/models/spree/promotion_handler/cart.rb +2 -2
  40. data/app/models/spree/promotion_handler/coupon.rb +1 -2
  41. data/app/models/spree/promotion_handler/free_shipping.rb +32 -21
  42. data/app/models/spree/promotion_handler/page.rb +1 -1
  43. data/app/models/spree/reimbursement.rb +1 -1
  44. data/app/models/spree/return_authorization.rb +0 -28
  45. data/app/models/spree/return_item.rb +1 -1
  46. data/app/models/spree/shipment.rb +4 -4
  47. data/app/models/spree/shipping_method.rb +2 -2
  48. data/app/models/spree/shipping_rate.rb +1 -1
  49. data/app/models/spree/stock/availability_validator.rb +16 -17
  50. data/app/models/spree/stock/coordinator.rb +3 -3
  51. data/app/models/spree/stock/package.rb +1 -1
  52. data/app/models/spree/stock/quantifier.rb +5 -4
  53. data/app/models/spree/stock_location.rb +2 -2
  54. data/app/models/spree/store.rb +2 -2
  55. data/app/models/spree/store_credit.rb +1 -1
  56. data/app/models/spree/tax/tax_helpers.rb +3 -3
  57. data/app/models/spree/tax_rate.rb +7 -1
  58. data/app/models/spree/taxonomy.rb +1 -1
  59. data/app/models/spree/variant/scopes.rb +5 -5
  60. data/app/models/spree/variant/vat_price_generator.rb +8 -5
  61. data/app/models/spree/variant.rb +1 -0
  62. data/app/models/spree/wallet/add_payment_sources_to_wallet.rb +19 -10
  63. data/app/models/spree/wallet/default_payment_builder.rb +6 -6
  64. data/app/models/spree/wallet.rb +71 -0
  65. data/app/models/spree/wallet_payment_source.rb +17 -0
  66. data/app/models/spree/zone.rb +1 -1
  67. data/app/views/spree/carton_mailer/shipped_email.text.erb +1 -1
  68. data/app/views/spree/promotion_code_batch_mailer/promotion_code_batch_errored.text.erb +2 -0
  69. data/app/views/spree/promotion_code_batch_mailer/promotion_code_batch_finished.text.erb +2 -0
  70. data/app/views/spree/reimbursement_mailer/reimbursement_email.html.erb +0 -7
  71. data/app/views/spree/reimbursement_mailer/reimbursement_email.text.erb +0 -5
  72. data/app/views/spree/shared/_error_messages.html.erb +1 -1
  73. data/app/views/spree/shipment_mailer/shipped_email.html.erb +1 -1
  74. data/config/initializers/assets.rb +1 -1
  75. data/config/initializers/friendly_id.rb +1 -1
  76. data/config/locales/en.yml +50 -12
  77. data/db/default/spree/store_credit.rb +2 -1
  78. data/db/migrate/20130826062534_add_depth_to_spree_taxons.rb +4 -6
  79. data/db/migrate/20160420044191_create_spree_wallet_payment_sources.rb +23 -0
  80. data/db/migrate/20160420181916_migrate_credit_cards_to_wallet_payment_sources.rb +26 -0
  81. data/db/migrate/20161017102621_create_spree_promotion_code_batch.rb +36 -0
  82. data/db/migrate/20161129035810_add_index_to_spree_payments_number.rb +5 -0
  83. data/db/migrate/20170223235001_remove_spree_store_credits_column.rb +5 -0
  84. data/lib/generators/spree/dummy/templates/rails/application.rb +1 -1
  85. data/lib/generators/spree/dummy/templates/rails/test.rb +1 -1
  86. data/lib/generators/spree/install/install_generator.rb +6 -5
  87. data/lib/spree/core/controller_helpers/payment_parameters.rb +54 -0
  88. data/lib/spree/core/engine.rb +6 -9
  89. data/lib/spree/core/version.rb +1 -1
  90. data/lib/spree/core.rb +0 -1
  91. data/lib/spree/money.rb +18 -0
  92. data/lib/spree/permission_sets/default_customer.rb +1 -1
  93. data/lib/spree/permitted_attributes.rb +1 -1
  94. data/lib/spree/testing_support/authorization_helpers.rb +1 -0
  95. data/lib/spree/testing_support/capybara_ext.rb +13 -0
  96. data/lib/spree/testing_support/factories/order_factory.rb +5 -1
  97. data/lib/spree/testing_support/factories/payment_factory.rb +1 -1
  98. data/lib/spree/testing_support/factories/shipment_factory.rb +0 -1
  99. data/solidus_core.gemspec +3 -3
  100. data/spec/jobs/promotion_code_batch_job_spec.rb +65 -0
  101. data/spec/lib/calculated_adjustments_spec.rb +105 -1
  102. data/spec/lib/spree/core/testing_support/factories/order_factory_spec.rb +4 -1
  103. data/spec/lib/spree/core/testing_support/factories/payment_factory_spec.rb +8 -0
  104. data/spec/lib/spree/money_spec.rb +32 -0
  105. data/spec/lib/spree/permission_sets/default_customer_spec.rb +20 -0
  106. data/spec/mailers/promotion_code_batch_mailer_spec.rb +45 -0
  107. data/spec/models/spree/credit_card_spec.rb +86 -86
  108. data/spec/models/spree/gateway_spec.rb +3 -1
  109. data/spec/models/spree/inventory_unit_spec.rb +12 -4
  110. data/spec/models/spree/order/checkout_spec.rb +11 -32
  111. data/spec/models/spree/order/tax_spec.rb +2 -2
  112. data/spec/models/spree/order_contents_spec.rb +24 -1
  113. data/spec/models/spree/order_inventory_spec.rb +130 -83
  114. data/spec/models/spree/order_spec.rb +15 -117
  115. data/spec/models/spree/order_update_attributes_spec.rb +1 -44
  116. data/spec/models/spree/order_updater_spec.rb +10 -13
  117. data/spec/models/spree/payment_create_spec.rb +5 -1
  118. data/spec/models/spree/payment_method_spec.rb +16 -0
  119. data/spec/models/spree/payment_spec.rb +14 -8
  120. data/spec/models/spree/promotion_code/batch_builder_spec.rb +61 -0
  121. data/spec/models/spree/promotion_code_batch_spec.rb +58 -0
  122. data/spec/models/spree/promotion_code_spec.rb +4 -0
  123. data/spec/models/spree/promotion_spec.rb +3 -6
  124. data/spec/models/spree/return_authorization_spec.rb +0 -59
  125. data/spec/models/spree/shipment_spec.rb +4 -4
  126. data/spec/models/spree/stock/availability_validator_spec.rb +64 -9
  127. data/spec/models/spree/tax/item_adjuster_spec.rb +1 -2
  128. data/spec/models/spree/unit_cancel_spec.rb +0 -85
  129. data/spec/models/spree/user_spec.rb +3 -1
  130. data/spec/models/spree/variant/vat_price_generator_spec.rb +8 -2
  131. data/spec/models/spree/variant_spec.rb +16 -4
  132. data/spec/models/spree/wallet_payment_source_spec.rb +46 -0
  133. data/spec/models/spree/wallet_spec.rb +128 -0
  134. data/spec/support/concerns/payment_source.rb +64 -0
  135. metadata +51 -25
  136. data/app/assets/javascripts/spree.js.coffee.erb +0 -64
  137. data/app/models/spree/promotion_builder.rb +0 -55
  138. data/app/models/spree/promotion_code/code_builder.rb +0 -62
  139. data/config/initializers/premailer_assets.rb +0 -1
  140. data/lib/spree/core/unreturned_item_charger.rb +0 -106
  141. data/lib/tasks/exchanges.rake +0 -47
  142. data/spec/lib/spree/core/unreturned_item_charger_spec.rb +0 -126
  143. data/spec/lib/tasks/exchanges_spec.rb +0 -220
  144. data/spec/models/spree/promotion_builder_spec.rb +0 -120
  145. data/spec/models/spree/promotion_code/code_builder_spec.rb +0 -77
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3c934b38bc5fe5c396b4c0eff48366ee4d0191b7
4
- data.tar.gz: 909b4d8df7e9fae8bc877f2ea3ba94e9e4678cc1
3
+ metadata.gz: d5635c0bec12576a350d683b4140c8daa51e160a
4
+ data.tar.gz: 1163f3a0a622892863ba88006da9c321de52222f
5
5
  SHA512:
6
- metadata.gz: 663ef73baabdcb94f31638b3a84913f10b853748de77376c1018b9f026f703fdf8f3d2c78cc69bd6edb4997e3c506f2aff348fbbd7d7a03442863147c054a056
7
- data.tar.gz: dcfa1557ad792104c88a4f9eea1648711888417f8169594da523534d64e230caefbc86a759161ab5525e0b55c45fa123da14a6910a88b8bd6300593d7bacb934
6
+ metadata.gz: c7d0c449fce5ebc575ea2c176f0e7577158e3ee09184ff95828abe5a03704bf8f3821b98077c83bba86c9690ceac16bc7e256f1eae96ae76ecf3de78bcf7f162
7
+ data.tar.gz: 6ffdb536d3e89da7f98e03a662a681742f053db49b4ec6b24dc023524763da40d5648b71bc6cd9564170f367ee1a6d067330ab633a7f1f3c689b95f017b07dbb
data/Rakefile CHANGED
@@ -3,7 +3,6 @@ require 'rake'
3
3
  require 'rake/testtask'
4
4
  require 'rspec/core/rake_task'
5
5
  require 'spree/testing_support/common_rake'
6
- load 'lib/tasks/exchanges.rake'
7
6
 
8
7
  RSpec::Core::RakeTask.new
9
8
 
@@ -0,0 +1 @@
1
+ //= link_tree ../images
@@ -0,0 +1,72 @@
1
+ //= require jsuri
2
+
3
+ window.Spree = {};
4
+
5
+ Spree.ready = function(callback) {
6
+ if (typeof Turbolinks !== 'undefined' && Turbolinks.supported) {
7
+ jQuery(document).on('turbolinks:load', function() {
8
+ callback(jQuery);
9
+ });
10
+ } else {
11
+ jQuery(document).ready(callback);
12
+ }
13
+ };
14
+
15
+ Spree.mountedAt = function() {
16
+ return "<%= Rails.application.routes.url_helpers.spree_path(trailing_slash: true) %>";
17
+ };
18
+
19
+ Spree.pathFor = function(path) {
20
+ var locationOrigin;
21
+ locationOrigin = (window.location.protocol + "//" + window.location.hostname) + (window.location.port ? ":" + window.location.port : "");
22
+ return locationOrigin + Spree.mountedAt() + path;
23
+ };
24
+
25
+ Spree.url = function(uri, query) {
26
+ if (Spree.env === 'development' || Spree.env === 'test') {
27
+ console.warn('Spree.url is deprecated, please use Spree.ajax for your request instead.');
28
+ }
29
+ if (uri.path === undefined) {
30
+ uri = new Uri(uri);
31
+ }
32
+ if (query) {
33
+ $.each(query, function(key, value) {
34
+ return uri.addQueryParam(key, value);
35
+ });
36
+ }
37
+ return uri;
38
+ };
39
+
40
+ Spree.ajax = function(url, options) {
41
+ if (typeof url === "object") {
42
+ options = url;
43
+ url = undefined;
44
+ }
45
+ options = options || {};
46
+ options = $.extend(options, {
47
+ headers: {
48
+ "X-Spree-Token": Spree.api_key
49
+ }
50
+ });
51
+ return $.ajax(url, options);
52
+ };
53
+
54
+ Spree.routes = {
55
+ states_search: Spree.pathFor('api/states'),
56
+ apply_coupon_code: function(order_id) {
57
+ return Spree.pathFor("api/orders/" + order_id + "/apply_coupon_code");
58
+ }
59
+ };
60
+
61
+ Spree.getJSON = function(url, data, success) {
62
+ if (typeof data === 'function') {
63
+ success = data;
64
+ data = undefined;
65
+ }
66
+ return Spree.ajax({
67
+ dataType: "json",
68
+ url: url,
69
+ data: data,
70
+ success: success
71
+ });
72
+ };
@@ -8,6 +8,11 @@ module Spree
8
8
  end
9
9
 
10
10
  def cache_key_for_taxons
11
+ Spree::Deprecation.warn <<-WARN.strip_heredoc
12
+ cache_key_for_taxons is deprecated. Rails >= 5 has built-in support for collection cache keys.
13
+ Instead in your view use:
14
+ cache [I18n.locale, @taxons] do
15
+ WARN
11
16
  max_updated_at = @taxons.maximum(:updated_at).to_i
12
17
  parts = [@taxon.try(:id), max_updated_at].compact.join("-")
13
18
  "#{I18n.locale}/taxons/#{parts}"
@@ -0,0 +1,24 @@
1
+ module Spree
2
+ class PromotionCodeBatchJob < ActiveJob::Base
3
+ queue_as :default
4
+
5
+ def perform(promotion_code_batch)
6
+ PromotionCode::BatchBuilder.new(
7
+ promotion_code_batch
8
+ ).build_promotion_codes
9
+
10
+ if promotion_code_batch.email?
11
+ Spree::PromotionCodeBatchMailer
12
+ .promotion_code_batch_finished(promotion_code_batch)
13
+ .deliver_now
14
+ end
15
+ rescue => e
16
+ if promotion_code_batch.email?
17
+ Spree::PromotionCodeBatchMailer
18
+ .promotion_code_batch_errored(promotion_code_batch)
19
+ .deliver_now
20
+ end
21
+ raise e
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,13 @@
1
+ module Spree
2
+ class PromotionCodeBatchMailer < ApplicationMailer
3
+ def promotion_code_batch_finished(promotion_code_batch)
4
+ @promotion_code_batch = promotion_code_batch
5
+ mail(to: promotion_code_batch.email)
6
+ end
7
+
8
+ def promotion_code_batch_errored(promotion_code_batch)
9
+ @promotion_code_batch = promotion_code_batch
10
+ mail(to: promotion_code_batch.email)
11
+ end
12
+ end
13
+ end
@@ -4,7 +4,7 @@ module Spree
4
4
 
5
5
  included do
6
6
  has_one :calculator, class_name: "Spree::Calculator", as: :calculable, inverse_of: :calculable, dependent: :destroy, autosave: true
7
- accepts_nested_attributes_for :calculator
7
+ accepts_nested_attributes_for :calculator, update_only: true
8
8
  validates :calculator, presence: true
9
9
  end
10
10
 
@@ -16,8 +16,8 @@ module Spree
16
16
 
17
17
  def property_name=(name)
18
18
  unless name.blank?
19
- unless property = Property.find_by(name: name)
20
- property = Property.create(name: name, presentation: name)
19
+ unless property = Spree::Property.find_by(name: name)
20
+ property = Spree::Property.create(name: name, presentation: name)
21
21
  end
22
22
  self.property = property
23
23
  end
@@ -5,7 +5,7 @@ module Spree
5
5
  included do
6
6
  has_many :user_addresses, -> { active }, { foreign_key: "user_id", class_name: "Spree::UserAddress" } do
7
7
  def find_first_by_address_values(address_attrs)
8
- detect { |ua| ua.address == Address.new(address_attrs) }
8
+ detect { |ua| ua.address == Spree::Address.new(address_attrs) }
9
9
  end
10
10
 
11
11
  # @note this method enforces only one default address per user
@@ -37,7 +37,7 @@ module Spree
37
37
  end
38
38
 
39
39
  def bill_address_attributes=(attributes)
40
- self.bill_address = Address.immutable_merge(bill_address, attributes)
40
+ self.bill_address = Spree::Address.immutable_merge(bill_address, attributes)
41
41
  end
42
42
 
43
43
  def default_address=(address)
@@ -48,7 +48,7 @@ module Spree
48
48
  # see "Nested Attributes Examples" section of http://apidock.com/rails/ActionView/Helpers/FormHelper/fields_for
49
49
  # this #{fieldname}_attributes= method works with fields_for in the views
50
50
  # even without declaring accepts_nested_attributes_for
51
- self.default_address = Address.immutable_merge(default_address, attributes)
51
+ self.default_address = Spree::Address.immutable_merge(default_address, attributes)
52
52
  end
53
53
 
54
54
  alias_method :ship_address_attributes=, :default_address_attributes=
@@ -94,7 +94,7 @@ module Spree
94
94
  return nil unless address_attributes.present?
95
95
  address_attributes = address_attributes.to_h.with_indifferent_access
96
96
 
97
- new_address = Address.factory(address_attributes)
97
+ new_address = Spree::Address.factory(address_attributes)
98
98
  return new_address unless new_address.valid?
99
99
 
100
100
  first_one = user_addresses.empty?
@@ -23,6 +23,9 @@ module Spree
23
23
  has_many :store_credit_events, through: :store_credits
24
24
  money_methods :total_available_store_credit
25
25
 
26
+ has_many :credit_cards, class_name: "Spree::CreditCard", foreign_key: :user_id
27
+ has_many :wallet_payment_sources, foreign_key: 'user_id', class_name: 'Spree::WalletPaymentSource', inverse_of: :user
28
+
26
29
  after_create :auto_generate_spree_api_key
27
30
 
28
31
  include Spree::RansackableAttributes unless included_modules.include?(Spree::RansackableAttributes)
@@ -31,6 +34,10 @@ module Spree
31
34
  self.whitelisted_ransackable_attributes = %w[id email]
32
35
  end
33
36
 
37
+ def wallet
38
+ Spree::Wallet.new(self)
39
+ end
40
+
34
41
  # has_spree_role? simply needs to return true or false whether a user has a role or not.
35
42
  def has_spree_role?(role_in_question)
36
43
  spree_roles.any? { |role| role.name == role_in_question.to_s }
@@ -2,15 +2,22 @@ module Spree
2
2
  module UserPaymentSource
3
3
  extend ActiveSupport::Concern
4
4
 
5
- included do
6
- has_many :credit_cards, class_name: "Spree::CreditCard", foreign_key: :user_id
7
- end
8
-
9
5
  def default_credit_card
10
- credit_cards.default.first
6
+ Spree::Deprecation.warn(
7
+ "user.default_credit_card is deprecated. Please use user.wallet.default_wallet_payment_source instead.",
8
+ caller
9
+ )
10
+ default = wallet.default_wallet_payment_source
11
+ if default && default.payment_source.is_a?(Spree::CreditCard)
12
+ default.payment_source
13
+ end
11
14
  end
12
15
 
13
16
  def payment_sources
17
+ Spree::Deprecation.warn(
18
+ "user.payment_sources is deprecated. Please use user.wallet.wallet_payment_sources instead.",
19
+ caller
20
+ )
14
21
  credit_cards.with_payment_profile
15
22
  end
16
23
  end
@@ -105,20 +105,31 @@ module Spree
105
105
  value_attributes == other_address.value_attributes
106
106
  end
107
107
 
108
+ # @deprecated Do not use this. Use Address.== instead.
108
109
  def same_as?(other_address)
109
- Spree::Deprecation.warn("Address.same_as? is deprecated. It's equivalent to Address.==", caller)
110
+ Spree::Deprecation.warn("Address#same_as? is deprecated. It's equivalent to Address.==", caller)
110
111
  self == other_address
111
112
  end
112
113
 
114
+ # @deprecated Do not use this. Use Address.== instead.
113
115
  def same_as(other_address)
114
- Spree::Deprecation.warn("Address.same_as is deprecated. It's equivalent to Address.==", caller)
116
+ Spree::Deprecation.warn("Address#same_as is deprecated. It's equivalent to Address.==", caller)
115
117
  self == other_address
116
118
  end
117
119
 
120
+ # @deprecated Do not use this
118
121
  def empty?
122
+ Spree::Deprecation.warn("Address#empty? is deprecated.", caller)
119
123
  attributes.except('id', 'created_at', 'updated_at', 'country_id').all? { |_, v| v.nil? }
120
124
  end
121
125
 
126
+ # This exists because the default Object#blank?, checks empty? if it is
127
+ # defined, and we have defined empty.
128
+ # This should be removed once empty? is removed
129
+ def blank?
130
+ false
131
+ end
132
+
122
133
  # @return [Hash] an ActiveMerchant compatible address hash
123
134
  def active_merchant_hash
124
135
  {
@@ -157,7 +168,7 @@ module Spree
157
168
  # @return [Country] setter that sets self.country to the Country with a matching 2 letter iso
158
169
  # @raise [ActiveRecord::RecordNotFound] if country with the iso doesn't exist
159
170
  def country_iso=(iso)
160
- self.country = Country.find_by!(iso: iso)
171
+ self.country = Spree::Country.find_by!(iso: iso)
161
172
  end
162
173
 
163
174
  private
@@ -105,7 +105,7 @@ module Spree
105
105
  self.amount = source.compute_amount(adjustable)
106
106
 
107
107
  if promotion?
108
- self.eligible = source.promotion.eligible?(adjustable, promotion_code: promotion_code)
108
+ self.eligible = calculate_eligibility
109
109
  end
110
110
 
111
111
  # Persist only if changed
@@ -116,6 +116,18 @@ module Spree
116
116
  amount
117
117
  end
118
118
 
119
+ # Calculates based on attached promotion (if this is a promotion
120
+ # adjustment) whether this promotion is still eligible.
121
+ # @api private
122
+ # @return [true,false] Whether this adjustment is eligible
123
+ def calculate_eligibility
124
+ if !finalized? && source && promotion?
125
+ source.promotion.eligible?(adjustable, promotion_code: promotion_code)
126
+ else
127
+ eligible?
128
+ end
129
+ end
130
+
119
131
  private
120
132
 
121
133
  def require_promotion_code?
@@ -107,10 +107,6 @@ module Spree
107
107
  # @return [Boolean] Request company field for billing and shipping addresses. (default: +false+)
108
108
  preference :company, :boolean, default: false
109
109
 
110
- # @!attribute [rw] create_rma_for_unreturned_exchange
111
- # @return [Boolean] allows rma to be created for items after unreturned exchange charge has been made (default: +false+)
112
- preference :create_rma_for_unreturned_exchange, :boolean, default: false
113
-
114
110
  # @!attribute [rw] currency
115
111
  # Currency to use by default when not defined on the site (default: +"USD"+)
116
112
  # @return [String] ISO 4217 Three letter currency code
@@ -132,21 +128,6 @@ module Spree
132
128
  # prices are entered in the backend (default: nil)
133
129
  preference :admin_vat_country_iso, :string, default: nil
134
130
 
135
- # @!attribute [rw] expedited_exchanges
136
- # Kicks off an exchange shipment upon return authorization save.
137
- # charge customer if they do not return items within timely manner.
138
- # @note this requires payment profiles to be supported on your gateway of
139
- # choice as well as a delayed job handler to be configured with
140
- # activejob.
141
- # @return [Boolean] Use expidited exchanges (default: +false+)
142
- preference :expedited_exchanges, :boolean, default: false
143
-
144
- # @!attribute [rw] expedited_exchanges_days_window
145
- # @return [Integer] Number of days the customer has to return their item
146
- # after the expedited exchange is shipped in order to avoid being
147
- # charged (default: +14+)
148
- preference :expedited_exchanges_days_window, :integer, default: 14
149
-
150
131
  # @!attribute [rw] generate_api_key_for_all_roles
151
132
  # @return [Boolean] Allow generating api key automatically for user
152
133
  # at role_user creation for all roles. (default: +false+)
@@ -4,6 +4,8 @@ class Spree::Base < ActiveRecord::Base
4
4
 
5
5
  include Spree::RansackableAttributes
6
6
 
7
+ self.belongs_to_required_by_default = false
8
+
7
9
  def initialize_preference_defaults
8
10
  if has_attribute?(:preferences)
9
11
  self.preferences = default_preferences.merge(preferences)
@@ -1,20 +1,16 @@
1
1
  module Spree
2
2
  # The default `source` of a `Spree::Payment`.
3
3
  #
4
- class CreditCard < Spree::Base
5
- belongs_to :payment_method
6
- belongs_to :user, class_name: Spree.user_class, foreign_key: 'user_id'
4
+ class CreditCard < Spree::PaymentSource
5
+ belongs_to :user, class_name: Spree::UserClassHandle.new, foreign_key: 'user_id'
7
6
  belongs_to :address
8
- has_many :payments, as: :source
9
7
 
10
8
  before_save :set_last_digits
11
9
 
12
- after_save :ensure_one_default
13
-
14
10
  accepts_nested_attributes_for :address
15
11
 
16
- attr_reader :number, :verification_value
17
- attr_accessor :encrypted_data, :imported
12
+ attr_reader :number
13
+ attr_accessor :encrypted_data, :verification_value
18
14
 
19
15
  validates :month, :year, numericality: { only_integer: true }, if: :require_card_numbers?, on: :create
20
16
  validates :number, presence: true, if: :require_card_numbers?, on: :create, unless: :imported
@@ -22,7 +18,11 @@ module Spree
22
18
  validates :verification_value, presence: true, if: :require_card_numbers?, on: :create, unless: :imported
23
19
 
24
20
  scope :with_payment_profile, -> { where('gateway_customer_profile_id IS NOT NULL') }
25
- scope :default, -> { where(default: true) }
21
+
22
+ def self.default
23
+ Spree::Deprecation.warn("CreditCard.default is deprecated. Please use Spree::Wallet instead.")
24
+ joins(:wallet_payment_sources).where(spree_wallet_payment_sources: { default: true })
25
+ end
26
26
 
27
27
  # needed for some of the ActiveMerchant gateways (eg. SagePay)
28
28
  alias_attribute :brand, :cc_type
@@ -44,8 +44,30 @@ module Spree
44
44
  'laser' => /^(6304|6706|6709|6771(?!89))\d{8}(\d{4}|\d{6,7})?$/
45
45
  }.freeze
46
46
 
47
+ def default
48
+ Spree::Deprecation.warn("CreditCard.default is deprecated. Please use user.wallet.default_wallet_payment_source instead.", caller)
49
+ return false if user.nil?
50
+ user.wallet.default_wallet_payment_source.try!(:payment_source) == self
51
+ end
52
+
53
+ def default=(set_as_default)
54
+ Spree::Deprecation.warn("CreditCard.default= is deprecated. Please use user.wallet.default_wallet_payment_source= instead.", caller)
55
+ if user.nil?
56
+ raise "Cannot set 'default' on a credit card without a user"
57
+ elsif set_as_default # setting this card as default
58
+ wallet_payment_source = user.wallet.add(self)
59
+ user.wallet.default_wallet_payment_source = wallet_payment_source
60
+ true
61
+ else # removing this card as default
62
+ if user.wallet.default_wallet_payment_source.try!(:payment_source) == self
63
+ user.wallet.default_wallet_payment_source = nil
64
+ end
65
+ false
66
+ end
67
+ end
68
+
47
69
  def address_attributes=(attributes)
48
- self.address = Address.immutable_merge(address, attributes)
70
+ self.address = Spree::Address.immutable_merge(address, attributes)
49
71
  end
50
72
 
51
73
  # Sets the expiry date on this credit card.
@@ -123,31 +145,8 @@ module Spree
123
145
  "XXXX-XXXX-XXXX-#{last_digits}"
124
146
  end
125
147
 
126
- # @return [Array<String>] the actions available on this credit card
127
- def actions
128
- %w{capture void credit}
129
- end
130
-
131
- # @param payment [Spree::Payment] the payment we want to know if can be captured
132
- # @return [Boolean] true when the payment is in the pending or checkout states
133
- def can_capture?(payment)
134
- payment.pending? || payment.checkout?
135
- end
136
-
137
- # @param payment [Spree::Payment] the payment we want to know if can be voided
138
- # @return [Boolean] true when the payment is not failed or voided
139
- def can_void?(payment)
140
- !payment.failed? && !payment.void?
141
- end
142
-
143
- # Indicates whether its possible to credit the payment. Note that most
144
- # gateways require that the payment be settled first which generally
145
- # happens within 12-24 hours of the transaction.
146
- #
147
- # @param payment [Spree::Payment] the payment we want to know if can be credited
148
- # @return [Boolean] true when the payment is completed and can be credited
149
- def can_credit?(payment)
150
- payment.completed? && payment.credit_allowed > 0
148
+ def reusable?
149
+ has_payment_profile?
151
150
  end
152
151
 
153
152
  # @return [Boolean] true when there is a gateway customer or payment
@@ -192,13 +191,5 @@ module Spree
192
191
  def require_card_numbers?
193
192
  !encrypted_data.present? && !has_payment_profile?
194
193
  end
195
-
196
- def ensure_one_default
197
- if user_id && default
198
- CreditCard.where(default: true).where.not(id: id).where(user_id: user_id).each do |ucc|
199
- ucc.update_columns(default: false, updated_at: Time.current)
200
- end
201
- end
202
- end
203
194
  end
204
195
  end
@@ -79,7 +79,7 @@ module Spree
79
79
  prefix = success ? 'BGS' : 'FAIL'
80
80
  while record
81
81
  random = "#{prefix}-#{Array.new(6){ rand(6) }.join}"
82
- record = CreditCard.where(gateway_customer_profile_id: random).first
82
+ record = Spree::CreditCard.where(gateway_customer_profile_id: random).first
83
83
  end
84
84
  random
85
85
  end
@@ -42,16 +42,18 @@ module Spree
42
42
  source.has_payment_profile?
43
43
  end
44
44
 
45
- def sources_by_order(order)
45
+ def reusable_sources_by_order(order)
46
46
  source_ids = order.payments.where(payment_method_id: id).pluck(:source_id).uniq
47
- payment_source_class.where(id: source_ids).with_payment_profile
47
+ payment_source_class.where(id: source_ids).select(&:reusable?)
48
48
  end
49
+ alias_method :sources_by_order, :reusable_sources_by_order
50
+ deprecate sources_by_order: :reusable_sources_by_order, deprecator: Spree::Deprecation
49
51
 
50
52
  def reusable_sources(order)
51
53
  if order.completed?
52
- sources_by_order(order)
54
+ reusable_sources_by_order(order)
53
55
  elsif order.user_id
54
- credit_cards.where(user_id: order.user_id).with_payment_profile
56
+ order.user.wallet.wallet_payment_sources.map(&:payment_source).select(&:reusable?)
55
57
  else
56
58
  []
57
59
  end
@@ -21,6 +21,7 @@ module Spree
21
21
 
22
22
  before_destroy :ensure_can_destroy
23
23
 
24
+ scope :pending, -> { where pending: true }
24
25
  scope :backordered, -> { where state: 'backordered' }
25
26
  scope :on_hand, -> { where state: 'on_hand' }
26
27
  scope :pre_shipment, -> { where(state: PRE_SHIPMENT_STATES) }
@@ -29,7 +30,7 @@ module Spree
29
30
  scope :returned, -> { where state: 'returned' }
30
31
  scope :canceled, -> { where(state: 'canceled') }
31
32
  scope :not_canceled, -> { where.not(state: 'canceled') }
32
- scope :cancelable, -> { where(state: Spree::InventoryUnit::CANCELABLE_STATES) }
33
+ scope :cancelable, -> { where(state: Spree::InventoryUnit::CANCELABLE_STATES, pending: false) }
33
34
  scope :backordered_per_variant, ->(stock_item) do
34
35
  includes(:shipment, :order)
35
36
  .where("spree_shipments.state != 'canceled'").references(:shipment)
@@ -140,7 +141,7 @@ module Spree
140
141
  throw :abort
141
142
  end
142
143
 
143
- unless shipment.pending?
144
+ if shipment.shipped? || shipment.canceled?
144
145
  errors.add(:base, :cannot_destroy_shipment_state, state: shipment.state)
145
146
  throw :abort
146
147
  end