solidus_core 4.7.1 → 4.7.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 78c29ac128ed3b6ae1572035004a577b125403271d2d331f598a6fae3860003d
4
- data.tar.gz: aecc835e960dc5b51f163f41ea9abc07dba2ff27717f24c8623a563b14d5e9ad
3
+ metadata.gz: d3d8242467851026fff5d6e6c31639174974d747193e9bef00a77acbd7c6e912
4
+ data.tar.gz: 7336f44aad6dc32d2d477acffe0de1af5acb1df5fa7bd399b3b754e3647269e3
5
5
  SHA512:
6
- metadata.gz: b9a161abf80858e4511684189d7f66f93e9a0774f091448702f174586ae10a1c13669d6c0efa6afd9f20470602dc95e55a06bad734913e482195915d053b56d6
7
- data.tar.gz: ea34f9b2b35829c6888d11ceea67b3b056c1857ab9567fc941827d84c7b23789853ae1f9f2f6aec4381074208fd574742fa571ddbb0d72edee33fb90ccd0c535
6
+ metadata.gz: e0521407fa49fac2011d849d4fa08f03a165c32751ffdda07656dd985c3aa73a3ea0b90e4d7b6dfc7157a310fc371d3195b9e7e3f1d1b1b517d3c927370d01c8
7
+ data.tar.gz: 4619fdf8d485b61ba1610d4c579fd83f82e4f0710648719b07c4ec4e246915a6d2de458f351560c375b212c84a37db01d9b9463608f1f141e27e531e363a958f
@@ -49,7 +49,7 @@ module Spree
49
49
  if Spree::Config[:show_raw_product_description]
50
50
  raw(product.description)
51
51
  else
52
- raw(product.description.gsub(/(.*?)\r?\n\r?\n/m, '<p>\1</p>'))
52
+ sanitize(product.description.gsub(/(.*?)\r?\n\r?\n/m, '<p>\1</p>'))
53
53
  end
54
54
  end
55
55
 
@@ -130,14 +130,14 @@ module Spree
130
130
 
131
131
  # Updates the roles in keeping with the given ability's permissions
132
132
  #
133
- # Roles that are not accessible to the given ability will be ignored. It
134
- # also ensure not to remove non accessible roles when assigning new
135
- # accessible ones.
133
+ # Roles that the given ability cannot manage will be ignored. It also
134
+ # ensure not to remove non manageable roles when assigning new manageable
135
+ # ones.
136
136
  #
137
137
  # @param given_roles [Spree::Role]
138
138
  # @param ability [Spree::Ability]
139
139
  def update_spree_roles(given_roles, ability:)
140
- accessible_roles = Spree::Role.accessible_by(ability)
140
+ accessible_roles = Spree::Role.accessible_by(ability, :manage)
141
141
  non_accessible_roles = Spree::Role.all - accessible_roles
142
142
  new_accessible_roles = given_roles - non_accessible_roles
143
143
  self.spree_roles = spree_roles - accessible_roles + new_accessible_roles
@@ -113,7 +113,6 @@ module Spree
113
113
  end
114
114
 
115
115
  def gateway_options
