spree_core 5.0.4 → 5.1.0.beta2

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 (84) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/images/logo.png +0 -0
  3. data/app/finders/spree/countries/find.rb +0 -8
  4. data/app/finders/spree/products/find.rb +28 -1
  5. data/app/finders/spree/taxons/find.rb +1 -1
  6. data/app/helpers/spree/base_helper.rb +4 -16
  7. data/app/helpers/spree/integrations_helper.rb +15 -0
  8. data/app/helpers/spree/mail_helper.rb +4 -3
  9. data/app/helpers/spree/products_helper.rb +1 -4
  10. data/app/javascript/spree/core/controllers/disable_submit_button_controller.js +19 -0
  11. data/app/mailers/spree/invitation_mailer.rb +24 -0
  12. data/app/models/concerns/spree/integrations_concern.rb +11 -0
  13. data/app/models/concerns/spree/product_scopes.rb +6 -6
  14. data/app/models/concerns/spree/translatable_resource.rb +4 -0
  15. data/app/models/concerns/spree/translatable_resource_scopes.rb +17 -3
  16. data/app/models/concerns/spree/unique_name.rb +2 -0
  17. data/app/models/concerns/spree/user_management.rb +33 -0
  18. data/app/models/concerns/spree/user_methods.rb +19 -0
  19. data/app/models/concerns/spree/user_roles.rb +43 -17
  20. data/app/models/spree/ability.rb +8 -6
  21. data/app/models/spree/asset.rb +1 -6
  22. data/app/models/spree/base.rb +1 -0
  23. data/app/models/spree/base_analytics_event_handler.rb +7 -2
  24. data/app/models/spree/classification.rb +13 -0
  25. data/app/models/spree/custom_domain.rb +2 -1
  26. data/app/models/spree/export.rb +1 -1
  27. data/app/models/spree/integration.rb +63 -0
  28. data/app/models/spree/invitation.rb +153 -0
  29. data/app/models/spree/invitations/store.rb +6 -0
  30. data/app/models/spree/order.rb +16 -1
  31. data/app/models/spree/order_merger.rb +7 -5
  32. data/app/models/spree/product_property.rb +1 -14
  33. data/app/models/spree/property.rb +3 -1
  34. data/app/models/spree/reports/sales_total.rb +5 -1
  35. data/app/models/spree/role.rb +16 -0
  36. data/app/models/spree/role_user.rb +32 -1
  37. data/app/models/spree/shipment_handler.rb +1 -0
  38. data/app/models/spree/shipping_method.rb +1 -1
  39. data/app/models/spree/store.rb +9 -4
  40. data/app/models/spree/store_credit_category.rb +4 -0
  41. data/app/models/spree/taxon.rb +4 -3
  42. data/app/services/spree/country_to_timezone.rb +273 -0
  43. data/app/services/spree/seeds/admin_user.rb +4 -2
  44. data/app/services/spree/seeds/all.rb +3 -1
  45. data/app/services/spree/seeds/digital_delivery.rb +20 -0
  46. data/app/services/spree/seeds/returns_environment.rb +27 -0
  47. data/app/services/spree/seeds/tax_categories.rb +12 -0
  48. data/app/services/spree/stores/settings_defaults_by_country.rb +38 -0
  49. data/app/services/spree/tags/bulk_add.rb +13 -7
  50. data/app/views/spree/invitation_mailer/invitation_accepted.html.erb +12 -0
  51. data/app/views/spree/invitation_mailer/invitation_email.html.erb +21 -0
  52. data/config/locales/en.yml +43 -9
  53. data/db/migrate/20250407085228_create_spree_integrations.rb +12 -0
  54. data/db/migrate/20250410061306_create_spree_invitations.rb +20 -0
  55. data/db/migrate/20250418174652_add_resource_to_spree_role_users.rb +8 -0
  56. data/db/migrate/20250508060800_add_selected_locale_to_spree_admin_users.rb +8 -0
  57. data/db/migrate/20250509143831_add_session_id_to_spree_assets.rb +5 -0
  58. data/lib/generators/spree/authentication/devise/devise_generator.rb +5 -2
  59. data/lib/generators/spree/authentication/devise/templates/authentication_helpers.rb.tt +3 -3
  60. data/lib/generators/spree/dummy/dummy_generator.rb +1 -1
  61. data/lib/generators/spree/dummy/templates/app/assets/config/manifest.js +0 -0
  62. data/lib/generators/spree/dummy/templates/rails/application.rb +1 -2
  63. data/lib/generators/spree/install/install_generator.rb +5 -0
  64. data/lib/spree/core/controller_helpers/auth.rb +15 -14
  65. data/lib/spree/core/controller_helpers/common.rb +0 -71
  66. data/lib/spree/core/controller_helpers/currency.rb +11 -0
  67. data/lib/spree/core/controller_helpers/strong_parameters.rb +3 -2
  68. data/lib/spree/core/engine.rb +14 -3
  69. data/lib/spree/core/preferences/preferable.rb +10 -0
  70. data/lib/spree/core/preferences/preferable_class_methods.rb +52 -0
  71. data/lib/spree/core/version.rb +1 -1
  72. data/lib/spree/core.rb +1 -0
  73. data/lib/spree/permitted_attributes.rb +121 -13
  74. data/lib/spree/testing_support/controller_requests.rb +0 -92
  75. data/lib/spree/testing_support/factories/integration_factory.rb +7 -0
  76. data/lib/spree/testing_support/factories/invitation_factory.rb +6 -0
  77. data/lib/spree/testing_support/factories/page_block_factory.rb +1 -0
  78. data/lib/spree/testing_support/factories/promotion_action_factory.rb +4 -0
  79. data/lib/spree/testing_support/factories/user_factory.rb +14 -1
  80. data/lib/spree/translation_migrations.rb +27 -15
  81. data/lib/tasks/core.rake +8 -0
  82. metadata +43 -7
  83. data/app/validators/db_maximum_length_validator.rb +0 -16
  84. data/lib/generators/spree/dummy/templates/rails/script/rails +0 -6
