solidus_core 2.1.1 → 2.2.0.beta1

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 (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