116
- order.reload
117
116
  options = {
118
117
  email: order.email,
119
118
  customer: order.email,
@@ -8,6 +8,10 @@ module Spree
8
8
  # * :payment_method_id Id of payment method used for this payment
9
9
  # * :source_attributes Attributes used to build the source of this payment. Usually a {CreditCard}
10
10
  # * :wallet_payment_source_id (Integer): The id of a {WalletPaymentSource} to use
11
+ # * :gateway_customer_profile_id, :gateway_payment_profile_id (String): Gateway
12
+ # identifiers for a new {CreditCard}, e.g. a one-time token. Raises
13
+ # ActiveRecord::RecordNotFound if either already belongs to a {CreditCard}
14
+ # owned by a different user.
11
15
  # @param request_env [Hash] rack env of user creating the payment
12
16
  # @param payment [Payment] Internal use only. Instead of making a new payment, change the attributes for an existing one.
13
17
  def initialize(order, attributes, payment: nil, request_env: {})
@@ -44,6 +48,7 @@ module Spree
44
48
  def build_source
45
49
  payment_method = payment.payment_method
46
50
  if source_attributes.present? && payment_method.try(:payment_source_class)
51
+ ensure_gateway_profile_ownership!(payment_method.payment_source_class)
47
52
  payment.source = payment_method.payment_source_class.new(source_attributes)
48
53
  payment.source.payment_method_id = payment_method.id
49
54
  if order && payment.source.respond_to?(:user=)
@@ -52,6 +57,24 @@ module Spree
52
57
  end
53
58
  end
54
59
 
60
+ # Gateway profile ids may only be submitted for a new source when they are
61
+ # unknown to the store (e.g. a one-time token) or already belong to the
62
+ # order's user. Raises if either id is stored on a {CreditCard} owned by a
63
+ # different user, so customers cannot pay with another customer's stored
64
+ # gateway credential.
65
+ def ensure_gateway_profile_ownership!(source_class)
66
+ return unless source_class <= Spree::CreditCard
67
+
68
+ %i[gateway_customer_profile_id gateway_payment_profile_id].each do |attribute|
69
+ value = source_attributes[attribute]
70
+ next if value.blank?
71
+
72
+ foreign_cards = Spree::CreditCard.where(attribute => value).where.not(user_id: nil)
73
+ foreign_cards = foreign_cards.where.not(user_id: order.user_id) if order&.user_id
74
+ raise ActiveRecord::RecordNotFound if foreign_cards.exists?
75
+ end
76
+ end
77
+
55
78
  def build_from_wallet_payment_source
56
79
  wallet_payment_source_id = source_attributes.fetch(:wallet_payment_source_id)
57
80
  raise(ActiveRecord::RecordNotFound) if order.user.nil?
@@ -355,14 +355,17 @@ module Spree
355
355
  run_callbacks(:touch)
356
356
  end
357
357
 
358
- # Iterate through this product's taxons and taxonomies and touch their timestamps in a batch
358
+ # Iterate through this product's taxons and taxonomies and touch their timestamps
359
359
  def touch_taxons
360
- taxons_to_touch = taxons.flat_map(&:self_and_ancestors).uniq
361
- unless taxons_to_touch.empty?
362
- Spree::Taxon.where(id: taxons_to_touch.map(&:id)).update_all(updated_at: Time.current)
360
+ taxons_to_touch = taxons.flat_map(&:self_and_ancestors).uniq.sort_by(&:id)
361
+ return if taxons_to_touch.empty?
363
362
 
364
- taxonomy_ids_to_touch = taxons_to_touch.flat_map(&:taxonomy_id).uniq
365
- Spree::Taxonomy.where(id: taxonomy_ids_to_touch).update_all(updated_at: Time.current)
363
+ time = Time.current
364
+ taxons_to_touch.each { |taxon| taxon.update_column(:updated_at, time) }
365
+
366
+ taxonomy_ids_to_touch = taxons_to_touch.map(&:taxonomy_id).uniq
367
+ Spree::Taxonomy.where(id: taxonomy_ids_to_touch).order(:id).each do |taxonomy|
368
+ taxonomy.touch(time:)
366
369
  end
367
370
  end
368
371
 
@@ -41,6 +41,7 @@ module Spree
41
41
 
42
42
  validate :eligible_exchange_variant
43
43
  validate :belongs_to_same_customer_order
44
+ validate :belongs_to_return_authorization_order, if: -> { inventory_unit_id_changed? || return_authorization_id_changed? }
44
45
  validate :validate_acceptance_status_for_reimbursement
45
46
  validate :validate_no_other_completed_return_items
46
47
 
@@ -226,6 +227,14 @@ module Spree
226
227
  end
227
228
  end
228
229
 
230
+ def belongs_to_return_authorization_order
231
+ return unless return_authorization && inventory_unit
232
+
233
+ if return_authorization.order_id != inventory_unit.order_id
234
+ errors.add(:base, I18n.t("spree.return_items_cannot_be_associated_with_multiple_orders"))
235
+ end
236
+ end
237
+
229
238
  def eligible_exchange_variant
230
239
  return unless exchange_variant && exchange_variant_id_changed?
231
240
  unless eligible_exchange_variants.include?(exchange_variant)
@@ -140,8 +140,11 @@ module Spree
140
140
  private
141
141
 
142
142
  def touch_ancestors_and_taxonomy
143
- # Touches all ancestors at once to avoid recursive taxonomy touch, and reduce queries.
144
- self.class.default_scoped.where(id: ancestors.pluck(:id)).update_all(updated_at: Time.current)
143
+ # Touches ancestors directly rather than through #touch to avoid a recursive taxonomy touch.
144
+ time = Time.current
145
+ self.class.default_scoped.where(id: ancestors.pluck(:id)).order(:id).each do |ancestor|
146
+ ancestor.update_column(:updated_at, time)
147
+ end
145
148
  # Have taxonomy touch happen in #touch_ancestors_and_taxonomy rather than association option in order for imports to override.
146
149
  taxonomy.try!(:touch)
147
150
  end
@@ -25,6 +25,7 @@ module Spree
25
25
  def run
26
26
  # Early return if there is no VAT rates in the current store.
27
27
  return if !variant.tax_category || variant_vat_rates.empty?
28
+ return if variant.default_price&.amount.nil?
28
29
 
29
30
  country_isos_requiring_price.each do |country_iso|
30
31
  # Don't re-create the default price
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Spree
4
- VERSION = "4.7.1"
4
+ VERSION = "4.7.2"
5
5
 
6
6
  def self.solidus_version = VERSION
7
7
 
@@ -22,7 +22,8 @@ module Spree
22
22
 
23
23
  def preferences
24
24
  if respond_to?(:preference_source) && preference_source
25
- self.class.preference_sources[preference_source] || {}
25
+ source = self.class.preference_sources[preference_source]
26
+ source ? default_preferences.merge(source.to_hash) : {}
26
27
  else
27
28
  self[:preferences]
28
29
  end
@@ -2,7 +2,15 @@
2
2
 
3
3
  FactoryBot.define do
4
4
  factory :return_item, class: "Spree::ReturnItem" do
5
- association(:inventory_unit, factory: :inventory_unit, state: :shipped)
5
+ inventory_unit do
6
+ # When a return authorization is given, the inventory unit must belong
7
+ # to the same order.
8
+ if __override_names__.include?(:return_authorization) && return_authorization&.order
9
+ association(:inventory_unit, state: :shipped, order: return_authorization.order)
10
+ else
11
+ association(:inventory_unit, state: :shipped)
12
+ end
13
+ end
6
14
  association(:return_reason, factory: :return_reason)
7
15
  return_authorization do |_return_item|
8
16
  build(:return_authorization, order: inventory_unit.order)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solidus_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.7.1
4
+ version: 4.7.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Solidus Team