spree_core 4.5.0 → 4.7.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (143) hide show
  1. checksums.yaml +4 -4
  2. data/app/finders/spree/countries/find.rb +1 -1
  3. data/app/finders/spree/option_values/find_available.rb +1 -1
  4. data/app/finders/spree/product_properties/find_available.rb +1 -1
  5. data/app/finders/spree/products/find.rb +21 -13
  6. data/app/finders/spree/taxons/find.rb +7 -10
  7. data/app/helpers/spree/base_helper.rb +3 -7
  8. data/app/helpers/spree/products_helper.rb +3 -3
  9. data/app/models/concerns/spree/metadata.rb +7 -2
  10. data/app/models/concerns/spree/named_type.rb +1 -1
  11. data/app/models/concerns/spree/product_scopes.rb +27 -23
  12. data/app/models/concerns/spree/translatable_resource.rb +25 -0
  13. data/app/models/concerns/spree/translatable_resource_scopes.rb +24 -0
  14. data/app/models/concerns/spree/translatable_resource_slug.rb +15 -0
  15. data/app/models/concerns/spree/user_roles.rb +3 -3
  16. data/app/models/spree/address.rb +6 -4
  17. data/app/models/spree/asset.rb +1 -1
  18. data/app/models/spree/base.rb +6 -1
  19. data/app/models/spree/calculator/default_tax.rb +1 -1
  20. data/app/models/spree/cms/sections/image_gallery.rb +1 -7
  21. data/app/models/spree/cms/sections/side_by_side_images.rb +1 -7
  22. data/app/models/spree/cms_page.rb +2 -2
  23. data/app/models/spree/cms_section.rb +1 -1
  24. data/app/models/spree/country.rb +2 -2
  25. data/app/models/spree/credit_card.rb +1 -1
  26. data/app/models/spree/customer_return.rb +2 -2
  27. data/app/models/spree/data_feed/google.rb +15 -0
  28. data/app/models/spree/data_feed.rb +40 -0
  29. data/app/models/spree/digital_link.rb +5 -1
  30. data/app/models/spree/image.rb +2 -2
  31. data/app/models/spree/legacy_user.rb +3 -3
  32. data/app/models/spree/line_item.rb +1 -1
  33. data/app/models/spree/log_entry.rb +5 -1
  34. data/app/models/spree/menu.rb +1 -1
  35. data/app/models/spree/option_type.rb +6 -2
  36. data/app/models/spree/option_value.rb +5 -1
  37. data/app/models/spree/order/store_credit.rb +8 -0
  38. data/app/models/spree/order.rb +9 -9
  39. data/app/models/spree/order_contents.rb +31 -0
  40. data/app/models/spree/payment.rb +7 -15
  41. data/app/models/spree/payment_method.rb +1 -1
  42. data/app/models/spree/payment_source.rb +1 -1
  43. data/app/models/spree/preference.rb +5 -1
  44. data/app/models/spree/price.rb +1 -1
  45. data/app/models/spree/product.rb +64 -25
  46. data/app/models/spree/product_property.rb +13 -4
  47. data/app/models/spree/promotion.rb +2 -2
  48. data/app/models/spree/property.rb +8 -2
  49. data/app/models/spree/prototype.rb +1 -1
  50. data/app/models/spree/refund.rb +1 -1
  51. data/app/models/spree/reimbursement.rb +1 -1
  52. data/app/models/spree/return_authorization.rb +1 -1
  53. data/app/models/spree/return_item.rb +5 -1
  54. data/app/models/spree/role.rb +1 -1
  55. data/app/models/spree/shipment.rb +5 -5
  56. data/app/models/spree/shipping_category.rb +1 -1
  57. data/app/models/spree/shipping_method.rb +1 -1
  58. data/app/models/spree/stock/estimator.rb +1 -1
  59. data/app/models/spree/stock/splitter/weight.rb +1 -1
  60. data/app/models/spree/stock_item.rb +1 -1
  61. data/app/models/spree/stock_location.rb +1 -1
  62. data/app/models/spree/stock_transfer.rb +3 -3
  63. data/app/models/spree/store.rb +22 -3
  64. data/app/models/spree/store_credit.rb +2 -2
  65. data/app/models/spree/taxon.rb +47 -7
  66. data/app/models/spree/taxon_image.rb +2 -2
  67. data/app/models/spree/taxonomy.rb +5 -1
  68. data/app/models/spree/variant.rb +6 -9
  69. data/app/models/spree/wishlist.rb +6 -2
  70. data/app/models/spree/zone.rb +2 -2
  71. data/app/services/spree/data_feeds/google/optional_attributes.rb +23 -0
  72. data/app/services/spree/data_feeds/google/optional_sub_attributes.rb +21 -0
  73. data/app/services/spree/data_feeds/google/products_list.rb +14 -0
  74. data/app/services/spree/data_feeds/google/required_attributes.rb +67 -0
  75. data/app/services/spree/data_feeds/google/rss.rb +107 -0
  76. data/app/services/spree/locales/set_fallback_locale_for_store.rb +16 -0
  77. data/app/services/spree/seeds/countries.rb +12 -27
  78. data/app/services/spree/seeds/states.rb +8 -17
  79. data/app/services/spree/stock_locations/stock_items/create.rb +12 -18
  80. data/app/sorters/spree/products/sort.rb +23 -0
  81. data/app/validators/db_maximum_length_validator.rb +2 -6
  82. data/brakeman.ignore +326 -18
  83. data/config/initializers/friendly_id.rb +2 -0
  84. data/config/initializers/mobility.rb +16 -0
  85. data/config/initializers/rails61_fixes.rb +1 -3
  86. data/config/locales/en.yml +7 -0
  87. data/db/migrate/20220706112554_create_product_name_and_description_translations_for_mobility_table_backend.rb +27 -0
  88. data/db/migrate/20220715083542_create_spree_product_translations_for_mobility.rb +7 -0
  89. data/db/migrate/20220715120222_change_product_name_null_to_true.rb +5 -0
  90. data/db/migrate/20220718100743_create_spree_taxon_name_and_description_translations_for_mobility_table_backend.rb +27 -0
  91. data/db/migrate/20220718100948_change_taxon_name_null_to_true.rb +5 -0
  92. data/db/migrate/20220802070609_add_locale_to_friendly_id_slugs.rb +11 -0
  93. data/db/migrate/20220802073225_create_spree_product_slug_translations_for_mobility_table_backend.rb +5 -0
  94. data/db/migrate/20220804073928_transfer_data_to_translatable_tables.rb +66 -0
  95. data/db/migrate/20221215151408_add_selected_locale_to_spree_users.rb +8 -0
  96. data/db/migrate/20221219123957_add_deleted_at_to_product_translations.rb +6 -0
  97. data/db/migrate/20221220133432_add_uniqueness_constraint_to_product_translations.rb +5 -0
  98. data/db/migrate/20221229132350_create_spree_data_feed_settings.rb +14 -0
  99. data/db/migrate/20230103144439_create_option_type_translations.rb +26 -0
  100. data/db/migrate/20230103151034_create_option_value_translations.rb +26 -0
  101. data/db/migrate/20230109084253_create_product_property_translations.rb +25 -0
  102. data/db/migrate/20230109094907_transfer_options_data_to_translatable_tables.rb +58 -0
  103. data/db/migrate/20230109105943_create_property_translations.rb +26 -0
  104. data/db/migrate/20230109110840_transfer_property_data_to_translatable_tables.rb +59 -0
  105. data/db/migrate/20230110142344_backfill_friendly_id_slug_locale.rb +15 -0
  106. data/db/migrate/20230111121534_add_additional_taxon_translation_fields.rb +8 -0
  107. data/db/migrate/20230111122511_transfer_product_and_taxon_data_to_translatable_tables.rb +82 -0
  108. data/db/migrate/20230117115531_create_taxonomy_translations.rb +24 -0
  109. data/db/migrate/20230117120430_allow_null_taxonomy_name.rb +5 -0
  110. data/db/migrate/20230117121303_transfer_taxonomy_data_to_translatable_tables.rb +11 -0
  111. data/db/migrate/20230210142732_create_store_translations.rb +50 -0
  112. data/db/migrate/20230210142849_transfer_store_data_to_translatable_tables.rb +11 -0
  113. data/db/migrate/20230210230434_add_deleted_at_to_store_translations.rb +6 -0
  114. data/db/migrate/20230415155958_rename_data_feed_settings_table.rb +5 -0
  115. data/db/migrate/20230415160828_rename_data_feed_table_columns.rb +7 -0
  116. data/db/migrate/20230415161226_add_indexes_to_data_feeds_table.rb +5 -0
  117. data/db/migrate/20230512094803_rename_data_feeds_column_provider_to_type.rb +5 -0
  118. data/db/migrate/20230514162157_add_index_on_locale_and_permalink_to_spree_taxons.rb +5 -0
  119. data/lib/mobility/plugins/store_based_fallbacks.rb +55 -0
  120. data/lib/spree/core/configuration.rb +2 -1
  121. data/lib/spree/core/controller_helpers/auth.rb +1 -1
  122. data/lib/spree/core/controller_helpers/common.rb +5 -5
  123. data/lib/spree/core/controller_helpers/locale.rb +33 -2
  124. data/lib/spree/core/dependencies.rb +70 -94
  125. data/lib/spree/core/dependencies_helper.rb +19 -0
  126. data/lib/spree/core/engine.rb +7 -1
  127. data/lib/spree/core/preferences/preferable_class_methods.rb +1 -1
  128. data/lib/spree/core/product_duplicator.rb +4 -1
  129. data/lib/spree/core/product_filters.rb +7 -4
  130. data/lib/spree/core/search/base.rb +1 -1
  131. data/lib/spree/core/version.rb +1 -1
  132. data/lib/spree/core.rb +2 -0
  133. data/lib/spree/permitted_attributes.rb +1 -1
  134. data/lib/spree/testing_support/controller_requests.rb +10 -10
  135. data/lib/spree/testing_support/factories/google_data_feed_factory.rb +8 -0
  136. data/lib/spree/testing_support/factories/product_factory.rb +6 -0
  137. data/lib/spree/testing_support/factories/product_translation_factory.rb +6 -0
  138. data/lib/spree/testing_support/factories/store_factory.rb +3 -0
  139. data/lib/spree/testing_support/factories/variant_factory.rb +4 -0
  140. data/lib/spree/translation_migrations.rb +40 -0
  141. data/lib/spree_core.rb +1 -0
  142. data/spree_core.gemspec +6 -3
  143. metadata +147 -14