@@ -0,0 +1,8 @@
1
+ class AddSelectedLocaleToSpreeAdminUsers < ActiveRecord::Migration[7.2]
2
+ def change
3
+ if Spree.admin_user_class.present?
4
+ users_table_name = Spree.admin_user_class.table_name
5
+ add_column users_table_name, :selected_locale, :string unless column_exists?(users_table_name, :selected_locale)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,5 @@
1
+ class AddSessionIdToSpreeAssets < ActiveRecord::Migration[7.2]
2
+ def change
3
+ add_column :spree_assets, :session_id, :string
4
+ end
5
+ end
@@ -33,6 +33,8 @@ module Spree
33
33
  include Spree::UserPaymentSource
34
34
  RUBY
35
35
  end
36
+ gsub_file user_class_file, "< ApplicationRecord", "< Spree.base_class"
37
+
36
38
  say "Successfully added Spree user modules into #{user_class_file}"
37
39
  else
38
40
  say "Could not locate user model file at #{user_class_file}. Please add these lines manually:", :red
@@ -42,13 +44,14 @@ module Spree
42
44
  include Spree::UserMethods
43
45
  include Spree::UserPaymentSource
44
46
  RUBY
47
+
48
+ say "Please replace < ApplicationRecord with < Spree.base_class in #{user_class_file}"
45
49
  end
46
50
 
47
51
  append_file 'config/initializers/spree.rb' do
48
52
  %Q{
49
53
  if defined?(Devise) && Devise.respond_to?(:parent_controller)
50
- Devise.parent_controller = "Spree::StoreController"
51
- Devise.parent_mailer = "Spree::BaseMailer"
54
+ Devise.parent_controller = "Spree::BaseController"
52
55
  end\n}
