spree_core 5.4.0 → 5.4.2

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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/app/jobs/spree/imports/process_group_job.rb +45 -0
  3. data/app/jobs/spree/imports/process_rows_job.rb +51 -5
  4. data/app/models/concerns/spree/payment_source_concern.rb +21 -0
  5. data/app/models/spree/address.rb +1 -1
  6. data/app/models/spree/gateway/bogus.rb +10 -6
  7. data/app/models/spree/import.rb +15 -0
  8. data/app/models/spree/import_row.rb +14 -2
  9. data/app/models/spree/imports/product_translations.rb +4 -0
  10. data/app/models/spree/imports/products.rb +5 -0
  11. data/app/models/spree/order.rb +0 -6
  12. data/app/models/spree/payment.rb +1 -0
  13. data/app/models/spree/payment_session.rb +5 -0
  14. data/app/models/spree/product.rb +5 -10
  15. data/app/models/spree/promotion.rb +2 -2
  16. data/app/models/spree/search_provider/base.rb +13 -1
  17. data/app/models/spree/search_provider/database.rb +44 -29
  18. data/app/models/spree/search_provider/filters_result.rb +5 -0
  19. data/app/models/spree/search_provider/meilisearch.rb +99 -82
  20. data/app/models/spree/search_provider/search_result.rb +1 -1
  21. data/app/models/spree/shipment.rb +5 -1
  22. data/app/models/spree/shipping_rate.rb +26 -1
  23. data/app/models/spree/taxon.rb +1 -2
  24. data/app/models/spree/variant.rb +6 -3
  25. data/app/services/spree/credit_cards/destroy.rb +10 -26
  26. data/app/services/spree/gift_cards/apply.rb +5 -1
  27. data/app/services/spree/imports/row_processors/base.rb +19 -2
  28. data/app/services/spree/imports/row_processors/product_translation.rb +1 -1
  29. data/app/services/spree/imports/row_processors/product_variant.rb +2 -2
  30. data/app/services/spree/payments/handle_webhook.rb +6 -0
  31. data/app/services/spree/seeds/zones.rb +8 -2
  32. data/app/subscribers/spree/event_log_subscriber.rb +9 -7
  33. data/config/initializers/carmen.rb +23 -0
  34. data/config/locales/en.yml +0 -1
  35. data/db/migrate/20260424000001_add_unique_index_to_spree_payments_response_code.rb +51 -0
  36. data/db/migrate/20260424100000_add_processing_groups_to_spree_imports.rb +6 -0
  37. data/db/sample_data/markets.rb +34 -0
  38. data/db/sample_data/orders.rb +1 -1
  39. data/db/sample_data/shipping_methods.rb +25 -3
  40. data/lib/generators/spree/dummy/dummy_generator.rb +1 -1
  41. data/lib/spree/core/configuration.rb +3 -0
  42. data/lib/spree/core/engine.rb +3 -6
  43. data/lib/spree/core/version.rb +1 -1
  44. data/lib/spree/events.rb +6 -0
  45. data/lib/spree/permitted_attributes.rb +3 -3
  46. data/lib/spree/testing_support/factories/payment_factory.rb +1 -1
  47. data/lib/tasks/markets.rake +2 -5
  48. metadata +23 -12
@@ -28,3 +28,37 @@ if eu_zone
28
28
  eu_market.save!
29
29
  end
30
30
  end
31
+
32
+ # Additional sample markets for the remaining continents. Each market pulls
33
+ # its countries from the matching shipping zone so it only includes countries
34
+ # with shipping coverage (and therefore valid market countries). Countries
35
+ # already assigned to another market in the store are skipped, because
36
+ # Spree::MarketCountry requires each country to belong to at most one market
37
+ # per store.
38
+ [
39
+ { name: 'South America', zone: 'South America', currency: 'USD', default_locale: 'es', supported_locales: 'es,pt' },
40
+ { name: 'Middle East', zone: 'Middle East', currency: 'USD', default_locale: 'en', supported_locales: 'en,ar' },
41
+ { name: 'Africa', zone: 'Africa', currency: 'USD', default_locale: 'en', supported_locales: 'en,fr,ar' },
42
+ { name: 'Asia', zone: 'Asia', currency: 'USD', default_locale: 'en', supported_locales: 'en' },
43
+ { name: 'Oceania', zone: 'Australia and Oceania', currency: 'AUD', default_locale: 'en', supported_locales: 'en' }
44
+ ].each do |attrs|
45
+ zone = Spree::Zone.find_by(name: attrs[:zone])
46
+ next unless zone
47
+
48
+ market = store.markets.find_or_initialize_by(name: attrs[:name])
49
+
50
+ assigned_scope = Spree::MarketCountry.joins(:market).
51
+ where(spree_markets: { store_id: store.id, deleted_at: nil })
52
+ assigned_scope = assigned_scope.where.not(market_id: market.id) if market.persisted?
53
+ assigned_country_ids = assigned_scope.pluck(:country_id).to_set
54
+
55
+ countries = zone.zone_members.where(zoneable_type: 'Spree::Country').map(&:zoneable).uniq.compact
56
+ countries = countries.reject { |c| assigned_country_ids.include?(c.id) }
57
+ next if countries.empty?
58
+
59
+ market.currency = attrs[:currency]
60
+ market.default_locale = attrs[:default_locale]
61
+ market.supported_locales = attrs[:supported_locales]
62
+ market.countries = countries
63
+ market.save!
64
+ end
@@ -122,7 +122,7 @@ if method
122
122
  source: credit_card.clone,
123
123
  payment_method: method
124
124
  ).first_or_create!
125
- payment.update_columns(state: 'pending', response_code: '12345')
125
+ payment.update_columns(state: 'pending', response_code: "BGS-#{SecureRandom.hex(6)}")
126
126
  end
127
127
  end
128
128
 
@@ -6,6 +6,12 @@ rescue ActiveRecord::RecordNotFound
6
6
  end
7
7
 
8
8
  europe_vat = Spree::Zone.find_by!(name: 'EU_VAT')
9
+ central_america_and_caribbean = Spree::Zone.find_by(name: 'Central America and Caribbean')
10
+ south_america = Spree::Zone.find_by(name: 'South America')
11
+ middle_east = Spree::Zone.find_by(name: 'Middle East')
12
+ africa = Spree::Zone.find_by(name: 'Africa')
13
+ asia = Spree::Zone.find_by(name: 'Asia')
14
+ australia_and_oceania = Spree::Zone.find_by(name: 'Australia and Oceania')
9
15
  shipping_category = Spree::ShippingCategory.find_or_create_by!(name: 'Default')
10
16
 
11
17
  shipping_methods = [
@@ -13,10 +19,18 @@ shipping_methods = [
13
19
  { name: 'UPS Two Day (USD)', zones: [north_america], display_on: 'both', shipping_categories: [shipping_category] },
14
20
  { name: 'UPS One Day (USD)', zones: [north_america], display_on: 'both', shipping_categories: [shipping_category] },
15
21
  { name: 'UPS Ground (EU)', zones: [europe_vat], display_on: 'both', shipping_categories: [shipping_category] },
16
- { name: 'UPS Ground (EUR)', zones: [europe_vat], display_on: 'both', shipping_categories: [shipping_category] }
22
+ { name: 'UPS Ground (EUR)', zones: [europe_vat], display_on: 'both', shipping_categories: [shipping_category] },
23
+ { name: 'DHL Standard (Central America and Caribbean)', zones: [central_america_and_caribbean].compact, display_on: 'both', shipping_categories: [shipping_category] },
24
+ { name: 'DHL Standard (South America)', zones: [south_america].compact, display_on: 'both', shipping_categories: [shipping_category] },
25
+ { name: 'DHL Standard (Middle East)', zones: [middle_east].compact, display_on: 'both', shipping_categories: [shipping_category] },
26
+ { name: 'DHL Standard (Africa)', zones: [africa].compact, display_on: 'both', shipping_categories: [shipping_category] },
27
+ { name: 'DHL Standard (Asia)', zones: [asia].compact, display_on: 'both', shipping_categories: [shipping_category] },
28
+ { name: 'DHL Standard (Australia and Oceania)', zones: [australia_and_oceania].compact, display_on: 'both', shipping_categories: [shipping_category] }
17
29
  ]
18
30
 
19
31
  shipping_methods.each do |attributes|
32
+ next if attributes[:zones].empty?
33
+
20
34
  Spree::ShippingMethod.where(name: attributes[:name]).first_or_create! do |shipping_method|
21
35
  shipping_method.calculator = Spree::Calculator::Shipping::FlatRate.create!
22
36
  shipping_method.zones = attributes[:zones]
@@ -30,9 +44,17 @@ end
30
44
  'UPS Ground (EU)' => [5, 'USD'],
31
45
  'UPS One Day (USD)' => [15, 'USD'],
32
46
  'UPS Two Day (USD)' => [10, 'USD'],
33
- 'UPS Ground (EUR)' => [8, 'EUR']
47
+ 'UPS Ground (EUR)' => [8, 'EUR'],
48
+ 'DHL Standard (Central America and Caribbean)' => [15, 'USD'],
49
+ 'DHL Standard (South America)' => [20, 'USD'],
50
+ 'DHL Standard (Middle East)' => [20, 'USD'],
51
+ 'DHL Standard (Africa)' => [25, 'USD'],
52
+ 'DHL Standard (Asia)' => [20, 'USD'],
53
+ 'DHL Standard (Australia and Oceania)' => [25, 'USD']
34
54
  }.each do |shipping_method_name, (price, currency)|
