spree_core 5.4.0 → 5.4.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 063ec32e04e9cca4d9987ddc55b8bf72266d6f9aaf204f2e7da96ad57365495d
4
- data.tar.gz: 9b13ad923ebcad513038a2bbe63d880c9b285e73e18e93a3f73983bec23cc6a1
3
+ metadata.gz: 3bed2ace5a7bcb6bc6b8c598cfb3ec19cb3dc0ea02854744543ae228ed9c636b
4
+ data.tar.gz: 81642ee18f7e01079090ec1c5d162dc25186aa5bd72ac2e799a5a3457ebd1a1a
5
5
  SHA512:
6
- metadata.gz: a4cbe7e4ea5cab60434be37aed988f0c1b5d2276a43f94b31bf4150dbd933e8ddb64f0a4ddffb316c9e5d10449b6de0563c2ccaa4baf31bd1fb7b511a2b55ab8
7
- data.tar.gz: 52d17f39e82f7db6155af88252181cfe0fc60362cc29a46233f9748c09b6cd6b0a4cd03b6e9f544d12c1e7c2f895bd75b91c8d6142794b326e30f16d9738e08f
6
+ metadata.gz: 5a68e9d3b365c52c811c9a81fa7e2b3968de8f52ddfd7ef829ee47232c809b43715297b09d60f7a0d765b4c30fde3b9a0dfe181d4cff6bd50cb7ddd8c724f590
7
+ data.tar.gz: 122681c279ef487105deb809c4701c318c9cf7e767e3b4e7c86b630b59246f46093e921ea51fb15f82cb72a888f07ae962420b79fd0521c0440253337e50f940
@@ -102,7 +102,6 @@ module Spree
102
102
  go_to_state :payment, if: ->(order) { order.payment? || order.payment_required? }
103
103
  go_to_state :confirm, if: ->(order) { order.confirmation_required? }
104
104
  go_to_state :complete
105
- remove_transition from: :delivery, to: :confirm, unless: ->(order) { order.confirmation_required? }
106
105
  end
107
106
 
108
107
  self.whitelisted_ransackable_associations = %w[shipments user created_by approver canceler promotions bill_address ship_address line_items store]
@@ -1013,7 +1012,6 @@ module Spree
1013
1012
 
1014
1013
  update_with_updater!
1015
1014
  send_order_canceled_webhook
1016
- publish_order_canceled_event
1017
1015
  end
1018
1016
 
1019
1017
  def after_resume
@@ -1094,10 +1092,6 @@ module Spree
1094
1092
  publish_event('order.completed')
1095
1093
  end
1096
1094
 
1097
- def publish_order_canceled_event
1098
- publish_event('order.canceled')
1099
- end
1100
-
1101
1095
  def publish_order_resumed_event
1102
1096
  publish_event('order.resumed')
1103
1097
  end
@@ -232,7 +232,7 @@ module Spree
232
232
 
233
233
  def adjusted_credits_count(promotable)
234
234
  adjustments = promotable.is_a?(Order) ? promotable.all_adjustments : promotable.adjustments
235
- credits_count - adjustments.promotion.where(source_id: actions.pluck(:id)).size
235
+ credits_count - adjustments.eligible.promotion.where(source_id: actions.pluck(:id)).select(:order_id).distinct.count
236
236
  end
237
237
 
238
238
  def credits
@@ -240,7 +240,7 @@ module Spree
240
240
  end
241
241
 
242
242
  def credits_count
243
- credits.count
243
+ credits.select(:order_id).distinct.count
244
244
  end
245
245
 
246
246
  def line_item_actionable?(order, line_item)
@@ -112,8 +112,10 @@ module Spree
112
112
  self.whitelisted_ransackable_attributes = ['number']
113
113
 
114
114
  extend DisplayMoney
115
- money_methods :cost, :discounted_cost, :final_price, :item_cost, :additional_tax_total, :included_tax_total, :tax_total
115
+ money_methods :cost, :discounted_cost, :final_price, :item_cost, :additional_tax_total, :included_tax_total, :tax_total, :promo_total
116
116
  alias display_amount display_cost
117
+ alias_attribute :discount_total, :promo_total
118
+ alias display_discount_total display_promo_total
117
119
 
118
120
  normalizes :tracking, with: ->(value) { value&.to_s&.squish&.presence }
119
121
 
@@ -197,6 +199,8 @@ module Spree
197
199
  def final_price
198
200
  cost + adjustment_total
199
201
  end
202
+ alias total final_price
203
+ alias display_total display_final_price
200
204
 
201
205
  def final_price_with_items
202
206
  item_cost + final_price
