spree_core 5.4.3 → 5.5.0.rc2
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 +4 -4
- data/app/helpers/spree/base_helper.rb +0 -82
- data/app/helpers/spree/currency_helper.rb +0 -12
- data/app/helpers/spree/products_helper.rb +0 -8
- data/app/jobs/spree/base_job.rb +18 -0
- data/app/jobs/spree/events/subscriber_job.rb +2 -1
- data/app/jobs/spree/exports/generate_job.rb +11 -0
- data/app/jobs/spree/images/save_from_url_job.rb +23 -8
- data/app/jobs/spree/imports/assign_tags_job.rb +11 -0
- data/app/jobs/spree/imports/base_job.rb +15 -0
- data/app/jobs/spree/imports/create_categories_job.rb +37 -0
- data/app/jobs/spree/imports/create_rows_job.rb +1 -3
- data/app/jobs/spree/imports/process_group_job.rb +8 -6
- data/app/jobs/spree/imports/process_rows_job.rb +1 -3
- data/app/jobs/spree/media/migrate_product_assets_job.rb +83 -0
- data/app/jobs/spree/products/refresh_metrics_job.rb +15 -4
- data/app/jobs/spree/reports/generate_job.rb +11 -0
- data/app/jobs/spree/search_provider/index_job.rb +5 -1
- data/app/jobs/spree/search_provider/remove_job.rb +4 -0
- data/app/jobs/spree/stock_reservations/expire_job.rb +11 -0
- data/app/models/concerns/spree/calculated_adjustments.rb +34 -1
- data/app/models/concerns/spree/display_on.rb +31 -0
- data/app/models/concerns/spree/metafields.rb +167 -5
- data/app/models/concerns/spree/preference_schema.rb +191 -0
- data/app/models/concerns/spree/prefixed_id.rb +94 -11
- data/app/models/concerns/spree/product_scopes.rb +36 -17
- data/app/models/concerns/spree/ransackable_attributes.rb +5 -1
- data/app/models/concerns/spree/search_indexable.rb +8 -7
- data/app/models/concerns/spree/searchable.rb +11 -2
- data/app/models/concerns/spree/stores/channels.rb +20 -0
- data/app/models/concerns/spree/stores/markets.rb +21 -5
- data/app/models/concerns/spree/typed_associations.rb +120 -0
- data/app/models/concerns/spree/user_methods.rb +71 -12
- data/app/models/spree/ability.rb +4 -117
- data/app/models/spree/api_key.rb +60 -0
- data/app/models/spree/asset.rb +28 -5
- data/app/models/spree/authentication/strategy_registry.rb +72 -0
- data/app/models/spree/base.rb +18 -1
- data/app/models/spree/channel.rb +159 -0
- data/app/models/spree/country.rb +2 -0
- data/app/models/spree/current.rb +7 -3
- data/app/models/spree/custom_field.rb +9 -0
- data/app/models/spree/custom_field_definition.rb +7 -0
- data/app/models/spree/customer_group.rb +8 -2
- data/app/models/spree/export.rb +45 -3
- data/app/models/spree/exports/coupon_codes.rb +4 -0
- data/app/models/spree/exports/newsletter_subscribers.rb +4 -0
- data/app/models/spree/exports/product_translations.rb +4 -0
- data/app/models/spree/gateway.rb +25 -0
- data/app/models/spree/gift_card.rb +1 -1
- data/app/models/spree/gift_card_batch.rb +4 -1
- data/app/models/spree/import.rb +5 -0
- data/app/models/spree/import_row.rb +12 -0
- data/app/models/spree/line_item.rb +6 -1
- data/app/models/spree/market.rb +32 -1
- data/app/models/spree/metafield.rb +38 -0
- data/app/models/spree/metafield_definition.rb +29 -6
- data/app/models/spree/metafields/json.rb +10 -0
- data/app/models/spree/newsletter_subscriber.rb +19 -3
- data/app/models/spree/option_type.rb +48 -7
- data/app/models/spree/order/checkout.rb +3 -3
- data/app/models/spree/order.rb +102 -6
- data/app/models/spree/order_approval.rb +19 -0
- data/app/models/spree/order_cancellation.rb +19 -0
- data/app/models/spree/order_routing/has_strategy_preference.rb +28 -0
- data/app/models/spree/order_routing/rules/default_location.rb +16 -0
- data/app/models/spree/order_routing/rules/minimize_splits.rb +45 -0
- data/app/models/spree/order_routing/rules/preferred_location.rb +22 -0
- data/app/models/spree/order_routing/strategy/base.rb +47 -0
- data/app/models/spree/order_routing/strategy/legacy.rb +33 -0
- data/app/models/spree/order_routing/strategy/reducer.rb +68 -0
- data/app/models/spree/order_routing/strategy/rules.rb +83 -0
- data/app/models/spree/order_routing_rule.rb +75 -0
- data/app/models/spree/permission_sets/configuration_management.rb +16 -0
- data/app/models/spree/permission_sets/product_display.rb +2 -0
- data/app/models/spree/permission_sets/product_management.rb +2 -0
- data/app/models/spree/price.rb +14 -1
- data/app/models/spree/price_list.rb +129 -17
- data/app/models/spree/price_rule.rb +11 -1
- data/app/models/spree/price_rules/customer_group_rule.rb +15 -1
- data/app/models/spree/price_rules/market_rule.rb +16 -1
- data/app/models/spree/price_rules/user_rule.rb +21 -2
- data/app/models/spree/product/channels.rb +149 -0
- data/app/models/spree/product/legacy_multi_store_support.rb +40 -0
- data/app/models/spree/product/slugs.rb +1 -1
- data/app/models/spree/product.rb +172 -31
- data/app/models/spree/product_publication.rb +43 -0
- data/app/models/spree/promotion/actions/create_adjustment.rb +4 -0
- data/app/models/spree/promotion/actions/create_item_adjustments.rb +4 -0
- data/app/models/spree/promotion/actions/create_line_items.rb +32 -14
- data/app/models/spree/promotion/rules/country.rb +40 -18
- data/app/models/spree/promotion/rules/customer_group.rb +10 -1
- data/app/models/spree/promotion/rules/product.rb +4 -0
- data/app/models/spree/promotion/rules/taxon.rb +24 -1
- data/app/models/spree/promotion/rules/user.rb +21 -0
- data/app/models/spree/promotion/rules/user_logged_in.rb +6 -0
- data/app/models/spree/promotion.rb +22 -1
- data/app/models/spree/promotion_action.rb +17 -11
- data/app/models/spree/promotion_rule.rb +17 -18
- data/app/models/spree/search_provider/meilisearch.rb +12 -2
- data/app/models/spree/stock/availability_validator.rb +1 -1
- data/app/models/spree/stock/quantifier.rb +89 -9
- data/app/models/spree/stock_item.rb +36 -0
- data/app/models/spree/stock_location.rb +52 -0
- data/app/models/spree/stock_reservation.rb +38 -0
- data/app/models/spree/stock_reservations/insufficient_stock_error.rb +12 -0
- data/app/models/spree/store.rb +18 -72
- data/app/models/spree/store_credit.rb +0 -8
- data/app/models/spree/store_product.rb +11 -23
- data/app/models/spree/taxon.rb +0 -5
- data/app/models/spree/user_identity.rb +1 -2
- data/app/models/spree/variant.rb +132 -18
- data/app/models/spree/variant_media.rb +46 -0
- data/app/models/spree/webhook_delivery.rb +1 -1
- data/app/models/spree/webhook_endpoint.rb +24 -0
- data/app/models/spree/wished_item.rb +0 -13
- data/app/presenters/spree/csv/product_variant_presenter.rb +23 -3
- data/app/presenters/spree/search_provider/product_presenter.rb +11 -4
- data/app/presenters/spree/variant_presenter.rb +4 -3
- data/app/services/spree/addresses/update.rb +6 -8
- data/app/services/spree/cart/add_item.rb +10 -0
- data/app/services/spree/cart/empty.rb +2 -0
- data/app/services/spree/cart/remove_line_item.rb +10 -0
- data/app/services/spree/cart/remove_out_of_stock_items.rb +1 -1
- data/app/services/spree/cart/set_quantity.rb +10 -0
- data/app/services/spree/carts/complete.rb +1 -0
- data/app/services/spree/carts/create.rb +1 -0
- data/app/services/spree/carts/update.rb +18 -2
- data/app/services/spree/carts/upsert_items.rb +6 -6
- data/app/services/spree/imports/row_processors/customer.rb +4 -1
- data/app/services/spree/imports/row_processors/product_variant.rb +95 -57
- data/app/services/spree/newsletter/link_user.rb +53 -0
- data/app/services/spree/newsletter/subscribe.rb +31 -9
- data/app/services/spree/orders/approve.rb +27 -6
- data/app/services/spree/orders/build_shipments.rb +29 -0
- data/app/services/spree/orders/cancel.rb +34 -3
- data/app/services/spree/orders/complete.rb +53 -0
- data/app/services/spree/orders/create.rb +156 -0
- data/app/services/spree/orders/update.rb +51 -0
- data/app/services/spree/orders/upsert_items.rb +70 -0
- data/app/services/spree/prices/bulk_upsert.rb +201 -0
- data/app/services/spree/products/duplicator.rb +1 -1
- data/app/services/spree/products/prepare_nested_attributes.rb +2 -30
- data/app/services/spree/sample_data/loader.rb +30 -0
- data/app/services/spree/stock_reservations/extend.rb +19 -0
- data/app/services/spree/stock_reservations/release.rb +12 -0
- data/app/services/spree/stock_reservations/reserve.rb +103 -0
- data/app/services/spree/taxons/remove_products.rb +7 -1
- data/app/subscribers/spree/product_metrics_subscriber.rb +3 -7
- data/app/views/spree/invitation_mailer/invitation_email.html.erb +4 -0
- data/config/locales/en.yml +28 -10
- data/config/routes.rb +9 -0
- data/db/migrate/20260429000001_create_spree_order_cancellations.rb +25 -0
- data/db/migrate/20260429000002_create_spree_order_approvals.rb +22 -0
- data/db/migrate/20260429000003_add_status_to_spree_orders.rb +6 -0
- data/db/migrate/20260429000004_add_scopes_to_spree_api_keys.rb +11 -0
- data/db/migrate/20260501000001_create_spree_stock_reservations.rb +19 -0
- data/db/migrate/20260507162651_create_spree_variant_media.rb +23 -0
- data/db/migrate/20260508175303_add_pickup_to_spree_stock_locations.rb +12 -0
- data/db/migrate/20260508204040_create_spree_channels.rb +18 -0
- data/db/migrate/20260508204041_create_spree_order_routing_rules.rb +18 -0
- data/db/migrate/20260508204042_add_preferred_stock_location_to_spree_orders.rb +5 -0
- data/db/migrate/20260508204043_add_channel_id_to_spree_orders.rb +10 -0
- data/db/migrate/20260511000001_backfill_status_on_spree_orders.rb +57 -0
- data/db/migrate/20260515000001_add_store_id_to_spree_newsletter_subscribers.rb +25 -0
- data/db/migrate/20260529000001_add_unique_index_to_spree_price_rules.rb +41 -0
- data/db/migrate/20260529000002_add_unique_index_to_spree_promotion_rules.rb +37 -0
- data/db/migrate/20260601000001_create_spree_product_publications.rb +14 -0
- data/db/migrate/20260601000002_add_store_id_to_spree_products.rb +16 -0
- data/db/migrate/20260602000001_add_default_to_spree_channels.rb +14 -0
- data/db/migrate/20260612000001_change_spree_user_identities_info_to_jsonb.rb +13 -0
- data/db/sample_data/channels.rb +12 -0
- data/db/sample_data/orders.rb +1 -1
- data/db/sample_data/products.csv +212 -212
- data/lib/generators/spree/api_resource/api_resource_generator.rb +353 -0
- data/lib/generators/spree/api_resource/templates/admin_controller.rb.tt +23 -0
- data/lib/generators/spree/api_resource/templates/admin_controller_spec.rb.tt +59 -0
- data/lib/generators/spree/api_resource/templates/admin_serializer.rb.tt +11 -0
- data/lib/generators/spree/api_resource/templates/factory.rb.tt +26 -0
- data/lib/generators/spree/api_resource/templates/store_aliased_serializer.rb.tt +12 -0
- data/lib/generators/spree/api_resource/templates/store_controller.rb.tt +31 -0
- data/lib/generators/spree/api_resource/templates/store_controller_spec.rb.tt +61 -0
- data/lib/generators/spree/api_resource/templates/store_serializer.rb.tt +17 -0
- data/lib/generators/spree/controller_decorator/controller_decorator_generator.rb +66 -0
- data/lib/generators/spree/controller_decorator/templates/controller_decorator.rb.tt +25 -0
- data/lib/generators/spree/model/model_generator.rb +73 -7
- data/lib/generators/spree/model/templates/create_table_migration.rb.tt +40 -0
- data/lib/generators/spree/model/templates/model.rb.tt +28 -2
- data/lib/generators/spree/subscriber/subscriber_generator.rb +116 -0
- data/lib/generators/spree/subscriber/templates/subscriber.rb.tt +17 -0
- data/lib/generators/spree/subscriber/templates/subscriber_spec.rb.tt +9 -0
- data/lib/spree/core/configuration.rb +7 -0
- data/lib/spree/core/controller_helpers/auth.rb +0 -12
- data/lib/spree/core/controller_helpers/currency.rb +0 -17
- data/lib/spree/core/controller_helpers/order.rb +0 -19
- data/lib/spree/core/dependencies.rb +5 -2
- data/lib/spree/core/engine.rb +54 -7
- data/lib/spree/core/permission_configuration.rb +15 -0
- data/lib/spree/core/preferences/masking.rb +47 -0
- data/lib/spree/core/preferences/preferable_class_methods.rb +7 -1
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/core.rb +56 -5
- data/lib/spree/permitted_attributes.rb +9 -7
- data/lib/spree/testing_support/factories/address_factory.rb +16 -9
- data/lib/spree/testing_support/factories/api_key_factory.rb +1 -0
- data/lib/spree/testing_support/factories/channel_factory.rb +8 -0
- data/lib/spree/testing_support/factories/line_item_factory.rb +2 -8
- data/lib/spree/testing_support/factories/newsletter_subscriber_factory.rb +2 -0
- data/lib/spree/testing_support/factories/product_factory.rb +16 -7
- data/lib/spree/testing_support/factories/product_publication_factory.rb +6 -0
- data/lib/spree/testing_support/factories/refresh_token_factory.rb +15 -0
- data/lib/spree/testing_support/factories/stock_location_factory.rb +2 -2
- data/lib/spree/testing_support/factories/stock_reservation_factory.rb +31 -0
- data/lib/spree/testing_support/factories/variant_factory.rb +3 -3
- data/lib/spree/testing_support/order_walkthrough.rb +1 -1
- data/lib/spree/testing_support/store.rb +10 -0
- data/lib/spree/upgrades/5_4_to_5_5/manifest.yml +53 -0
- data/lib/tasks/channels.rake +94 -0
- data/lib/tasks/cli.rake +2 -1
- data/lib/tasks/core.rake +1 -0
- data/lib/tasks/media.rake +27 -0
- data/lib/tasks/products.rake +4 -6
- data/lib/tasks/publications.rake +60 -0
- data/lib/tasks/upgrade.rake +211 -0
- metadata +87 -18
- data/app/finders/spree/variants/visible_finder.rb +0 -23
- data/app/paginators/spree/shared/paginate.rb +0 -30
- data/app/presenters/spree/filters/price_presenter.rb +0 -23
- data/app/presenters/spree/filters/price_range_presenter.rb +0 -30
- data/app/presenters/spree/filters/quantified_price_range_presenter.rb +0 -45
- data/app/presenters/spree/product_summary_presenter.rb +0 -27
- data/app/presenters/spree/variants/options_presenter.rb +0 -82
- data/app/services/spree/classifications/reposition.rb +0 -23
- data/app/sorters/spree/orders/sort.rb +0 -10
- data/lib/spree/core/controller_helpers/common.rb +0 -14
- data/lib/spree/core/token_generator.rb +0 -23
- data/lib/spree/database_type_utilities.rb +0 -22
- data/lib/spree/testing_support/bar_ability.rb +0 -14
- data/lib/spree/testing_support/factories/store_product_factory.rb +0 -6
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<% if namespace_chain.empty? -%>
|
|
2
|
+
module Spree
|
|
3
|
+
module <%= decorator_name %>
|
|
4
|
+
def self.prepended(base)
|
|
5
|
+
# base.before_action :my_filter
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
# add custom methods here
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
Spree::<%= controller_name %>.prepend Spree::<%= decorator_name %>
|
|
13
|
+
<% else -%>
|
|
14
|
+
module Spree::<%= namespace_chain %>
|
|
15
|
+
module <%= decorator_name %>
|
|
16
|
+
def self.prepended(base)
|
|
17
|
+
# base.before_action :my_filter
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# add custom methods here
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
<%= prepend_invocation %>
|
|
25
|
+
<% end -%>
|
|
@@ -2,20 +2,86 @@ require "rails/generators/active_record/model/model_generator"
|
|
|
2
2
|
|
|
3
3
|
module Spree
|
|
4
4
|
class ModelGenerator < ActiveRecord::Generators::ModelGenerator
|
|
5
|
-
|
|
6
5
|
def self.source_paths
|
|
7
|
-
|
|
8
|
-
paths << File.expand_path('templates', __dir__)
|
|
9
|
-
paths.flatten
|
|
6
|
+
[File.expand_path('templates', __dir__), *superclass.source_paths]
|
|
10
7
|
end
|
|
11
8
|
|
|
12
|
-
class_option :parent,
|
|
9
|
+
class_option :parent,
|
|
10
|
+
type: :string,
|
|
11
|
+
default: 'Spree.base_class',
|
|
12
|
+
desc: 'The parent class expression for the generated model'
|
|
13
|
+
|
|
14
|
+
class_option :id_prefix,
|
|
15
|
+
type: :string,
|
|
16
|
+
desc: 'Prefix for prefixed IDs (default: snake_cased class name, e.g. brand)'
|
|
17
|
+
|
|
18
|
+
class_option :paranoid,
|
|
19
|
+
type: :boolean,
|
|
20
|
+
default: false,
|
|
21
|
+
desc: 'Enable acts_as_paranoid soft-delete (adds deleted_at column + index)'
|
|
22
|
+
|
|
23
|
+
class_option :metafields,
|
|
24
|
+
type: :boolean,
|
|
25
|
+
default: false,
|
|
26
|
+
desc: 'Include Spree::Metafields and Spree::Metadata concerns'
|
|
13
27
|
|
|
14
|
-
desc 'Creates a new Spree model'
|
|
28
|
+
desc 'Creates a new Spree model with prefixed IDs and Spree.base_class parent'
|
|
15
29
|
|
|
16
|
-
# Override to prevent module file from being created
|
|
17
30
|
def create_module_file
|
|
18
31
|
return
|
|
19
32
|
end
|
|
33
|
+
|
|
34
|
+
no_tasks do
|
|
35
|
+
def id_prefix
|
|
36
|
+
options[:id_prefix] || file_name
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def paranoid?
|
|
40
|
+
options[:paranoid]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def metafields?
|
|
44
|
+
options[:metafields]
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def class_path
|
|
48
|
+
['spree']
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def table_name
|
|
52
|
+
"spree_#{super.delete_prefix('spree_')}"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Resolution: explicit class hint in attribute spec → Spree.user_class
|
|
56
|
+
# for user-named columns → Spree.admin_user_class for admin-user-named
|
|
57
|
+
# columns → Spree::<CamelCasedName> default. The Rails attribute parser
|
|
58
|
+
# splits on `:` so explicit hints can only be unqualified names; users
|
|
59
|
+
# needing a namespace edit the generated belongs_to.
|
|
60
|
+
def belongs_to_class_name_expr(attribute)
|
|
61
|
+
explicit = attribute.attr_options.keys.find { |k| k.to_s.match?(/\A(::)?[A-Z]/) }
|
|
62
|
+
return "'#{explicit}'" if explicit
|
|
63
|
+
|
|
64
|
+
case attribute.name
|
|
65
|
+
when 'user', 'user_id'
|
|
66
|
+
'"::#{Spree.user_class}"'
|
|
67
|
+
when 'admin_user', 'admin_user_id', 'created_by', 'created_by_id',
|
|
68
|
+
'approver', 'approver_id', 'canceler', 'canceler_id'
|
|
69
|
+
'"::#{Spree.admin_user_class}"'
|
|
70
|
+
else
|
|
71
|
+
"'Spree::#{attribute.name.camelize}'"
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def column_default_for(attribute)
|
|
76
|
+
return nil unless attribute.attr_options.key?(:default)
|
|
77
|
+
|
|
78
|
+
value = attribute.attr_options[:default]
|
|
79
|
+
case value
|
|
80
|
+
when true, false, nil then value.inspect
|
|
81
|
+
when Numeric then value.to_s
|
|
82
|
+
else value.to_s.inspect
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
20
86
|
end
|
|
21
87
|
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
|
|
2
|
+
def change
|
|
3
|
+
create_table :<%= table_name %><%= primary_key_type %> do |t|
|
|
4
|
+
<% attributes.reject(&:reference?).reject(&:virtual?).each do |attribute| -%>
|
|
5
|
+
<% if attribute.password_digest? -%>
|
|
6
|
+
t.string :password_digest, null: false
|
|
7
|
+
<% elsif attribute.token? -%>
|
|
8
|
+
t.string :<%= attribute.name %>, null: false
|
|
9
|
+
<% else -%>
|
|
10
|
+
<% default_expr = column_default_for(attribute) -%>
|
|
11
|
+
t.<%= attribute.type %> :<%= attribute.name %>, null: false<%= ", default: #{default_expr}" if default_expr %>
|
|
12
|
+
<% end -%>
|
|
13
|
+
<% end -%>
|
|
14
|
+
<% attributes.select(&:reference?).each do |attribute| -%>
|
|
15
|
+
t.references :<%= attribute.name %>, null: false, index: true, foreign_key: false<%= ', polymorphic: true' if attribute.polymorphic? %>
|
|
16
|
+
<% end -%>
|
|
17
|
+
<% if paranoid? -%>
|
|
18
|
+
t.datetime :deleted_at
|
|
19
|
+
|
|
20
|
+
<% end -%>
|
|
21
|
+
<% if options[:timestamps] -%>
|
|
22
|
+
t.timestamps
|
|
23
|
+
<% end -%>
|
|
24
|
+
end
|
|
25
|
+
<% attributes.select(&:token?).each do |attribute| -%>
|
|
26
|
+
add_index :<%= table_name %>, :<%= attribute.name %>, unique: true,
|
|
27
|
+
name: 'index_<%= table_name %>_on_<%= attribute.name %>'
|
|
28
|
+
<% end -%>
|
|
29
|
+
<% attributes.select(&:has_uniq_index?).reject(&:token?).each do |attribute| -%>
|
|
30
|
+
add_index :<%= table_name %>, :<%= attribute.name %>, unique: true,
|
|
31
|
+
name: 'index_<%= table_name %>_on_<%= attribute.name %>'
|
|
32
|
+
<% end -%>
|
|
33
|
+
<% attributes.select { |a| a.has_index? && !a.has_uniq_index? && !a.reference? && !a.token? }.each do |attribute| -%>
|
|
34
|
+
add_index :<%= table_name %>, :<%= attribute.name %>
|
|
35
|
+
<% end -%>
|
|
36
|
+
<% if paranoid? -%>
|
|
37
|
+
add_index :<%= table_name %>, :deleted_at
|
|
38
|
+
<% end -%>
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -1,7 +1,22 @@
|
|
|
1
1
|
module Spree
|
|
2
|
-
class <%= class_name.demodulize %> < <%= parent_class_name
|
|
2
|
+
class <%= class_name.demodulize %> < <%= parent_class_name %>
|
|
3
|
+
<% if metafields? -%>
|
|
4
|
+
include Spree::Metafields
|
|
5
|
+
include Spree::Metadata
|
|
6
|
+
|
|
7
|
+
<% end -%>
|
|
8
|
+
<% if paranoid? -%>
|
|
9
|
+
acts_as_paranoid
|
|
10
|
+
|
|
11
|
+
<% end -%>
|
|
12
|
+
has_prefix_id :<%= id_prefix %>
|
|
13
|
+
|
|
3
14
|
<% attributes.select(&:reference?).each do |attribute| -%>
|
|
4
|
-
|
|
15
|
+
<% if attribute.polymorphic? -%>
|
|
16
|
+
belongs_to :<%= attribute.name %>, polymorphic: true
|
|
17
|
+
<% else -%>
|
|
18
|
+
belongs_to :<%= attribute.name %>, class_name: <%= belongs_to_class_name_expr(attribute) %>
|
|
19
|
+
<% end -%>
|
|
5
20
|
<% end -%>
|
|
6
21
|
<% attributes.select(&:rich_text?).each do |attribute| -%>
|
|
7
22
|
has_rich_text :<%= attribute.name %>
|
|
@@ -18,5 +33,16 @@ module Spree
|
|
|
18
33
|
<% if attributes.any?(&:password_digest?) -%>
|
|
19
34
|
has_secure_password
|
|
20
35
|
<% end -%>
|
|
36
|
+
<% required_attrs = attributes.reject { |a| a.reference? || a.type == :boolean || a.token? || a.attachment? || a.attachments? || a.rich_text? || a.password_digest? } -%>
|
|
37
|
+
<% if required_attrs.any? %>
|
|
38
|
+
<% required_attrs.each do |attr| -%>
|
|
39
|
+
validates :<%= attr.name %>, presence: true<% if attr.has_uniq_index? %>, uniqueness: { scope: spree_base_uniqueness_scope }<% end %>
|
|
40
|
+
|
|
41
|
+
<% end -%>
|
|
42
|
+
<% end -%>
|
|
43
|
+
<% ransackable = attributes.reject { |a| a.reference? || a.attachment? || a.attachments? || a.rich_text? || a.token? || a.password_digest? }.map(&:name) -%>
|
|
44
|
+
self.whitelisted_ransackable_attributes = %w[<%= ransackable.join(' ') %>]
|
|
45
|
+
self.whitelisted_ransackable_associations = %w[]
|
|
46
|
+
self.whitelisted_ransackable_scopes = %w[]
|
|
21
47
|
end
|
|
22
48
|
end
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Spree
|
|
4
|
+
# spree:subscriber — scaffold an event subscriber and register it.
|
|
5
|
+
#
|
|
6
|
+
# bin/rails g spree:subscriber OmsOrderSync order.completed order.canceled
|
|
7
|
+
# bin/rails g spree:subscriber MyApp::BrandSync brand.created brand.updated
|
|
8
|
+
# bin/rails g spree:subscriber CriticalSync order.completed --sync
|
|
9
|
+
#
|
|
10
|
+
# Subscribers are not auto-discovered — they must be appended to the
|
|
11
|
+
# Spree.subscribers array. Forgetting that step produces a silent no-op,
|
|
12
|
+
# so this generator also maintains the registration in
|
|
13
|
+
# config/initializers/spree.rb with an idempotent line per subscriber.
|
|
14
|
+
class SubscriberGenerator < Rails::Generators::NamedBase
|
|
15
|
+
desc 'Creates a Spree event subscriber and registers it in an initializer'
|
|
16
|
+
|
|
17
|
+
# Every Spree app ships config/initializers/spree.rb (created by
|
|
18
|
+
# spree:install) — registrations go there rather than into a second
|
|
19
|
+
# initializer file.
|
|
20
|
+
INITIALIZER_PATH = 'config/initializers/spree.rb'
|
|
21
|
+
REGISTRATION_ANCHOR = "Rails.application.config.after_initialize do\n"
|
|
22
|
+
|
|
23
|
+
argument :events, type: :array, default: [], banner: 'event.name event.name'
|
|
24
|
+
|
|
25
|
+
class_option :sync,
|
|
26
|
+
type: :boolean,
|
|
27
|
+
default: false,
|
|
28
|
+
desc: 'Run the subscriber synchronously (async: false) instead of via ActiveJob'
|
|
29
|
+
|
|
30
|
+
class_option :skip_spec,
|
|
31
|
+
type: :boolean,
|
|
32
|
+
default: false,
|
|
33
|
+
desc: "Don't generate a spec file"
|
|
34
|
+
|
|
35
|
+
def self.source_paths
|
|
36
|
+
[File.expand_path('templates', __dir__), *superclass.source_paths]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def create_subscriber_file
|
|
40
|
+
template 'subscriber.rb.tt', File.join('app/subscribers', class_path, "#{subscriber_file_name}.rb")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def register_subscriber
|
|
44
|
+
if File.exist?(destination_path(INITIALIZER_PATH))
|
|
45
|
+
content = File.read(destination_path(INITIALIZER_PATH))
|
|
46
|
+
if content.include?(registration_line.strip)
|
|
47
|
+
say_status :identical, "#{INITIALIZER_PATH} (#{subscriber_class_name} already registered)", :blue
|
|
48
|
+
elsif content.include?(REGISTRATION_ANCHOR)
|
|
49
|
+
inject_into_file INITIALIZER_PATH, registration_line, after: REGISTRATION_ANCHOR
|
|
50
|
+
else
|
|
51
|
+
append_to_file INITIALIZER_PATH, registration_block
|
|
52
|
+
end
|
|
53
|
+
else
|
|
54
|
+
create_file INITIALIZER_PATH, registration_block.lstrip
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def create_spec_file
|
|
59
|
+
return if options[:skip_spec]
|
|
60
|
+
|
|
61
|
+
template 'subscriber_spec.rb.tt', File.join('spec/subscribers', class_path, "#{subscriber_file_name}_spec.rb")
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def warn_about_missing_events
|
|
65
|
+
return if events.any?
|
|
66
|
+
|
|
67
|
+
say_status :note, "no events given — edit `subscribes_to` in the generated subscriber (e.g. 'order.completed')", :yellow
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
private
|
|
71
|
+
|
|
72
|
+
# "OmsOrderSync" and "OmsOrderSyncSubscriber" both produce
|
|
73
|
+
# OmsOrderSyncSubscriber / oms_order_sync_subscriber.
|
|
74
|
+
def bare_subscriber_name
|
|
75
|
+
base = class_name.demodulize.sub(/Subscriber\z/, '')
|
|
76
|
+
"#{base}Subscriber"
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def subscriber_file_name
|
|
80
|
+
bare_subscriber_name.underscore
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def subscriber_class_name
|
|
84
|
+
(class_path.map { |part| part.camelize } + [bare_subscriber_name]).join('::')
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def namespace_modules
|
|
88
|
+
class_path.map(&:camelize)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def subscribes_to_arguments
|
|
92
|
+
listed = events.any? ? events.map { |e| "'#{e}'" } : ["'TODO.replace_with_event_name'"]
|
|
93
|
+
listed << 'async: false' if options[:sync]
|
|
94
|
+
listed.join(', ')
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def registration_line
|
|
98
|
+
" Spree.subscribers << #{subscriber_class_name}\n"
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def registration_block
|
|
102
|
+
<<~RUBY
|
|
103
|
+
|
|
104
|
+
# Event subscribers must be registered explicitly — Spree does not
|
|
105
|
+
# auto-discover classes in app/subscribers/.
|
|
106
|
+
Rails.application.config.after_initialize do
|
|
107
|
+
#{registration_line.chomp}
|
|
108
|
+
end
|
|
109
|
+
RUBY
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def destination_path(relative)
|
|
113
|
+
File.join(destination_root, relative)
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<% namespace_modules.each_with_index do |mod, i| -%>
|
|
2
|
+
<%= ' ' * i %>module <%= mod %>
|
|
3
|
+
<% end -%>
|
|
4
|
+
<% depth = namespace_modules.size -%>
|
|
5
|
+
<%= ' ' * depth %>class <%= bare_subscriber_name %> < Spree::Subscriber
|
|
6
|
+
<%= ' ' * (depth + 1) %>subscribes_to <%= subscribes_to_arguments %>
|
|
7
|
+
|
|
8
|
+
<%= ' ' * (depth + 1) %>def handle(event)
|
|
9
|
+
<%= ' ' * (depth + 2) %># Event payloads carry prefixed IDs — look records up with find_by_prefix_id:
|
|
10
|
+
<%= ' ' * (depth + 2) %>#
|
|
11
|
+
<%= ' ' * (depth + 2) %># record = Spree::Order.find_by_prefix_id(event.payload['id'])
|
|
12
|
+
<%= ' ' * (depth + 2) %># return unless record
|
|
13
|
+
<%= ' ' * (depth + 1) %>end
|
|
14
|
+
<%= ' ' * depth %>end
|
|
15
|
+
<% namespace_modules.each_with_index do |_, i| -%>
|
|
16
|
+
<%= ' ' * (namespace_modules.size - 1 - i) %>end
|
|
17
|
+
<% end -%>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
require 'rails_helper'
|
|
2
|
+
|
|
3
|
+
RSpec.describe <%= subscriber_class_name %> do
|
|
4
|
+
it 'handles <%= events.first || 'the subscribed event' %>' do
|
|
5
|
+
event = Spree::Event.new(name: <%= (events.first || 'some.event').inspect %>, payload: { 'id' => 'prefixed_id_here' })
|
|
6
|
+
|
|
7
|
+
expect { described_class.new.handle(event) }.not_to raise_error
|
|
8
|
+
end
|
|
9
|
+
end
|
|
@@ -25,6 +25,10 @@ module Spree
|
|
|
25
25
|
# Alphabetized to more easily lookup particular preferences
|
|
26
26
|
preference :address_requires_state, :boolean, default: true, deprecated: true # should state/state_name be required
|
|
27
27
|
preference :address_requires_phone, :boolean, default: false # Determines whether we require phone in address
|
|
28
|
+
# Origin where the admin SPA is hosted (e.g. `https://admin.shop.com`).
|
|
29
|
+
# Used by admin mailers; falls back to `http://localhost:5173` in dev
|
|
30
|
+
# and the store's storefront URL otherwise. Set this in production.
|
|
31
|
+
preference :admin_url, :string, default: nil
|
|
28
32
|
preference :allow_checkout_on_gateway_error, :boolean, default: false
|
|
29
33
|
preference :allow_empty_price_amount, :boolean, default: false
|
|
30
34
|
preference :allow_guest_checkout, :boolean, default: true, deprecated: true # this is only used in the rails frontend, and is not implemented in API
|
|
@@ -88,6 +92,9 @@ module Spree
|
|
|
88
92
|
preference :require_master_price, :boolean, default: false
|
|
89
93
|
preference :restock_inventory, :boolean, default: true # Determines if a return item is restocked automatically once it has been received
|
|
90
94
|
preference :return_eligibility_number_of_days, :integer, default: 365
|
|
95
|
+
preference :reserve_stock_on, :string, default: 'checkout' # 'checkout' (default) or 'cart' — landing in 6.0 alongside Cart/Order split
|
|
96
|
+
preference :stock_reservations_enabled, :boolean, default: true # Hold stock during checkout to prevent overselling
|
|
97
|
+
preference :default_stock_reservation_ttl_minutes, :integer, default: 10 # Fallback TTL when a Store doesn't override
|
|
91
98
|
preference :send_core_emails, :boolean, default: true, deprecated: true # Default mail headers settings
|
|
92
99
|
preference :shipping_instructions, :boolean, deprecated: true
|
|
93
100
|
preference :show_only_complete_orders_by_default, :boolean, deprecated: true
|
|
@@ -3,7 +3,6 @@ module Spree
|
|
|
3
3
|
module ControllerHelpers
|
|
4
4
|
module Auth
|
|
5
5
|
extend ActiveSupport::Concern
|
|
6
|
-
include Spree::Core::TokenGenerator
|
|
7
6
|
|
|
8
7
|
included do
|
|
9
8
|
if defined?(helper_method)
|
|
@@ -20,17 +19,6 @@ module Spree
|
|
|
20
19
|
@current_ability ||= Spree.ability_class.new(try_spree_current_user, { store: current_store })
|
|
21
20
|
end
|
|
22
21
|
|
|
23
|
-
def current_oauth_token
|
|
24
|
-
Spree::Deprecation.warn('Spree::Current.oauth_token is deprecated and will be removed in Spree 5.5')
|
|
25
|
-
|
|
26
|
-
get_last_access_token = ->(user) { Spree::OauthAccessToken.active_for(user).where(expires_in: nil).last }
|
|
27
|
-
create_access_token = ->(user) { Spree::OauthAccessToken.create!(resource_owner: user) }
|
|
28
|
-
user = try_spree_current_user
|
|
29
|
-
return unless user
|
|
30
|
-
|
|
31
|
-
@current_oauth_token ||= get_last_access_token.call(user) || create_access_token.call(user)
|
|
32
|
-
end
|
|
33
|
-
|
|
34
22
|
# this will work for devise out of the box
|
|
35
23
|
# for other auth systems you will need to override this method
|
|
36
24
|
def store_location(location = nil)
|
|
@@ -7,7 +7,6 @@ module Spree
|
|
|
7
7
|
included do
|
|
8
8
|
if defined?(helper_method)
|
|
9
9
|
helper_method :supported_currencies
|
|
10
|
-
helper_method :supported_currencies_for_all_stores
|
|
11
10
|
helper_method :current_currency
|
|
12
11
|
helper_method :supported_currency?
|
|
13
12
|
helper_method :currency_param
|
|
@@ -38,22 +37,6 @@ module Spree
|
|
|
38
37
|
@supported_currencies ||= current_store&.supported_currencies_list
|
|
39
38
|
end
|
|
40
39
|
|
|
41
|
-
# Returns the list of supported currencies for all stores.
|
|
42
|
-
# @deprecated This method will be removed in Spree 5.5.
|
|
43
|
-
# @return [Array<String>] the list of supported currencies, eg. `["USD", "EUR"]`
|
|
44
|
-
def supported_currencies_for_all_stores
|
|
45
|
-
Spree::Deprecation.warn(
|
|
46
|
-
'supported_currencies_for_all_stores is deprecated and will be removed in Spree 5.5.'
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
@supported_currencies_for_all_stores ||= begin
|
|
50
|
-
(
|
|
51
|
-
Spree::Store.pluck(:supported_currencies).map { |c| c&.split(',') }.flatten + Spree::Store.pluck(:default_currency)
|
|
52
|
-
).
|
|
53
|
-
compact.uniq.map { |code| ::Money::Currency.find(code.strip) }
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
|
|
57
40
|
# Checks if the given currency is supported.
|
|
58
41
|
# @param currency_iso_code [String] the ISO code of the currency, eg. `USD`
|
|
59
42
|
# @return [Boolean] `true` if the currency is supported, `false` otherwise
|
|
@@ -7,7 +7,6 @@ module Spree
|
|
|
7
7
|
included do
|
|
8
8
|
if defined?(helper_method)
|
|
9
9
|
helper_method :current_order
|
|
10
|
-
helper_method :simple_current_order
|
|
11
10
|
end
|
|
12
11
|
end
|
|
13
12
|
|
|
@@ -15,24 +14,6 @@ module Spree
|
|
|
15
14
|
@order_token ||= cookies.signed[:token] || params[:order_token]
|
|
16
15
|
end
|
|
17
16
|
|
|
18
|
-
# @deprecated Use `current_order` instead. This method will be removed in Spree 5.5.
|
|
19
|
-
def simple_current_order
|
|
20
|
-
Spree::Deprecation.warn(
|
|
21
|
-
'simple_current_order is deprecated and will be removed in Spree 5.5. Use current_order instead.'
|
|
22
|
-
)
|
|
23
|
-
|
|
24
|
-
return @simple_current_order if @simple_current_order
|
|
25
|
-
|
|
26
|
-
@simple_current_order = find_order_by_token_or_user
|
|
27
|
-
|
|
28
|
-
if @simple_current_order
|
|
29
|
-
@simple_current_order.last_ip_address = ip_address
|
|
30
|
-
return @simple_current_order
|
|
31
|
-
else
|
|
32
|
-
@simple_current_order = current_store.orders.new
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
17
|
# The current incomplete order from the token for use in cart and during checkout
|
|
37
18
|
def current_order(options = {})
|
|
38
19
|
options[:create_order_if_necessary] ||= false
|
|
@@ -44,6 +44,9 @@ module Spree
|
|
|
44
44
|
# order
|
|
45
45
|
order_approve_service: 'Spree::Orders::Approve',
|
|
46
46
|
order_cancel_service: 'Spree::Orders::Cancel',
|
|
47
|
+
order_complete_service: 'Spree::Orders::Complete',
|
|
48
|
+
order_create_service: 'Spree::Orders::Create',
|
|
49
|
+
order_update_service: 'Spree::Orders::Update',
|
|
47
50
|
order_updater: 'Spree::OrderUpdater',
|
|
48
51
|
|
|
49
52
|
# shipment
|
|
@@ -62,7 +65,7 @@ module Spree
|
|
|
62
65
|
posts_sorter: nil,
|
|
63
66
|
products_sorter: 'Spree::Products::Sort',
|
|
64
67
|
# paginator
|
|
65
|
-
collection_paginator:
|
|
68
|
+
collection_paginator: nil,
|
|
66
69
|
|
|
67
70
|
# coupons
|
|
68
71
|
# TODO: we should split this service into 2 separate - Add and Remove
|
|
@@ -80,7 +83,7 @@ module Spree
|
|
|
80
83
|
credit_cards_destroy_service: 'Spree::CreditCards::Destroy',
|
|
81
84
|
|
|
82
85
|
# classifications
|
|
83
|
-
classification_reposition_service:
|
|
86
|
+
classification_reposition_service: nil,
|
|
84
87
|
|
|
85
88
|
# line items
|
|
86
89
|
line_item_create_service: 'Spree::LineItems::Create',
|
data/lib/spree/core/engine.rb
CHANGED
|
@@ -11,6 +11,7 @@ module Spree
|
|
|
11
11
|
:payment_methods,
|
|
12
12
|
:adjusters,
|
|
13
13
|
:stock_splitters,
|
|
14
|
+
:order_routing,
|
|
14
15
|
:promotions,
|
|
15
16
|
:pricing,
|
|
16
17
|
:line_item_comparison_hooks,
|
|
@@ -25,6 +26,7 @@ module Spree
|
|
|
25
26
|
:page_blocks,
|
|
26
27
|
:reports,
|
|
27
28
|
:translatable_resources,
|
|
29
|
+
:taggable_types,
|
|
28
30
|
:metafields,
|
|
29
31
|
:analytics_events,
|
|
30
32
|
:analytics_event_handlers,
|
|
@@ -35,6 +37,7 @@ module Spree
|
|
|
35
37
|
SpreeCalculators = Struct.new(:shipping_methods, :tax_rates, :promotion_actions_create_adjustments, :promotion_actions_create_item_adjustments)
|
|
36
38
|
PromoEnvironment = Struct.new(:rules, :actions)
|
|
37
39
|
PricingEnvironment = Struct.new(:rules)
|
|
40
|
+
OrderRoutingEnvironment = Struct.new(:strategies, :rules)
|
|
38
41
|
SpreeValidators = Struct.new(:addresses)
|
|
39
42
|
MetafieldsEnvironment = Struct.new(:types, :enabled_resources)
|
|
40
43
|
isolate_namespace Spree
|
|
@@ -75,6 +78,15 @@ module Spree
|
|
|
75
78
|
initializer 'spree.register.adjustable_adjusters' do |app|
|
|
76
79
|
end
|
|
77
80
|
|
|
81
|
+
# Seed the order routing registries early so engines and apps can append
|
|
82
|
+
# their own strategies / rule kinds from initializer files. Core's defaults
|
|
83
|
+
# are concatenated in after_initialize below.
|
|
84
|
+
initializer 'spree.register.order_routing', before: :load_config_initializers do |app|
|
|
85
|
+
app.config.spree.order_routing = OrderRoutingEnvironment.new
|
|
86
|
+
app.config.spree.order_routing.strategies = []
|
|
87
|
+
app.config.spree.order_routing.rules = []
|
|
88
|
+
end
|
|
89
|
+
|
|
78
90
|
initializer 'spree.register.metafields' do |app|
|
|
79
91
|
app.config.spree.metafields = MetafieldsEnvironment.new
|
|
80
92
|
app.config.spree.metafields.types = []
|
|
@@ -133,6 +145,23 @@ module Spree
|
|
|
133
145
|
Spree::Adjustable::Adjuster::Tax
|
|
134
146
|
]
|
|
135
147
|
|
|
148
|
+
# Selectable order routing strategies. The internal Reducer collaborator
|
|
149
|
+
# is intentionally NOT listed — it is not a Strategy::Base. Plugins add
|
|
150
|
+
# their own (or remove Legacy) via this array.
|
|
151
|
+
Rails.application.config.spree.order_routing.strategies.concat [
|
|
152
|
+
Spree::OrderRouting::Strategy::Rules,
|
|
153
|
+
Spree::OrderRouting::Strategy::Legacy
|
|
154
|
+
]
|
|
155
|
+
|
|
156
|
+
# Available order routing rule kinds. STI dispatches at runtime via the
|
|
157
|
+
# +type+ column; this array is the curated allowlist that drives admin
|
|
158
|
+
# pickers and the rule +type+ validation. Plugins append their own.
|
|
159
|
+
Rails.application.config.spree.order_routing.rules.concat [
|
|
160
|
+
Spree::OrderRouting::Rules::PreferredLocation,
|
|
161
|
+
Spree::OrderRouting::Rules::MinimizeSplits,
|
|
162
|
+
Spree::OrderRouting::Rules::DefaultLocation
|
|
163
|
+
]
|
|
164
|
+
|
|
136
165
|
Rails.application.config.spree.calculators.promotion_actions_create_adjustments = [
|
|
137
166
|
Spree::Calculator::FlatPercentItemTotal,
|
|
138
167
|
Spree::Calculator::FlatRate,
|
|
@@ -161,12 +190,18 @@ module Spree
|
|
|
161
190
|
Spree::Promotion::Rules::OptionValue,
|
|
162
191
|
]
|
|
163
192
|
|
|
193
|
+
# Default registry. MarketRule is included so existing installs
|
|
194
|
+
# don't lose access to saved rule rows in the admin. ZoneRule is
|
|
195
|
+
# intentionally excluded — Zones are being removed in 6.0 (see
|
|
196
|
+
# docs/plans/6.0-tax-provider.md) and we don't want to invest
|
|
197
|
+
# in admin UI for a model on its way out. The class itself
|
|
198
|
+
# stays so legacy data continues to load; it just doesn't show
|
|
199
|
+
# up in the "Add rule" picker.
|
|
164
200
|
Rails.application.config.spree.pricing.rules.concat [
|
|
165
|
-
Spree::PriceRules::ZoneRule,
|
|
166
|
-
Spree::PriceRules::MarketRule,
|
|
167
201
|
Spree::PriceRules::UserRule,
|
|
168
202
|
Spree::PriceRules::CustomerGroupRule,
|
|
169
|
-
Spree::PriceRules::VolumeRule
|
|
203
|
+
Spree::PriceRules::VolumeRule,
|
|
204
|
+
Spree::PriceRules::MarketRule
|
|
170
205
|
]
|
|
171
206
|
|
|
172
207
|
Rails.application.config.spree.promotions.actions = [
|
|
@@ -216,6 +251,18 @@ module Spree
|
|
|
216
251
|
Spree::Policy
|
|
217
252
|
]
|
|
218
253
|
|
|
254
|
+
# Resources that expose tags via `acts_as_taggable_on :tags`. The
|
|
255
|
+
# Admin API's `/tags` autocomplete endpoint accepts these as
|
|
256
|
+
# `taggable_type`, and the SPA `<TagCombobox>` targets them by name.
|
|
257
|
+
# Extend in an app initializer (after :load_config_initializers) to
|
|
258
|
+
# surface custom taggables — e.g.
|
|
259
|
+
# Rails.application.config.spree.taggable_types << 'MyApp::Vendor'.
|
|
260
|
+
Rails.application.config.spree.taggable_types = [
|
|
261
|
+
'Spree::Product',
|
|
262
|
+
'Spree::Order',
|
|
263
|
+
Spree.user_class.to_s
|
|
264
|
+
]
|
|
265
|
+
|
|
219
266
|
Rails.application.config.spree.metafields.types = [
|
|
220
267
|
Spree::Metafields::ShortText,
|
|
221
268
|
Spree::Metafields::LongText,
|
|
@@ -301,12 +348,12 @@ module Spree
|
|
|
301
348
|
]
|
|
302
349
|
|
|
303
350
|
# Pre-load authentication strategy classes to avoid reflection at request time
|
|
304
|
-
Rails.application.config.spree.store_authentication_strategies =
|
|
351
|
+
Rails.application.config.spree.store_authentication_strategies = Spree::Authentication::StrategyRegistry.new(
|
|
305
352
|
email: Spree::Authentication::Strategies::EmailPasswordStrategy
|
|
306
|
-
|
|
307
|
-
Rails.application.config.spree.admin_authentication_strategies =
|
|
353
|
+
)
|
|
354
|
+
Rails.application.config.spree.admin_authentication_strategies = Spree::Authentication::StrategyRegistry.new(
|
|
308
355
|
email: Spree::Authentication::Strategies::EmailPasswordStrategy
|
|
309
|
-
|
|
356
|
+
)
|
|
310
357
|
end
|
|
311
358
|
|
|
312
359
|
initializer 'spree.promo.register.promotions.actions' do |app|
|
|
@@ -105,6 +105,21 @@ module Spree
|
|
|
105
105
|
@role_permissions = {}
|
|
106
106
|
end
|
|
107
107
|
|
|
108
|
+
# Returns a deep copy of this configuration. Useful for snapshotting
|
|
109
|
+
# state before a test mutates it; restore with {#replace}.
|
|
110
|
+
def dup
|
|
111
|
+
copy = super
|
|
112
|
+
copy.instance_variable_set(:@role_permissions, @role_permissions.deep_dup)
|
|
113
|
+
copy
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Replaces this configuration's state with a deep copy of `other`'s.
|
|
117
|
+
# Pair with {#dup} to snapshot/restore around code that mutates the
|
|
118
|
+
# global Spree.permissions config.
|
|
119
|
+
def replace(other)
|
|
120
|
+
@role_permissions = other.instance_variable_get(:@role_permissions).deep_dup
|
|
121
|
+
end
|
|
122
|
+
|
|
108
123
|
private
|
|
109
124
|
|
|
110
125
|
def normalize_role_name(role_name)
|