35
- shipping_method = Spree::ShippingMethod.find_by!(name: shipping_method_name)
55
+ shipping_method = Spree::ShippingMethod.find_by(name: shipping_method_name)
56
+ next unless shipping_method
57
+
36
58
  shipping_method.calculator.preferences = { amount: price, currency: currency }
37
59
  shipping_method.calculator.save!
38
60
  shipping_method.save!
@@ -106,7 +106,7 @@ module Spree
106
106
  def inject_yaml_permitted_classes
107
107
  inside dummy_path do
108
108
  inject_into_file 'config/application.rb', %Q[
109
- config.active_record.yaml_column_permitted_classes = [Symbol, BigDecimal, ActiveSupport::HashWithIndifferentAccess, ActiveSupport::TimeWithZone]
109
+ config.active_record.yaml_column_permitted_classes = [Symbol, BigDecimal, ActiveSupport::HashWithIndifferentAccess, ActiveSupport::TimeWithZone, ActiveSupport::TimeZone, Time]
110
110
  ], after: /config\.load_defaults.*$/, verbose: true
111
111
  end
112
112
  end
@@ -117,6 +117,9 @@ module Spree
117
117
  preference :gift_card_batch_web_limit, :integer, default: 500 # number of gift card codes to be generated in the web process, more than this will be generated in a background job
118
118
  preference :gift_card_batch_limit, :integer, default: 50_000
119
119
 
120
+ # imports
121
+ preference :large_import_threshold, :integer, default: 500 # imports with more rows than this skip per-row UI broadcasts and use bulk processing
122
+
120
123
  end
121
124
  end
122
125
  end
@@ -47,7 +47,7 @@ module Spree
47
47
  app.config.spree = Environment.new(SpreeCalculators.new, SpreeValidators.new, Spree::Core::Configuration.new, Spree::Core::Dependencies.new)
48
48
 
49
49
  app.config.active_record.yaml_column_permitted_classes ||= []
50
- app.config.active_record.yaml_column_permitted_classes.concat([Symbol, BigDecimal, ActiveSupport::HashWithIndifferentAccess, ActiveSupport::TimeWithZone])
50
+ app.config.active_record.yaml_column_permitted_classes.concat([Symbol, BigDecimal, ActiveSupport::HashWithIndifferentAccess, ActiveSupport::TimeWithZone, ActiveSupport::TimeZone, Time])
51
51
  Spree::Config = app.config.spree.preferences
52
52
  Spree::RuntimeConfig = app.config.spree.preferences # for compatibility
53
53
  Spree::Dependencies = app.config.spree.dependencies
@@ -289,13 +289,10 @@ module Spree
289
289
  Spree::Addresses::PhoneValidator
290
290
  ]
291
291
 
292
- # Attach event log subscriber if enabled
293
- if Spree::Config.events_log_enabled
294
- Spree::EventLogSubscriber.attach_to_notifications
295
- end
296
-
297
292
  # Add core event subscribers
298
293
  # Other engines add their subscribers in their own after_initialize blocks