53
56
  end
54
57
  end
@@ -38,13 +38,13 @@ module Spree
38
38
  end
39
39
 
40
40
  def spree_admin_login_path(opts = {})
41
- spree_login_path(opts)
41
+ new_session_path(Spree.admin_user_class.model_name.singular_route_key, opts)
42
42
  end
43
43
 
44
44
  def spree_admin_logout_path(opts = {})
45
- spree_logout_path(opts)
45
+ destroy_session_path(Spree.admin_user_class.model_name.singular_route_key, opts)
46
46
  end
47
47
  end
48
48
  end
49
49
 
50
- ApplicationController.include Spree::AuthenticationHelpers if defined?(ApplicationController)
50
+ ApplicationController.include Spree::AuthenticationHelpers if defined?(ApplicationController)
@@ -54,8 +54,8 @@ module Spree
54
54
  template 'rails/application.rb', "#{dummy_path}/config/application.rb", force: true
55
55
  template 'rails/routes.rb', "#{dummy_path}/config/routes.rb", force: true
56
56
  template 'rails/test.rb', "#{dummy_path}/config/environments/test.rb", force: true
57
- template 'rails/script/rails', "#{dummy_path}/spec/dummy/script/rails", force: true
58
57
  template 'initializers/devise.rb', "#{dummy_path}/config/initializers/devise.rb", force: true
58
+ template "app/assets/config/manifest.js", "#{dummy_path}/app/assets/config/manifest.js", force: true
59
59
  end
60
60
 
61
61
  def test_dummy_inject_extension_requirements
@@ -2,9 +2,8 @@ require File.expand_path('../boot', __FILE__)
2
2
 
3
3
  require 'rails/all'
4
4
 
5
- Bundler.require(*Rails.groups(assets: %w(development test)))
5
+ Bundler.require(*Rails.groups)
6
6
 
7
7
  require '<%= lib_name %>'
8
8
 
9
9
  <%= application_definition %>
10
-
@@ -78,6 +78,11 @@ module Spree
78
78
  def install_storefront
79
79
  if @install_storefront && Spree::Core::Engine.frontend_available?
80
80
  generate 'spree:storefront:install'
81
+
82
+ # generate devise controllers if authentication is devise
83
+ if @authentication == 'devise'
84
+ generate 'spree:storefront:devise'
85
+ end
81
86
  end
82
87
  end
83
88
 
@@ -17,12 +17,12 @@ module Spree
17
17
 
18
18
  # Needs to be overridden so that we use Spree's Ability rather than anyone else's.
19
19
  def current_ability
20
- @current_ability ||= Spree::Dependencies.ability_class.constantize.new(try_spree_current_user)
20
+ @current_ability ||= Spree::Dependencies.ability_class.constantize.new(try_spree_current_user, { store: current_store })
21
21
  end
22
22
 
23
23
  def redirect_back_or_default(default)
24
- redirect_to(session['spree_user_return_to'] || request.env['HTTP_REFERER'] || default)
25
- session['spree_user_return_to'] = nil
24
+ Spree::Deprecation.warn('redirect_back_or_default is deprecated and will be removed in Spree 5.2. Please use redirect_back(fallback_location: default) instead.')
25
+ redirect_back(fallback_location: default)
26
26
  end
27
27
 
28
28
  def set_token
@@ -44,18 +44,19 @@ module Spree
44
44
  @current_oauth_token ||= get_last_access_token.call(user) || create_access_token.call(user)
45
45
  end
46
46
 
47
- def store_location
48
- # disallow return to login, logout, signup pages
49
- authentication_routes = [:spree_signup_path, :spree_login_path, :spree_logout_path]
50
- disallowed_urls = []
51
- authentication_routes.each do |route|
52
- disallowed_urls << send(route) if respond_to?(route)
53
- end
47
+ # this will work for devise out of the box
48
+ # for other auth systems you will need to override this method
49
+ def store_location(location = nil)
50
+ return if try_spree_current_user
54
51
 
