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.
Files changed (144) hide show
  1. checksums.yaml +4 -4
  2. data/app/finders/spree/products/find.rb +1 -28
  3. data/app/helpers/spree/base_helper.rb +1 -54
  4. data/app/mailers/spree/base_mailer.rb +4 -3
  5. data/app/models/concerns/spree/adjustment_source.rb +0 -8
  6. data/app/models/concerns/spree/admin_user_methods.rb +0 -2
  7. data/app/models/concerns/spree/image_methods.rb +4 -0
  8. data/app/models/concerns/spree/metadata.rb +10 -0
  9. data/app/models/concerns/spree/product_scopes.rb +2 -47
  10. data/app/models/concerns/spree/stores/markets.rb +7 -7
  11. data/app/models/concerns/spree/vat_price_calculation.rb +2 -2
  12. data/app/models/spree/ability.rb +5 -5
  13. data/app/models/spree/address.rb +3 -2
  14. data/app/models/spree/adjustable/promotion_accumulator.rb +1 -1
  15. data/app/models/spree/adjustment.rb +1 -20
  16. data/app/models/spree/api_key.rb +57 -2
  17. data/app/models/spree/country.rb +7 -3
  18. data/app/models/spree/credit_card.rb +0 -27
  19. data/app/models/spree/current.rb +38 -2
  20. data/app/models/spree/exports/products.rb +0 -6
  21. data/app/models/spree/gateway/bogus.rb +9 -9
  22. data/app/models/spree/gateway.rb +0 -3
  23. data/app/models/spree/gift_card_batch.rb +4 -0
  24. data/app/models/spree/image/configuration/active_storage.rb +0 -2
  25. data/app/models/spree/image.rb +7 -31
  26. data/app/models/spree/log_entry.rb +8 -5
  27. data/app/models/spree/order/checkout.rb +0 -18
  28. data/app/models/spree/order.rb +20 -11
  29. data/app/models/spree/payment/gateway_options.rb +2 -2
  30. data/app/models/spree/payment/processing.rb +5 -5
  31. data/app/models/spree/payment.rb +1 -1
  32. data/app/models/spree/payment_connection_error.rb +3 -0
  33. data/app/models/spree/payment_method/check.rb +1 -1
  34. data/app/models/spree/payment_method/store_credit.rb +5 -5
  35. data/app/models/spree/payment_response.rb +70 -0
  36. data/app/models/spree/permission_sets/default_customer.rb +0 -5
  37. data/app/models/spree/permission_sets/product_display.rb +0 -2
  38. data/app/models/spree/permission_sets/product_management.rb +0 -2
  39. data/app/models/spree/product.rb +4 -72
  40. data/app/models/spree/promotion.rb +2 -14
  41. data/app/models/spree/promotion_handler/coupon.rb +3 -3
  42. data/app/models/spree/prototype.rb +0 -3
  43. data/app/models/spree/refund.rb +6 -2
  44. data/app/models/spree/shipment/emails.rb +1 -0
  45. data/app/models/spree/shipping_category.rb +3 -3
  46. data/app/models/spree/store.rb +10 -49
  47. data/app/models/spree/store_credit.rb +4 -0
  48. data/app/models/spree/tax_category.rb +1 -11
  49. data/app/models/spree/taxon.rb +0 -16
  50. data/app/models/spree/variant.rb +2 -40
  51. data/app/models/spree/zone.rb +1 -4
  52. data/app/services/spree/cart/add_item.rb +8 -4
  53. data/app/services/spree/cart/create.rb +13 -2
  54. data/app/services/spree/products/duplicator.rb +0 -12
  55. data/app/services/spree/products/prepare_nested_attributes.rb +0 -12
  56. data/config/locales/en.yml +3 -20
  57. data/db/migrate/20210914000000_spree_four_three.rb +0 -38
  58. data/db/migrate/20210915064329_add_metadata_to_spree_multiple_tables.rb +0 -1
  59. data/db/migrate/20260226000000_add_locale_to_spree_orders.rb +5 -0
  60. data/db/migrate/20260226100000_add_token_digest_to_spree_api_keys.rb +21 -0
  61. data/lib/generators/spree/cursor_rules/templates/spree_rules.mdc +1 -3
  62. data/lib/spree/core/configuration.rb +0 -3
  63. data/lib/spree/core/controller_helpers/strong_parameters.rb +1 -2
  64. data/lib/spree/core/dependencies.rb +2 -10
  65. data/lib/spree/core/engine.rb +0 -13
  66. data/lib/spree/core/pricing/resolver.rb +1 -9
  67. data/lib/spree/core/version.rb +1 -1
  68. data/lib/spree/core.rb +10 -25
  69. data/lib/spree/permitted_attributes.rb +2 -14
  70. data/lib/spree/testing_support/factories/order_factory.rb +1 -0
  71. data/lib/spree/testing_support/factories/payment_method_factory.rb +1 -6
  72. data/lib/spree/testing_support/factories/product_factory.rb +0 -7
  73. data/lib/spree/testing_support/factories/prototype_factory.rb +0 -2
  74. data/lib/tasks/core.rake +0 -265
  75. metadata +8 -101
  76. data/app/finders/spree/posts/find.rb +0 -137
  77. data/app/finders/spree/product_properties/find_available.rb +0 -20
  78. data/app/helpers/spree/mail_helper.rb +0 -27
  79. data/app/jobs/spree/api_key_touch_job.rb +0 -9
  80. data/app/mailers/spree/test_mailer.rb +0 -8
  81. data/app/models/action_text/video_embed.rb +0 -13
  82. data/app/models/concerns/spree/has_one_link.rb +0 -42
  83. data/app/models/concerns/spree/linkable.rb +0 -9
  84. data/app/models/concerns/spree/previewable.rb +0 -17
  85. data/app/models/spree/data_feed/google.rb +0 -15
  86. data/app/models/spree/data_feed.rb +0 -42
  87. data/app/models/spree/gateway/bogus_simple.rb +0 -24
  88. data/app/models/spree/post.rb +0 -108
  89. data/app/models/spree/post_category.rb +0 -46
  90. data/app/models/spree/product_property.rb +0 -51
  91. data/app/models/spree/property.rb +0 -86
  92. data/app/models/spree/property_prototype.rb +0 -9
  93. data/app/models/spree/store_favicon_image.rb +0 -20
  94. data/app/models/spree/store_logo.rb +0 -4
  95. data/app/models/spree/store_mailer_logo.rb +0 -7
  96. data/app/models/spree/taxon_image/configuration/active_storage.rb +0 -26
  97. data/app/models/spree/taxon_image.rb +0 -28
  98. data/app/presenters/spree/filters/properties_presenter.rb +0 -23
  99. data/app/presenters/spree/filters/property_presenter.rb +0 -42
  100. data/app/services/spree/data_feeds/google/optional_attributes.rb +0 -23
  101. data/app/services/spree/data_feeds/google/optional_sub_attributes.rb +0 -21
  102. data/app/services/spree/data_feeds/google/products_list.rb +0 -14
  103. data/app/services/spree/data_feeds/google/required_attributes.rb +0 -68
  104. data/app/services/spree/data_feeds/google/rss.rb +0 -109
  105. data/app/sorters/spree/posts/sort.rb +0 -40
  106. data/app/views/action_text/video_embeds/_thumbnail.html.erb +0 -1
  107. data/app/views/action_text/video_embeds/_video_embed.html.erb +0 -3
  108. data/app/views/layouts/action_text/contents/_content.html.erb +0 -3
  109. data/app/views/spree/test_mailer/test_email.html.erb +0 -40
  110. data/app/views/spree/test_mailer/test_email.text.erb +0 -4
  111. data/config/initializers/oembed.rb +0 -1
  112. data/db/migrate/20221229132350_create_spree_data_feed_settings.rb +0 -14
  113. data/db/migrate/20230109084253_create_product_property_translations.rb +0 -24
  114. data/db/migrate/20230109105943_create_property_translations.rb +0 -24
  115. data/db/migrate/20230415155958_rename_data_feed_settings_table.rb +0 -5
  116. data/db/migrate/20230415160828_rename_data_feed_table_columns.rb +0 -7
  117. data/db/migrate/20230415161226_add_indexes_to_data_feeds_table.rb +0 -5
  118. data/db/migrate/20230512094803_rename_data_feeds_column_provider_to_type.rb +0 -5
  119. data/db/migrate/20240914153106_add_display_on_to_spree_properties.rb +0 -5
  120. data/db/migrate/20240915144935_add_position_to_spree_properties.rb +0 -6
  121. data/db/migrate/20250121160028_create_spree_posts_and_spree_post_categories.rb +0 -33
  122. data/db/migrate/20250127083740_add_kind_to_spree_properties.rb +0 -5
  123. data/db/migrate/20250217171018_create_action_text_video_embeds.rb +0 -11
  124. data/db/migrate/20250305121657_remove_spree_posts_indices.rb +0 -7
  125. data/db/migrate/20250730154601_add_unique_index_on_spree_properties_name.rb +0 -24
  126. data/db/sample_data/posts.rb +0 -7
  127. data/lib/spree/core/controller_helpers/search.rb +0 -17
  128. data/lib/spree/core/product_filters.rb +0 -218
  129. data/lib/spree/core/query_filters/comparable.rb +0 -50
  130. data/lib/spree/core/query_filters/date.rb +0 -8
  131. data/lib/spree/core/query_filters/number.rb +0 -8
  132. data/lib/spree/core/query_filters/text.rb +0 -36
  133. data/lib/spree/core/query_filters.rb +0 -11
  134. data/lib/spree/core/search/base.rb +0 -144
  135. data/lib/spree/testing_support/factories/favicon_image_factory.rb +0 -9
  136. data/lib/spree/testing_support/factories/google_data_feed_factory.rb +0 -7
  137. data/lib/spree/testing_support/factories/post_category_factory.rb +0 -7
  138. data/lib/spree/testing_support/factories/post_factory.rb +0 -22
  139. data/lib/spree/testing_support/factories/product_property_factory.rb +0 -7
  140. data/lib/spree/testing_support/factories/property_factory.rb +0 -28
  141. data/lib/spree/testing_support/factories/taxon_image_factory.rb +0 -9
  142. data/lib/spree/testing_support/flash.rb +0 -25
  143. data/lib/spree/testing_support/flatpickr_capybara.rb +0 -124
  144. data/lib/tasks/exchanges.rake +0 -66
@@ -1,7 +0,0 @@
1
- class RemoveSpreePostsIndices < ActiveRecord::Migration[7.2]
2
- def change
3
- if index_name_exists?(:spree_posts, 'index_spree_posts_on_slug_and_store_id')
4
- remove_index :spree_posts, name: 'index_spree_posts_on_slug_and_store_id'
5
- end
6
- end
7
- end
@@ -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
@@ -1,7 +0,0 @@
1
- store = Spree::Store.default
2
-
3
- store.posts.where(title: 'Hello World').first_or_create!(
4
- content: 'This is a test post',
5
- published_at: Time.current,
6
- author: Spree.admin_user_class.first
7
- )
@@ -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,8 +0,0 @@
1
- module Spree
2
- module Core
3
- module QueryFilters
4
- class Date < Comparable
5
- end
6
- end
7
- end
8
- end
@@ -1,8 +0,0 @@
1
- module Spree
2
- module Core
3
- module QueryFilters
4
- class Number < Comparable
5
- end
6
- end
7
- end
8
- 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,11 +0,0 @@
1
- module Spree
2
- module Core
3
- module QueryFilters
4
- end
5
- end
6
- end
7
-
8
- require 'spree/core/query_filters/comparable'
9
- require 'spree/core/query_filters/number'
10
- require 'spree/core/query_filters/date'
11
- require 'spree/core/query_filters/text'
@@ -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,9 +0,0 @@
1
- FactoryBot.define do
2
- factory :favicon_image, class: Spree::StoreFaviconImage do
3
- transient do
4
- filepath { Spree::Core::Engine.root.join('spec', 'fixtures', 'favicon.ico') }
5
- end
6
-
7
- attachment { Rack::Test::UploadedFile.new(filepath) }
8
- end
9
- end
@@ -1,7 +0,0 @@
1
- FactoryBot.define do
2
- factory :google_data_feed, class: Spree::DataFeed::Google do
3
- active { true }
4
- association :store, factory: :store
5
- name { 'test' }
6
- end
7
- end
@@ -1,7 +0,0 @@
1
- FactoryBot.define do
2
- factory :post_category, class: Spree::PostCategory do
3
- sequence(:title) { |n| "Category ##{n + 1}" }
4
- description { FFaker::Lorem.sentence }
5
- store { Spree::Store.default || create(:store) }
6
- end
7
- 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,7 +0,0 @@
1
- FactoryBot.define do
2
- factory :product_property, class: Spree::ProductProperty do
3
- product
4
- value { "val-#{rand(50)}" }
5
- property
6
- end
7
- 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