@@ -0,0 +1,40 @@
1
+ module Spree
2
+ class DataFeed < Base
3
+ belongs_to :store, class_name: 'Spree::Store', foreign_key: 'store_id'
4
+
5
+ scope :for_store, ->(store) { where(store: store) }
6
+
7
+ before_validation :generate_slug
8
+
9
+ with_options presence: true do
10
+ validates :store
11
+ validates :name, uniqueness: true
12
+ validates :slug, uniqueness: { scope: :store_id }
13
+ end
14
+
15
+ def formatted_url
16
+ "#{store.formatted_url}/api/v2/data_feeds/#{self.class.provider_name}/#{slug}.rss"
17
+ end
18
+
19
+ private
20
+
21
+ def generate_slug
22
+ new_slug = slug.blank? ? SecureRandom.uuid : slug.parameterize
23
+ write_attribute(:slug, new_slug)
24
+ end
25
+
26
+ class << self
27
+ def label
28
+ raise NotImplementedError
29
+ end
30
+
31
+ def provider_name
32
+ raise NotImplementedError
33
+ end
34
+
35
+ def available_types
36
+ Rails.application.config.spree.data_feed_types
37
+ end
38
+ end
39
+ end
40
+ end
@@ -1,6 +1,10 @@
1
1
  module Spree