@@ -7,7 +7,7 @@ module Spree
7
7
  belongs_to :shipping_method, -> { with_deleted }, class_name: 'Spree::ShippingMethod', inverse_of: :shipping_rates
8
8
  extend Spree::DisplayMoney
9
9
 
10
- money_methods :base_price, :final_price, :tax_amount
10
+ money_methods :base_price, :final_price, :tax_amount, :additional_tax_total, :included_tax_total, :tax_total
11
11
 
12
12
  delegate :order, :currency, :with_free_shipping_promotion?, to: :shipment
13
13
  delegate :name, to: :shipping_method
@@ -29,14 +29,37 @@ module Spree
29
29
  alias display_cost display_price
30
30
  alias_attribute :base_price, :cost
31
31
 
32
+ # Returns true if the shipping rate is free
33
+ #
34
+ # @return [Boolean]
32
35
  def free?
33
36
  final_price.zero?
34
37
  end
35
38
 
39
+ # Returns the tax amount for the shipping rate
40
+ #
41
+ # @return [BigDecimal]
36
42
  def tax_amount
37
43
  @tax_amount ||= tax_rate&.calculator&.compute_shipping_rate(self) || BigDecimal(0)
38
44
  end
39
45
 
46
+ # Returns the additional tax total for the shipping rate
47
+ #
48
+ # @return [BigDecimal]
49
+ def additional_tax_total
50
+ tax_rate&.included_in_price? ? BigDecimal(0) : tax_amount
51
+ end
52
+
53
+ # Returns the included tax total for the shipping rate
54
+ #
55
+ # @return [BigDecimal]
56
+ def included_tax_total
57
+ tax_rate&.included_in_price? ? tax_amount : BigDecimal(0)
58
+ end
59
+
60
+ alias tax_total tax_amount
61
+ alias display_tax_total display_tax_amount
62
+
40
63
  # returns base price - any available discounts for this Shipment
41
64
  # useful when you want to present a list of available shipping rates
42
65
  def final_price
@@ -46,6 +69,8 @@ module Spree
46
69
  cost + discount_amount
47
70
  end
48
71
  end
72
+ alias total final_price
73
+ alias display_total display_final_price
49
74
 
50
75
  # Returns the delivery range for the shipping method
51
76
  #
@@ -72,10 +72,9 @@ module Spree
72
72
  #
73
73
  # Callbacks
74
74
  #
75
- before_validation :set_permalink, on: :create, if: :name
75
+ before_validation :set_permalink, if: :name
76
76
  before_validation :copy_taxonomy_from_parent
77
77
  before_save :set_pretty_name
78
- before_save :set_permalink
79
78
  after_save :touch_ancestors_and_taxonomy
80
79
  after_update :sync_taxonomy_name
81
80
  after_touch :touch_ancestors_and_taxonomy
@@ -470,14 +470,17 @@ module Spree
470
470
  # @param backorderable [Boolean] the backorderable flag
471
471
  # @param stock_location [Spree::StockLocation] the stock location to set the stock for
472
472
  # @return [void]
473
- def set_stock(count_on_hand, backorderable = nil, stock_location = nil)
474
- stock_location ||= Spree::Store.current.default_stock_location
475
- stock_item = stock_items.find_or_initialize_by(stock_location: stock_location)
473
+ def set_stock(count_on_hand, backorderable = nil)
474
+ stock_item = stock_items.find_or_initialize_by(stock_location: default_stock_location)
476
475
  stock_item.count_on_hand = count_on_hand
477
476
  stock_item.backorderable = backorderable if backorderable.present?
478
477
  stock_item.save!
479
478
  end
480
479
 
480
+ def default_stock_location
481
+ Spree::Store.current.default_stock_location
482
+ end
483
+
481
484
  def price_modifier_amount_in(currency, options = {})
482
485
  return 0 unless options.present?
483
486
 
@@ -47,7 +47,7 @@ module Spree
47
47
  end
48
48
 
49
49
  if attributes['inventory_count'].present?
50
- variant.set_stock(attributes['inventory_count'].to_i, attributes['inventory_backorderable']&.to_b, store.default_stock_location)
50
+ variant.set_stock(attributes['inventory_count'].to_i, attributes['inventory_backorderable']&.to_b)
51
51
  end
52
52
 
53
53
  handle_images(variant)
@@ -7,17 +7,23 @@ module Spree
7
7
  eu_vat = Spree::Zone.where(name: 'EU_VAT', description: 'Countries that make up the EU VAT zone.', kind: 'country').first_or_create!
8
8
  uk_vat = Spree::Zone.where(name: 'UK_VAT', kind: 'country').first_or_create!
