spree_core 5.4.0.rc2 → 5.4.0.rc3
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/models/concerns/spree/product_scopes.rb +10 -0
- data/app/models/spree/order/gift_card.rb +23 -3
- data/app/models/spree/order.rb +18 -1
- data/app/models/spree/price.rb +29 -0
- data/app/models/spree/price_history.rb +29 -0
- data/app/models/spree/promotion_handler/coupon.rb +9 -2
- data/app/services/spree/cart/remove_out_of_stock_items.rb +20 -5
- data/app/services/spree/carts/update.rb +9 -7
- data/app/services/spree/checkout/add_store_credit.rb +26 -2
- data/config/locales/en.yml +1 -0
- data/db/migrate/20260323000000_create_spree_price_histories.rb +20 -0
- data/lib/spree/core/configuration.rb +2 -0
- data/lib/spree/core/version.rb +1 -1
- data/lib/spree/testing_support/factories/price_history_factory.rb +9 -0
- data/lib/tasks/price_history.rake +36 -0
- metadata +8 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: feb2c702a17f0e10532d677c7c6cdb4a4092476ce33966db067ff095e0fd3d51
|
|
4
|
+
data.tar.gz: 6cfb1613127976496083e9d11d5a073e20c7d94b139d2df2f621e4c18ae52936
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8abff3fa43c5226f1eb1c3dd1a5d1bd84fedfd9ef62895da5df6402df1bd9e0fcb68a9fd646790d90ea5efa04292330aeab50e9269d1352a8970c2c8ff362d39
|
|
7
|
+
data.tar.gz: 2cde221d1575d9d48c633d4aacdc588d775aff1445c0bdc5c895ff82e77444e3a5341d5fc1677d6c5013accd73f182f1e2ea5bb5b9532470d13dae4a7e316061
|
|
@@ -3,6 +3,16 @@ module Spree
|
|
|
3
3
|
extend ActiveSupport::Concern
|
|
4
4
|
|
|
5
5
|
included do
|
|
6
|
+
cattr_accessor :search_scopes do
|
|
7
|
+
[]
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.add_search_scope(name, &block)
|
|
11
|
+
Spree::Deprecation.warn("add_search_scope is deprecated and will be removed in Spree 6.0. Use scope :#{name}, &block instead or use method instead")
|
|
12
|
+
singleton_class.send(:define_method, name.to_sym, &block)
|
|
13
|
+
search_scopes << name.to_sym
|
|
14
|
+
end
|
|
15
|
+
|
|
6
16
|
scope :ascend_by_updated_at, -> { order("#{Product.quoted_table_name}.updated_at ASC") }
|
|
7
17
|
scope :descend_by_updated_at, -> { order("#{Product.quoted_table_name}.updated_at DESC") }
|
|
8
18
|
scope :ascend_by_name, -> { order("#{Product.quoted_table_name}.name ASC") }
|
|
@@ -34,11 +34,31 @@ module Spree
|
|
|
34
34
|
Spree.gift_card_remove_service.call(order: self)
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
+
# Recalculates the gift card payment amount based on the current order total.
|
|
38
|
+
# Updates the existing payment in place instead of remove + re-apply
|
|
39
|
+
# to avoid creating unnecessary invalid payment records.
|
|
37
40
|
def recalculate_gift_card
|
|
38
|
-
|
|
41
|
+
return unless gift_card.present?
|
|
42
|
+
|
|
43
|
+
payment = payments.checkout.store_credits.where(source: gift_card.store_credits).first
|
|
44
|
+
return unless payment
|
|
45
|
+
|
|
46
|
+
# with_lock acquires a row lock and wraps in a transaction.
|
|
47
|
+
# The entire read-compute-write must be inside the lock to prevent
|
|
48
|
+
# stale amount_remaining from concurrent requests.
|
|
49
|
+
gift_card.with_lock do
|
|
50
|
+
new_amount = [gift_card.amount_remaining + payment.amount, total].min
|
|
51
|
+
next if payment.amount == new_amount
|
|
39
52
|
|
|
40
|
-
|
|
41
|
-
|
|
53
|
+
difference = new_amount - payment.amount
|
|
54
|
+
# Uses update_column to bypass Payment#max_amount validation which
|
|
55
|
+
# can fail during recalculation due to stale in-memory order state.
|
|
56
|
+
# Bounds are enforced via min() above.
|
|
57
|
+
payment.update_column(:amount, new_amount)
|
|
58
|
+
payment.source.update_column(:amount, new_amount)
|
|
59
|
+
gift_card.amount_used += difference
|
|
60
|
+
gift_card.save!
|
|
61
|
+
end
|
|
42
62
|
end
|
|
43
63
|
|
|
44
64
|
def redeem_gift_card
|
data/app/models/spree/order.rb
CHANGED
|
@@ -49,10 +49,27 @@ module Spree
|
|
|
49
49
|
:included_tax_total, :additional_tax_total, :tax_total,
|
|
50
50
|
:shipment_total, :promo_total, :total,
|
|
51
51
|
:cart_promo_total, :pre_tax_item_amount, :pre_tax_total,
|
|
52
|
-
:payment_total
|
|
52
|
+
:payment_total, :amount_due
|
|
53
53
|
|
|
54
54
|
alias display_ship_total display_shipment_total
|
|
55
55
|
alias_attribute :ship_total, :shipment_total
|
|
56
|
+
def amount_due
|
|
57
|
+
outstanding_balance
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Transient warnings populated by remove_out_of_stock_items!
|
|
61
|
+
attribute :warnings, default: -> { [] }
|
|
62
|
+
|
|
63
|
+
# Removes out-of-stock/discontinued items and populates warnings.
|
|
64
|
+
# Returns self (reloaded if items were removed) with warnings set.
|
|
65
|
+
def remove_out_of_stock_items!
|
|
66
|
+
result = Spree::Cart::RemoveOutOfStockItems.call(order: self)
|
|
67
|
+
return self unless result.success?
|
|
68
|
+
|
|
69
|
+
order, _messages, warnings = result.value
|
|
70
|
+
order.warnings = warnings || []
|
|
71
|
+
order
|
|
72
|
+
end
|
|
56
73
|
|
|
57
74
|
# 5.5 API naming bridges (DB columns rename in 6.0)
|
|
58
75
|
alias_attribute :discount_total, :promo_total
|
data/app/models/spree/price.rb
CHANGED
|
@@ -13,8 +13,11 @@ module Spree
|
|
|
13
13
|
belongs_to :variant, -> { with_deleted }, class_name: 'Spree::Variant', inverse_of: :prices, touch: true
|
|
14
14
|
belongs_to :price_list, class_name: 'Spree::PriceList', optional: true
|
|
15
15
|
|
|
16
|
+
has_many :price_histories, class_name: 'Spree::PriceHistory', dependent: :delete_all
|
|
17
|
+
|
|
16
18
|
before_validation :ensure_currency
|
|
17
19
|
before_save :remove_compare_at_amount_if_equals_amount
|
|
20
|
+
after_save :record_price_history, if: :should_record_price_history?
|
|
18
21
|
|
|
19
22
|
# legacy behavior
|
|
20
23
|
validates :amount, allow_nil: true, numericality: {
|
|
@@ -156,8 +159,34 @@ module Spree
|
|
|
156
159
|
!zero?
|
|
157
160
|
end
|
|
158
161
|
|
|
162
|
+
# Returns the price history record with the lowest amount in the last 30 days
|
|
163
|
+
# Used for EU Omnibus Directive compliance
|
|
164
|
+
#
|
|
165
|
+
# @return [Spree::PriceHistory, nil]
|
|
166
|
+
def prior_price
|
|
167
|
+
price_histories.where(recorded_at: 30.days.ago..).order(:amount).first
|
|
168
|
+
end
|
|
169
|
+
|
|
159
170
|
private
|
|
160
171
|
|
|
172
|
+
def should_record_price_history?
|
|
173
|
+
price_list_id.nil? &&
|
|
174
|
+
amount.present? &&
|
|
175
|
+
saved_change_to_amount? &&
|
|
176
|
+
Spree::Config[:track_price_history]
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def record_price_history
|
|
180
|
+
Spree::PriceHistory.create!(
|
|
181
|
+
price: self,
|
|
182
|
+
variant_id: variant_id,
|
|
183
|
+
amount: amount,
|
|
184
|
+
compare_at_amount: compare_at_amount,
|
|
185
|
+
currency: currency,
|
|
186
|
+
recorded_at: Time.current
|
|
187
|
+
)
|
|
188
|
+
end
|
|
189
|
+
|
|
161
190
|
def ensure_currency
|
|
162
191
|
self.currency ||= Spree::Store.default.default_currency
|
|
163
192
|
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Spree
|
|
4
|
+
class PriceHistory < Spree.base_class
|
|
5
|
+
belongs_to :price, class_name: 'Spree::Price'
|
|
6
|
+
belongs_to :variant, class_name: 'Spree::Variant'
|
|
7
|
+
|
|
8
|
+
validates :amount, presence: true, numericality: { greater_than_or_equal_to: 0 }
|
|
9
|
+
validates :currency, presence: true
|
|
10
|
+
validates :recorded_at, presence: true
|
|
11
|
+
|
|
12
|
+
scope :for_variant, ->(variant_id) { where(variant_id: variant_id) }
|
|
13
|
+
scope :for_currency, ->(currency) { where(currency: currency) }
|
|
14
|
+
scope :in_period, ->(from, to = Time.current) { where(recorded_at: from..to) }
|
|
15
|
+
scope :recent, ->(days = 30) { in_period(days.days.ago) }
|
|
16
|
+
|
|
17
|
+
def money
|
|
18
|
+
Spree::Money.new(amount || 0, currency: currency)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def display_amount
|
|
22
|
+
money.to_s
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def amount_in_cents
|
|
26
|
+
money.amount_in_cents
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -11,7 +11,7 @@ module Spree
|
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def apply
|
|
14
|
-
if load_gift_card_code
|
|
14
|
+
if gift_cards_enabled? && load_gift_card_code
|
|
15
15
|
|
|
16
16
|
if @gift_card.expired?
|
|
17
17
|
set_error_code :gift_card_expired
|
|
@@ -47,7 +47,7 @@ module Spree
|
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
def remove(coupon_code)
|
|
50
|
-
if order.gift_card
|
|
50
|
+
if gift_cards_enabled? && order.gift_card
|
|
51
51
|
result = order.remove_gift_card
|
|
52
52
|
|
|
53
53
|
if result.success?
|
|
@@ -212,6 +212,13 @@ module Spree
|
|
|
212
212
|
Spree::CouponCode.unused.find_by(promotion_id: discount.source.promotion_id, code: coupon_code)&.apply_order!(order)
|
|
213
213
|
end
|
|
214
214
|
|
|
215
|
+
# Whether the coupon handler should also handle gift card codes.
|
|
216
|
+
# Defaults to true for backwards compatibility. Pass enable_gift_cards: false
|
|
217
|
+
# when using the dedicated gift card endpoint.
|
|
218
|
+
def gift_cards_enabled?
|
|
219
|
+
options.fetch(:enable_gift_cards, true)
|
|
220
|
+
end
|
|
221
|
+
|
|
215
222
|
def load_gift_card_code
|
|
216
223
|
return unless order.coupon_code.present?
|
|
217
224
|
|
|
@@ -5,8 +5,9 @@ module Spree
|
|
|
5
5
|
|
|
6
6
|
def call(order:)
|
|
7
7
|
@messages = []
|
|
8
|
+
@warnings = []
|
|
8
9
|
|
|
9
|
-
return success([order, @messages]) if order.item_count.zero? || order.line_items.none?
|
|
10
|
+
return success([order, @messages, @warnings]) if order.item_count.zero? || order.line_items.none?
|
|
10
11
|
|
|
11
12
|
line_items = order.line_items.includes(variant: [:product, :stock_items, :stock_locations, { stock_items: :stock_location }])
|
|
12
13
|
|
|
@@ -17,9 +18,9 @@ module Spree
|
|
|
17
18
|
end
|
|
18
19
|
|
|
19
20
|
if @messages.any? # If any line item was removed, reload the order
|
|
20
|
-
success([order.reload, @messages])
|
|
21
|
+
success([order.reload, @messages, @warnings])
|
|
21
22
|
else
|
|
22
|
-
success([order, @messages])
|
|
23
|
+
success([order, @messages, @warnings])
|
|
23
24
|
end
|
|
24
25
|
end
|
|
25
26
|
|
|
@@ -28,7 +29,14 @@ module Spree
|
|
|
28
29
|
def valid_status?(line_item)
|
|
29
30
|
product = line_item.product
|
|
30
31
|
if !product.active? || product.deleted? || product.discontinued? || line_item.variant.discontinued?
|
|
31
|
-
|
|
32
|
+
message = Spree.t('cart_line_item.discontinued', li_name: line_item.name)
|
|
33
|
+
@messages << message
|
|
34
|
+
@warnings << {
|
|
35
|
+
code: 'line_item_removed',
|
|
36
|
+
message: message,
|
|
37
|
+
line_item_id: line_item.prefixed_id,
|
|
38
|
+
variant_id: line_item.variant.prefixed_id
|
|
39
|
+
}
|
|
32
40
|
return false
|
|
33
41
|
end
|
|
34
42
|
true
|
|
@@ -36,7 +44,14 @@ module Spree
|
|
|
36
44
|
|
|
37
45
|
def stock_available?(line_item)
|
|
38
46
|
if line_item.insufficient_stock?
|
|
39
|
-
|
|
47
|
+
message = Spree.t('cart_line_item.out_of_stock', li_name: line_item.name)
|
|
48
|
+
@messages << message
|
|
49
|
+
@warnings << {
|
|
50
|
+
code: 'line_item_removed',
|
|
51
|
+
message: message,
|
|
52
|
+
line_item_id: line_item.prefixed_id,
|
|
53
|
+
variant_id: line_item.variant.prefixed_id
|
|
54
|
+
}
|
|
40
55
|
return false
|
|
41
56
|
end
|
|
42
57
|
true
|
|
@@ -89,18 +89,20 @@ module Spree
|
|
|
89
89
|
cart.state = 'address'
|
|
90
90
|
end
|
|
91
91
|
|
|
92
|
-
# Auto-advance as far as the checkout state machine allows
|
|
93
|
-
#
|
|
94
|
-
#
|
|
95
|
-
#
|
|
96
|
-
#
|
|
97
|
-
# Failure is swallowed — the update itself already succeeded.
|
|
92
|
+
# Auto-advance as far as the checkout state machine allows, but never
|
|
93
|
+
# to complete. The complete transition must always be explicit via
|
|
94
|
+
# the /carts/:id/complete endpoint — otherwise gift cards or store
|
|
95
|
+
# credits that fully cover the order total would auto-complete the
|
|
96
|
+
# cart during address/delivery updates.
|
|
98
97
|
def try_advance
|
|
99
98
|
return if cart.complete? || cart.canceled?
|
|
100
99
|
|
|
100
|
+
steps = cart.checkout_steps
|
|
101
101
|
loop do
|
|
102
|
+
current_index = steps.index(cart.state).to_i
|
|
103
|
+
next_step = steps[current_index + 1]
|
|
104
|
+
break if next_step.nil? || next_step == 'complete'
|
|
102
105
|
break unless cart.next
|
|
103
|
-
break if cart.confirm? || cart.complete?
|
|
104
106
|
end
|
|
105
107
|
rescue StandardError => e
|
|
106
108
|
Rails.error.report(e, context: { order_id: cart.id, state: cart.state }, source: 'spree.checkout')
|
|
@@ -12,9 +12,13 @@ module Spree
|
|
|
12
12
|
return failure(nil, Spree.t(:error_user_does_not_have_any_store_credits)) unless @order.user&.store_credits&.any?
|
|
13
13
|
|
|
14
14
|
ApplicationRecord.transaction do
|
|
15
|
-
@order.payments.store_credits.where(state: :checkout)
|
|
15
|
+
existing = @order.payments.store_credits.where(state: :checkout)
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
if existing.any?
|
|
18
|
+
update_existing_payments(existing, remaining_total)
|
|
19
|
+
else
|
|
20
|
+
apply_store_credits(remaining_total)
|
|
21
|
+
end
|
|
18
22
|
end
|
|
19
23
|
|
|
20
24
|
if @order.reload.payments.store_credits.valid.any?
|
|
@@ -27,6 +31,26 @@ module Spree
|
|
|
27
31
|
|
|
28
32
|
private
|
|
29
33
|
|
|
34
|
+
# Update existing checkout store credit payments in place to avoid
|
|
35
|
+
# creating unnecessary invalid payment records on every recalculation.
|
|
36
|
+
def update_existing_payments(payments, remaining_total)
|
|
37
|
+
payments.each do |payment|
|
|
38
|
+
credit = payment.source
|
|
39
|
+
available = credit.amount_remaining + payment.amount
|
|
40
|
+
new_amount = [available, remaining_total].min
|
|
41
|
+
|
|
42
|
+
if new_amount.positive?
|
|
43
|
+
payment.update_column(:amount, new_amount)
|
|
44
|
+
remaining_total -= new_amount
|
|
45
|
+
else
|
|
46
|
+
payment.invalidate!
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# If there's still remaining total, apply from additional store credits
|
|
51
|
+
apply_store_credits(remaining_total) if remaining_total.positive?
|
|
52
|
+
end
|
|
53
|
+
|
|
30
54
|
def apply_store_credits(remaining_total)
|
|
31
55
|
payment_method = Spree::PaymentMethod::StoreCredit.available.first
|
|
32
56
|
raise 'Store credit payment method could not be found' unless payment_method
|
data/config/locales/en.yml
CHANGED
|
@@ -1222,6 +1222,7 @@ en:
|
|
|
1222
1222
|
gift_card_expired: The Gift Card has expired.
|
|
1223
1223
|
gift_card_mismatched_currency: Gift Card cannot be applied with current currency.
|
|
1224
1224
|
gift_card_mismatched_customer: This gift card is associated with another user.
|
|
1225
|
+
gift_card_not_found: The Gift Card was not found.
|
|
1225
1226
|
gift_card_removed: The Gift Card was successfully removed from your order
|
|
1226
1227
|
gift_card_using_store_credit_error: You can't apply the Gift Card after you applied the store credit.
|
|
1227
1228
|
gift_cards: Gift Cards
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
class CreateSpreePriceHistories < ActiveRecord::Migration[7.2]
|
|
2
|
+
def change
|
|
3
|
+
create_table :spree_price_histories do |t|
|
|
4
|
+
t.references :price, null: false, index: false
|
|
5
|
+
t.references :variant, null: false, index: false
|
|
6
|
+
t.decimal :amount, precision: 10, scale: 2, null: false
|
|
7
|
+
t.decimal :compare_at_amount, precision: 10, scale: 2
|
|
8
|
+
t.string :currency, null: false
|
|
9
|
+
t.datetime :recorded_at, null: false
|
|
10
|
+
t.datetime :created_at, null: false
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
add_index :spree_price_histories, [:variant_id, :currency, :recorded_at],
|
|
14
|
+
name: 'idx_price_histories_variant_currency_recorded'
|
|
15
|
+
add_index :spree_price_histories, [:price_id, :recorded_at],
|
|
16
|
+
name: 'idx_price_histories_price_recorded'
|
|
17
|
+
add_index :spree_price_histories, :recorded_at,
|
|
18
|
+
name: 'idx_price_histories_recorded_at'
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -96,6 +96,8 @@ module Spree
|
|
|
96
96
|
preference :tax_using_ship_address, :boolean, default: true
|
|
97
97
|
preference :title_site_name_separator, :string, deprecated: true
|
|
98
98
|
preference :track_inventory_levels, :boolean, default: true # Determines whether to track on_hand values for variants / products.
|
|
99
|
+
preference :track_price_history, :boolean, default: true # Records price changes for Omnibus Directive compliance. Disable for non-EU stores.
|
|
100
|
+
preference :price_history_retention_days, :integer, default: 30 # Days to retain price history records. Used by spree:price_history:prune rake task.
|
|
99
101
|
preference :use_user_locale, :boolean, default: true
|
|
100
102
|
|
|
101
103
|
# Sets the path used for products, taxons and pages.
|
data/lib/spree/core/version.rb
CHANGED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
namespace :spree do
|
|
4
|
+
namespace :price_history do
|
|
5
|
+
desc 'Seed price history from existing base prices (run once after migration)'
|
|
6
|
+
task seed: :environment do
|
|
7
|
+
count = 0
|
|
8
|
+
Spree::Price.where(deleted_at: nil, price_list_id: nil).find_each do |price|
|
|
9
|
+
next if price.amount.nil?
|
|
10
|
+
next if Spree::PriceHistory.exists?(price_id: price.id)
|
|
11
|
+
|
|
12
|
+
Spree::PriceHistory.create!(
|
|
13
|
+
price: price,
|
|
14
|
+
variant_id: price.variant_id,
|
|
15
|
+
amount: price.amount,
|
|
16
|
+
compare_at_amount: price.compare_at_amount,
|
|
17
|
+
currency: price.currency,
|
|
18
|
+
recorded_at: price.updated_at || Time.current
|
|
19
|
+
)
|
|
20
|
+
count += 1
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
puts "Seeded #{count} price history records"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
desc 'Prune price history older than retention period'
|
|
27
|
+
task prune: :environment do
|
|
28
|
+
retention_days = Spree::Config[:price_history_retention_days] || 30
|
|
29
|
+
deleted = Spree::PriceHistory
|
|
30
|
+
.where('recorded_at < ?', retention_days.days.ago)
|
|
31
|
+
.delete_all
|
|
32
|
+
|
|
33
|
+
puts "Pruned #{deleted} price history records older than #{retention_days} days"
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
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.4.0.
|
|
4
|
+
version: 5.4.0.rc3
|
|
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-25 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/policy.rb
|
|
1053
1053
|
- app/models/spree/preference.rb
|
|
1054
1054
|
- app/models/spree/price.rb
|
|
1055
|
+
- app/models/spree/price_history.rb
|
|
1055
1056
|
- app/models/spree/price_list.rb
|
|
1056
1057
|
- app/models/spree/price_rule.rb
|
|
1057
1058
|
- app/models/spree/price_rules/customer_group_rule.rb
|
|
@@ -1472,6 +1473,7 @@ files:
|
|
|
1472
1473
|
- db/migrate/20260315000000_create_spree_allowed_origins.rb
|
|
1473
1474
|
- db/migrate/20260315100000_add_product_media_support.rb
|
|
1474
1475
|
- db/migrate/20260317000000_create_spree_refresh_tokens.rb
|
|
1476
|
+
- db/migrate/20260323000000_create_spree_price_histories.rb
|
|
1475
1477
|
- db/sample_data/customers.csv
|
|
1476
1478
|
- db/sample_data/metafield_definitions.rb
|
|
1477
1479
|
- db/sample_data/orders.rb
|
|
@@ -1599,6 +1601,7 @@ files:
|
|
|
1599
1601
|
- lib/spree/testing_support/factories/payment_source_factory.rb
|
|
1600
1602
|
- lib/spree/testing_support/factories/policy_factory.rb
|
|
1601
1603
|
- lib/spree/testing_support/factories/price_factory.rb
|
|
1604
|
+
- lib/spree/testing_support/factories/price_history_factory.rb
|
|
1602
1605
|
- lib/spree/testing_support/factories/price_list_factory.rb
|
|
1603
1606
|
- lib/spree/testing_support/factories/price_rule_factory.rb
|
|
1604
1607
|
- lib/spree/testing_support/factories/product_factory.rb
|
|
@@ -1670,6 +1673,7 @@ files:
|
|
|
1670
1673
|
- lib/tasks/dependencies.rake
|
|
1671
1674
|
- lib/tasks/images.rake
|
|
1672
1675
|
- lib/tasks/markets.rake
|
|
1676
|
+
- lib/tasks/price_history.rake
|
|
1673
1677
|
- lib/tasks/products.rake
|
|
1674
1678
|
- lib/tasks/sample_data.rake
|
|
1675
1679
|
- lib/tasks/search.rake
|
|
@@ -1695,9 +1699,9 @@ licenses:
|
|
|
1695
1699
|
- BSD-3-Clause
|
|
1696
1700
|
metadata:
|
|
1697
1701
|
bug_tracker_uri: https://github.com/spree/spree/issues
|
|
1698
|
-
changelog_uri: https://github.com/spree/spree/releases/tag/v5.4.0.
|
|
1702
|
+
changelog_uri: https://github.com/spree/spree/releases/tag/v5.4.0.rc3
|
|
1699
1703
|
documentation_uri: https://docs.spreecommerce.org/
|
|
1700
|
-
source_code_uri: https://github.com/spree/spree/tree/v5.4.0.
|
|
1704
|
+
source_code_uri: https://github.com/spree/spree/tree/v5.4.0.rc3
|
|
1701
1705
|
post_install_message:
|
|
1702
1706
|
rdoc_options: []
|
|
1703
1707
|
require_paths:
|