2
2
  class DigitalLink < Spree::Base
3
- has_secure_token
3
+ if Rails::VERSION::STRING >= '7.1.0'
4
+ has_secure_token on: :save
5
+ else
6
+ has_secure_token
7
+ end
4
8
 
5
9
  if defined?(Spree::Webhooks)
6
10
  include Spree::Webhooks::HasWebhooks
@@ -1,8 +1,8 @@
1
1
  module Spree
2
2
  class Image < Asset
3
- include Configuration::ActiveStorage
3
+ include Spree::Image::Configuration::ActiveStorage
4
4
  include Rails.application.routes.url_helpers
5
- include ::Spree::ImageMethods
5
+ include Spree::ImageMethods
6
6
 
7
7
  # In Rails 5.x class constants are being undefined/redefined during the code reloading process
8
8
  # in a rails development environment, after which the actual ruby objects stored in those class constants
@@ -1,9 +1,9 @@
1
1
  # Default implementation of User. This class is intended to be modified by extensions (ex. spree_auth_devise)
2
2
  module Spree
3
3
  class LegacyUser < Spree::Base
4
- include UserAddress
5
- include UserPaymentSource
6
- include UserMethods
4
+ include Spree::UserAddress
5
+ include Spree::UserPaymentSource
6
+ include Spree::UserMethods
7
7
  include Spree::Metadata
8
8
 
9
9
  self.table_name = 'spree_users'
@@ -1,6 +1,6 @@
1
1
  module Spree
2
2
  class LineItem < Spree::Base
3
- include Metadata
3
+ include Spree::Metadata
4
4
  if defined?(Spree::Webhooks)
5
5
  include Spree::Webhooks::HasWebhooks
6
6
  end
@@ -15,7 +15,11 @@ module Spree
15
15
  end
16
16
 
17
17
  def parsed_details