9
9
  north_america = Spree::Zone.where(name: 'North America', description: 'USA + Canada', kind: 'country').first_or_create!
10
- Spree::Zone.where(name: 'South America', description: 'South America', kind: 'country').first_or_create!
10
+ central_america_and_caribbean = Spree::Zone.where(name: 'Central America and Caribbean', description: 'Central America and Caribbean', kind: 'country').first_or_create!
11
+ south_america = Spree::Zone.where(name: 'South America', description: 'South America', kind: 'country').first_or_create!
11
12
  middle_east = Spree::Zone.where(name: 'Middle East', description: 'Middle East', kind: 'country').first_or_create!
13
+ africa = Spree::Zone.where(name: 'Africa', description: 'Africa', kind: 'country').first_or_create!
12
14
  asia = Spree::Zone.where(name: 'Asia', description: 'Asia', kind: 'country').first_or_create!
13
15
  australia_and_oceania = Spree::Zone.where(name: 'Australia and Oceania', description: 'Australia and Oceania', kind: 'country').first_or_create!
14
16
 
15
17
  create_zone_members(eu_vat, %w(PL FI PT RO DE FR SK HU SI IE AT ES IT BE SE LV BG LT CY LU MT DK NL EE HR CZ GR))
16
18
  create_zone_members(north_america, %w(US CA))
19
+ create_zone_members(central_america_and_caribbean, %w(MX GT BZ SV HN NI CR PA CU DO HT JM BS BB TT PR AG DM GD KN LC VC AI AW BM KY CW GP MQ MS BL MF SX TC VG VI))
20
+ create_zone_members(south_america, %w(AR BO BR CL CO EC FK GF GY PY PE SR UY VE))
17
21
  create_zone_members(middle_east, %w(BH CY EG IR IQ IL JO KW LB OM QA SA SY TR AE YE))
22
+ create_zone_members(africa, %w(DZ AO BJ BW BF BI CV CM CF TD KM CG CD CI DJ EG GQ ER SZ ET GA GM GH GN GW KE LS LR LY
23
+ MG MW ML MR MU YT MA MZ NA NE NG RE RW SH ST SN SC SL SO ZA SS SD TZ TG TN UG ZM ZW))
18
24
  create_zone_members(asia, %w(AF AM AZ BH BD BT BN KH CN CX CC GE HK IN ID IR IQ IL JP JO KZ KW KG LA LB MO MY MV MN MM NP
19
25
  KP OM PK PS PH QA SA SG KR LK SY TW TJ TH TR TM AE UZ VN YE))
20
- create_zone_members(australia_and_oceania, %w(AU NZ))
26
+ create_zone_members(australia_and_oceania, %w(AU NZ PG FJ SB VU NC PF WS AS GU KI MH FM NR NU NF MP PW PN TK TO TV WF CK))
21
27
  uk_vat.zone_members.where(zoneable: Spree::Country.find_by(iso: 'GB')).first_or_create!
22
28
  end
23
29
 
@@ -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
@@ -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!
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- VERSION = '5.4.0'.freeze
2
+ VERSION = '5.4.1'.freeze
3
3
 
4
4
  def self.version
5
5
  VERSION
@@ -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
 
@@ -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.1
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-14 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
408
  - !ruby/object:Gem::Version
409
- version: 1.3.0
409
+ version: '1.3'
410
+ - - "<"
411
+ - !ruby/object:Gem::Version
412
+ version: '4'
410
413
  type: :runtime
411
414
  prerelease: false
412
415
  version_requirements: !ruby/object:Gem::Requirement
413
416
  requirements:
414
- - - '='
417
+ - - ">="
415
418
  - !ruby/object:Gem::Version
416
- version: 1.3.0
419
+ version: '1.3'
420
+ - - "<"
421
+ - !ruby/object:Gem::Version
422
+ version: '4'
417
423
  - !ruby/object:Gem::Dependency
418
424
  name: mobility
419
425
  requirement: !ruby/object:Gem::Requirement
@@ -1733,9 +1739,9 @@ licenses:
1733
1739
  - BSD-3-Clause
1734
1740
  metadata:
1735
1741
  bug_tracker_uri: https://github.com/spree/spree/issues
1736
- changelog_uri: https://github.com/spree/spree/releases/tag/v5.4.0
1742
+ changelog_uri: https://github.com/spree/spree/releases/tag/v5.4.1
1737
1743
  documentation_uri: https://docs.spreecommerce.org/
1738
- source_code_uri: https://github.com/spree/spree/tree/v5.4.0
1744
+ source_code_uri: https://github.com/spree/spree/tree/v5.4.1
1739
1745
  post_install_message:
1740
1746
  rdoc_options: []
1741
1747
  require_paths: