spree_core 5.6.0.rc5 → 5.6.0.rc6
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/jobs/spree/imports/base_job.rb +13 -0
- data/app/jobs/spree/imports/create_categories_job.rb +4 -2
- data/app/jobs/spree/imports/process_group_job.rb +34 -32
- data/app/models/concerns/spree/webhook_payload_redaction.rb +1 -1
- data/app/models/spree/digital_link.rb +7 -1
- data/app/models/spree/gift_card_batch.rb +1 -1
- data/app/models/spree/product.rb +1 -0
- data/db/sample_data/wholesale.rb +19 -19
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/upgrades/5_5_to_5_6/manifest.yml +10 -0
- data/lib/tasks/product_tag_tenants.rake +26 -0
- metadata +5 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2118af5f16565f54bbb6e6bc66ed0db0bd44e8ad250b226dca1f2ae6dfd50dc9
|
|
4
|
+
data.tar.gz: 85cf95c960549e5557cb62c51d3b22516ce91d19b2532001c613fe2da036229c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 629b648d7bcc536638305dc942cc5fe8a08ddf9bcba35a7a4e132e84c72f486c106af32711d887b3b67097b35cac9b8664b3f8667630a6d90f56b3e1f815c974
|
|
7
|
+
data.tar.gz: 1077ccfe23cf6e5c98bd565a559551a344dec7ce20d0e3fe83b06dc9a8be02e74c5107d8edc48d2c0397c24248197d9097fdbb77896ed07b8f7bcd5da9a0d568
|
|
@@ -10,6 +10,19 @@ module Spree
|
|
|
10
10
|
# taxon creation races).
|
|
11
11
|
class BaseJob < Spree::BaseJob
|
|
12
12
|
queue_as Spree.queues.imports
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def with_store_content_locale(store, &block)
|
|
17
|
+
locale = store&.default_locale
|
|
18
|
+
return yield if locale.blank?
|
|
19
|
+
|
|
20
|
+
previous_content_locale = Spree::Current.content_locale
|
|
21
|
+
Spree::Current.content_locale = locale
|
|
22
|
+
I18n.with_locale(locale, &block)
|
|
23
|
+
ensure
|
|
24
|
+
Spree::Current.content_locale = previous_content_locale unless locale.blank?
|
|
25
|
+
end
|
|
13
26
|
end
|
|
14
27
|
end
|
|
15
28
|
end
|
|
@@ -9,9 +9,11 @@ module Spree
|
|
|
9
9
|
def perform(product_id, store_id, taxon_pretty_names)
|
|
10
10
|
product = Spree::Product.find(product_id)
|
|
11
11
|
store = Spree::Store.find(store_id)
|
|
12
|
-
taxons = taxon_pretty_names.filter_map { |taxon_pretty_name| find_or_create_taxon(store, taxon_pretty_name) }
|
|
13
12
|
|
|
14
|
-
|
|
13
|
+
with_store_content_locale(store) do
|
|
14
|
+
taxons = taxon_pretty_names.filter_map { |taxon_pretty_name| find_or_create_taxon(store, taxon_pretty_name) }
|
|
15
|
+
product.taxons = taxons
|
|
16
|
+
end
|
|
15
17
|
end
|
|
16
18
|
|
|
17
19
|
private
|
|
@@ -25,43 +25,45 @@ module Spree
|
|
|
25
25
|
import = Spree::Import.find(import_id)
|
|
26
26
|
Spree::Current.store = import.store
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
with_store_content_locale(import.store) do
|
|
29
|
+
mappings = import.mappings.mapped.to_a
|
|
30
|
+
schema_fields = import.schema_fields
|
|
31
|
+
large = import.large_import?
|
|
32
|
+
grouped = import.group_column.present? && mappings.any? { |m| m.schema_field == import.group_column }
|
|
33
|
+
started_at = Time.current
|
|
34
|
+
processed_rows = []
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
row_ids.each_slice(ROWS_BATCH_SIZE) do |ids|
|
|
37
|
+
# Skip rows already completed on a prior attempt so retries don't double-process them.
|
|
38
|
+
rows = import.rows.where(id: ids).pending_and_failed.order(:row_number).to_a
|
|
39
|
+
# Share the already-loaded import across rows: each row's processor reads
|
|
40
|
+
# `row.import` (store, ability, lookup cache), and without this every row
|
|
41
|
+
# lazily loads its own Import instance and rebuilds all of that per row.
|
|
42
|
+
rows.each { |row| row.association(:import).target = import }
|
|
42
43
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
44
|
+
if large
|
|
45
|
+
Spree::Events.disable do
|
|
46
|
+
rows.each { |row| row.bulk_process!(mappings: mappings, schema_fields: schema_fields) }
|
|
47
|
+
end
|
|
48
|
+
elsif grouped
|
|
49
|
+
# A group is one product plus its variants: per-record lifecycle
|
|
50
|
+
# events (variant.created, price.created, product.updated per
|
|
51
|
+
# touch) are noise to subscribers — one product event is published
|
|
52
|
+
# for the whole group below. import_row.* events still flow.
|
|
53
|
+
Spree::Events.disable_lifecycle do
|
|
54
|
+
rows.each { |row| row.process!(mappings: mappings, schema_fields: schema_fields) }
|
|
55
|
+
end
|
|
56
|
+
else
|
|
57
|
+
rows.each do |row|
|
|
58
|
+
row.process!(mappings: mappings, schema_fields: schema_fields)
|
|
59
|
+
end
|
|
58
60
|
end
|
|
61
|
+
processed_rows.concat(rows)
|
|
59
62
|
end
|
|
60
|
-
processed_rows.concat(rows)
|
|
61
|
-
end
|
|
62
63
|
|
|
63
|
-
|
|
64
|
-
|
|
64
|
+
publish_group_events(processed_rows, started_at) if grouped
|
|
65
|
+
check_import_completion(import, large)
|
|
66
|
+
end
|
|
65
67
|
end
|
|
66
68
|
|
|
67
69
|
private
|
|
@@ -17,7 +17,7 @@ module Spree
|
|
|
17
17
|
extend ActiveSupport::Concern
|
|
18
18
|
|
|
19
19
|
# Payload keys under `data` whose values are live credentials.
|
|
20
|
-
SENSITIVE_PAYLOAD_KEYS = %w[reset_token unsubscribe_token].freeze
|
|
20
|
+
SENSITIVE_PAYLOAD_KEYS = %w[reset_token unsubscribe_token verification_token].freeze
|
|
21
21
|
|
|
22
22
|
REDACTION_PLACEHOLDER = '[REDACTED]'
|
|
23
23
|
|
|
@@ -46,9 +46,15 @@ module Spree
|
|
|
46
46
|
|
|
47
47
|
# This method should be called when a download is initiated.
|
|
48
48
|
# It returns +true+ or +false+ depending on whether the authorization is granted.
|
|
49
|
+
#
|
|
50
|
+
# The access-limit check and the counter increment run inside a row lock so
|
|
51
|
+
# concurrent requests sharing the same token cannot each pass the cap before
|
|
52
|
+
# any of them increments the counter (TOCTOU race).
|
|
49
53
|
def authorize!
|
|
50
54
|
ActiveRecord::Base.connected_to(role: :writing) do
|
|
51
|
-
|
|
55
|
+
with_lock do
|
|
56
|
+
authorizable? && increment!(:access_counter, touch: true)
|
|
57
|
+
end
|
|
52
58
|
end
|
|
53
59
|
end
|
|
54
60
|
|
|
@@ -62,7 +62,7 @@ module Spree
|
|
|
62
62
|
|
|
63
63
|
def generate_code
|
|
64
64
|
loop do
|
|
65
|
-
code = "#{prefix.downcase}#{SecureRandom.hex(
|
|
65
|
+
code = "#{prefix.downcase}#{SecureRandom.hex(8).downcase}"
|
|
66
66
|
break code unless Spree::GiftCard.exists?(code: code) || @gift_cards_to_insert.detect { |gc| gc[:code] == code }
|
|
67
67
|
end
|
|
68
68
|
end
|
data/app/models/spree/product.rb
CHANGED
data/db/sample_data/wholesale.rb
CHANGED
|
@@ -43,29 +43,29 @@ unless price_list.price_rules.any? { |rule| rule.is_a?(Spree::PriceRules::Custom
|
|
|
43
43
|
rule.save!
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
46
|
+
# Same paths the admin UI uses: add_products materializes a blank row per
|
|
47
|
+
# variant × supported currency (skipping rows that already exist), then trade
|
|
48
|
+
# prices (40% off that currency's own retail price) fill in wherever a base
|
|
49
|
+
# price exists and the row is still blank. Both steps are idempotent, so
|
|
50
|
+
# re-running sample data converges partial state — new products, newly
|
|
51
|
+
# supported currencies, or a previously interrupted run — without clobbering
|
|
52
|
+
# hand-edited amounts.
|
|
53
|
+
price_list.add_products(store.products.ids)
|
|
54
|
+
|
|
55
|
+
blank_prices = price_list.prices.where(amount: nil).pluck(:id, :variant_id, :currency)
|
|
56
|
+
if blank_prices.any?
|
|
57
|
+
base_amounts = Spree::Price.where(price_list_id: nil, variant_id: blank_prices.map { |_, variant_id, _| variant_id }.uniq)
|
|
58
|
+
.pluck(:variant_id, :currency, :amount)
|
|
59
|
+
.each_with_object({}) { |(variant_id, currency, amount), memo| memo[[variant_id, currency]] = amount }
|
|
60
|
+
|
|
61
|
+
rows = blank_prices.filter_map do |id, variant_id, currency|
|
|
62
|
+
amount = base_amounts[[variant_id, currency]]
|
|
56
63
|
next if amount.blank?
|
|
57
64
|
|
|
58
|
-
{
|
|
59
|
-
variant_id: variant_id,
|
|
60
|
-
price_list_id: price_list.id,
|
|
61
|
-
amount: (amount * 0.6).round(2),
|
|
62
|
-
currency: currency,
|
|
63
|
-
created_at: now,
|
|
64
|
-
updated_at: now
|
|
65
|
-
}
|
|
65
|
+
{ id: id, variant_id: variant_id, currency: currency, amount: (amount * 0.6).round(2) }
|
|
66
66
|
end
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
price_list.bulk_update_prices(rows) if rows.any?
|
|
69
69
|
end
|
|
70
70
|
|
|
71
71
|
price_list.activate if price_list.can_activate?
|
data/lib/spree/core/version.rb
CHANGED
|
@@ -57,3 +57,13 @@ steps:
|
|
|
57
57
|
notes: |
|
|
58
58
|
Recomputes the descendant-inclusive products_count counter cache on every
|
|
59
59
|
taxon in batches.
|
|
60
|
+
|
|
61
|
+
- id: product_tag_tenants
|
|
62
|
+
name: "Backfill tenant on product taggings"
|
|
63
|
+
task: "spree:upgrade:backfill_product_tag_tenants"
|
|
64
|
+
notes: |
|
|
65
|
+
Sets the tenant column on existing Spree::Product taggings from each
|
|
66
|
+
product's store_id, so product tag autocomplete is bounded to the owning
|
|
67
|
+
store (matching Spree::Order). New product taggings tenant themselves;
|
|
68
|
+
only rows created before the upgrade need this. Until it runs, older
|
|
69
|
+
product tags are hidden from the store-scoped tag vocabulary.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
namespace :spree do
|
|
2
|
+
namespace :upgrade do
|
|
3
|
+
desc <<~DESC
|
|
4
|
+
Backfills the +tenant+ column on existing +Spree::Product+ taggings from
|
|
5
|
+
each product's +store_id+, so product tag vocabulary is bounded to the
|
|
6
|
+
owning store (matching +Spree::Order+, which already tenants its taggings).
|
|
7
|
+
|
|
8
|
+
Run once after upgrading to the release that adds
|
|
9
|
+
+acts_as_taggable_tenant :store_id+ to +Spree::Product+. New product
|
|
10
|
+
taggings get their tenant automatically; only rows created before the
|
|
11
|
+
upgrade need this. Idempotent — re-running only touches rows still
|
|
12
|
+
missing a tenant.
|
|
13
|
+
DESC
|
|
14
|
+
task backfill_product_tag_tenants: :environment do
|
|
15
|
+
taggings = ActsAsTaggableOn::Tagging.arel_table.name
|
|
16
|
+
products = Spree::Product.table_name
|
|
17
|
+
|
|
18
|
+
updated = ActsAsTaggableOn::Tagging.
|
|
19
|
+
where(taggable_type: 'Spree::Product', tenant: nil).
|
|
20
|
+
joins("INNER JOIN #{products} ON #{products}.id = #{taggings}.taggable_id").
|
|
21
|
+
update_all("tenant = #{products}.store_id")
|
|
22
|
+
|
|
23
|
+
puts " Backfilled tenant on #{updated} product tagging(s)."
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
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.6.0.
|
|
4
|
+
version: 5.6.0.rc6
|
|
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-07-
|
|
13
|
+
date: 2026-07-23 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
16
|
name: i18n-tasks
|
|
@@ -1837,6 +1837,7 @@ files:
|
|
|
1837
1837
|
- lib/tasks/markets.rake
|
|
1838
1838
|
- lib/tasks/media.rake
|
|
1839
1839
|
- lib/tasks/price_history.rake
|
|
1840
|
+
- lib/tasks/product_tag_tenants.rake
|
|
1840
1841
|
- lib/tasks/products.rake
|
|
1841
1842
|
- lib/tasks/publications.rake
|
|
1842
1843
|
- lib/tasks/role_users.rake
|
|
@@ -1867,9 +1868,9 @@ licenses:
|
|
|
1867
1868
|
- BSD-3-Clause
|
|
1868
1869
|
metadata:
|
|
1869
1870
|
bug_tracker_uri: https://github.com/spree/spree/issues
|
|
1870
|
-
changelog_uri: https://github.com/spree/spree/releases/tag/v5.6.0.
|
|
1871
|
+
changelog_uri: https://github.com/spree/spree/releases/tag/v5.6.0.rc6
|
|
1871
1872
|
documentation_uri: https://docs.spreecommerce.org/
|
|
1872
|
-
source_code_uri: https://github.com/spree/spree/tree/v5.6.0.
|
|
1873
|
+
source_code_uri: https://github.com/spree/spree/tree/v5.6.0.rc6
|
|
1873
1874
|
post_install_message:
|
|
1874
1875
|
rdoc_options: []
|
|
1875
1876
|
require_paths:
|