18
- @details ||= YAML.safe_load(details, [ActiveMerchant::Billing::Response])
18
+ @details ||= if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.1.0')
19
+ YAML.safe_load(details, permitted_classes: [ActiveMerchant::Billing::Response])
20
+ else
21
+ YAML.safe_load(details, [ActiveMerchant::Billing::Response])
22
+ end
19
23
  end
20
24
  end
21
25
  end
@@ -1,6 +1,6 @@
1
1
  module Spree
2
2
  class Menu < Spree::Base
3
- include SingleStoreResource
3
+ include Spree::SingleStoreResource
4
4
  if defined?(Spree::Webhooks)
5
5
  include Spree::Webhooks::HasWebhooks
6
6
  end
@@ -1,11 +1,15 @@
1
1
  module Spree
2
2
  class OptionType < Spree::Base
3
- include UniqueName
4
- include Metadata
3
+ include Spree::UniqueName
4
+ include Spree::Metadata
5
+ include Spree::TranslatableResource
5
6
  if defined?(Spree::Webhooks)
6
7
  include Spree::Webhooks::HasWebhooks
7
8
  end
8
9
 
10
+ TRANSLATABLE_FIELDS = %i[name presentation].freeze
11
+ translates(*TRANSLATABLE_FIELDS)
12
+
9
13
  acts_as_list
10
14
  auto_strip_attributes :name, :presentation
11
15
 
@@ -1,10 +1,14 @@
1
1
  module Spree
2
2
  class OptionValue < Spree::Base
3
- include Metadata
3
+ include Spree::Metadata
4
+ include Spree::TranslatableResource
4
5
  if defined?(Spree::Webhooks)
5
6
  include Spree::Webhooks::HasWebhooks
6
7
  end
7
8
 
9
+ TRANSLATABLE_FIELDS = %i[name presentation].freeze
10
+ translates(*TRANSLATABLE_FIELDS)
11
+
8
12
  belongs_to :option_type, class_name: 'Spree::OptionType', touch: true, inverse_of: :option_values
9
13
 
10
14
  acts_as_list scope: :option_type
@@ -1,6 +1,14 @@
1
1
  module Spree
2
2
  class Order < Spree::Base
3
3
  module StoreCredit
4
+ def add_store_credit_payments(amount = nil)
5
+ Spree::Dependencies.checkout_add_store_credit_service.constantize.call(order: self, amount: amount)
6
+ end
7
+
8
+ def remove_store_credit_payments
9
+ Spree::Dependencies.checkout_remove_store_credit_service.constantize.call(order: self)
10
+ end
11
+
4
12
  def covered_by_store_credit?
5
13
  return false unless user
6
14
 
@@ -20,11 +20,11 @@ module Spree
20
20
  include Spree::Core::NumberGenerator.new(prefix: 'R')
21
21
  include Spree::Core::TokenGenerator
22
22
 
23
- include NumberIdentifier
24
- include NumberAsParam
25
- include SingleStoreResource
26
- include MemoizedData
27
- include Metadata
23
+ include Spree::NumberIdentifier
24
+ include Spree::NumberAsParam
25
+ include Spree::SingleStoreResource
26
+ include Spree::MemoizedData
27
+ include Spree::Metadata
28
28
  if defined?(Spree::Webhooks)
29
29
  include Spree::Webhooks::HasWebhooks
30
30
  end
@@ -415,7 +415,7 @@ module Spree
415
415
 
416
416
  def available_payment_methods(store = nil)
417
417
  if store.present?
418
- ActiveSupport::Deprecation.warn('The `store` parameter is deprecated and will be removed in Spree 5. Order is already associated with Store')
418
+ Spree::Deprecation.warn('The `store` parameter is deprecated and will be removed in Spree 5. Order is already associated with Store')
419
419
  end
420
420
 
421
421
  @available_payment_methods ||= collect_payment_methods(store)
@@ -449,7 +449,7 @@ module Spree
449
449
  end
450
450
 
451
451
  def empty!
452
- ActiveSupport::Deprecation.warn(<<-DEPRECATION, caller)
452
+ Spree::Deprecation.warn(<<-DEPRECATION, caller)
453
453
  `Order#empty!` is deprecated and will be removed in Spree 5.0.
454
454
  Please use `Spree::Cart::Empty.call(order: order)` instead.
455
455
  DEPRECATION
@@ -647,7 +647,7 @@ module Spree
647
647
  end
648
648
 
649
649
  def validate_payments_attributes(attributes)
650
- ActiveSupport::Deprecation.warn('`Order#validate_payments_attributes` is deprecated and will be removed in Spree 5')
650
+ Spree::Deprecation.warn('`Order#validate_payments_attributes` is deprecated and will be removed in Spree 5')
651
651
 
652
652
  # Ensure the payment methods specified are allowed for this user
653
653
  payment_method_ids = available_payment_methods.map(&:id).map(&:to_s)
@@ -745,7 +745,7 @@ module Spree
745
745
 
746
746
  def collect_payment_methods(store = nil)
747
747
  if store.present?
748
- ActiveSupport::Deprecation.warn('The `store` parameter is deprecated and will be removed in Spree 5. Order is already associated with Store')
748
+ Spree::Deprecation.warn('The `store` parameter is deprecated and will be removed in Spree 5. Order is already associated with Store')
749
749
  end
750
750
  store ||= self.store
751
751
 
@@ -0,0 +1,31 @@
1
+ module Spree
2
+ class OrderContents
3
+ attr_accessor :order, :currency
4
+
5
+ def initialize(order)
6
+ @order = order
7
+ end
8
+
9
+ def add(variant, quantity = 1, options = {})
10
+ Spree::Dependencies.cart_add_item_service.constantize.call(order: order,
11
+ variant: variant,
12
+ quantity: quantity,
13
+ options: options).value
14
+ end
15
+
16
+ def remove(variant, quantity = 1, options = {})
17
+ Spree::Dependencies.cart_remove_item_service.constantize.call(order: order,
18
+ variant: variant,
19
+ quantity: quantity,
20
+ options: options).value
21
+ end
22
+
23
+ def remove_line_item(line_item, options = {})
24
+ Spree::Cart::RemoveLineItem.call(order: @order, line_item: line_item, options: options).value
25
+ end
26
+
27
+ def update_cart(params)
28
+ Spree::Dependencies.cart_update_service.constantize.call(order: order, params: params).value
29
+ end
30
+ end
31
+ end
@@ -3,9 +3,9 @@ require_dependency 'spree/payment/processing'
3
3
  module Spree
4
4
  class Payment < Spree::Base
5
5
  include Spree::Core::NumberGenerator.new(prefix: 'P', letters: true, length: 7)
6
- include NumberIdentifier
7
- include NumberAsParam
8
- include Metadata
6
+ include Spree::NumberIdentifier
7
+ include Spree::NumberAsParam
8
+ include Spree::Metadata
9
9
  if defined?(Spree::Webhooks)
10
10
  include Spree::Webhooks::HasWebhooks
11
11
  end
@@ -222,18 +222,10 @@ module Spree
222
222
 
223
223
  def validate_source
224
224
  if source && !source.valid?
225
- if Rails::VERSION::STRING >= '6.1'
226
- source.errors.map { |error| { field: error.attribute, message: error&.message } }.each do |err|
227
- next if err[:field].blank? || err[:message].blank?
228
-
229
- add_source_error(err[:field], err[:message])
230
- end
231
- else
232
- source.errors.messages.each do |field, error|
233
- next if field.blank? || error.empty?
234
-
235
- add_source_error(field, error.first)
236
- end
225
+ source.errors.map { |error| { field: error.attribute, message: error&.message } }.each do |err|
226
+ next if err[:field].blank? || err[:message].blank?
227
+
228
+ add_source_error(err[:field], err[:message])
237
229
  end
238
230
  end
239
231
  !errors.present?
@@ -3,7 +3,7 @@ module Spree
3
3
  acts_as_paranoid
4
4
  acts_as_list
5
5
 
6
- include MultiStoreResource
6
+ include Spree::MultiStoreResource
7
7
  include Spree::Metadata
8
8
  if defined?(Spree::Security::PaymentMethods)
9
9
  include Spree::Security::PaymentMethods
@@ -1,6 +1,6 @@
1
1
  module Spree
2
2
  class PaymentSource < Spree::Base
3
- include Metadata
3
+ include Spree::Metadata
4
4
 
5
5
  belongs_to :payment_method, class_name: 'Spree::PaymentMethod'
6
6
  belongs_to :user, class_name: 'Spree::User', optional: true
@@ -1,5 +1,9 @@
1
1
  class Spree::Preference < Spree::Base
2
- serialize :value
2
+ if Rails::VERSION::STRING >= '7.1.0'
3
+ serialize :value, coder: YAML
4
+ else
5
+ serialize :value
6
+ end
3
7
 
4
8
  validates :key, presence: true,
5
9
  uniqueness: { case_sensitive: false, allow_blank: true, scope: spree_base_uniqueness_scope }
@@ -1,6 +1,6 @@
1
1
  module Spree
2
2
  class Price < Spree::Base
3
- include VatPriceCalculation
3
+ include Spree::VatPriceCalculation
4
4
  if defined?(Spree::Webhooks)
5
5
  include Spree::Webhooks::HasWebhooks
6
6
  end
@@ -21,10 +21,12 @@
21
21
  module Spree
22
22
  class Product < Spree::Base
23
23
  extend FriendlyId
24
- include ProductScopes
25
- include MultiStoreResource
26
- include MemoizedData
27
- include Metadata
24
+ include Spree::ProductScopes
25
+ include Spree::MultiStoreResource
26
+ include Spree::TranslatableResource
27
+ include Spree::TranslatableResourceSlug
28
+ include Spree::MemoizedData
29
+ include Spree::Metadata
28
30
  if defined?(Spree::Webhooks)
29
31
  include Spree::Webhooks::HasWebhooks
30
32
  end
@@ -32,12 +34,36 @@ module Spree
32
34
  include Spree::VendorConcern
33
35
  end
34
36
 
35
- MEMOIZED_METHODS = %w(total_on_hand taxonomy_ids taxon_and_ancestors category
37
+ MEMOIZED_METHODS = %w[total_on_hand taxonomy_ids taxon_and_ancestors category
36
38
  default_variant_id tax_category default_variant
37
- purchasable? in_stock? backorderable?)
39
+ purchasable? in_stock? backorderable?]
40
+
41
+ TRANSLATABLE_FIELDS = %i[name description slug meta_description meta_keywords meta_title].freeze
42
+ translates(*TRANSLATABLE_FIELDS)
43
+
44
+ self::Translation.class_eval do
45
+ before_save :set_slug
46
+ acts_as_paranoid
47
+ # deleted translation values also need to be accessible for index views listing deleted resources
48
+ default_scope { unscope(where: :deleted_at) }
49
+ def set_slug
50
+ self.slug = generate_slug
51
+ end
52
+
53
+ private
38
54
 
39
- friendly_id :slug_candidates, use: :history
55
+ def generate_slug
56
+ if name.blank? && slug.blank?
57
+ translated_model.name.to_url
58
+ elsif slug.blank?
59
+ name.to_url
60
+ else
61
+ slug.to_url
62
+ end
63
+ end
64
+ end
40
65
 
66
+ friendly_id :slug_candidates, use: [:history, :mobility]
41
67
  acts_as_paranoid
42
68
  auto_strip_attributes :name
43
69
 
@@ -306,14 +332,26 @@ module Spree
306
332
  end
307
333
 
308
334
  def property(property_name)
309
- product_properties.joins(:property).find_by(spree_properties: { name: property_name }).try(:value)
335
+ product_properties.joins(:property).
336
+ join_translation_table(Property).
337
+ find_by(Property.translation_table_alias => { name: property_name }).try(:value)
310
338
  end
311
339
 
312
340
  def set_property(property_name, property_value, property_presentation = property_name)
313
341
  ApplicationRecord.transaction do
314
- # Works around spree_i18n #301
315
- property = Property.create_with(presentation: property_presentation).find_or_create_by(name: property_name)
316
- product_property = ProductProperty.where(product: self, property: property).first_or_initialize
342
+ # Manual first_or_create to work around Mobility bug
343
+ property = if Property.where(name: property_name).exists?
344
+ Property.where(name: property_name).first
345
+ else
346
+ Property.create(name: property_name, presentation: property_presentation)
347
+ end
348
+
349
+ product_property = if ProductProperty.where(product: self, property: property).exists?
350
+ ProductProperty.where(product: self, property: property).first
351
+ else
352
+ ProductProperty.create(product: self, property: property)
353
+ end
354
+
317
355
  product_property.value = property_value
318
356
  product_property.save!
319
357
  end
@@ -337,11 +375,16 @@ module Spree
337
375
  end
338
376
 
339
377
  def brand
340
- @brand ||= taxons.joins(:taxonomy).find_by(spree_taxonomies: { name: Spree.t(:taxonomy_brands_name) })
378
+ @brand ||= taxons.joins(:taxonomy).
379
+ join_translation_table(Taxonomy).
380
+ find_by(Taxonomy.translation_table_alias => { name: Spree.t(:taxonomy_brands_name) })
341
381
  end
342
382
 
343
383
  def category
344
- @category ||= taxons.joins(:taxonomy).order(depth: :desc).find_by(spree_taxonomies: { name: Spree.t(:taxonomy_categories_name) })
384
+ @category ||= taxons.joins(:taxonomy).
385
+ join_translation_table(Taxonomy).
386
+ order(depth: :desc).
387
+ find_by(Taxonomy.translation_table_alias => { name: Spree.t(:taxonomy_categories_name) })
345
388
  end
346
389
 
347
390
  def taxons_for_store(store)
