spree_core 5.4.0.beta → 5.4.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.
- checksums.yaml +4 -4
- data/app/finders/spree/products/find.rb +1 -28
- data/app/helpers/spree/base_helper.rb +1 -54
- data/app/mailers/spree/base_mailer.rb +4 -3
- data/app/models/concerns/spree/adjustment_source.rb +0 -8
- data/app/models/concerns/spree/admin_user_methods.rb +0 -2
- data/app/models/concerns/spree/image_methods.rb +4 -0
- data/app/models/concerns/spree/metadata.rb +10 -0
- data/app/models/concerns/spree/product_scopes.rb +2 -47
- data/app/models/concerns/spree/stores/markets.rb +7 -7
- data/app/models/concerns/spree/vat_price_calculation.rb +2 -2
- data/app/models/spree/ability.rb +5 -5
- data/app/models/spree/address.rb +3 -2
- data/app/models/spree/adjustable/promotion_accumulator.rb +1 -1
- data/app/models/spree/adjustment.rb +1 -20
- data/app/models/spree/api_key.rb +57 -2
- data/app/models/spree/country.rb +7 -3
- data/app/models/spree/credit_card.rb +0 -27
- data/app/models/spree/current.rb +38 -2
- data/app/models/spree/exports/products.rb +0 -6
- data/app/models/spree/gateway/bogus.rb +9 -9
- data/app/models/spree/gateway.rb +0 -3
- data/app/models/spree/gift_card_batch.rb +4 -0
- data/app/models/spree/image/configuration/active_storage.rb +0 -2
- data/app/models/spree/image.rb +7 -31
- data/app/models/spree/log_entry.rb +8 -5
- data/app/models/spree/order/checkout.rb +0 -18
- data/app/models/spree/order.rb +20 -11
- data/app/models/spree/payment/gateway_options.rb +2 -2
- data/app/models/spree/payment/processing.rb +5 -5
- data/app/models/spree/payment.rb +1 -1
- data/app/models/spree/payment_connection_error.rb +3 -0
- data/app/models/spree/payment_method/check.rb +1 -1
- data/app/models/spree/payment_method/store_credit.rb +5 -5
- data/app/models/spree/payment_response.rb +70 -0
- data/app/models/spree/permission_sets/default_customer.rb +0 -5
- data/app/models/spree/permission_sets/product_display.rb +0 -2
- data/app/models/spree/permission_sets/product_management.rb +0 -2
- data/app/models/spree/product.rb +4 -72
- data/app/models/spree/promotion.rb +2 -14
- data/app/models/spree/promotion_handler/coupon.rb +3 -3
- data/app/models/spree/prototype.rb +0 -3
- data/app/models/spree/refund.rb +6 -2
- data/app/models/spree/shipment/emails.rb +1 -0
- data/app/models/spree/shipping_category.rb +3 -3
- data/app/models/spree/store.rb +10 -49
- data/app/models/spree/store_credit.rb +4 -0
- data/app/models/spree/tax_category.rb +1 -11
- data/app/models/spree/taxon.rb +0 -16
- data/app/models/spree/variant.rb +2 -40
- data/app/models/spree/zone.rb +1 -4
- data/app/services/spree/cart/add_item.rb +8 -4
- data/app/services/spree/cart/create.rb +13 -2
- data/app/services/spree/products/duplicator.rb +0 -12
- data/app/services/spree/products/prepare_nested_attributes.rb +0 -12
- data/config/locales/en.yml +3 -20
- data/db/migrate/20210914000000_spree_four_three.rb +0 -38
- data/db/migrate/20210915064329_add_metadata_to_spree_multiple_tables.rb +0 -1
- data/db/migrate/20260226000000_add_locale_to_spree_orders.rb +5 -0
- data/db/migrate/20260226100000_add_token_digest_to_spree_api_keys.rb +21 -0
- data/lib/generators/spree/cursor_rules/templates/spree_rules.mdc +1 -3
- data/lib/spree/core/configuration.rb +0 -3
- data/lib/spree/core/controller_helpers/strong_parameters.rb +1 -2
- data/lib/spree/core/dependencies.rb +2 -10
- data/lib/spree/core/engine.rb +0 -13
- data/lib/spree/core/pricing/resolver.rb +1 -9
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/core.rb +10 -25
- data/lib/spree/permitted_attributes.rb +2 -14
- data/lib/spree/testing_support/factories/order_factory.rb +1 -0
- data/lib/spree/testing_support/factories/payment_method_factory.rb +1 -6
- data/lib/spree/testing_support/factories/product_factory.rb +0 -7
- data/lib/spree/testing_support/factories/prototype_factory.rb +0 -2
- data/lib/tasks/core.rake +0 -265
- metadata +8 -101
- data/app/finders/spree/posts/find.rb +0 -137
- data/app/finders/spree/product_properties/find_available.rb +0 -20
- data/app/helpers/spree/mail_helper.rb +0 -27
- data/app/jobs/spree/api_key_touch_job.rb +0 -9
- data/app/mailers/spree/test_mailer.rb +0 -8
- data/app/models/action_text/video_embed.rb +0 -13
- data/app/models/concerns/spree/has_one_link.rb +0 -42
- data/app/models/concerns/spree/linkable.rb +0 -9
- data/app/models/concerns/spree/previewable.rb +0 -17
- data/app/models/spree/data_feed/google.rb +0 -15
- data/app/models/spree/data_feed.rb +0 -42
- data/app/models/spree/gateway/bogus_simple.rb +0 -24
- data/app/models/spree/post.rb +0 -108
- data/app/models/spree/post_category.rb +0 -46
- data/app/models/spree/product_property.rb +0 -51
- data/app/models/spree/property.rb +0 -86
- data/app/models/spree/property_prototype.rb +0 -9
- data/app/models/spree/store_favicon_image.rb +0 -20
- data/app/models/spree/store_logo.rb +0 -4
- data/app/models/spree/store_mailer_logo.rb +0 -7
- data/app/models/spree/taxon_image/configuration/active_storage.rb +0 -26
- data/app/models/spree/taxon_image.rb +0 -28
- data/app/presenters/spree/filters/properties_presenter.rb +0 -23
- data/app/presenters/spree/filters/property_presenter.rb +0 -42
- data/app/services/spree/data_feeds/google/optional_attributes.rb +0 -23
- data/app/services/spree/data_feeds/google/optional_sub_attributes.rb +0 -21
- data/app/services/spree/data_feeds/google/products_list.rb +0 -14
- data/app/services/spree/data_feeds/google/required_attributes.rb +0 -68
- data/app/services/spree/data_feeds/google/rss.rb +0 -109
- data/app/sorters/spree/posts/sort.rb +0 -40
- data/app/views/action_text/video_embeds/_thumbnail.html.erb +0 -1
- data/app/views/action_text/video_embeds/_video_embed.html.erb +0 -3
- data/app/views/layouts/action_text/contents/_content.html.erb +0 -3
- data/app/views/spree/test_mailer/test_email.html.erb +0 -40
- data/app/views/spree/test_mailer/test_email.text.erb +0 -4
- data/config/initializers/oembed.rb +0 -1
- data/db/migrate/20221229132350_create_spree_data_feed_settings.rb +0 -14
- data/db/migrate/20230109084253_create_product_property_translations.rb +0 -24
- data/db/migrate/20230109105943_create_property_translations.rb +0 -24
- data/db/migrate/20230415155958_rename_data_feed_settings_table.rb +0 -5
- data/db/migrate/20230415160828_rename_data_feed_table_columns.rb +0 -7
- data/db/migrate/20230415161226_add_indexes_to_data_feeds_table.rb +0 -5
- data/db/migrate/20230512094803_rename_data_feeds_column_provider_to_type.rb +0 -5
- data/db/migrate/20240914153106_add_display_on_to_spree_properties.rb +0 -5
- data/db/migrate/20240915144935_add_position_to_spree_properties.rb +0 -6
- data/db/migrate/20250121160028_create_spree_posts_and_spree_post_categories.rb +0 -33
- data/db/migrate/20250127083740_add_kind_to_spree_properties.rb +0 -5
- data/db/migrate/20250217171018_create_action_text_video_embeds.rb +0 -11
- data/db/migrate/20250305121657_remove_spree_posts_indices.rb +0 -7
- data/db/migrate/20250730154601_add_unique_index_on_spree_properties_name.rb +0 -24
- data/db/sample_data/posts.rb +0 -7
- data/lib/spree/core/controller_helpers/search.rb +0 -17
- data/lib/spree/core/product_filters.rb +0 -218
- data/lib/spree/core/query_filters/comparable.rb +0 -50
- data/lib/spree/core/query_filters/date.rb +0 -8
- data/lib/spree/core/query_filters/number.rb +0 -8
- data/lib/spree/core/query_filters/text.rb +0 -36
- data/lib/spree/core/query_filters.rb +0 -11
- data/lib/spree/core/search/base.rb +0 -144
- data/lib/spree/testing_support/factories/favicon_image_factory.rb +0 -9
- data/lib/spree/testing_support/factories/google_data_feed_factory.rb +0 -7
- data/lib/spree/testing_support/factories/post_category_factory.rb +0 -7
- data/lib/spree/testing_support/factories/post_factory.rb +0 -22
- data/lib/spree/testing_support/factories/product_property_factory.rb +0 -7
- data/lib/spree/testing_support/factories/property_factory.rb +0 -28
- data/lib/spree/testing_support/factories/taxon_image_factory.rb +0 -9
- data/lib/spree/testing_support/flash.rb +0 -25
- data/lib/spree/testing_support/flatpickr_capybara.rb +0 -124
- data/lib/tasks/exchanges.rake +0 -66
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
class AddUniqueIndexOnSpreePropertiesName < ActiveRecord::Migration[7.2]
|
|
2
|
-
def change
|
|
3
|
-
# we don't need to run this migration in multi-tenant mode as it's already handled there
|
|
4
|
-
return if defined?(SpreeMultiTenant)
|
|
5
|
-
|
|
6
|
-
# Rename duplicated properties
|
|
7
|
-
duplicates = Spree::Property.select(:name).group(:name).having('COUNT(*) > 1').reorder('').pluck(:name)
|
|
8
|
-
|
|
9
|
-
duplicates.each do |duplicate_name|
|
|
10
|
-
properties = Spree::Property.where(name: duplicate_name)
|
|
11
|
-
|
|
12
|
-
properties.each_with_index do |property, index|
|
|
13
|
-
next if index == 0 # Keep the first one unchanged
|
|
14
|
-
|
|
15
|
-
new_name = "#{duplicate_name}_#{index}"
|
|
16
|
-
property.update_columns(name: new_name, updated_at: Time.current)
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
# Add indexes
|
|
21
|
-
remove_index :spree_properties, :name, if_exists: true
|
|
22
|
-
add_index :spree_properties, :name, unique: true, if_not_exists: true
|
|
23
|
-
end
|
|
24
|
-
end
|
data/db/sample_data/posts.rb
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
module Spree
|
|
2
|
-
module Core
|
|
3
|
-
module ControllerHelpers
|
|
4
|
-
module Search
|
|
5
|
-
def build_searcher(params)
|
|
6
|
-
Spree::Deprecation.warn("Spree::Core::ControllerHelpers::Search is deprecated and will be removed in Spree 5.5.")
|
|
7
|
-
|
|
8
|
-
Spree.searcher_class.new(params).tap do |searcher|
|
|
9
|
-
searcher.current_user = try_spree_current_user
|
|
10
|
-
searcher.current_currency = current_currency&.upcase
|
|
11
|
-
searcher.current_store = current_store
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
end
|
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
module Spree
|
|
2
|
-
module Core
|
|
3
|
-
# THIS FILE SHOULD BE OVER-RIDDEN IN YOUR SITE EXTENSION!
|
|
4
|
-
# the exact code probably won't be useful, though you're welcome to modify and reuse
|
|
5
|
-
# the current contents are mainly for testing and documentation
|
|
6
|
-
|
|
7
|
-
# To override this file...
|
|
8
|
-
# 1) Make a copy of it in your sites local /lib/spree folder
|
|
9
|
-
# 2) Add it to the config load path, or require it in an initializer, e.g...
|
|
10
|
-
#
|
|
11
|
-
# # config/initializers/spree.rb
|
|
12
|
-
# require 'spree/core/product_filters'
|
|
13
|
-
#
|
|
14
|
-
|
|
15
|
-
# set up some basic filters for use with products
|
|
16
|
-
#
|
|
17
|
-
# Each filter has two parts
|
|
18
|
-
# * a parametrized named scope which expects a list of labels
|
|
19
|
-
# * an object which describes/defines the filter
|
|
20
|
-
#
|
|
21
|
-
# The filter description has three components
|
|
22
|
-
# * a name, for displaying on pages
|
|
23
|
-
# * a named scope which will 'execute' the filter
|
|
24
|
-
# * a mapping of presentation labels to the relevant condition (in the context of the named scope)
|
|
25
|
-
# * an optional list of labels and values (for use with object selection - see taxons examples below)
|
|
26
|
-
#
|
|
27
|
-
# The named scopes here have a suffix '_any', following Ransack's convention for a
|
|
28
|
-
# scope which returns results which match any of the inputs. This is purely a convention,
|
|
29
|
-
# but might be a useful reminder.
|
|
30
|
-
#
|
|
31
|
-
# When creating a form, the name of the checkbox group for a filter F should be
|
|
32
|
-
# the name of F's scope with [] appended, eg "price_range_any[]", and for
|
|
33
|
-
# each label you should have a checkbox with the label as its value. On submission,
|
|
34
|
-
# Rails will send the action a hash containing (among other things) an array named
|
|
35
|
-
# after the scope whose values are the active labels.
|
|
36
|
-
#
|
|
37
|
-
# Ransack will then convert this array to a call to the named scope with the array
|
|
38
|
-
# contents, and the named scope will build a query with the disjunction of the conditions
|
|
39
|
-
# relating to the labels, all relative to the scope's context.
|
|
40
|
-
#
|
|
41
|
-
# The details of how/when filters are used is a detail for specific models (eg products
|
|
42
|
-
# or taxons), eg see the taxon model/controller.
|
|
43
|
-
|
|
44
|
-
# See specific filters below for concrete examples.
|
|
45
|
-
# @deprecated This module is deprecated and will be removed in Spree 5.5.
|
|
46
|
-
# Use Spree::Api::V3::FiltersAggregator instead.
|
|
47
|
-
module ProductFilters
|
|
48
|
-
def self.deprecated_warning
|
|
49
|
-
Spree::Deprecation.warn(
|
|
50
|
-
'Spree::Core::ProductFilters is deprecated and will be removed in Spree 5.5. ' \
|
|
51
|
-
'Please use Spree::Api::V3::FiltersAggregator instead.'
|
|
52
|
-
)
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
# Example: filtering by price
|
|
56
|
-
# The named scope just maps incoming labels onto their conditions, and builds the conjunction
|
|
57
|
-
# 'price' is in the base scope's context (ie, "select foo from products where ...") so
|
|
58
|
-
# we can access the field right away
|
|
59
|
-
# The filter identifies which scope to use, then sets the conditions for each price range
|
|
60
|
-
#
|
|
61
|
-
# If user checks off three different price ranges then the argument passed to
|
|
62
|
-
# below scope would be something like ["$10 - $15", "$15 - $18", "$18 - $20"]
|
|
63
|
-
#
|
|
64
|
-
Spree::Product.add_search_scope :price_range_any do |*opts|
|
|
65
|
-
conds = opts.map { |o| Spree::Core::ProductFilters.price_filter[:conds][o] }.reject(&:nil?)
|
|
66
|
-
scope = conds.shift
|
|
67
|
-
conds.each do |new_scope|
|
|
68
|
-
scope = scope.or(new_scope)
|
|
69
|
-
end
|
|
70
|
-
Spree::Product.joins(master: :default_price).where(scope)
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
def self.format_price(amount)
|
|
74
|
-
Spree::Money.new(amount)
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
def self.price_filter
|
|
78
|
-
deprecated_warning
|
|
79
|
-
v = Spree::Price.arel_table
|
|
80
|
-
conds = [[Spree.t(:under_price, price: format_price(10)), v[:amount].lteq(10)],
|
|
81
|
-
["#{format_price(10)} - #{format_price(15)}", v[:amount].between(10..15)],
|
|
82
|
-
["#{format_price(15)} - #{format_price(18)}", v[:amount].between(15..18)],
|
|
83
|
-
["#{format_price(18)} - #{format_price(20)}", v[:amount].between(18..20)],
|
|
84
|
-
[Spree.t(:or_over_price, price: format_price(20)), v[:amount].gteq(20)]]
|
|
85
|
-
{
|
|
86
|
-
name: Spree.t(:price_range),
|
|
87
|
-
scope: :price_range_any,
|
|
88
|
-
conds: Hash[*conds.flatten],
|
|
89
|
-
labels: conds.map { |k, _v| [k, k] }
|
|
90
|
-
}
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
# Example: filtering by possible brands
|
|
94
|
-
#
|
|
95
|
-
# First, we define the scope. Two interesting points here: (a) we run our conditions
|
|
96
|
-
# in the scope where the info for the 'brand' property has been loaded; and (b)
|
|
97
|
-
# because we may want to filter by other properties too, we give this part of the
|
|
98
|
-
# query a unique name (which must be used in the associated conditions too).
|
|
99
|
-
#
|
|
100
|
-
# Secondly, the filter. Instead of a static list of values, we pull out all existing
|
|
101
|
-
# brands from the db, and then build conditions which test for string equality on
|
|
102
|
-
# the (uniquely named) field "p_brand.value". There's also a test for brand info
|
|
103
|
-
# being blank: note that this relies on with_property doing a left outer join
|
|
104
|
-
# rather than an inner join.
|
|
105
|
-
Spree::Product.add_search_scope :brand_any do |*opts|
|
|
106
|
-
conds = opts.map { |o| ProductFilters.brand_filter[:conds][o] }.reject(&:nil?)
|
|
107
|
-
scope = conds.shift
|
|
108
|
-
conds.each do |new_scope|
|
|
109
|
-
scope = scope.or(new_scope)
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
if Spree.use_translations?
|
|
113
|
-
Product.with_property('brand').join_translation_table(ProductProperty).where(scope)
|
|
114
|
-
else
|
|
115
|
-
Product.with_property('brand').where(scope)
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
def self.brand_filter
|
|
120
|
-
deprecated_warning
|
|
121
|
-
brand_property = Spree::Property.find_by(name: 'brand')
|
|
122
|
-
brands = brand_property ? Spree::ProductProperty.where(property_id: brand_property.id).pluck(:value).uniq.map(&:to_s) : []
|
|
123
|
-
|
|
124
|
-
conditions = brands.map do |brand|
|
|
125
|
-
table_name = Spree.use_translations? ? ProductProperty.translation_table_alias : ProductProperty.table_name
|
|
126
|
-
|
|
127
|
-
[brand, { table_name.to_s => { value: brand } }]
|
|
128
|
-
end.to_h
|
|
129
|
-
|
|
130
|
-
{
|
|
131
|
-
name: I18n.t('spree.taxonomy_brands_name'),
|
|
132
|
-
scope: :brand_any,
|
|
133
|
-
conds: conditions,
|
|
134
|
-
labels: brands.sort.map { |k| [k, k] }
|
|
135
|
-
}
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
# Example: a parameterized filter
|
|
139
|
-
# The filter above may show brands which aren't applicable to the current taxon,
|
|
140
|
-
# so this one only shows the brands that are relevant to a particular taxon and
|
|
141
|
-
# its descendants.
|
|
142
|
-
#
|
|
143
|
-
# We don't have to give a new scope since the conditions here are a subset of the
|
|
144
|
-
# more general filter, so decoding will still work - as long as the filters on a
|
|
145
|
-
# page all have unique names (ie, you can't use the two brand filters together
|
|
146
|
-
# if they use the same scope). To be safe, the code uses a copy of the scope.
|
|
147
|
-
#
|
|
148
|
-
# HOWEVER: what happens if we want a more precise scope? we can't pass
|
|
149
|
-
# parametrized scope names to Ransack, only atomic names, so couldn't ask
|
|
150
|
-
# for taxon T's customized filter to be used. BUT: we can arrange for the form
|
|
151
|
-
# to pass back a hash instead of an array, where the key acts as the (taxon)
|
|
152
|
-
# parameter and value is its label array, and then get a modified named scope
|
|
153
|
-
# to get its conditions from a particular filter.
|
|
154
|
-
#
|
|
155
|
-
# The brand-finding code can be simplified if a few more named scopes were added to
|
|
156
|
-
# the product properties model.
|
|
157
|
-
Spree::Product.add_search_scope :selective_brand_any do |*opts|
|
|
158
|
-
Spree::Product.brand_any(*opts)
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
def self.selective_brand_filter(taxon = nil)
|
|
162
|
-
deprecated_warning
|
|
163
|
-
taxon ||= Spree::Taxonomy.first.root
|
|
164
|
-
brand_property = Spree::Property.find_by(name: 'brand')
|
|
165
|
-
scope = Spree::ProductProperty.where(property: brand_property).
|
|
166
|
-
joins(product: :taxons).
|
|
167
|
-
where("#{Spree::Taxon.table_name}.id" => [taxon] + taxon.descendants)
|
|
168
|
-
brands = scope.pluck(:value).uniq
|
|
169
|
-
{
|
|
170
|
-
name: 'Applicable Brands',
|
|
171
|
-
scope: :selective_brand_any,
|
|
172
|
-
labels: brands.sort.map { |k| [k, k] }
|
|
173
|
-
}
|
|
174
|
-
end
|
|
175
|
-
|
|
176
|
-
# Provide filtering on the immediate children of a taxon
|
|
177
|
-
#
|
|
178
|
-
# This doesn't fit the pattern of the examples above, so there's a few changes.
|
|
179
|
-
# Firstly, it uses an existing scope which was not built for filtering - and so
|
|
180
|
-
# has no need of a conditions mapping, and secondly, it has a mapping of name
|
|
181
|
-
# to the argument type expected by the other scope.
|
|
182
|
-
#
|
|
183
|
-
# This technique is useful for filtering on objects (by passing ids) or with a
|
|
184
|
-
# scope that can be used directly (eg. testing only ever on a single property).
|
|
185
|
-
#
|
|
186
|
-
# This scope selects products in any of the active taxons or their children.
|
|
187
|
-
#
|
|
188
|
-
def self.taxons_below(taxon)
|
|
189
|
-
deprecated_warning
|
|
190
|
-
return Spree::Core::ProductFilters.all_taxons if taxon.nil?
|
|
191
|
-
|
|
192
|
-
{
|
|
193
|
-
name: 'Taxons under ' + taxon.name,
|
|
194
|
-
scope: :taxons_id_in_tree_any,
|
|
195
|
-
labels: taxon.children.sort_by(&:position).map { |t| [t.name, t.id] },
|
|
196
|
-
conds: nil
|
|
197
|
-
}
|
|
198
|
-
end
|
|
199
|
-
|
|
200
|
-
# Filtering by the list of all taxons
|
|
201
|
-
#
|
|
202
|
-
# Similar idea as above, but we don't want the descendants' products, hence
|
|
203
|
-
# it uses one of the auto-generated scopes from Ransack.
|
|
204
|
-
#
|
|
205
|
-
# idea: expand the format to allow nesting of labels?
|
|
206
|
-
def self.all_taxons
|
|
207
|
-
deprecated_warning
|
|
208
|
-
taxons = Spree::Taxonomy.all.map { |t| [t.root] + t.root.descendants }.flatten
|
|
209
|
-
{
|
|
210
|
-
name: 'All taxons',
|
|
211
|
-
scope: :taxons_id_equals_any,
|
|
212
|
-
labels: taxons.sort_by(&:name).map { |t| [t.name, t.id] },
|
|
213
|
-
conds: nil # not needed
|
|
214
|
-
}
|
|
215
|
-
end
|
|
216
|
-
end
|
|
217
|
-
end
|
|
218
|
-
end
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
module Spree
|
|
2
|
-
module Core
|
|
3
|
-
module QueryFilters
|
|
4
|
-
# @deprecated This class is deprecated and will be removed in Spree 5.5.
|
|
5
|
-
class Comparable
|
|
6
|
-
def initialize(attribute:)
|
|
7
|
-
Spree::Deprecation.warn(
|
|
8
|
-
"#{self.class.name} is deprecated and will be removed in Spree 5.5."
|
|
9
|
-
)
|
|
10
|
-
@attribute = attribute
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def call(scope:, filter:)
|
|
14
|
-
scope = gt(scope, filter[:gt])
|
|
15
|
-
scope = gteq(scope, filter[:gteq])
|
|
16
|
-
scope = lt(scope, filter[:lt])
|
|
17
|
-
lteq(scope, filter[:lteq])
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
private
|
|
21
|
-
|
|
22
|
-
attr_reader :attribute
|
|
23
|
-
|
|
24
|
-
def gt(scope, value)
|
|
25
|
-
return scope unless value
|
|
26
|
-
|
|
27
|
-
scope.where(attribute.gt(value))
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def gteq(scope, value)
|
|
31
|
-
return scope unless value
|
|
32
|
-
|
|
33
|
-
scope.where(attribute.gteq(value))
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def lt(scope, value)
|
|
37
|
-
return scope unless value
|
|
38
|
-
|
|
39
|
-
scope.where(attribute.lt(value))
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def lteq(scope, value)
|
|
43
|
-
return scope unless value
|
|
44
|
-
|
|
45
|
-
scope.where(attribute.lteq(value))
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
end
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
module Spree
|
|
2
|
-
module Core
|
|
3
|
-
module QueryFilters
|
|
4
|
-
# @deprecated This class is deprecated and will be removed in Spree 5.5.
|
|
5
|
-
class Text
|
|
6
|
-
def initialize(attribute:)
|
|
7
|
-
Spree::Deprecation.warn(
|
|
8
|
-
'Spree::Core::QueryFilters::Text is deprecated and will be removed in Spree 5.5.'
|
|
9
|
-
)
|
|
10
|
-
@attribute = attribute
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def call(scope:, filter:)
|
|
14
|
-
scope = eq(scope, filter[:eq])
|
|
15
|
-
contains(scope, filter[:contains])
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
private
|
|
19
|
-
|
|
20
|
-
attr_reader :attribute
|
|
21
|
-
|
|
22
|
-
def eq(scope, value)
|
|
23
|
-
return scope unless value
|
|
24
|
-
|
|
25
|
-
scope.where(attribute.eq(value))
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def contains(scope, value)
|
|
29
|
-
return scope unless value
|
|
30
|
-
|
|
31
|
-
scope.where(attribute.matches("%#{value}%"))
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
module Spree
|
|
2
|
-
module Core
|
|
3
|
-
module Search
|
|
4
|
-
class Base
|
|
5
|
-
attr_accessor :properties, :current_user, :current_currency, :current_store, :taxon
|
|
6
|
-
|
|
7
|
-
def initialize(params)
|
|
8
|
-
Spree::Deprecation.warn("Spree::Core::Search::Base is deprecated and will be removed in Spree 5.5. Please use `Spree::Products::Find` finder instead.")
|
|
9
|
-
|
|
10
|
-
@properties = {}
|
|
11
|
-
@current_store = params[:current_store] || Spree::Store.default
|
|
12
|
-
@current_currency = @current_store.default_currency
|
|
13
|
-
@taxon = params[:taxon]
|
|
14
|
-
|
|
15
|
-
prepare(params)
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def retrieve_products
|
|
19
|
-
@products = extended_base_scope.page(page || 1).per(per_page)
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def method_missing(name)
|
|
23
|
-
if @properties.key? name
|
|
24
|
-
@properties[name]
|
|
25
|
-
else
|
|
26
|
-
super
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
protected
|
|
31
|
-
|
|
32
|
-
def extended_base_scope
|
|
33
|
-
base_scope = current_store.products.spree_base_scopes
|
|
34
|
-
base_scope = get_products_conditions_for(base_scope, keywords)
|
|
35
|
-
base_scope = Spree.products_finder.new(**product_finder_params(base_scope)).execute
|
|
36
|
-
base_scope = add_search_scopes(base_scope)
|
|
37
|
-
add_eagerload_scopes(base_scope)
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def product_finder_params(base_scope)
|
|
41
|
-
{
|
|
42
|
-
scope: base_scope,
|
|
43
|
-
params: {
|
|
44
|
-
store: current_store,
|
|
45
|
-
filter: {
|
|
46
|
-
price: price,
|
|
47
|
-
option_value_ids: option_value_ids,
|
|
48
|
-
properties: product_properties,
|
|
49
|
-
taxons: taxon&.id,
|
|
50
|
-
currency: current_currency
|
|
51
|
-
},
|
|
52
|
-
sort_by: sort_by
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
def add_eagerload_scopes(scope)
|
|
58
|
-
scope.includes(
|
|
59
|
-
:tax_category,
|
|
60
|
-
variants: [
|
|
61
|
-
{ images: { attachment_attachment: :blob } }
|
|
62
|
-
],
|
|
63
|
-
master: [
|
|
64
|
-
:prices,
|
|
65
|
-
{ images: { attachment_attachment: :blob } }
|
|
66
|
-
]
|
|
67
|
-
)
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def add_search_scopes(base_scope)
|
|
71
|
-
if search.is_a?(ActionController::Parameters)
|
|
72
|
-
search.each do |name, scope_attribute|
|
|
73
|
-
scope_name = name.to_sym
|
|
74
|
-
|
|
75
|
-
base_scope = if base_scope.respond_to?(:search_scopes) && base_scope.search_scopes.include?(scope_name.to_sym)
|
|
76
|
-
base_scope.send(scope_name, *scope_attribute)
|
|
77
|
-
else
|
|
78
|
-
base_scope.merge(Spree::Product.ransack(scope_name => scope_attribute).result)
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
base_scope
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
# method should return new scope based on base_scope
|
|
86
|
-
def get_products_conditions_for(base_scope, query)
|
|
87
|
-
unless query.blank?
|
|
88
|
-
base_scope = base_scope.i18n { name.matches("%#{query}%").or(description.matches("%#{query}%")) }
|
|
89
|
-
end
|
|
90
|
-
base_scope
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
def get_products_option_values_conditions(base_scope, option_value_ids)
|
|
94
|
-
unless option_value_ids.blank?
|
|
95
|
-
base_scope = base_scope.joins(variants: :option_values).where(spree_option_values: { id: option_value_ids })
|
|
96
|
-
end
|
|
97
|
-
base_scope
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
def get_price_range(price_param)
|
|
101
|
-
return if price_param.blank?
|
|
102
|
-
|
|
103
|
-
less_than_string = I18n.t('activerecord.attributes.spree/product.less_than')
|
|
104
|
-
|
|
105
|
-
if price_param.include? less_than_string
|
|
106
|
-
low_price = 0
|
|
107
|
-
high_price = Monetize.parse(price_param.remove("#{less_than_string} ")).to_i
|
|
108
|
-
else
|
|
109
|
-
low_price, high_price = Monetize.parse_collection(price_param).map(&:to_i)
|
|
110
|
-
high_price = BigDecimal::INFINITY if high_price&.zero?
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
"#{low_price},#{high_price}"
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
def build_option_value_ids(params)
|
|
117
|
-
filter_params = Spree::OptionType.filterable.map(&:filter_param)
|
|
118
|
-
|
|
119
|
-
filter_params.reduce([]) do |acc, filter_param|
|
|
120
|
-
acc + params[filter_param].to_s.split(',')
|
|
121
|
-
end
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
def prepare(params)
|
|
125
|
-
@properties[:keywords] = params[:keywords]
|
|
126
|
-
@properties[:option_value_ids] = build_option_value_ids(params)
|
|
127
|
-
@properties[:price] = get_price_range(params[:price])
|
|
128
|
-
@properties[:search] = params[:search]
|
|
129
|
-
@properties[:sort_by] = params[:sort_by] || 'default'
|
|
130
|
-
@properties[:include_images] = params[:include_images]
|
|
131
|
-
|
|
132
|
-
per_page = params[:per_page].to_i
|
|
133
|
-
@properties[:per_page] = per_page > 0 ? per_page : Spree::Config[:products_per_page]
|
|
134
|
-
@properties[:page] = if params[:page].respond_to?(:to_i)
|
|
135
|
-
params[:page].to_i <= 0 ? 1 : params[:page].to_i
|
|
136
|
-
else
|
|
137
|
-
1
|
|
138
|
-
end
|
|
139
|
-
@properties[:product_properties] = params[:properties]
|
|
140
|
-
end
|
|
141
|
-
end
|
|
142
|
-
end
|
|
143
|
-
end
|
|
144
|
-
end
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
FactoryBot.define do
|
|
2
|
-
factory :post, class: Spree::Post do
|
|
3
|
-
store { Spree::Store.default || create(:store) }
|
|
4
|
-
post_category { association(:post_category, store: store) }
|
|
5
|
-
title { FFaker::Lorem.sentence }
|
|
6
|
-
content { FFaker::Lorem.paragraph }
|
|
7
|
-
published_at { Time.current }
|
|
8
|
-
association :author, factory: :admin_user
|
|
9
|
-
|
|
10
|
-
trait :with_image do
|
|
11
|
-
image { Rack::Test::UploadedFile.new(Spree::Core::Engine.root.join('spec/fixtures/thinking-cat.jpg'), 'image/jpeg') }
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
trait :published do
|
|
15
|
-
published_at { Time.current }
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
trait :unpublished do
|
|
19
|
-
published_at { nil }
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
FactoryBot.define do
|
|
2
|
-
factory :property, class: Spree::Property do
|
|
3
|
-
sequence(:name) { |n| "baseball_cap_color_#{n}" }
|
|
4
|
-
presentation { 'cap color' }
|
|
5
|
-
|
|
6
|
-
trait :filterable do
|
|
7
|
-
filterable { true }
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
trait :brand do
|
|
11
|
-
name { 'brand' }
|
|
12
|
-
presentation { 'Brand' }
|
|
13
|
-
filter_param { 'brand' }
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
trait :manufacturer do
|
|
17
|
-
name { 'manufacturer' }
|
|
18
|
-
presentation { 'Manufacturer' }
|
|
19
|
-
filter_param { 'manufacturer' }
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
trait :material do
|
|
23
|
-
name { 'material' }
|
|
24
|
-
presentation { 'Material' }
|
|
25
|
-
filter_param { 'material' }
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
FactoryBot.define do
|
|
2
|
-
factory :taxon_image, class: Spree::TaxonImage do
|
|
3
|
-
before(:create) do |taxon_image|
|
|
4
|
-
if taxon_image.class.method_defined?(:attachment)
|
|
5
|
-
taxon_image.attachment.attach(io: File.new(Spree::Core::Engine.root + 'spec/fixtures/thinking-cat.jpg'), filename: 'thinking-cat.jpg')
|
|
6
|
-
end
|
|
7
|
-
end
|
|
8
|
-
end
|
|
9
|
-
end
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
module Spree
|
|
2
|
-
module TestingSupport
|
|
3
|
-
module Flash
|
|
4
|
-
def assert_flash_success(flash)
|
|
5
|
-
flash = convert_flash(flash)
|
|
6
|
-
|
|
7
|
-
within("[class='flash success']") do
|
|
8
|
-
expect(page).to have_content(flash)
|
|
9
|
-
end
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def assert_successful_update_message(resource)
|
|
13
|
-
flash = Spree.t(:successfully_updated, resource: Spree.t(resource))
|
|
14
|
-
assert_flash_success(flash)
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
private
|
|
18
|
-
|
|
19
|
-
def convert_flash(flash)
|
|
20
|
-
flash = Spree.t(flash) if flash.is_a?(Symbol)
|
|
21
|
-
flash
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|