spree_core 5.4.2 → 5.4.3
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/events/subscriber_job.rb +1 -1
- data/app/models/concerns/spree/publishable.rb +1 -1
- data/app/models/spree/asset.rb +9 -9
- data/app/models/spree/event.rb +6 -6
- data/app/models/spree/export.rb +2 -2
- data/app/models/spree/exports/product_translations.rb +1 -1
- data/app/models/spree/gateway/bogus.rb +6 -1
- data/app/models/spree/line_item.rb +1 -1
- data/app/models/spree/market.rb +25 -0
- data/app/models/spree/order_inventory.rb +24 -2
- data/app/models/spree/payment_setup_sessions/bogus.rb +4 -0
- data/app/models/spree/shipment.rb +10 -4
- data/app/models/spree/subscriber.rb +12 -12
- data/app/presenters/spree/csv/formula_sanitizer.rb +28 -0
- data/app/services/spree/credit_cards/destroy.rb +1 -1
- data/app/services/spree/payments/handle_webhook.rb +3 -10
- data/app/subscribers/spree/event_log_subscriber.rb +1 -1
- data/config/locales/en.yml +8 -0
- data/db/migrate/20260504103113_add_type_to_spree_payment_setup_sessions.rb +6 -0
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/events/adapters/active_support_notifications.rb +1 -1
- data/lib/spree/events/adapters/base.rb +3 -3
- data/lib/spree/events/registry.rb +1 -1
- data/lib/spree/events.rb +1 -1
- metadata +7 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d8ff8a33cfaa4b9554bb3658995a2ed99d1715cb2365d3da012fce5dd2bbd518
|
|
4
|
+
data.tar.gz: fd19b449aa211be4cbec760db28e573064f9112d8c0922bf78517e51c0fc5002
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5a392b8f08c1732f3b661a8758d37d63ac70e2aa7cf39d01dff5521c0e3267b1ee87ed190ea2cdddf914c7bf83462ebb6c7809736b5243610ab6d5e55c411300
|
|
7
|
+
data.tar.gz: 841e2707d2535a628a1cc2c743d594276a1cda0a969dd243ed8d82329f53f5d96bda3433517e40d0e261ef79159a7faae9cb57ebb1c5975b6bd2ea00f17d7641
|
|
@@ -10,7 +10,7 @@ module Spree
|
|
|
10
10
|
# @example Direct usage (typically called by the adapter)
|
|
11
11
|
# Spree::Events::SubscriberJob.perform_later(
|
|
12
12
|
# 'MySubscriber',
|
|
13
|
-
# { name: 'order.
|
|
13
|
+
# { name: 'order.completed', payload: {...}, ... }
|
|
14
14
|
# )
|
|
15
15
|
#
|
|
16
16
|
class SubscriberJob < Spree::BaseJob
|
|
@@ -122,7 +122,7 @@ module Spree
|
|
|
122
122
|
|
|
123
123
|
# Publish an event with this model's data
|
|
124
124
|
#
|
|
125
|
-
# @param event_name [String] The event name (e.g., 'order.
|
|
125
|
+
# @param event_name [String] The event name (e.g., 'order.completed')
|
|
126
126
|
# @param payload [Hash, nil] Custom payload (defaults to event_payload)
|
|
127
127
|
# @param metadata [Hash] Additional metadata
|
|
128
128
|
# @return [Spree::Event] The published event
|
data/app/models/spree/asset.rb
CHANGED
|
@@ -153,31 +153,31 @@ module Spree
|
|
|
153
153
|
end
|
|
154
154
|
|
|
155
155
|
def increment_viewable_media_count
|
|
156
|
-
case
|
|
157
|
-
when
|
|
156
|
+
case viewable
|
|
157
|
+
when Spree::Variant
|
|
158
158
|
Spree::Variant.increment_counter(:media_count, viewable_id)
|
|
159
159
|
Spree::Product.increment_counter(:media_count, viewable.product_id)
|
|
160
|
-
when
|
|
160
|
+
when Spree::Product
|
|
161
161
|
Spree::Product.increment_counter(:media_count, viewable_id)
|
|
162
162
|
end
|
|
163
163
|
end
|
|
164
164
|
|
|
165
165
|
def decrement_viewable_media_count
|
|
166
|
-
case
|
|
167
|
-
when
|
|
166
|
+
case viewable
|
|
167
|
+
when Spree::Variant
|
|
168
168
|
Spree::Variant.decrement_counter(:media_count, viewable_id)
|
|
169
169
|
Spree::Product.decrement_counter(:media_count, viewable.product_id)
|
|
170
|
-
when
|
|
170
|
+
when Spree::Product
|
|
171
171
|
Spree::Product.decrement_counter(:media_count, viewable_id)
|
|
172
172
|
end
|
|
173
173
|
end
|
|
174
174
|
|
|
175
175
|
def update_viewable_thumbnail
|
|
176
|
-
case
|
|
177
|
-
when
|
|
176
|
+
case viewable
|
|
177
|
+
when Spree::Variant
|
|
178
178
|
viewable.update_thumbnail!
|
|
179
179
|
viewable.product.update_thumbnail!
|
|
180
|
-
when
|
|
180
|
+
when Spree::Product
|
|
181
181
|
viewable.update_thumbnail!
|
|
182
182
|
end
|
|
183
183
|
end
|
data/app/models/spree/event.rb
CHANGED
|
@@ -6,20 +6,20 @@ module Spree
|
|
|
6
6
|
# Events are immutable objects that carry information about something
|
|
7
7
|
# that happened in the system. They contain:
|
|
8
8
|
# - An id (UUID)
|
|
9
|
-
# - A name (e.g., 'order.
|
|
9
|
+
# - A name (e.g., 'order.completed', 'product.created')
|
|
10
10
|
# - A store_id (the store where the event originated)
|
|
11
11
|
# - A payload (serialized data about the event)
|
|
12
12
|
# - Metadata (contextual information like spree_version)
|
|
13
13
|
#
|
|
14
14
|
# @example Creating an event
|
|
15
15
|
# event = Spree::Event.new(
|
|
16
|
-
# name: 'order.
|
|
16
|
+
# name: 'order.completed',
|
|
17
17
|
# payload: order.serializable_hash
|
|
18
18
|
# )
|
|
19
19
|
#
|
|
20
20
|
# @example Accessing event data
|
|
21
21
|
# event.id # => "550e8400-e29b-41d4-a716-446655440000"
|
|
22
|
-
# event.name # => 'order.
|
|
22
|
+
# event.name # => 'order.completed'
|
|
23
23
|
# event.store_id # => 1
|
|
24
24
|
# event.payload # => { 'id' => 1, 'number' => 'R123456' }
|
|
25
25
|
# event.created_at # => 2024-01-15 10:30:00 UTC
|
|
@@ -61,19 +61,19 @@ module Spree
|
|
|
61
61
|
end
|
|
62
62
|
|
|
63
63
|
# Returns the resource type from the event name
|
|
64
|
-
# @return [String] The resource type (e.g., 'order' from 'order.
|
|
64
|
+
# @return [String] The resource type (e.g., 'order' from 'order.completed')
|
|
65
65
|
def resource_type
|
|
66
66
|
@resource_type ||= name.to_s.split('.').first
|
|
67
67
|
end
|
|
68
68
|
|
|
69
69
|
# Returns the action from the event name
|
|
70
|
-
# @return [String] The action (e.g., '
|
|
70
|
+
# @return [String] The action (e.g., 'completed' from 'order.completed')
|
|
71
71
|
def action
|
|
72
72
|
@action ||= name.to_s.split('.').drop(1).join('.')
|
|
73
73
|
end
|
|
74
74
|
|
|
75
75
|
# Checks if the event matches a pattern
|
|
76
|
-
# Supports wildcards: 'order.*' matches 'order.
|
|
76
|
+
# Supports wildcards: 'order.*' matches 'order.completed', 'order.canceled'
|
|
77
77
|
# @param pattern [String] The pattern to match against
|
|
78
78
|
# @return [Boolean]
|
|
79
79
|
def matches?(pattern)
|
data/app/models/spree/export.rb
CHANGED
|
@@ -83,10 +83,10 @@ module Spree
|
|
|
83
83
|
batch.each do |record|
|
|
84
84
|
if multi_line_csv?
|
|
85
85
|
record.to_csv(store).each do |line|
|
|
86
|
-
csv << line
|
|
86
|
+
csv << Spree::CSV::FormulaSanitizer.row(line)
|
|
87
87
|
end
|
|
88
88
|
else
|
|
89
|
-
csv << record.to_csv(store)
|
|
89
|
+
csv << Spree::CSV::FormulaSanitizer.row(record.to_csv(store))
|
|
90
90
|
end
|
|
91
91
|
end
|
|
92
92
|
end
|
|
@@ -120,9 +120,14 @@ module Spree
|
|
|
120
120
|
true
|
|
121
121
|
end
|
|
122
122
|
|
|
123
|
+
def payment_setup_session_class
|
|
124
|
+
PaymentSetupSessions::Bogus
|
|
125
|
+
end
|
|
126
|
+
|
|
123
127
|
def create_payment_setup_session(customer:, external_data: {})
|
|
124
|
-
|
|
128
|
+
payment_setup_session_class.create(
|
|
125
129
|
customer: customer,
|
|
130
|
+
payment_method: self,
|
|
126
131
|
status: 'pending',
|
|
127
132
|
external_id: "bogus_seti_#{SecureRandom.hex(12)}",
|
|
128
133
|
external_client_secret: "bogus_seti_secret_#{SecureRandom.hex(8)}",
|
|
@@ -293,7 +293,7 @@ module Spree
|
|
|
293
293
|
end
|
|
294
294
|
|
|
295
295
|
def verify_order_inventory_before_destroy
|
|
296
|
-
Spree::OrderInventory.new(order, self).verify(target_shipment)
|
|
296
|
+
Spree::OrderInventory.new(order, self).verify(target_shipment, removing: true)
|
|
297
297
|
end
|
|
298
298
|
|
|
299
299
|
def update_adjustments
|
data/app/models/spree/market.rb
CHANGED
|
@@ -28,6 +28,7 @@ module Spree
|
|
|
28
28
|
# Callbacks
|
|
29
29
|
#
|
|
30
30
|
before_save :ensure_single_default
|
|
31
|
+
before_destroy :ensure_can_be_deleted
|
|
31
32
|
|
|
32
33
|
#
|
|
33
34
|
# Scopes
|
|
@@ -80,12 +81,36 @@ module Spree
|
|
|
80
81
|
@supported_locales_list ||= (supported_locales.to_s.split(',').map(&:strip) << default_locale).compact.uniq.sort
|
|
81
82
|
end
|
|
82
83
|
|
|
84
|
+
# Returns true when the market is safe to delete. A market cannot be deleted
|
|
85
|
+
# if it is the default market or the only market in the store, since
|
|
86
|
+
# Spree::Current.currency would have no fallback.
|
|
87
|
+
#
|
|
88
|
+
# @return [Boolean]
|
|
89
|
+
def can_be_deleted?
|
|
90
|
+
!default? && !last_in_store?
|
|
91
|
+
end
|
|
92
|
+
|
|
83
93
|
private
|
|
84
94
|
|
|
95
|
+
def last_in_store?
|
|
96
|
+
!self.class.where(store_id: store_id).where.not(id: id).exists?
|
|
97
|
+
end
|
|
98
|
+
|
|
85
99
|
def ensure_single_default
|
|
86
100
|
return unless default? && default_changed?
|
|
87
101
|
|
|
88
102
|
self.class.where(store_id: store_id, default: true).where.not(id: id).update_all(default: false)
|
|
89
103
|
end
|
|
104
|
+
|
|
105
|
+
def ensure_can_be_deleted
|
|
106
|
+
return if can_be_deleted?
|
|
107
|
+
|
|
108
|
+
if default?
|
|
109
|
+
errors.add(:base, :cannot_destroy_default_market)
|
|
110
|
+
else
|
|
111
|
+
errors.add(:base, :cannot_destroy_last_market)
|
|
112
|
+
end
|
|
113
|
+
throw(:abort)
|
|
114
|
+
end
|
|
90
115
|
end
|
|
91
116
|
end
|
|
@@ -17,13 +17,23 @@ module Spree
|
|
|
17
17
|
# In case shipment is passed the stock location should only unstock or
|
|
18
18
|
# restock items if the order is completed. That is so because stock items
|
|
19
19
|
# are always unstocked when the order is completed through +shipment.finalize+
|
|
20
|
-
def verify(shipment = nil, is_updated: false)
|
|
20
|
+
def verify(shipment = nil, is_updated: false, removing: false)
|
|
21
21
|
return unless order.completed? || shipment.present?
|
|
22
22
|
|
|
23
23
|
units_count = inventory_units.reload.sum(&:quantity)
|
|
24
24
|
line_item_changed = is_updated ? !line_item.saved_changes? : !line_item.changed?
|
|
25
25
|
|
|
26
|
-
if
|
|
26
|
+
if removing
|
|
27
|
+
# When the line item is being destroyed, only remove existing inventory.
|
|
28
|
+
# Adding here would create units that the LineItem `dependent: :destroy`
|
|
29
|
+
# cascade can't see (set_up_inventory writes through shipment.inventory_units,
|
|
30
|
+
# leaving line_item.inventory_units stale), producing an orphaned unit.
|
|
31
|
+
#
|
|
32
|
+
# Bypass `remove` because it routes through `set_quantity_to_remove` which
|
|
33
|
+
# assumes a quantity-change scenario; here we want to drain everything tied
|
|
34
|
+
# to this line item regardless of `line_item.quantity`.
|
|
35
|
+
remove_all_units(units_count, shipment) if units_count.positive?
|
|
36
|
+
elsif units_count < line_item.quantity
|
|
27
37
|
quantity = line_item.quantity - units_count
|
|
28
38
|
|
|
29
39
|
shipment ||= determine_target_shipment
|
|
@@ -49,6 +59,18 @@ module Spree
|
|
|
49
59
|
end
|
|
50
60
|
end
|
|
51
61
|
|
|
62
|
+
def remove_all_units(quantity, target_shipment = nil)
|
|
63
|
+
if target_shipment.present?
|
|
64
|
+
remove_from_shipment(target_shipment, quantity)
|
|
65
|
+
else
|
|
66
|
+
order.shipments.each do |shipment|
|
|
67
|
+
break if quantity.zero?
|
|
68
|
+
|
|
69
|
+
quantity -= remove_from_shipment(shipment, quantity)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
52
74
|
def set_quantity_to_remove(units_count)
|
|
53
75
|
if (units_count - line_item.quantity).zero?
|
|
54
76
|
line_item.quantity
|
|
@@ -272,16 +272,22 @@ module Spree
|
|
|
272
272
|
def manifest
|
|
273
273
|
# Grouping by the ID means that we don't have to call out to the association accessor
|
|
274
274
|
# This makes the grouping by faster because it results in less SQL cache hits.
|
|
275
|
-
inventory_units.group_by(&:variant_id).
|
|
276
|
-
units.group_by(&:line_item_id).
|
|
275
|
+
inventory_units.group_by(&:variant_id).flat_map do |_variant_id, units|
|
|
276
|
+
units.group_by(&:line_item_id).filter_map do |_line_item_id, units|
|
|
277
|
+
line_item = units.first.line_item
|
|
278
|
+
# Defensively skip orphaned inventory units (line item destroyed
|
|
279
|
+
# without cascading) so a single bad row doesn't crash callers that
|
|
280
|
+
# rely on line_item being present (item_cost, item_weight, the admin
|
|
281
|
+
# shipment manifest view, etc.).
|
|
282
|
+
next if line_item.nil?
|
|
283
|
+
|
|
277
284
|
states = {}
|
|
278
285
|
units.group_by(&:state).each { |state, iu| states[state] = iu.sum(&:quantity) }
|
|
279
286
|
|
|
280
|
-
line_item = units.first.line_item
|
|
281
287
|
variant = units.first.variant
|
|
282
288
|
ManifestItem.new(line_item, variant, units.sum(&:quantity), states)
|
|
283
289
|
end
|
|
284
|
-
end
|
|
290
|
+
end
|
|
285
291
|
end
|
|
286
292
|
|
|
287
293
|
def process_order_payments
|
|
@@ -9,7 +9,7 @@ module Spree
|
|
|
9
9
|
#
|
|
10
10
|
# @example Basic subscriber
|
|
11
11
|
# class OrderCompletedNotifier < Spree::Subscriber
|
|
12
|
-
# subscribes_to 'order.
|
|
12
|
+
# subscribes_to 'order.completed'
|
|
13
13
|
#
|
|
14
14
|
# def call(event)
|
|
15
15
|
# order_id = event.payload['id']
|
|
@@ -19,7 +19,7 @@ module Spree
|
|
|
19
19
|
#
|
|
20
20
|
# @example Multi-event subscriber
|
|
21
21
|
# class OrderAuditLogger < Spree::Subscriber
|
|
22
|
-
# subscribes_to 'order.
|
|
22
|
+
# subscribes_to 'order.completed', 'order.canceled', 'order.resumed'
|
|
23
23
|
#
|
|
24
24
|
# def call(event)
|
|
25
25
|
# AuditLog.create!(
|
|
@@ -41,11 +41,11 @@ module Spree
|
|
|
41
41
|
#
|
|
42
42
|
# @example Subscriber with method routing
|
|
43
43
|
# class PaymentSubscriber < Spree::Subscriber
|
|
44
|
-
# subscribes_to 'payment.
|
|
44
|
+
# subscribes_to 'payment.completed', 'payment.voided', 'refund.created'
|
|
45
45
|
#
|
|
46
|
-
# on 'payment.
|
|
47
|
-
# on 'payment.
|
|
48
|
-
# on '
|
|
46
|
+
# on 'payment.completed', :handle_complete
|
|
47
|
+
# on 'payment.voided', :handle_void
|
|
48
|
+
# on 'refund.created', :handle_refund
|
|
49
49
|
#
|
|
50
50
|
# private
|
|
51
51
|
#
|
|
@@ -64,7 +64,7 @@ module Spree
|
|
|
64
64
|
#
|
|
65
65
|
# @example Synchronous subscriber (runs immediately, not via ActiveJob)
|
|
66
66
|
# class CriticalOrderHandler < Spree::Subscriber
|
|
67
|
-
# subscribes_to 'order.
|
|
67
|
+
# subscribes_to 'order.completed', async: false
|
|
68
68
|
#
|
|
69
69
|
# def call(event)
|
|
70
70
|
# # This runs synchronously
|
|
@@ -81,10 +81,10 @@ module Spree
|
|
|
81
81
|
# @return [void]
|
|
82
82
|
#
|
|
83
83
|
# @example
|
|
84
|
-
# subscribes_to 'order.
|
|
85
|
-
# subscribes_to 'order.
|
|
84
|
+
# subscribes_to 'order.completed'
|
|
85
|
+
# subscribes_to 'order.completed', 'order.canceled'
|
|
86
86
|
# subscribes_to 'order.*'
|
|
87
|
-
# subscribes_to 'order.
|
|
87
|
+
# subscribes_to 'order.completed', async: false
|
|
88
88
|
#
|
|
89
89
|
def subscribes_to(*patterns, **options)
|
|
90
90
|
@subscription_patterns ||= []
|
|
@@ -102,8 +102,8 @@ module Spree
|
|
|
102
102
|
# @return [void]
|
|
103
103
|
#
|
|
104
104
|
# @example
|
|
105
|
-
# on 'payment.
|
|
106
|
-
# on 'payment.
|
|
105
|
+
# on 'payment.completed', :handle_complete
|
|
106
|
+
# on 'payment.voided', :handle_void
|
|
107
107
|
#
|
|
108
108
|
def on(pattern, method_name)
|
|
109
109
|
@event_handlers ||= {}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module CSV
|
|
3
|
+
# Neutralizes CSV formula injection (CWE-1236 / OWASP "CSV Injection")
|
|
4
|
+
# by prefixing cells that would otherwise be evaluated as a formula
|
|
5
|
+
# when the exported file is opened in Excel, Google Sheets, LibreOffice,
|
|
6
|
+
# or Numbers.
|
|
7
|
+
#
|
|
8
|
+
# The leading apostrophe is the OWASP-recommended marker — spreadsheets
|
|
9
|
+
# render the cell as plain text without displaying the apostrophe.
|
|
10
|
+
module FormulaSanitizer
|
|
11
|
+
TRIGGERS = ["=", "+", "-", "@", "\t", "\r", "\n"].freeze
|
|
12
|
+
|
|
13
|
+
module_function
|
|
14
|
+
|
|
15
|
+
def cell(value)
|
|
16
|
+
return value unless value.is_a?(String)
|
|
17
|
+
return value if value.empty?
|
|
18
|
+
return value unless TRIGGERS.include?(value[0])
|
|
19
|
+
|
|
20
|
+
"'#{value}"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def row(values)
|
|
24
|
+
values.map { |v| cell(v) }
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -11,7 +11,7 @@ module Spree
|
|
|
11
11
|
"#{self.class.name} is deprecated and will be removed in Spree 6.0. " \
|
|
12
12
|
'Use card.destroy directly instead. Payment cleanup is now handled ' \
|
|
13
13
|
'automatically by the before_destroy callback in PaymentSourceConcern.',
|
|
14
|
-
|
|
14
|
+
caller_locations(2)
|
|
15
15
|
)
|
|
16
16
|
|
|
17
17
|
if card.destroy
|
|
@@ -28,6 +28,8 @@ module Spree
|
|
|
28
28
|
|
|
29
29
|
private
|
|
30
30
|
|
|
31
|
+
# `Spree::Payment#confirm!` honors the payment method's `auto_capture?` setting:
|
|
32
|
+
# auto_capture → complete! + capture_event; otherwise → pend! (auth-only, payment_state=balance_due).
|
|
31
33
|
def handle_success(payment_session, order, metadata)
|
|
32
34
|
order.with_lock do
|
|
33
35
|
# Idempotency: if the session was already completed (by the API
|
|
@@ -36,19 +38,10 @@ module Spree
|
|
|
36
38
|
return success(payment_session)
|
|
37
39
|
end
|
|
38
40
|
|
|
39
|
-
# Ensure payment record exists
|
|
40
41
|
payment = payment_session.find_or_create_payment!(metadata)
|
|
41
|
-
|
|
42
|
-
# Mark payment as completed — the webhook confirms the gateway processed it
|
|
43
|
-
if payment.present? && !payment.completed?
|
|
44
|
-
payment.started_processing! if payment.checkout?
|
|
45
|
-
payment.complete! if payment.can_complete?
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
# Mark session as completed
|
|
42
|
+
payment.confirm! if payment.present? && !payment.completed?
|
|
49
43
|
payment_session.complete if payment_session.can_complete?
|
|
50
44
|
|
|
51
|
-
# Complete order if not already done
|
|
52
45
|
unless order.reload.completed?
|
|
53
46
|
Spree::Dependencies.carts_complete_service.constantize.call(cart: order)
|
|
54
47
|
end
|
|
@@ -9,7 +9,7 @@ module Spree
|
|
|
9
9
|
# Rails.application.config.filter_parameters.
|
|
10
10
|
#
|
|
11
11
|
# @example Output
|
|
12
|
-
# [Spree Event] order.
|
|
12
|
+
# [Spree Event] order.completed | payload: {"id"=>1} | 0.5ms
|
|
13
13
|
#
|
|
14
14
|
class EventLogSubscriber
|
|
15
15
|
NAMESPACE = 'spree'
|
data/config/locales/en.yml
CHANGED
|
@@ -299,6 +299,11 @@ en:
|
|
|
299
299
|
attributes:
|
|
300
300
|
currency:
|
|
301
301
|
must_match_order_currency: Must match order currency
|
|
302
|
+
spree/market:
|
|
303
|
+
attributes:
|
|
304
|
+
base:
|
|
305
|
+
cannot_destroy_default_market: Cannot delete the default market.
|
|
306
|
+
cannot_destroy_last_market: Cannot delete the only market.
|
|
302
307
|
spree/market_country:
|
|
303
308
|
attributes:
|
|
304
309
|
country:
|
|
@@ -1311,6 +1316,9 @@ en:
|
|
|
1311
1316
|
inventory_error_flash_for_insufficient_quantity: An item in your cart has become unavailable.
|
|
1312
1317
|
inventory_state: Inventory State
|
|
1313
1318
|
invitation_accepted: Invitation accepted!
|
|
1319
|
+
invitation_expired:
|
|
1320
|
+
body: This invitation link is no longer valid. Please ask the person who invited you to send a new one.
|
|
1321
|
+
heading: Invitation invalid or expired
|
|
1314
1322
|
invitation_mailer:
|
|
1315
1323
|
greeting: Hi %{user_name},
|
|
1316
1324
|
invitation_accepted:
|
data/lib/spree/core/version.rb
CHANGED
|
@@ -12,7 +12,7 @@ module Spree
|
|
|
12
12
|
#
|
|
13
13
|
# @example Publishing an event
|
|
14
14
|
# adapter = ActiveSupportNotifications.new(registry)
|
|
15
|
-
# adapter.publish('order.
|
|
15
|
+
# adapter.publish('order.completed', { id: 1 })
|
|
16
16
|
#
|
|
17
17
|
class ActiveSupportNotifications < Base
|
|
18
18
|
NAMESPACE = 'spree'
|
|
@@ -43,13 +43,13 @@ module Spree
|
|
|
43
43
|
|
|
44
44
|
# Publish an event to all matching subscribers.
|
|
45
45
|
#
|
|
46
|
-
# @param event_name [String] the event name (e.g., 'order.
|
|
46
|
+
# @param event_name [String] the event name (e.g., 'order.completed')
|
|
47
47
|
# @param payload [Hash] the event payload (should be serializable)
|
|
48
48
|
# @param metadata [Hash] additional metadata for the event
|
|
49
49
|
# @return [Spree::Event] the published event
|
|
50
50
|
#
|
|
51
51
|
# @example
|
|
52
|
-
# adapter.publish('order.
|
|
52
|
+
# adapter.publish('order.completed', order.serializable_hash, { user_id: 1 })
|
|
53
53
|
#
|
|
54
54
|
def publish(event_name, payload, metadata = {})
|
|
55
55
|
raise NotImplementedError, "#{self.class}#publish must be implemented"
|
|
@@ -67,7 +67,7 @@ module Spree
|
|
|
67
67
|
# @option options [Boolean] :async (true) whether to run async via ActiveJob
|
|
68
68
|
#
|
|
69
69
|
# @example
|
|
70
|
-
# adapter.subscribe('order.
|
|
70
|
+
# adapter.subscribe('order.completed', MySubscriber)
|
|
71
71
|
# adapter.subscribe('order.*', AuditLogger, async: false)
|
|
72
72
|
#
|
|
73
73
|
def subscribe(pattern, subscriber, options = {})
|
|
@@ -15,7 +15,7 @@ module Spree
|
|
|
15
15
|
# @example
|
|
16
16
|
# registry = Spree::Events::Registry.new
|
|
17
17
|
# registry.register('order.*', MySubscriber, async: true)
|
|
18
|
-
# registry.subscriptions_for('order.
|
|
18
|
+
# registry.subscriptions_for('order.completed') # => [Subscription]
|
|
19
19
|
#
|
|
20
20
|
class Registry
|
|
21
21
|
# Immutable subscription data using Ruby 3.2+ Data class
|
data/lib/spree/events.rb
CHANGED
|
@@ -36,7 +36,7 @@ module Spree
|
|
|
36
36
|
|
|
37
37
|
# Publish an event to all matching subscribers
|
|
38
38
|
#
|
|
39
|
-
# @param name [String] The event name (e.g., 'order.
|
|
39
|
+
# @param name [String] The event name (e.g., 'order.completed')
|
|
40
40
|
# @param payload [Hash] The event payload (should be serializable)
|
|
41
41
|
# @param metadata [Hash] Additional metadata for the event
|
|
42
42
|
# @return [Spree::Event] The published event
|
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.
|
|
4
|
+
version: 5.4.3
|
|
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-
|
|
13
|
+
date: 2026-05-19 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
16
|
name: i18n-tasks
|
|
@@ -1052,6 +1052,7 @@ files:
|
|
|
1052
1052
|
- app/models/spree/payment_session.rb
|
|
1053
1053
|
- app/models/spree/payment_sessions/bogus.rb
|
|
1054
1054
|
- app/models/spree/payment_setup_session.rb
|
|
1055
|
+
- app/models/spree/payment_setup_sessions/bogus.rb
|
|
1055
1056
|
- app/models/spree/payment_source.rb
|
|
1056
1057
|
- app/models/spree/permission_sets/base.rb
|
|
1057
1058
|
- app/models/spree/permission_sets/configuration_management.rb
|
|
@@ -1218,6 +1219,7 @@ files:
|
|
|
1218
1219
|
- app/paginators/spree/shared/paginate.rb
|
|
1219
1220
|
- app/presenters/spree/csv/coupon_code_presenter.rb
|
|
1220
1221
|
- app/presenters/spree/csv/customer_presenter.rb
|
|
1222
|
+
- app/presenters/spree/csv/formula_sanitizer.rb
|
|
1221
1223
|
- app/presenters/spree/csv/gift_card_presenter.rb
|
|
1222
1224
|
- app/presenters/spree/csv/metafields_helper.rb
|
|
1223
1225
|
- app/presenters/spree/csv/newsletter_subscriber_presenter.rb
|
|
@@ -1514,6 +1516,7 @@ files:
|
|
|
1514
1516
|
- db/migrate/20260408000001_add_unique_index_to_spree_zone_members.rb
|
|
1515
1517
|
- db/migrate/20260424000001_add_unique_index_to_spree_payments_response_code.rb
|
|
1516
1518
|
- db/migrate/20260424100000_add_processing_groups_to_spree_imports.rb
|
|
1519
|
+
- db/migrate/20260504103113_add_type_to_spree_payment_setup_sessions.rb
|
|
1517
1520
|
- db/sample_data/customers.csv
|
|
1518
1521
|
- db/sample_data/markets.rb
|
|
1519
1522
|
- db/sample_data/metafield_definitions.rb
|
|
@@ -1744,9 +1747,9 @@ licenses:
|
|
|
1744
1747
|
- BSD-3-Clause
|
|
1745
1748
|
metadata:
|
|
1746
1749
|
bug_tracker_uri: https://github.com/spree/spree/issues
|
|
1747
|
-
changelog_uri: https://github.com/spree/spree/releases/tag/v5.4.
|
|
1750
|
+
changelog_uri: https://github.com/spree/spree/releases/tag/v5.4.3
|
|
1748
1751
|
documentation_uri: https://docs.spreecommerce.org/
|
|
1749
|
-
source_code_uri: https://github.com/spree/spree/tree/v5.4.
|
|
1752
|
+
source_code_uri: https://github.com/spree/spree/tree/v5.4.3
|
|
1750
1753
|
post_install_message:
|
|
1751
1754
|
rdoc_options: []
|
|
1752
1755
|
require_paths:
|