@@ -415,7 +458,11 @@ module Spree
415
458
 
416
459
  def punch_slug
417
460
  # punch slug with date prefix to allow reuse of original
418
- update_column :slug, "#{Time.current.to_i}_#{slug}"[0..254] unless frozen?
461
+ return if frozen?
462
+
463
+ translations.with_deleted.each do |t|
464
+ t.update_column :slug, "#{Time.current.to_i}_#{t.slug}"[0..254]
465
+ end
419
466
  end
420
467
 
421
468
  def update_slug_history
@@ -460,18 +507,10 @@ module Spree
460
507
  # We call master.default_price here to ensure price is initialized.
461
508
  # Required to avoid Variant#check_price validation failing on create.
462
509
  unless master.default_price && master.valid?
463
- if Rails::VERSION::STRING >= '6.1'
464
- master.errors.map { |error| { field: error.attribute, message: error&.message } }.each do |err|
465
- next if err[:field].blank? || err[:message].blank?
466
-
467
- errors.add(err[:field], err[:message])
468
- end
469
- else
470
- master.errors.messages.each do |field, error|
471
- next if field.blank? || error.empty?
510
+ master.errors.map { |error| { field: error.attribute, message: error&.message } }.each do |err|
511
+ next if err[:field].blank? || err[:message].blank?
472
512
 
473
- errors.add(field, error.first)
474
- end
513
+ errors.add(err[:field], err[:message])
475
514
  end
476
515
  end
477
516
  end
@@ -1,8 +1,14 @@
1
1
  module Spree
2
2
  class ProductProperty < Spree::Base
3
3
  include Spree::FilterParam
4
+ include Spree::TranslatableResource
4
5
 
5
- auto_strip_attributes :value
6
+ TRANSLATABLE_FIELDS = %i[value filter_param].freeze
7
+ translates(*TRANSLATABLE_FIELDS)
8
+
9
+ self::Translation.class_eval do
10
+ auto_strip_attributes :value
11
+ end
6
12
 
7
13
  acts_as_list scope: :product
8
14
 
@@ -27,12 +33,15 @@ module Spree
27
33
  delegate :name, :presentation, to: :property, prefix: true, allow_nil: true
28
34
 
29
35
  def property_name=(name)
30
- ActiveSupport::Deprecation.warn(<<-DEPRECATION, caller)
36
+ Spree::Deprecation.warn(<<-DEPRECATION, caller)
31
37
  `ProductProperty#property_name=` is deprecated and will be removed in Spree 5.0.
32
38
  DEPRECATION
33
39
  if name.present?
34
- # don't use `find_by :name` to workaround globalize/globalize#423 bug
35
- self.property = Property.where(name: name).first_or_create(presentation: name)
40
+ self.property = if Property.where(name: name).exists?
41
+ Property.where(name: name).first
42
+ else
43
+ Property.create(name: name, presentation: name)
44
+ end
36
45
  end
37
46
  end
38
47
 
@@ -1,7 +1,7 @@
1
1
  module Spree
2
2
  class Promotion < Spree::Base
3
- include MultiStoreResource
4
- include Metadata
3
+ include Spree::MultiStoreResource
4
+ include Spree::Metadata
5
5
  if defined?(Spree::Webhooks)
6
6
  include Spree::Webhooks::HasWebhooks
7
7
  end
@@ -1,12 +1,18 @@
1
1
  module Spree
2
2
  class Property < Spree::Base
3
3
  include Spree::FilterParam
4
- include Metadata
4
+ include Spree::Metadata
5
+ include Spree::TranslatableResource
5
6
  if defined?(Spree::Webhooks)
6
7
  include Spree::Webhooks::HasWebhooks
7
8
  end
8
9
 
9
- auto_strip_attributes :name, :presentation
10
+ TRANSLATABLE_FIELDS = %i[name presentation filter_param].freeze
11
+ translates(*TRANSLATABLE_FIELDS)
12
+
13
+ self::Translation.class_eval do
14
+ auto_strip_attributes :name, :presentation
15
+ end
10
16
 
11
17
  has_many :property_prototypes, class_name: 'Spree::PropertyPrototype'
12
18
  has_many :prototypes, through: :property_prototypes, class_name: 'Spree::Prototype'
@@ -1,6 +1,6 @@
1
1
  module Spree
2
2
  class Prototype < Spree::Base
3
- include Metadata
3
+ include Spree::Metadata
4
4
  if defined?(Spree::Webhooks)
5
5
  include Spree::Webhooks::HasWebhooks
6
6
  end
@@ -1,6 +1,6 @@
1
1
  module Spree
2
2
  class Refund < Spree::Base
3
- include Metadata
3
+ include Spree::Metadata
4
4
  if defined?(Spree::Webhooks)
5
5
  include Spree::Webhooks::HasWebhooks
6
6
  end
@@ -1,7 +1,7 @@
1
1
  module Spree
2
2
  class Reimbursement < Spree::Base
3
3
  include Spree::Core::NumberGenerator.new(prefix: 'RI', length: 9)
4
- include NumberIdentifier
4
+ include Spree::NumberIdentifier
5
5
  if defined?(Spree::Webhooks)
6
6
  include Spree::Webhooks::HasWebhooks
7
7
  end
@@ -1,7 +1,7 @@
1
1
  module Spree
2
2
  class ReturnAuthorization < Spree::Base
3
3
  include Spree::Core::NumberGenerator.new(prefix: 'RA', length: 9)
4
- include NumberIdentifier
4
+ include Spree::NumberIdentifier
5
5
  if defined?(Spree::Webhooks)
6
6
  include Spree::Webhooks::HasWebhooks
7
7
  end
@@ -62,7 +62,11 @@ module Spree
62
62
  scope :exchange_required, -> { eager_load(:exchange_inventory_units).where(spree_inventory_units: { original_return_item_id: nil }).distinct }
63
63
  scope :resellable, -> { where resellable: true }
64
64
 
65
- serialize :acceptance_status_errors
65
+ if Rails::VERSION::STRING >= '7.1.0'
66
+ serialize :acceptance_status_errors, coder: YAML
67
+ else
68
+ serialize :acceptance_status_errors
69
+ end
66
70
 
67
71
  delegate :eligible_for_return?, :requires_manual_intervention?, to: :validator
68
72
  delegate :variant, to: :inventory_unit
@@ -1,6 +1,6 @@
1
1
  module Spree
2
2
  class Role < Spree::Base
3
- include UniqueName
3
+ include Spree::UniqueName
4
4
 
5
5
  has_many :role_users, class_name: 'Spree::RoleUser', dependent: :destroy
6
6
  has_many :users, through: :role_users, class_name: "::#{Spree.user_class}"
@@ -3,9 +3,9 @@ require 'ostruct'
3
3
  module Spree
4
4
  class Shipment < Spree::Base
5
5
  include Spree::Core::NumberGenerator.new(prefix: 'H', length: 11)
6
- include NumberIdentifier
7
- include NumberAsParam
8
- include Metadata
6
+ include Spree::NumberIdentifier
7
+ include Spree::NumberAsParam
8
+ include Spree::Metadata
9
9
  if defined?(Spree::Webhooks)
10
10
  include Spree::Webhooks::HasWebhooks
11
11
  end
@@ -249,8 +249,8 @@ module Spree
249
249
  end
250
250
 
251
251
  def selected_shipping_rate_id=(id)
252
- shipping_rates.update_all(selected: false)
253
- shipping_rates.touch_all # Bust cache dependent on "updated_at" timestamp
252
+ # Explicitly updates the timestamp in order to bust cache dependent on "updated_at"
253
+ shipping_rates.update_all(selected: false, updated_at: Time.current)
254
254
  shipping_rates.update(id, selected: true)
255
255
  save!
256
256
  end
@@ -1,6 +1,6 @@
1
1
  module Spree
2
2
  class ShippingCategory < Spree::Base
3
- include UniqueName
3
+ include Spree::UniqueName
4
4
  if defined?(Spree::Webhooks)
5
5
  include Spree::Webhooks::HasWebhooks
6
6
  end
@@ -2,7 +2,7 @@ module Spree
2
2
  class ShippingMethod < Spree::Base
3
3
  acts_as_paranoid
4
4
  include Spree::CalculatedAdjustments
5
- include Metadata
5
+ include Spree::Metadata
6
6
  if defined?(Spree::Webhooks)
7
7
  include Spree::Webhooks::HasWebhooks
8
8
  end
@@ -1,7 +1,7 @@
1
1
  module Spree
2
2
  module Stock
3
3
  class Estimator
4
- include VatPriceCalculation
4
+ include Spree::VatPriceCalculation
5
5
 
6
6
  attr_reader :order, :currency
7
7
 
@@ -15,7 +15,7 @@ module Spree
15
15
  private
16
16
 
17
17
  def reduce(package)
18
- contents = split_package_contents_over_threshold(package).sort { |x, y| y.weight <=> x.weight }
18
+ contents = split_package_contents_over_threshold(package).sort_by(&:weight).reverse
19
19
  # Treat current package as one of the generated packages for convenience and add the heaviest item
20
20
  # This also prevents an additional package if no fit is possible
21
21
  package.contents.clear