spree_core 5.4.0.beta10 → 5.4.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/assets/images/payment_icons/banktransfer.svg +1 -3
- data/app/models/concerns/spree/search_indexable.rb +1 -1
- data/app/models/spree/address.rb +15 -1
- data/app/models/spree/search_provider/database.rb +0 -1
- data/app/models/spree/search_provider/meilisearch.rb +147 -112
- data/app/presenters/spree/search_provider/product_presenter.rb +0 -6
- data/app/services/spree/addresses/create.rb +2 -2
- data/app/services/spree/addresses/update.rb +2 -2
- data/config/locales/en.yml +2 -0
- data/lib/spree/core/dependencies.rb +4 -1
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/core.rb +1 -0
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5de0595dccb2046acb60805390c641e66c9e87c070c25df2587d5a8eaf9bc358
|
|
4
|
+
data.tar.gz: 6cd99e1b81481dd826565d1f579ea64965dfa04a808905f830505110f330473d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1d27ab08a797c2f5419f36bd3ad368f1cecaf6610d1ca9289e9b5dea81f62a4856b8b767b23129b1dd20e0e0fd0c02f619581e58b7b347642cc801a2808de453
|
|
7
|
+
data.tar.gz: d551a808c3d989cf88e02c18b00bd9582b7672459b59e9c0ea281b6797cf5b0b95b698e32f98adc7a180723ab98e84aae99bc163ac5ee7de7a3d6745abc97e80
|
|
@@ -1,3 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" fill="
|
|
2
|
-
<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 18.75a60.07 60.07 0 0 1 15.797 2.101c.727.198 1.453-.342 1.453-1.096V18.75M3.75 4.5v.75A.75.75 0 0 1 3 6h-.75m0 0v-.375c0-.621.504-1.125 1.125-1.125H20.25M2.25 6v9m18-10.5v.75c0 .414.336.75.75.75h.75m-1.5-1.5h.375c.621 0 1.125.504 1.125 1.125v9.75c0 .621-.504 1.125-1.125 1.125h-.375m1.5-1.5H21a.75.75 0 0 0-.75.75v.75m0 0H3.75m0 0h-.375a1.125 1.125 0 0 1-1.125-1.125V15m1.5 1.5v-.75A.75.75 0 0 0 3 15h-.75M15 10.5a3 3 0 1 1-6 0 3 3 0 0 1 6 0Zm3 0h.008v.008H18V10.5Zm-12 0h.008v.008H6V10.5Z" />
|
|
3
|
-
</svg>
|
|
1
|
+
<svg width="38" height="24" viewBox="0 0 38 24" fill="none" xmlns="http://www.w3.org/2000/svg" role="img" aria-labelledby="pi-banktransfer"><title id="pi-banktransfer">Bank Transfer</title><g clip-path="url(#pi-banktransfer-clip)"><path opacity=".07" d="M35 0H3C1.3 0 0 1.3 0 3v18c0 1.7 1.4 3 3 3h32c1.7 0 3-1.3 3-3V3c0-1.7-1.4-3-3-3z" fill="#000"/><path d="M35 1c1.1 0 2 .9 2 2v18c0 1.1-.9 2-2 2H3c-1.1 0-2-.9-2-2V3c0-1.1.9-2 2-2h32z" fill="#fff"/><path fill-rule="evenodd" clip-rule="evenodd" d="M10 7l-4 2v1h8V9L10 7zM7 10.75v3.5h1v-3.5H7zm2 0v3.5h1v-3.5H9zm2 0v3.5h1.5v-3.5H11zM6 15v1h8v-1H6zM28 7l-4 2v1h8V9l-4-2zm-3 3.75v3.5h1v-3.5h-1zm2 0v3.5h1v-3.5h-1zm2 0v3.5h1.5v-3.5H29zM24 15v1h8v-1h-8z" fill="#4A4A4A"/><path d="M15.5 10h7M15.5 10l1.5-1.25M15.5 10l1.5 1.25" stroke="#4A4A4A" stroke-width=".9" stroke-linecap="round" stroke-linejoin="round"/><path d="M22.5 14h-7M22.5 14l-1.5-1.25M22.5 14l-1.5 1.25" stroke="#4A4A4A" stroke-width=".9" stroke-linecap="round" stroke-linejoin="round"/></g><defs><clipPath id="pi-banktransfer-clip"><path fill="#fff" d="M0 0h38v24H0z"/></clipPath></defs></svg>
|
|
@@ -29,7 +29,7 @@ module Spree
|
|
|
29
29
|
# => { id: 1, name: "Shirt", price_USD: 19.99, ... }
|
|
30
30
|
def search_presentation(store = nil)
|
|
31
31
|
store ||= Spree::Current.store
|
|
32
|
-
Spree::
|
|
32
|
+
Spree::Dependencies.search_product_presenter_class.new(self, store).call
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
# Remove this record from search index synchronously (inline, no job).
|
data/app/models/spree/address.rb
CHANGED
|
@@ -106,12 +106,26 @@ module Spree
|
|
|
106
106
|
end
|
|
107
107
|
|
|
108
108
|
def user_default_billing?
|
|
109
|
-
|
|
109
|
+
Spree::Deprecation.warn('Spree::Address#user_default_billing? is deprecated and will be removed in Spree 6.0. Use #is_default_billing? instead.')
|
|
110
|
+
is_default_billing?
|
|
110
111
|
end
|
|
111
112
|
|
|
112
113
|
def user_default_shipping?
|
|
114
|
+
Spree::Deprecation.warn('Spree::Address#user_default_shipping? is deprecated and will be removed in Spree 6.0. Use #is_default_shipping? instead.')
|
|
115
|
+
is_default_shipping?
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# In 6.0 these become real columns on Address, replacing User#bill_address_id / ship_address_id.
|
|
119
|
+
# For now they delegate to the User FK so the API shape is stable.
|
|
120
|
+
def is_default_billing?
|
|
121
|
+
user.present? && id == user.bill_address_id
|
|
122
|
+
end
|
|
123
|
+
alias_method :is_default_billing, :is_default_billing?
|
|
124
|
+
|
|
125
|
+
def is_default_shipping?
|
|
113
126
|
user.present? && id == user.ship_address_id
|
|
114
127
|
end
|
|
128
|
+
alias_method :is_default_shipping, :is_default_shipping?
|
|
115
129
|
|
|
116
130
|
# first_name / last_name aliases are defined via alias_attribute above
|
|
117
131
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require 'pagy/toolbox/paginators/meilisearch'
|
|
2
|
+
|
|
1
3
|
module Spree
|
|
2
4
|
module SearchProvider
|
|
3
5
|
class Meilisearch < Base
|
|
@@ -29,7 +31,13 @@ module Spree
|
|
|
29
31
|
|
|
30
32
|
Rails.logger.debug { "[Meilisearch] index=#{index_name} query=#{query.inspect} #{search_params.compact.inspect}" }
|
|
31
33
|
|
|
32
|
-
|
|
34
|
+
begin
|
|
35
|
+
ms_result = client.index(index_name).search(query.to_s, search_params)
|
|
36
|
+
rescue ::Meilisearch::ApiError => e
|
|
37
|
+
Rails.logger.warn { "[Meilisearch] Search failed: #{e.message}. Run `rake spree:search:reindex` to initialize the index." }
|
|
38
|
+
Rails.error.report(e, handled: true, context: { index: index_name, query: query })
|
|
39
|
+
return empty_result(scope, page, limit)
|
|
40
|
+
end
|
|
33
41
|
|
|
34
42
|
Rails.logger.debug { "[Meilisearch] #{ms_result['estimatedTotalHits']} hits in #{ms_result['processingTimeMs']}ms" }
|
|
35
43
|
|
|
@@ -60,7 +68,7 @@ module Spree
|
|
|
60
68
|
end
|
|
61
69
|
|
|
62
70
|
def index(product)
|
|
63
|
-
documents =
|
|
71
|
+
documents = presenter_class.new(product, store).call
|
|
64
72
|
client.index(index_name).add_documents(documents, 'prefixed_id')
|
|
65
73
|
end
|
|
66
74
|
|
|
@@ -85,9 +93,9 @@ module Spree
|
|
|
85
93
|
ensure_index_settings!
|
|
86
94
|
|
|
87
95
|
scope.reorder(id: :asc)
|
|
88
|
-
.
|
|
96
|
+
.preload_associations_lazily
|
|
89
97
|
.find_in_batches(batch_size: 500) do |batch|
|
|
90
|
-
documents = batch.flat_map { |product|
|
|
98
|
+
documents = batch.flat_map { |product| presenter_class.new(product, store).call }
|
|
91
99
|
index_batch(documents)
|
|
92
100
|
end
|
|
93
101
|
end
|
|
@@ -103,6 +111,10 @@ module Spree
|
|
|
103
111
|
|
|
104
112
|
private
|
|
105
113
|
|
|
114
|
+
def presenter_class
|
|
115
|
+
Spree::Dependencies.search_product_presenter_class
|
|
116
|
+
end
|
|
117
|
+
|
|
106
118
|
def client
|
|
107
119
|
@client ||= ::Meilisearch::Client.new(
|
|
108
120
|
ENV.fetch('MEILISEARCH_URL', 'http://localhost:7700'),
|
|
@@ -134,153 +146,165 @@ module Spree
|
|
|
134
146
|
%w[price -price name -name -available_on available_on best_selling]
|
|
135
147
|
end
|
|
136
148
|
|
|
137
|
-
#
|
|
138
|
-
#
|
|
139
|
-
# so that Meilisearch results match what the AR scope would return.
|
|
140
|
-
# All values are sanitized to prevent filter injection.
|
|
149
|
+
# Build Meilisearch filter conditions from API params.
|
|
150
|
+
# Combines system scoping (always applied) with user-facing filters.
|
|
141
151
|
def build_filters(filters)
|
|
142
|
-
conditions =
|
|
152
|
+
conditions = system_filter_conditions
|
|
153
|
+
conditions.concat(user_filter_conditions(filters))
|
|
154
|
+
conditions
|
|
155
|
+
end
|
|
143
156
|
|
|
144
|
-
|
|
145
|
-
|
|
157
|
+
# System scoping — always applied. Rarely overridden.
|
|
158
|
+
# Mirrors the AR scope: store.products.active(currency) with locale.
|
|
159
|
+
def system_filter_conditions
|
|
160
|
+
conditions = []
|
|
146
161
|
conditions << "store_ids = '#{store.id}'"
|
|
147
162
|
conditions << "status = 'active'"
|
|
148
163
|
conditions << "locale = '#{locale.to_s.gsub(/[^a-zA-Z_-]/, '')}'"
|
|
149
164
|
conditions << "currency = '#{currency.to_s.gsub(/[^A-Z]/, '')}'"
|
|
150
165
|
conditions << "(discontinue_on = 0 OR discontinue_on > #{Time.current.to_i})"
|
|
166
|
+
conditions
|
|
167
|
+
end
|
|
151
168
|
|
|
169
|
+
# User-facing filters — override to add custom filter pre/post processing.
|
|
170
|
+
def user_filter_conditions(filters)
|
|
171
|
+
conditions = []
|
|
152
172
|
filters = filters.to_unsafe_h if filters.respond_to?(:to_unsafe_h)
|
|
153
173
|
return conditions if filters.blank?
|
|
154
174
|
|
|
155
175
|
filters.each do |key, value|
|
|
156
176
|
next if value.blank?
|
|
157
177
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
conditions << "price <= #{value.to_f}"
|
|
164
|
-
when 'in_stock'
|
|
165
|
-
conditions << 'in_stock = true' if value.to_s != '0'
|
|
166
|
-
when 'out_of_stock'
|
|
167
|
-
conditions << 'in_stock = false' if value.to_s != '0'
|
|
168
|
-
when 'categories_id_eq'
|
|
169
|
-
conditions << "category_ids = '#{sanitize_prefixed_id(value)}'" if valid_prefixed_id?(value)
|
|
170
|
-
when 'with_option_value_ids'
|
|
171
|
-
Array(value).each do |ov|
|
|
172
|
-
conditions << "option_value_ids = '#{sanitize_prefixed_id(ov)}'" if valid_prefixed_id?(ov)
|
|
173
|
-
end
|
|
178
|
+
condition = build_filter_condition(key.to_s, value)
|
|
179
|
+
if condition.is_a?(Array)
|
|
180
|
+
conditions.concat(condition)
|
|
181
|
+
elsif condition
|
|
182
|
+
conditions << condition
|
|
174
183
|
end
|
|
175
184
|
end
|
|
176
185
|
|
|
177
186
|
conditions
|
|
178
187
|
end
|
|
179
188
|
|
|
189
|
+
# Translate a single Ransack-style filter param into Meilisearch filter syntax.
|
|
190
|
+
# Override in subclasses to handle custom filter keys — call super for built-in filters.
|
|
191
|
+
def build_filter_condition(key, value)
|
|
192
|
+
case key
|
|
193
|
+
when 'price_gte'
|
|
194
|
+
"price >= #{value.to_f}"
|
|
195
|
+
when 'price_lte'
|
|
196
|
+
"price <= #{value.to_f}"
|
|
197
|
+
when 'in_stock'
|
|
198
|
+
'in_stock = true' if value.to_s != '0'
|
|
199
|
+
when 'out_of_stock'
|
|
200
|
+
'in_stock = false' if value.to_s != '0'
|
|
201
|
+
when 'categories_id_eq'
|
|
202
|
+
"category_ids = '#{sanitize_prefixed_id(value)}'" if valid_prefixed_id?(value)
|
|
203
|
+
when 'with_option_value_ids'
|
|
204
|
+
Array(value).filter_map { |ov| "option_value_ids = '#{sanitize_prefixed_id(ov)}'" if valid_prefixed_id?(ov) }
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# Sort param to Meilisearch sort syntax.
|
|
209
|
+
# Override in subclasses to handle custom sort keys — call super for built-in sorts.
|
|
180
210
|
def build_sort(sort)
|
|
181
211
|
return nil if sort.blank?
|
|
182
212
|
|
|
213
|
+
sort_mapping(sort)
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
# Map a sort param to Meilisearch sort syntax.
|
|
217
|
+
# Override in subclasses to add custom sorts — call super for built-in sorts.
|
|
218
|
+
def sort_mapping(sort)
|
|
183
219
|
case sort
|
|
184
|
-
when 'price'
|
|
185
|
-
|
|
186
|
-
when '
|
|
187
|
-
|
|
188
|
-
when '
|
|
189
|
-
|
|
190
|
-
when '
|
|
191
|
-
['name:desc']
|
|
192
|
-
when '-available_on'
|
|
193
|
-
['available_on:desc']
|
|
194
|
-
when 'available_on'
|
|
195
|
-
['available_on:asc']
|
|
196
|
-
when 'best_selling'
|
|
197
|
-
['units_sold_count:desc']
|
|
220
|
+
when 'price' then ['price:asc']
|
|
221
|
+
when '-price' then ['price:desc']
|
|
222
|
+
when 'name' then ['name:asc']
|
|
223
|
+
when '-name' then ['name:desc']
|
|
224
|
+
when '-available_on' then ['available_on:desc']
|
|
225
|
+
when 'available_on' then ['available_on:asc']
|
|
226
|
+
when 'best_selling' then ['units_sold_count:desc']
|
|
198
227
|
end
|
|
199
228
|
end
|
|
200
229
|
|
|
201
|
-
# Transform Meilisearch facetDistribution into
|
|
230
|
+
# Transform Meilisearch facetDistribution into standard filter response format.
|
|
231
|
+
# Override in subclasses to add custom facets — call super and append.
|
|
202
232
|
def build_facet_response(facet_distribution)
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
if facet_distribution['
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
type: 'price_range',
|
|
211
|
-
min: amounts.min,
|
|
212
|
-
max: amounts.max,
|
|
213
|
-
currency: currency
|
|
214
|
-
}
|
|
215
|
-
end
|
|
233
|
+
facets = []
|
|
234
|
+
facets << build_price_facet(facet_distribution['price']) if facet_distribution['price'].present?
|
|
235
|
+
facets << build_availability_facet(facet_distribution['in_stock']) if facet_distribution['in_stock'].present?
|
|
236
|
+
facets.concat(build_option_facets(facet_distribution['option_value_ids'])) if facet_distribution['option_value_ids'].present?
|
|
237
|
+
facets << build_category_facet(facet_distribution['category_ids']) if facet_distribution['category_ids'].present?
|
|
238
|
+
facets.compact
|
|
239
|
+
end
|
|
216
240
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
]
|
|
228
|
-
}
|
|
229
|
-
end
|
|
241
|
+
def build_price_facet(distribution)
|
|
242
|
+
amounts = distribution.keys.map(&:to_f)
|
|
243
|
+
{
|
|
244
|
+
id: 'price',
|
|
245
|
+
type: 'price_range',
|
|
246
|
+
min: amounts.min,
|
|
247
|
+
max: amounts.max,
|
|
248
|
+
currency: currency
|
|
249
|
+
}
|
|
250
|
+
end
|
|
230
251
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
next unless ov
|
|
242
|
-
|
|
243
|
-
ot = ov.option_type
|
|
244
|
-
by_option_type[ot] ||= []
|
|
245
|
-
by_option_type[ot] << { id: ov.prefixed_id, name: ov.name, label: ov.label, position: ov.position, count: count }
|
|
246
|
-
end
|
|
252
|
+
def build_availability_facet(distribution)
|
|
253
|
+
{
|
|
254
|
+
id: 'availability',
|
|
255
|
+
type: 'availability',
|
|
256
|
+
options: [
|
|
257
|
+
{ id: 'in_stock', count: distribution['true'] || 0 },
|
|
258
|
+
{ id: 'out_of_stock', count: distribution['false'] || 0 }
|
|
259
|
+
]
|
|
260
|
+
}
|
|
261
|
+
end
|
|
247
262
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
263
|
+
def build_option_facets(distribution)
|
|
264
|
+
prefixed_ids = distribution.keys
|
|
265
|
+
raw_ids = prefixed_ids.filter_map { |pid| Spree::OptionValue.decode_prefixed_id(pid) }
|
|
266
|
+
option_values = Spree::OptionValue.where(id: raw_ids).includes(:option_type).preload_associations_lazily.index_by(&:prefixed_id)
|
|
267
|
+
|
|
268
|
+
# Group by option type
|
|
269
|
+
by_option_type = {}
|
|
270
|
+
distribution.each do |ov_prefixed_id, count|
|
|
271
|
+
ov = option_values[ov_prefixed_id]
|
|
272
|
+
next unless ov
|
|
273
|
+
|
|
274
|
+
ot = ov.option_type
|
|
275
|
+
by_option_type[ot] ||= []
|
|
276
|
+
by_option_type[ot] << { id: ov.prefixed_id, name: ov.name, label: ov.label, position: ov.position, count: count }
|
|
257
277
|
end
|
|
258
278
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
id: 'categories',
|
|
267
|
-
type: 'category',
|
|
268
|
-
options: facet_distribution['category_ids'].filter_map do |prefixed_id, count|
|
|
269
|
-
cat = categories[prefixed_id]
|
|
270
|
-
next unless cat
|
|
271
|
-
|
|
272
|
-
{ id: cat.prefixed_id, name: cat.name, permalink: cat.permalink, count: count }
|
|
273
|
-
end
|
|
279
|
+
by_option_type.map do |option_type, values|
|
|
280
|
+
{
|
|
281
|
+
id: option_type.prefixed_id,
|
|
282
|
+
type: 'option',
|
|
283
|
+
name: option_type.name,
|
|
284
|
+
label: option_type.label,
|
|
285
|
+
options: values.sort_by { |o| o[:position] }
|
|
274
286
|
}
|
|
275
287
|
end
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
def build_category_facet(distribution)
|
|
291
|
+
prefixed_ids = distribution.keys
|
|
292
|
+
raw_ids = prefixed_ids.filter_map { |pid| Spree::Taxon.decode_prefixed_id(pid) }
|
|
293
|
+
categories = Spree::Taxon.where(id: raw_ids).index_by(&:prefixed_id)
|
|
276
294
|
|
|
277
|
-
|
|
295
|
+
{
|
|
296
|
+
id: 'categories',
|
|
297
|
+
type: 'category',
|
|
298
|
+
options: distribution.filter_map do |prefixed_id, count|
|
|
299
|
+
cat = categories[prefixed_id]
|
|
300
|
+
next unless cat
|
|
301
|
+
|
|
302
|
+
{ id: cat.prefixed_id, name: cat.name, permalink: cat.permalink, count: count }
|
|
303
|
+
end
|
|
304
|
+
}
|
|
278
305
|
end
|
|
279
306
|
|
|
280
307
|
def build_pagy(ms_result, page, limit)
|
|
281
|
-
require 'pagy'
|
|
282
|
-
require 'pagy/toolbox/paginators/meilisearch'
|
|
283
|
-
|
|
284
308
|
fake_result = Struct.new(:raw_answer).new({
|
|
285
309
|
'totalHits' => ms_result['estimatedTotalHits'] || 0,
|
|
286
310
|
'hitsPerPage' => limit,
|
|
@@ -290,6 +314,17 @@ module Spree
|
|
|
290
314
|
Pagy::MeilisearchPaginator.paginate(fake_result, {})
|
|
291
315
|
end
|
|
292
316
|
|
|
317
|
+
def empty_result(scope, page, limit)
|
|
318
|
+
SearchResult.new(
|
|
319
|
+
products: scope.none,
|
|
320
|
+
filters: [],
|
|
321
|
+
sort_options: available_sort_options.map { |id| { id: id } },
|
|
322
|
+
default_sort: 'manual',
|
|
323
|
+
total_count: 0,
|
|
324
|
+
pagy: Pagy::Offset.new(count: 0, page: page, limit: limit)
|
|
325
|
+
)
|
|
326
|
+
end
|
|
327
|
+
|
|
293
328
|
def valid_prefixed_id?(value)
|
|
294
329
|
value.to_s.match?(PREFIXED_ID_PATTERN)
|
|
295
330
|
end
|
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
module Spree
|
|
2
2
|
module SearchProvider
|
|
3
3
|
class ProductPresenter
|
|
4
|
-
# Associations needed by this presenter — used by reindex and rake task for preloading
|
|
5
|
-
REQUIRED_PRELOADS = [
|
|
6
|
-
:taxons, :option_types, :primary_media, :store_products,
|
|
7
|
-
{ variants_including_master: [:prices, :option_values] }
|
|
8
|
-
].freeze
|
|
9
|
-
|
|
10
4
|
attr_reader :product, :store
|
|
11
5
|
|
|
12
6
|
def initialize(product, store)
|
|
@@ -8,8 +8,8 @@ module Spree
|
|
|
8
8
|
|
|
9
9
|
def call(address_params: {}, user: nil, **opts)
|
|
10
10
|
order = opts[:order]
|
|
11
|
-
default_billing = opts.fetch(:default_billing, false)
|
|
12
|
-
default_shipping = opts.fetch(:default_shipping, false)
|
|
11
|
+
default_billing = address_params.key?(:is_default_billing) ? address_params.delete(:is_default_billing) : opts.fetch(:default_billing, false)
|
|
12
|
+
default_shipping = address_params.key?(:is_default_shipping) ? address_params.delete(:is_default_shipping) : opts.fetch(:default_shipping, false)
|
|
13
13
|
|
|
14
14
|
address_params = fill_country_and_state_ids(address_params)
|
|
15
15
|
|
|
@@ -8,8 +8,8 @@ module Spree
|
|
|
8
8
|
|
|
9
9
|
def call(address:, address_params:, **opts)
|
|
10
10
|
order = opts[:order]
|
|
11
|
-
default_billing = opts.fetch(:default_billing, false)
|
|
12
|
-
default_shipping = opts.fetch(:default_shipping, false)
|
|
11
|
+
default_billing = address_params.key?(:is_default_billing) ? address_params.delete(:is_default_billing) : opts.fetch(:default_billing, false)
|
|
12
|
+
default_shipping = address_params.key?(:is_default_shipping) ? address_params.delete(:is_default_shipping) : opts.fetch(:default_shipping, false)
|
|
13
13
|
address_changes_except = opts.fetch(:address_changes_except, [])
|
|
14
14
|
create_new_address_on_update = opts.fetch(:create_new_address_on_update, false)
|
|
15
15
|
Spree::Deprecation.warn('Spree::Addresses::Update create_new_address_on_update parameter is deprecated and will be removed in Spree 5.5.') if create_new_address_on_update
|
data/config/locales/en.yml
CHANGED
|
@@ -103,7 +103,10 @@ module Spree
|
|
|
103
103
|
products_finder: 'Spree::Products::Find',
|
|
104
104
|
taxon_finder: 'Spree::Taxons::Find',
|
|
105
105
|
line_item_by_variant_finder: 'Spree::LineItems::FindByVariant',
|
|
106
|
-
variant_finder: 'Spree::Variants::Find'
|
|
106
|
+
variant_finder: 'Spree::Variants::Find',
|
|
107
|
+
|
|
108
|
+
# search
|
|
109
|
+
search_product_presenter: 'Spree::SearchProvider::ProductPresenter'
|
|
107
110
|
}.freeze
|
|
108
111
|
|
|
109
112
|
include Spree::DependenciesHelper
|
data/lib/spree/core/version.rb
CHANGED
data/lib/spree/core.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: spree_core
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 5.4.0.
|
|
4
|
+
version: 5.4.0.rc2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sean Schofield
|
|
@@ -10,7 +10,7 @@ authors:
|
|
|
10
10
|
autorequire:
|
|
11
11
|
bindir: bin
|
|
12
12
|
cert_chain: []
|
|
13
|
-
date: 2026-03-
|
|
13
|
+
date: 2026-03-23 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
16
|
name: i18n-tasks
|
|
@@ -1695,9 +1695,9 @@ licenses:
|
|
|
1695
1695
|
- BSD-3-Clause
|
|
1696
1696
|
metadata:
|
|
1697
1697
|
bug_tracker_uri: https://github.com/spree/spree/issues
|
|
1698
|
-
changelog_uri: https://github.com/spree/spree/releases/tag/v5.4.0.
|
|
1698
|
+
changelog_uri: https://github.com/spree/spree/releases/tag/v5.4.0.rc2
|
|
1699
1699
|
documentation_uri: https://docs.spreecommerce.org/
|
|
1700
|
-
source_code_uri: https://github.com/spree/spree/tree/v5.4.0.
|
|
1700
|
+
source_code_uri: https://github.com/spree/spree/tree/v5.4.0.rc2
|
|
1701
1701
|
post_install_message:
|
|
1702
1702
|
rdoc_options: []
|
|
1703
1703
|
require_paths:
|