55
- disallowed_urls.map! { |url| url[/\/\w+$/] }
56
- unless disallowed_urls.include?(request.fullpath)
57
- session['spree_user_return_to'] = request.fullpath.gsub('//', '/')
58
- end
52
+ location ||= request.fullpath
53
+ session_key = store_location_session_key
54
+
55
+ session[session_key] = location
56
+ end
57
+
58
+ def store_location_session_key
59
+ "#{Spree.user_class.model_name.singular_route_key.to_sym}_return_to"
59
60
  end
60
61
 
61
62
  # proxy method to *possible* spree_current_user method
@@ -2,77 +2,6 @@ module Spree
2
2
  module Core
3
3
  module ControllerHelpers
4
4
  module Common
5
- extend ActiveSupport::Concern
6
- included do
7
- helper_method :title
8
- helper_method :title=
9
- helper_method :accurate_title
10
-
11
- layout :get_layout
12
-
13
- protected
14
-
15
- # can be used in views as well as controllers.
16
- # e.g. <% self.title = 'This is a custom title for this view' %>
17
- attr_writer :title
18
-
19
- def title
20
- Spree::Deprecation.warn(<<-DEPRECATION, caller)
21
- ControllerHelpers::Common is deprecated and will be removed in Spree 5.0.
22
- DEPRECATION
23
- title_string = @title.present? ? @title : accurate_title
24
- if title_string.present?
25
- if Spree::Config[:always_put_site_name_in_title] && !title_string.include?(default_title)
26
- [title_string, default_title].join(" #{Spree::Config[:title_site_name_separator]} ")
27
- else
28
- title_string
29
- end
30
- else
31
- default_title
32
- end
33
- end
34
-
35
- def default_title
36
- Spree::Deprecation.warn(<<-DEPRECATION, caller)
37
- ControllerHelpers::Common is deprecated and will be removed in Spree 5.0.
38
- DEPRECATION
39
- current_store.name
40
- end
41
-
42
- # this is a hook for subclasses to provide title
43
- def accurate_title
44
- Spree::Deprecation.warn(<<-DEPRECATION, caller)
45
- ControllerHelpers::Common is deprecated and will be removed in Spree 5.0.
46
- DEPRECATION
47
- current_store.seo_title
48
- end
49
-
50
- private
51
-
52
- def set_user_language
53
- Spree::Deprecation.warn(<<-DEPRECATION, caller)
54
- ControllerHelpers::Common#set_user_language is deprecated and will be removed in Spree 5.0.
55
- Please use `before_action :set_locale` instead
56
- DEPRECATION
57
-
58
- set_locale
59
- end
60
-
61
- # Returns which layout to render.
62
- #
63
- # You can set the layout you want to render inside your Spree configuration with the +:layout+ option.
64
- #
65
- # Default layout is: +app/views/spree/layouts/spree_application+
66
- #
67
- def get_layout
68
- Spree::Deprecation.warn(<<-DEPRECATION, caller)
69
- ControllerHelpers::Common is deprecated and will be removed in Spree 5.0.
70
- DEPRECATION
71
- return unless defined?(Spree::Frontend)
72
-
73
- layout ||= Spree::Frontend::Config[:layout]
74
- end
75
- end
76
5
  end
77
6
  end
78
7
  end
@@ -14,6 +14,8 @@ module Spree
14
14
  end
15
15
  end
16
16
 
17
+ # Returns the currently selected currency.
18
+ # @return [String] the currently selected currency, eg. `USD`
17
19
  def current_currency
18
20
  @current_currency ||= if defined?(session) && session.key?(:currency) && supported_currency?(session[:currency])
19
21
  session[:currency]
@@ -26,10 +28,14 @@ module Spree
26
28
  end&.upcase