294
+ # Note: Spree::EventLogSubscriber is attached in to_prepare (below) so it
295
+ # survives Zeitwerk code reloads in development.
299
296
  Spree.subscribers.concat [
300
297
  Spree::ExportSubscriber,
301
298
  Spree::ReportSubscriber,
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- VERSION = '5.4.0'.freeze
2
+ VERSION = '5.4.2'.freeze
3
3
 
4
4
  def self.version
5
5
  VERSION
data/lib/spree/events.rb CHANGED
@@ -28,6 +28,12 @@ module Spree
28
28
  #
29
29
  module Events
30
30
  class << self
31
+ # Reference to the AS::N subscription created by Spree::EventLogSubscriber.
32
+ # Stored here (on a module in lib/, not reloaded by Zeitwerk) so that code
33
+ # reloads in development don't orphan the subscription and cause events to
34
+ # be logged multiple times.
35
+ attr_accessor :log_subscription
36
+
31
37
  # Publish an event to all matching subscribers
32
38
  #
33
39
  # @param name [String] The event name (e.g., 'order.complete')
@@ -115,7 +115,7 @@ module Spree
115
115
 
116
116
  @@customer_return_attributes = [:stock_location_id, {
117
117
  return_items_attributes: [:id, :inventory_unit_id, :return_authorization_id, :returned, :pre_tax_amount,
118
- :acceptance_status, :exchange_variant_id, :resellable]
118
+ :acceptance_status, :exchange_variant_id, :resellable, :return_quantity]
119
119
  }]
120
120
 
121
121
  @@digital_attributes = [:attachment, :variant_id]
@@ -222,14 +222,14 @@ module Spree
222
222
  :id, :inventory_unit_id,
223
223
  :preferred_reimbursement_type_id,
224
224
  :return_authorization_id, :returned, :pre_tax_amount,
225
- :acceptance_status, :exchange_variant_id, :resellable
225
+ :acceptance_status, :exchange_variant_id, :resellable, :return_quantity
226
226
  ]
227
227
  }
228
228
  ]
229
229
 
230
230
  @@return_authorization_reason_attributes = [:name, :active]
231
231
 
232
- @@return_item_attributes = [:inventory_unit_id, :return_authorization_id, :returned, :pre_tax_amount, :acceptance_status, :exchange_variant_id, :resellable]
232
+ @@return_item_attributes = [:inventory_unit_id, :return_authorization_id, :returned, :pre_tax_amount, :acceptance_status, :exchange_variant_id, :resellable, :return_quantity]
233
233
 
234
234
  @@role_attributes = [:name]
235
235
 
@@ -3,7 +3,7 @@ FactoryBot.define do
3
3
  order { create(:order, total: amount) }
4
4
  amount { 45.75 }
5
5
  state { 'checkout' }
6
- response_code { '12345' }
6
+ response_code { "BGS-#{SecureRandom.hex(6)}" }
7
7
 
8
8
  payment_method { create(:credit_card_payment_method, stores: [order.store]) }
9
9
  association(:source, factory: :credit_card)
@@ -27,13 +27,10 @@ namespace :spree do
27
27
  name: primary_country&.name || 'Default',
28
28
  currency: iso_country&.currency_code || store.read_attribute(:default_currency) || 'USD',
29
29
  default_locale: iso_country&.languages_official&.first || store.read_attribute(:default_locale) || 'en',
30
- default: true
30
+ default: true,
31
+ country_ids: countries.map(&:id)
31
32
  )
32
33
 
33
- countries.each do |country|
34
- market.market_countries.build(country: country).save!(validate: false)
35
- end
36
-
37
34
  store.update_column(:checkout_zone_id, nil) if checkout_zone_id
38
35
 
39
36
  puts " Created market '#{market.name}' with #{countries.size} countries for store '#{store.name}' (#{store.code})"
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.2
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-04-08 00:00:00.000000000 Z
13
+ date: 2026-04-27 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: i18n-tasks
@@ -404,16 +404,22 @@ dependencies:
404
404
  name: active_storage_validations
405
405
  requirement: !ruby/object:Gem::Requirement
406
406
  requirements:
407
- - - '='
407
+ - - ">="
408
+ - !ruby/object:Gem::Version
409
+ version: '1.3'
410
+ - - "<"
408
411
  - !ruby/object:Gem::Version
409
- version: 1.3.0
412
+ version: '4'
410
413
  type: :runtime