27
29
  end
28
30
 
31
+ # Returns the list of supported currencies for the current store.
32
+ # @return [Array<Money::Currency>] the list of supported currencies
29
33
  def supported_currencies
30
34
  @supported_currencies ||= current_store&.supported_currencies_list
31
35
  end
32
36
 
37
+ # Returns the list of supported currencies for all stores.
38
+ # @return [Array<String>] the list of supported currencies, eg. `["USD", "EUR"]`
33
39
  def supported_currencies_for_all_stores
34
40
  @supported_currencies_for_all_stores ||= begin
35
41
  (
@@ -39,12 +45,17 @@ module Spree
39
45
  end
40
46
  end
41
47
 
48
+ # Checks if the given currency is supported.
49
+ # @param currency_iso_code [String] the ISO code of the currency, eg. `USD`
50
+ # @return [Boolean] `true` if the currency is supported, `false` otherwise
42
51
  def supported_currency?(currency_iso_code)
43
52
  return false if supported_currencies.nil?
44
53
 
45
54
  supported_currencies.map(&:iso_code).include?(currency_iso_code.upcase)
46
55
  end
47
56
 
57
+ # Returns the currency parameter from the request.
58
+ # @return [String] the currency parameter, eg. `USD`
48
59
  def currency_param
49
60
  return if current_currency == current_store.default_currency
50
61
 
@@ -33,8 +33,9 @@ module Spree
33
33
 
34
34
  def permitted_product_attributes
35
35
  permitted_attributes.product_attributes + [
36
- :store_id,
37
- product_properties_attributes: permitted_product_properties_attributes
36
+ variants_attributes: permitted_variant_attributes + ['id', :_destroy],
37
+ master_attributes: permitted_variant_attributes + ['id'],
38
+ product_properties_attributes: permitted_product_properties_attributes + ['id', :_destroy]
38
39
  ]
39
40
  end
40
41
 
@@ -21,8 +21,10 @@ module Spree
21
21
  :page_sections,
22
22
  :page_blocks,
23
23
  :reports,
24
+ :translatable_resources,
24
25
  :analytics_events,
25
- :analytics_event_handlers)
26
+ :analytics_event_handlers,
27
+ :integrations)
26
28
  SpreeCalculators = Struct.new(:shipping_methods, :tax_rates, :promotion_actions_create_adjustments, :promotion_actions_create_item_adjustments)
27
29
  PromoEnvironment = Struct.new(:rules, :actions)
28
30
  isolate_namespace Spree
@@ -40,7 +42,7 @@ module Spree
40
42
  Spree::Config = app.config.spree.preferences
41
43
  Spree::RuntimeConfig = app.config.spree.preferences # for compatibility
42
44
  Spree::Dependencies = app.config.spree.dependencies
43
- Spree::Deprecation = ActiveSupport::Deprecation.new
45
+ Spree::Deprecation = ActiveSupport::Deprecation.new('6.0', 'Spree')
44
46
  end
45
47
 
46
48
  initializer 'spree.register.calculators', before: :after_initialize do |app|
@@ -234,6 +236,13 @@ module Spree
234
236
  Spree::Reports::SalesTotal
235
237
  ]
236
238
 
239
+ Rails.application.config.spree.translatable_resources = [
240
+ Spree::Product,
241
+ Spree::Taxon,
242
+ Spree::Taxonomy,
243
+ Spree::Store
244
+ ]
245
+
237
246
  Rails.application.config.spree.analytics_events = {
238
247
  product_viewed: 'Product Viewed',
239
248
  product_list_viewed: 'Product List Viewed',
@@ -257,9 +266,11 @@ module Spree
257
266
  checkout_email_entered: 'Checkout Email Entered',
258
267
  checkout_step_viewed: 'Checkout Step Viewed',
259
268
  checkout_step_completed: 'Checkout Step Completed',
260
- order_completed: 'Order Completed'
269
+ order_completed: 'Order Completed',
261
270
  }
262
271
  Rails.application.config.spree.analytics_event_handlers = []
272
+
273
+ Rails.application.config.spree.integrations = []
263
274
  end
264
275
 
265
276
  initializer 'spree.promo.register.promotions.actions' do |app|
@@ -108,6 +108,16 @@ module Spree::Preferences::Preferable
108
108
  preference_keys.each { |pref| preferences[pref] = preference_default(pref) }
109
109
  end
110
110
 
111
+ def preference_change(name, changes_or_previous_changes)
112
+ preference_changes = changes_or_previous_changes.with_indifferent_access.fetch('preferences', [{}, {}])
113
+ before_preferences = preference_changes[0] || {}
114
+ after_preferences = preference_changes[1] || {}
115
+
116
+ return if before_preferences[name] == after_preferences[name]
117
+
118
+ [before_preferences[name], after_preferences[name]]
119
+ end
120
+
111
121
  private
112
122
 
113
123
  def convert_preference_value(value, type, nullable: false)
@@ -43,6 +43,34 @@ module Spree::Preferences
43
43
  define_method prefers_query_method(name) do
44
44
  preferences.fetch(name).to_b
45
45
  end
46
+
47
+ define_method preference_change_method(name) do
48
+ preference_change(name, changes) if respond_to?(:changes)
49
+ end
50
+
51
+ define_method preference_was_method(name) do
52
+ return unless respond_to?(:changes)
53
+
54
+ preference_change(name, changes)&.first || get_preference(name)
55
+ end
56
+
57
+ define_method preference_changed_method(name) do
58
+ respond_to?(:changes) && preference_change(name, changes).present?
59
+ end
60
+
61
+ define_method preference_previous_change_method(name) do
62
+ preference_change(name, previous_changes) if respond_to?(:previous_changes)
63
+ end
64
+
65
+ define_method preference_previous_was_method(name) do
66
+ return unless respond_to?(:previous_changes)
67
+
68
+ preference_change(name, previous_changes)&.first
69
+ end
70
+
71
+ define_method preference_previous_changed_method(name) do
72
+ respond_to?(:previous_changes) && preference_change(name, previous_changes).present?
73
+ end
46
74
  end
47
75
 
48
76
  def preference_getter_method(name)
@@ -68,5 +96,29 @@ module Spree::Preferences
68
96
  def prefers_query_method(name)
69
97
  "prefers_#{name}?".to_sym
70
98
  end
99
+
100
+ def preference_change_method(name)
101
+ "preferred_#{name}_change".to_sym
102
+ end
103
+
104
+ def preference_was_method(name)
105
+ "preferred_#{name}_was".to_sym
106
+ end
107
+
108
+ def preference_changed_method(name)
109
+ "preferred_#{name}_changed?".to_sym
110
+ end
111
+
112
+ def preference_previous_change_method(name)
113
+ "preferred_#{name}_previous_change".to_sym
114
+ end
115
+
116
+ def preference_previous_was_method(name)
117
+ "preferred_#{name}_previously_was".to_sym
118
+ end
119
+
120
+ def preference_previous_changed_method(name)
121
+ "preferred_#{name}_previously_changed?".to_sym
122
+ end
71
123
  end
72
124
  end
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- VERSION = '5.0.4'.freeze
2
+ VERSION = '5.1.0.beta2'.freeze
3
3
 
4
4
  def self.version
5
5
  VERSION
data/lib/spree/core.rb CHANGED
@@ -31,6 +31,7 @@ require 'request_store'
31
31
  require 'wannabe_bool'
32
32
  require 'geocoder'
33
33
  require 'oembed'
34
+ require 'safely_block'
34
35
 
35
36
  # This is required because ActiveModel::Validations#invalid? conflicts with the
36
37
  # invalid state of a Payment. In the future this should be removed.