411
414
  prerelease: false
412
415
  version_requirements: !ruby/object:Gem::Requirement
413
416
  requirements:
414
- - - '='
417
+ - - ">="
418
+ - !ruby/object:Gem::Version
419
+ version: '1.3'
420
+ - - "<"
415
421
  - !ruby/object:Gem::Version
416
- version: 1.3.0
422
+ version: '4'
417
423
  - !ruby/object:Gem::Dependency
418
424
  name: mobility
419
425
  requirement: !ruby/object:Gem::Requirement
@@ -584,16 +590,16 @@ dependencies:
584
590
  name: pagy
585
591
  requirement: !ruby/object:Gem::Requirement
586
592
  requirements:
587
- - - "~>"
593
+ - - ">="
588
594
  - !ruby/object:Gem::Version
589
- version: '43.0'
595
+ version: '43.3'
590
596
  type: :runtime
591
597
  prerelease: false
592
598
  version_requirements: !ruby/object:Gem::Requirement
593
599
  requirements:
594
- - - "~>"
600
+ - - ">="
595
601
  - !ruby/object:Gem::Version
596
- version: '43.0'
602
+ version: '43.3'
597
603
  description: Spree Models, Helpers, Services and core libraries
598
604
  email: hello@spreecommerce.org
599
605
  executables: []
@@ -859,6 +865,7 @@ files:
859
865
  - app/jobs/spree/gift_cards/bulk_generate_job.rb
860
866
  - app/jobs/spree/images/save_from_url_job.rb
861
867
  - app/jobs/spree/imports/create_rows_job.rb
868
+ - app/jobs/spree/imports/process_group_job.rb
862
869
  - app/jobs/spree/imports/process_rows_job.rb
863
870
  - app/jobs/spree/payments/handle_webhook_job.rb
864
871
  - app/jobs/spree/products/auto_match_taxons_job.rb
@@ -1144,6 +1151,7 @@ files:
1144
1151
  - app/models/spree/role_user.rb
1145
1152
  - app/models/spree/search_provider/base.rb
1146
1153
  - app/models/spree/search_provider/database.rb
1154
+ - app/models/spree/search_provider/filters_result.rb
1147
1155
  - app/models/spree/search_provider/meilisearch.rb
1148
1156
  - app/models/spree/search_provider/search_result.rb
1149
1157
  - app/models/spree/shipment.rb
@@ -1359,6 +1367,7 @@ files:
1359
1367
  - config/importmap.rb
1360
1368
  - config/initializers/active_storage.rb
1361
1369
  - config/initializers/acts_as_taggable_on.rb
1370
+ - config/initializers/carmen.rb
1362
1371
  - config/initializers/friendly_id.rb
1363
1372
  - config/initializers/inflections.rb
1364
1373
  - config/initializers/mobility.rb
@@ -1503,6 +1512,8 @@ files:
1503
1512
  - db/migrate/20260402000002_add_color_code_to_spree_option_values.rb
1504
1513
  - db/migrate/20260403000000_add_market_to_spree_orders.rb
1505
1514
  - db/migrate/20260408000001_add_unique_index_to_spree_zone_members.rb
1515
+ - db/migrate/20260424000001_add_unique_index_to_spree_payments_response_code.rb
1516
+ - db/migrate/20260424100000_add_processing_groups_to_spree_imports.rb
1506
1517
  - db/sample_data/customers.csv
1507
1518
  - db/sample_data/markets.rb
1508
1519
  - db/sample_data/metafield_definitions.rb
@@ -1733,9 +1744,9 @@ licenses:
1733
1744
  - BSD-3-Clause
1734
1745
  metadata:
1735
1746
  bug_tracker_uri: https://github.com/spree/spree/issues
1736
- changelog_uri: https://github.com/spree/spree/releases/tag/v5.4.0
1747
+ changelog_uri: https://github.com/spree/spree/releases/tag/v5.4.2
1737
1748
  documentation_uri: https://docs.spreecommerce.org/
1738
- source_code_uri: https://github.com/spree/spree/tree/v5.4.0
1749
+ source_code_uri: https://github.com/spree/spree/tree/v5.4.2
1739
1750
  post_install_message:
1740
1751
  rdoc_options: []
1741
1752
  require_paths: