spree_core 5.2.0.rc3 → 5.2.0

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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/app/helpers/spree/integrations_helper.rb +1 -1
  3. data/app/jobs/spree/images/save_from_url_job.rb +1 -1
  4. data/app/models/concerns/spree/calculated_adjustments.rb +1 -1
  5. data/app/models/concerns/spree/user_methods.rb +1 -1
  6. data/app/models/spree/address.rb +1 -1
  7. data/app/models/spree/adjustable/adjustments_updater.rb +1 -1
  8. data/app/models/spree/asset.rb +2 -2
  9. data/app/models/spree/calculator.rb +1 -1
  10. data/app/models/spree/data_feed.rb +1 -1
  11. data/app/models/spree/export.rb +1 -1
  12. data/app/models/spree/gateway/bogus.rb +1 -1
  13. data/app/models/spree/import.rb +1 -1
  14. data/app/models/spree/metafield_definition.rb +3 -3
  15. data/app/models/spree/order/payments.rb +2 -0
  16. data/app/models/spree/order.rb +1 -0
  17. data/app/models/spree/payment/processing.rb +13 -0
  18. data/app/models/spree/payment.rb +20 -0
  19. data/app/models/spree/payment_method.rb +1 -1
  20. data/app/models/spree/product.rb +37 -3
  21. data/app/models/spree/stock/coordinator.rb +1 -1
  22. data/app/models/spree/taxon.rb +1 -0
  23. data/app/models/spree/theme.rb +4 -4
  24. data/app/services/spree/compare_line_items.rb +1 -1
  25. data/app/views/spree/shared/_base_mailer_stylesheets.html.erb +5 -0
  26. data/config/locales/en.yml +4 -0
  27. data/lib/generators/spree/cursor_rules/templates/spree_rules.mdc +1 -1
  28. data/lib/generators/spree/install/templates/config/initializers/spree.rb +31 -24
  29. data/lib/generators/spree/model/model_generator.rb +21 -0
  30. data/lib/generators/spree/model/templates/model.rb.tt +22 -0
  31. data/lib/generators/spree/model_decorator/model_decorator_generator.rb +37 -0
  32. data/lib/generators/spree/model_decorator/templates/model_decorator.rb.tt +12 -0
  33. data/lib/spree/analytics.rb +2 -2
  34. data/lib/spree/core/engine.rb +10 -4
  35. data/lib/spree/core/partials.rb +42 -0
  36. data/lib/spree/core/token_generator.rb +1 -0
  37. data/lib/spree/core/version.rb +1 -1
  38. data/lib/spree/core.rb +191 -0
  39. data/lib/spree/testing_support/factories/order_factory.rb +7 -4
  40. metadata +10 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 531657763d76e0ce76fb2845acfeb30c110343666bc5e8e727de1f21249da4cd
4
- data.tar.gz: 2d4f33f07d6b90d61c9578575889c7c597a39b98e19597c90f902e312832af2c
3
+ metadata.gz: ae177c6a311a310cbcb6d6faf5b879afc52177f9f6bf4c7063edb5ece85fc755
4
+ data.tar.gz: 54794ac79f785c9965c7a1f69fe0c88470fdf751cb789cab9db047b6d9ddbaa4
5
5
  SHA512:
6
- metadata.gz: 1a5aa4b5e32b63a67c2cb557a77014fe1d6cbd55d4f1df437480ff2c3502e4f9fbb533caea745e90a3cb7fd8013439d591f4247c5203e44e75dec638a62abf3e
7
- data.tar.gz: 7b66c4d564e21310dbc962eb1398886441a0a374b85f955a1e317cdbaef8fb27ea312d1987c33c611138e6ff1bf48e9f4de6a7301f0666423658bf7f831ec0ab
6
+ metadata.gz: a0f404ec813d9fc4eaabcab6cac7a461aae2671d43a55c5b59b3e53c10fbb442acf6fa01171690999f576f93e90ab77a26f767881f77dbe6f14dd73ec5619689
7
+ data.tar.gz: d4bacd845e8c842ab4ee8e394feb1006a4289c85ca7569e017eee6053fe29492dfc30466e413793b1af07b00a2f2575487d8746cf9a9ecdf959292b4cc0e6763
@@ -9,7 +9,7 @@ module Spree
9
9
  end
10
10
 
11
11
  def grouped_available_store_integrations
12
- Rails.application.config.spree.integrations.group_by(&:integration_group).sort_by { |group, _| group }
12
+ Spree.integrations.group_by(&:integration_group).sort_by { |group, _| group }
13
13
  end
14
14
  end
15
15
  end
@@ -13,7 +13,7 @@ module Spree
13
13
 
14
14
  Spree::Image.ensure_metafield_definition_exists!(Spree::Image::EXTERNAL_URL_METAFIELD_KEY)
15
15
 
16
- external_url = external_url.downcase.strip
16
+ external_url = external_url.strip
17
17
  external_id = external_id.to_s.downcase.strip if external_id.present?
18
18
 
19
19
  image = find_or_initialize_image(viewable, external_url, external_id)
@@ -30,7 +30,7 @@ module Spree
30
30
  end
31
31
 
32
32
  def self.spree_calculators
33
- Rails.application.config.spree.calculators
33
+ Spree.calculators
34
34
  end
35
35
  end
36
36
  end
@@ -160,7 +160,7 @@ module Spree
160
160
  private
161
161
 
162
162
  def check_completed_orders
163
- raise Spree::Core::DestroyWithOrdersError if !has_spree_role?(Spree::Role::ADMIN_ROLE) && orders.complete.present?
163
+ raise Spree::Core::DestroyWithOrdersError if !spree_admin? && orders.complete.present?
164
164
  end
165
165
 
166
166
  def clone_billing_address
@@ -76,7 +76,7 @@ module Spree
76
76
  allow_nil: true }
77
77
 
78
78
  def address_validators
79
- Rails.application.config.spree.validators.addresses.each do |validator|
79
+ Spree.validators.addresses.each do |validator|
80
80
  validates_with validator
81
81
  end
82
82
  end
@@ -55,7 +55,7 @@ module Spree
55
55
  end
56
56
 
57
57
  def adjusters
58
- Rails.application.config.spree.adjusters
58
+ Spree.adjusters
59
59
  end
60
60
 
61
61
  def tax_adjuster
@@ -22,7 +22,7 @@ module Spree
22
22
  scope :with_session_uploaded_assets_uuid, lambda { |uuid|
23
23
  where(session_id: uuid)
24
24
  }
25
- scope :with_external_url, ->(url) { url.present? ? with_metafield_key_value(EXTERNAL_URL_METAFIELD_KEY, url.downcase.strip) : none }
25
+ scope :with_external_url, ->(url) { url.present? ? with_metafield_key_value(EXTERNAL_URL_METAFIELD_KEY, url.strip) : none }
26
26
 
27
27
  def product
28
28
  @product ||= viewable_type == 'Spree::Variant' ? viewable&.product : nil
@@ -33,7 +33,7 @@ module Spree
33
33
  end
34
34
 
35
35
  def external_url=(url)
36
- set_metafield(EXTERNAL_URL_METAFIELD_KEY, url.downcase.strip)
36
+ set_metafield(EXTERNAL_URL_METAFIELD_KEY, url.strip)
37
37
  end
38
38
 
39
39
  def skip_import?
@@ -26,7 +26,7 @@ module Spree
26
26
 
27
27
  # Returns all calculators applicable for kind of work
28
28
  def self.calculators
29
- Rails.application.config.spree.calculators
29
+ Spree.calculators
30
30
  end
31
31
 
32
32
  def to_s
@@ -33,7 +33,7 @@ module Spree
33
33
  end
34
34
 
35
35
  def available_types
36
- Rails.application.config.spree.data_feed_types
36
+ Spree.data_feed_types
37
37
  end
38
38
  end
39
39
  end
@@ -175,7 +175,7 @@ module Spree
175
175
 
176
176
  class << self
177
177
  def available_types
178
- Rails.application.config.spree.export_types
178
+ Spree.export_types
179
179
  end
180
180
 
181
181
  def available_models
@@ -60,7 +60,7 @@ module Spree
60
60
  end
61
61
 
62
62
  def void(_response_code, _credit_card, _options = {})
63
- ActiveMerchant::Billing::Response.new(true, 'Bogus Gateway: Forced success', {}, test: true, authorization: '12345')
63
+ ActiveMerchant::Billing::Response.new(true, 'Bogus Gateway: Forced success', {}, test: true, authorization: 'void-12345')
64
64
  end
65
65
 
66
66
  def cancel(_response_code, _payment = nil)
@@ -224,7 +224,7 @@ module Spree
224
224
  # Returns the available types for the import
225
225
  # @return [Array<Class>]
226
226
  def available_types
227
- Rails.application.config.spree.import_types
227
+ Spree.import_types
228
228
  end
229
229
 
230
230
  # Returns the available models for the import
@@ -61,13 +61,13 @@ module Spree
61
61
  # Returns the available types
62
62
  # @return [Array<Class>]
63
63
  def self.available_types
64
- Rails.application.config.spree.metafield_types
64
+ Spree.metafields.types
65
65
  end
66
66
 
67
67
  # Returns the available resources
68
68
  # @return [Array<Class>]
69
69
  def self.available_resources
70
- Rails.application.config.spree.metafield_enabled_resources
70
+ Spree.metafields.enabled_resources
71
71
  end
72
72
 
73
73
  private
@@ -81,7 +81,7 @@ module Spree
81
81
  end
82
82
 
83
83
  def set_default_type
84
- self.metafield_type ||= Rails.application.config.spree.metafield_types.first.to_s
84
+ self.metafield_type ||= Spree.metafields.types.first.to_s
85
85
  end
86
86
 
87
87
  def set_name_from_key
@@ -44,6 +44,8 @@ module Spree
44
44
  def process_payments_with(method)
45
45
  # Don't run if there is nothing to pay.
46
46
  return if payment_total >= total
47
+ # Don't run if there are authorized payments
48
+ return if pending_payments.any? && unprocessed_payments.empty?
47
49
  # Prevent orders from transitioning to complete without a successfully processed payment.
48
50
  raise Core::GatewayError, Spree.t(:no_payment_found) if unprocessed_payments.empty?
49
51
 
@@ -910,6 +910,7 @@ module Spree
910
910
  payments.completed.store_credits.each(&:void!)
911
911
  else
912
912
  payments.completed.each(&:cancel!)
913
+ payments.incomplete.not_store_credits.each(&:void_transaction!)
913
914
  payments.store_credits.pending.each(&:void!)
914
915
  end
915
916
 
@@ -26,6 +26,19 @@ module Spree
26
26
  handle_payment_preconditions { process_purchase }
27
27
  end
28
28
 
29
+ # Confirms a payment by completing it or pending it depending on the payment method's auto_capture setting
30
+ # Useful for payments that are authorized/captured with SDK/Drop-in elements
31
+ def confirm!
32
+ started_processing! if checkout?
33
+
34
+ if payment_method&.auto_capture? && can_complete?
35
+ complete!
36
+ capture_events.create!(amount: amount)
37
+ elsif can_pend?
38
+ pend!
39
+ end
40
+ end
41
+
29
42
  # Takes the amount in cents to capture.
30
43
  # Can be used to capture partial amounts of a payment, and will create
31
44
  # a new pending payment record for the remaining amount to capture later.
@@ -255,6 +255,26 @@ module Spree
255
255
  payment_method&.source_required?
256
256
  end
257
257
 
258
+ def add_gateway_processing_error(error_message)
259
+ if has_metafield?('gateway.processing_errors')
260
+ errors = JSON.parse(get_metafield('gateway.processing_errors').value)
261
+ errors << { message: error_message }
262
+
263
+ set_metafield('gateway.processing_errors', errors.to_json)
264
+ else
265
+ set_metafield('gateway.processing_errors', [{ message: error_message }].to_json)
266
+ end
267
+ end
268
+
269
+ def gateway_processing_error_messages
270
+ @gateway_processing_error_messages ||= begin
271
+ errors = JSON.parse(get_metafield('gateway.processing_errors')&.value || '[]')
272
+ errors.map { |error| error['message'] }
273
+ rescue JSON::ParserError
274
+ []
275
+ end
276
+ end
277
+
258
278
  private
259
279
 
260
280
  def set_amount
@@ -29,7 +29,7 @@ module Spree
29
29
  has_many :gateway_customers, class_name: 'Spree::GatewayCustomer', dependent: :destroy
30
30
 
31
31
  def self.providers
32
- Rails.application.config.spree.payment_methods
32
+ Spree.payment_methods
33
33
  end
34
34
 
35
35
  def provider_class
@@ -255,8 +255,6 @@ module Spree
255
255
  delegate :display_amount, :display_price, :has_default_price?, :track_inventory?,
256
256
  :display_compare_at_price, :images, to: :default_variant
257
257
 
258
- delegate :name, to: :brand, prefix: true, allow_nil: true
259
-
260
258
  alias master_images images
261
259
 
262
260
  state_machine :status, initial: :draft do
@@ -550,7 +548,22 @@ module Spree
550
548
  super || variants_including_master.with_deleted.find_by(is_master: true)
551
549
  end
552
550
 
551
+ # Returns the brand for the product
552
+ # If a brand association is defined (e.g., belongs_to :brand), it will be used
553
+ # Otherwise, falls back to brand_taxon for compatibility
554
+ # @return [Spree::Brand, Spree::Taxon]
553
555
  def brand
556
+ if self.class.reflect_on_association(:brand)
557
+ super
558
+ else
559
+ Spree::Deprecation.warn('Spree::Product#brand is deprecated and will be removed in Spree 6. Please use Spree::Product#brand_taxon instead.')
560
+ brand_taxon
561
+ end
562
+ end
563
+
564
+ # Returns the brand taxon for the product
565
+ # @return [Spree::Taxon]
566
+ def brand_taxon
554
567
  @brand ||= if Spree.use_translations?
555
568
  taxons.joins(:taxonomy).
556
569
  join_translation_table(Taxonomy).
@@ -564,7 +577,28 @@ module Spree
564
577
  end
565
578
  end
566
579
 
580
+ # Returns the brand name for the product
581
+ # @return [String]
582
+ def brand_name
583
+ brand&.name
584
+ end
585
+
586
+ # Returns the category for the product
587
+ # If a category association is defined (e.g., belongs_to :category), it will be used
588
+ # Otherwise, falls back to category_taxon for compatibility
589
+ # @return [Spree::Category, Spree::Taxon]
567
590
  def category
591
+ if self.class.reflect_on_association(:category)
592
+ super
593
+ else
594
+ Spree::Deprecation.warn('Spree::Product#category is deprecated and will be removed in Spree 6. Please use Spree::Product#category_taxon instead.')
595
+ category_taxon
596
+ end
597
+ end
598
+
599
+ # Returns the category taxon for the product
600
+ # @return [Spree::Taxon]
601
+ def category_taxon
568
602
  @category ||= if Spree.use_translations?
569
603
  taxons.joins(:taxonomy).
570
604
  join_translation_table(Taxonomy).
@@ -580,7 +614,7 @@ module Spree
580
614
  end
581
615
 
582
616
  def main_taxon
583
- category || taxons.first
617
+ category_taxon || taxons.first
584
618
  end
585
619
 
586
620
  def taxons_for_store(store)
@@ -60,7 +60,7 @@ module Spree
60
60
 
61
61
  def splitters(_stock_location)
62
62
  # extension point to return custom splitters for a location
63
- Rails.application.config.spree.stock_splitters
63
+ Spree.stock_splitters
64
64
  end
65
65
  end
66
66
  end
@@ -324,6 +324,7 @@ module Spree
324
324
  # indicate which filters should be used for a taxon
325
325
  # this method should be customized to your own site
326
326
  def applicable_filters
327
+ Spree::Deprecation.warn('applicable_filters is deprecated and will be removed in Spree 6.0')
327
328
  fs = []
328
329
  # fs << ProductFilters.taxons_below(self)
329
330
  ## unless it's a root taxon? left open for demo purposes
@@ -56,7 +56,7 @@ module Spree
56
56
  #
57
57
  # @return [Array<Spree::Theme>]
58
58
  def self.available_themes
59
- @available_themes ||= Rails.application.config.spree.themes.sort_by(&:display_name)
59
+ @available_themes ||= Spree.page_builder.themes.sort_by(&:display_name)
60
60
  end
61
61
 
62
62
  def self.metadata
@@ -98,7 +98,7 @@ module Spree
98
98
  end
99
99
 
100
100
  def create_default_pages
101
- Rails.application.config.spree.pages.map(&:to_s).map(&:constantize).each do |page_class|
101
+ Spree.page_builder.pages.map(&:to_s).map(&:constantize).each do |page_class|
102
102
  next if page_class == Spree::Pages::Custom
103
103
 
104
104
  page_class.where(pageable: self).first_or_create!
@@ -160,7 +160,7 @@ module Spree
160
160
  # @return [Array<Class>]
161
161
  def available_layout_sections
162
162
  [
163
- *Rails.application.config.spree.theme_layout_sections,
163
+ *Spree.page_builder.theme_layout_sections,
164
164
  *custom_layout_sections
165
165
  ]
166
166
  end
@@ -181,7 +181,7 @@ module Spree
181
181
  return @available_page_sections if @available_page_sections
182
182
 
183
183
  @available_page_sections ||= [
184
- *Rails.application.config.spree.page_sections.find_all do |section_class|
184
+ *Spree.page_builder.page_sections.find_all do |section_class|
185
185
  section_class.role == 'content'
186
186
  end,
187
187
  *custom_page_sections
@@ -4,7 +4,7 @@ module Spree
4
4
  prepend Spree::ServiceModule::Base
5
5
 
6
6
  def call(order:, line_item:, options: {}, comparison_hooks: nil)
7
- comparison_hooks ||= Rails.application.config.spree.line_item_comparison_hooks
7
+ comparison_hooks ||= Spree.line_item_comparison_hooks
8
8
 
9
9
  legacy_part = comparison_hooks.all? do |hook|
10
10
  order.send(hook, line_item, options)
@@ -253,6 +253,11 @@
253
253
 
254
254
  .purchase_image {
255
255
  padding: 5px;
256
+ width: 100px;
257
+
258
+ img {
259
+ width: 100px;
260
+ }
256
261
  }
257
262
 
258
263
  .purchase_item p {
@@ -105,6 +105,8 @@ en:
105
105
  phone: Shipping address phone
106
106
  state: Shipping address state
107
107
  zipcode: Shipping address zipcode
108
+ spree/page_link:
109
+ open_in_new_tab: Open in new tab
108
110
  spree/payment:
109
111
  amount: Amount
110
112
  number: Number
@@ -200,6 +202,7 @@ en:
200
202
  spree/taxonomy:
201
203
  name: Name
202
204
  spree/user:
205
+ avatar: Avatar
203
206
  email: Email
204
207
  password: Password
205
208
  password_confirmation: Password Confirmation
@@ -1622,6 +1625,7 @@ en:
1622
1625
  payment_updated: Payment Updated
1623
1626
  payments: Payments
1624
1627
  payments_count: Payments count
1628
+ payments_gateway_processing_errors: "%{payment_method_name} processing errors"
1625
1629
  pending: Pending
1626
1630
  pending_sale: Pending Sale
1627
1631
  percent: Percent
@@ -255,7 +255,7 @@ bin/rails g spree:storefront:theme MyTheme
255
255
 
256
256
  ```ruby
257
257
  # Register theme in config/initializers/spree.rb
258
- Rails.application.config.spree.themes << Spree::Themes::MyTheme
258
+ Spree.page_builder.themes << Spree::Themes::MyTheme
259
259
  ```
260
260
 
261
261
  #### View Overrides
@@ -61,33 +61,40 @@ end
61
61
  # uncomment lines below to add your own custom business logic
62
62
  # such as promotions, shipping methods, etc
63
63
  Rails.application.config.after_initialize do
64
- # Rails.application.config.spree.shipping_methods << Spree::ShippingMethods::SuperExpensiveNotVeryFastShipping
65
- # Rails.application.config.spree.payment_methods << Spree::PaymentMethods::VerySafeAndReliablePaymentMethod
64
+ # Payment methods and shipping calculators
65
+ # Spree.payment_methods << Spree::PaymentMethods::VerySafeAndReliablePaymentMethod
66
+ # Spree.calculators.shipping_methods << Spree::ShippingMethods::SuperExpensiveNotVeryFastShipping
67
+ # Spree.calculators.tax_rates << Spree::TaxRates::FinanceTeamForcedMeToCodeThis
66
68
 
67
- # Rails.application.config.spree.calculators.tax_rates << Spree::TaxRates::FinanceTeamForcedMeToCodeThis
68
-
69
- # Rails.application.config.spree.stock_splitters << Spree::Stock::Splitters::SecretLogicSplitter
70
-
71
- # Rails.application.config.spree.adjusters << Spree::Adjustable::Adjuster::TaxTheRich
69
+ # Stock splitters and adjusters
70
+ # Spree.stock_splitters << Spree::Stock::Splitters::SecretLogicSplitter
71
+ # Spree.adjusters << Spree::Adjustable::Adjuster::TaxTheRich
72
72
 
73
73
  # Custom promotions
74
- # Rails.application.config.spree.calculators.promotion_actions_create_adjustments << Spree::Calculators::PromotionActions::CreateAdjustments::AddDiscountForFriends
75
- # Rails.application.config.spree.calculators.promotion_actions_create_item_adjustments << Spree::Calculators::PromotionActions::CreateItemAdjustments::FinanceTeamForcedMeToCodeThis
76
- # Rails.application.config.spree.promotions.rules << Spree::Promotions::Rules::OnlyForVIPCustomers
77
- # Rails.application.config.spree.promotions.actions << Spree::Promotions::Actions::GiftWithPurchase
78
-
79
- # Rails.application.config.spree.taxon_rules << Spree::TaxonRules::ProductsWithColor
80
-
81
- # Rails.application.config.spree.exports << Spree::Exports::Payments
82
- # Rails.application.config.spree.reports << Spree::Reports::MassivelyOvercomplexReportForCfo
83
-
84
- # Themes and page builder
85
- # Rails.application.config.spree.themes << Spree::Themes::NewShinyTheme
86
- # Rails.application.config.spree.theme_layout_sections << Spree::PageSections::SuperImportantCeoBio
87
- # Rails.application.config.spree.page_sections << Spree::PageSections::ContactFormToGetInTouch
88
- # Rails.application.config.spree.page_blocks << Spree::PageBlocks::BigRedButtonToCallSales
89
-
90
- # Rails.application.config.spree_storefront.head_partials << 'spree/shared/that_js_snippet_that_marketing_forced_me_to_include'
74
+ # Spree.calculators.promotion_actions_create_adjustments << Spree::Calculators::PromotionActions::CreateAdjustments::AddDiscountForFriends
75
+ # Spree.calculators.promotion_actions_create_item_adjustments << Spree::Calculators::PromotionActions::CreateItemAdjustments::FinanceTeamForcedMeToCodeThis
76
+ # Spree.promotions.rules << Spree::Promotions::Rules::OnlyForVIPCustomers
77
+ # Spree.promotions.actions << Spree::Promotions::Actions::GiftWithPurchase
78
+
79
+ # Taxon rules
80
+ # Spree.taxon_rules << Spree::TaxonRules::ProductsWithColor
81
+
82
+ # Exports and reports
83
+ # Spree.export_types << Spree::Exports::Payments
84
+ # Spree.reports << Spree::Reports::MassivelyOvercomplexReportForCfo
85
+
86
+ # Page builder (themes, pages, sections, blocks)
87
+ # Spree.page_builder.themes << Spree::Themes::NewShinyTheme
88
+ # Spree.page_builder.theme_layout_sections << Spree::PageSections::SuperImportantCeoBio
89
+ # Spree.page_builder.pages << Spree::Pages::CustomLandingPage
90
+ # Spree.page_builder.page_sections << Spree::PageSections::ContactFormToGetInTouch
91
+ # Spree.page_builder.page_blocks << Spree::PageBlocks::BigRedButtonToCallSales
92
+
93
+ # Storefront partials
94
+ # Spree.storefront.partials.head << 'spree/shared/that_js_snippet_that_marketing_forced_me_to_include'
95
+
96
+ # Admin partials
97
+ # Spree.admin.partials.product_form << 'spree/admin/products/custom_section'
91
98
  end
92
99
 
93
100
  Spree.user_class = <%= (options[:user_class].blank? ? 'Spree::LegacyUser' : options[:user_class]).inspect %>
@@ -0,0 +1,21 @@
1
+ require "rails/generators/active_record/model/model_generator"
2
+
3
+ module Spree
4
+ class ModelGenerator < ActiveRecord::Generators::ModelGenerator
5
+
6
+ def self.source_paths
7
+ paths = superclass.source_paths
8
+ paths << File.expand_path('templates', __dir__)
9
+ paths.flatten
10
+ end
11
+
12
+ class_option :parent, type: :string, default: "Spree::Base", desc: "The parent class for the generated model"
13
+
14
+ desc 'Creates a new Spree model'
15
+
16
+ # Override to prevent module file from being created
17
+ def create_module_file
18
+ return
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,22 @@
1
+ module Spree
2
+ class <%= class_name.demodulize %> < <%= parent_class_name.classify %>
3
+ <% attributes.select(&:reference?).each do |attribute| -%>
4
+ belongs_to :<%= attribute.name %><%= ", polymorphic: true" if attribute.polymorphic? %>
5
+ <% end -%>
6
+ <% attributes.select(&:rich_text?).each do |attribute| -%>
7
+ has_rich_text :<%= attribute.name %>
8
+ <% end -%>
9
+ <% attributes.select(&:attachment?).each do |attribute| -%>
10
+ has_one_attached :<%= attribute.name %>
11
+ <% end -%>
12
+ <% attributes.select(&:attachments?).each do |attribute| -%>
13
+ has_many_attached :<%= attribute.name %>
14
+ <% end -%>
15
+ <% attributes.select(&:token?).each do |attribute| -%>
16
+ has_secure_token<% if attribute.name != "token" %> :<%= attribute.name %><% end %>
17
+ <% end -%>
18
+ <% if attributes.any?(&:password_digest?) -%>
19
+ has_secure_password
20
+ <% end -%>
21
+ end
22
+ end
@@ -0,0 +1,37 @@
1
+ module Spree
2
+ class ModelDecoratorGenerator < Rails::Generators::NamedBase
3
+ desc 'Creates a model decorator for a Spree model'
4
+
5
+ argument :name, type: :string, required: true, banner: 'Spree::ModelName'
6
+
7
+ def self.source_paths
8
+ paths = superclass.source_paths
9
+ paths << File.expand_path('templates', __dir__)
10
+ paths.flatten
11
+ end
12
+
13
+ def create_model_decorator_file
14
+ template 'model_decorator.rb.tt', "app/models/#{file_path}_decorator.rb"
15
+ end
16
+
17
+ private
18
+
19
+ # Returns the model name without the Spree:: prefix
20
+ # e.g., "Spree::Product" => "Product", "Product" => "Product"
21
+ def model_name
22
+ name.sub(/^Spree::/, '').classify
23
+ end
24
+
25
+ # Returns the decorator module name
26
+ # e.g., "Spree::Product" => "ProductDecorator"
27
+ def decorator_name
28
+ "#{model_name}Decorator"
29
+ end
30
+
31
+ # Returns the file path for the decorator
32
+ # e.g., "Spree::Product" => "spree/product", "Product" => "spree/product"
33
+ def file_path
34
+ "spree/#{model_name.underscore}"
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,12 @@
1
+ module Spree
2
+ module <%= decorator_name %>
3
+ def self.prepended(base)
4
+ # base.belongs_to :brand
5
+ end
6
+
7
+ # add custom methods here
8
+ end
9
+ end
10
+
11
+ Spree::<%= model_name %>.prepend Spree::<%= decorator_name %>
12
+
@@ -1,11 +1,11 @@
1
1
  module Spree
2
2
  module Analytics
3
3
  def self.events
4
- @@supported_events ||= Rails.application.config.spree.analytics_events
4
+ @@supported_events ||= Spree.analytics.events
5
5
  end
6
6
 
7
7
  def self.event_handlers
8
- @@event_handlers ||= Rails.application.config.spree.analytics_event_handlers
8
+ @@event_handlers ||= Spree.analytics.handlers
9
9
  end
10
10
  end
11
11
  end
@@ -24,14 +24,14 @@ module Spree
24
24
  :page_blocks,
25
25
  :reports,
26
26
  :translatable_resources,
27
- :metafield_types,
28
- :metafield_enabled_resources,
27
+ :metafields,
29
28
  :analytics_events,
30
29
  :analytics_event_handlers,
31
30
  :integrations)
32
31
  SpreeCalculators = Struct.new(:shipping_methods, :tax_rates, :promotion_actions_create_adjustments, :promotion_actions_create_item_adjustments)
33
32
  PromoEnvironment = Struct.new(:rules, :actions)
34
33
  SpreeValidators = Struct.new(:addresses)
34
+ MetafieldsEnvironment = Struct.new(:types, :enabled_resources)
35
35
  isolate_namespace Spree
36
36
  engine_name 'spree'
37
37
 
@@ -66,6 +66,12 @@ module Spree
66
66
  initializer 'spree.register.adjustable_adjusters' do |app|
67
67
  end
68
68
 
69
+ initializer 'spree.register.metafields' do |app|
70
+ app.config.spree.metafields = MetafieldsEnvironment.new
71
+ app.config.spree.metafields.types = []
72
+ app.config.spree.metafields.enabled_resources = []
73
+ end
74
+
69
75
  # We need to define promotions rules here so extensions and existing apps
70
76
  # can add their custom classes on their initializer files
71
77
  initializer 'spree.promo.environment' do |app|
@@ -260,7 +266,7 @@ module Spree
260
266
  Spree::Policy
261
267
  ]
262
268
 
263
- Rails.application.config.spree.metafield_types = [
269
+ Rails.application.config.spree.metafields.types = [
264
270
  Spree::Metafields::ShortText,
265
271
  Spree::Metafields::LongText,
266
272
  Spree::Metafields::RichText,
@@ -269,7 +275,7 @@ module Spree
269
275
  Spree::Metafields::Json
270
276
  ]
271
277
 
272
- Rails.application.config.spree.metafield_enabled_resources = [
278
+ Rails.application.config.spree.metafields.enabled_resources = [
273
279
  Spree::Address,
274
280
  Spree::Asset,
275
281
  Spree::CreditCard,
@@ -0,0 +1,42 @@
1
+ # Ability to define partial injection points for Admin and Storefront
2
+ module Spree
3
+ module Core
4
+ class Partials
5
+ def initialize(config, environment)
6
+ @config = config
7
+ @environment = environment
8
+ define_dynamic_methods
9
+ end
10
+
11
+ attr_reader :config, :environment
12
+
13
+ def partial_members
14
+ environment.members.select { |member| member.to_s.end_with?('_partials') }
15
+ end
16
+
17
+ def keys
18
+ partial_members.map { |member| member.to_s.sub(/_partials$/, '') }
19
+ end
20
+
21
+ private
22
+
23
+ def define_dynamic_methods
24
+ # Get all members that end with _partials from the Environment
25
+ partial_members.each do |member|
26
+ # Strip the _partials suffix for the method name
27
+ method_name = member.to_s.sub(/_partials$/, '')
28
+
29
+ # Define getter method on singleton class
30
+ singleton_class.define_method(method_name) do
31
+ config.send(member)
32
+ end
33
+
34
+ # Define setter method on singleton class
35
+ singleton_class.define_method("#{method_name}=") do |value|
36
+ config.send("#{member}=", value)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -2,6 +2,7 @@ module Spree
2
2
  module Core
3
3
  module TokenGenerator
4
4
  def generate_token(model_class = Spree::Order)
5
+ Spree::Deprecation.warn('generate_token is deprecated and will be removed in Spree 6.0. Please use Rails secure token generator: https://api.rubyonrails.org/classes/ActiveRecord/SecureToken/ClassMethods.html')
5
6
  loop do
6
7
  token = "#{random_token}#{unique_ending}"
7
8
  break token unless model_class.exists?(token: token)
@@ -1,5 +1,5 @@
1
1
  module Spree
2
- VERSION = '5.2.0.rc3'.freeze
2
+ VERSION = '5.2.0'.freeze
3
3
 
4
4
  def self.version
5
5
  VERSION
data/lib/spree/core.rb CHANGED
@@ -168,6 +168,196 @@ module Spree
168
168
  yield(Spree::Dependencies)
169
169
  end
170
170
 
171
+ # Environment accessors for easier configuration access
172
+ # Instead of Rails.application.config.spree.payment_methods
173
+ # you can use Spree.payment_methods
174
+
175
+ def self.calculators
176
+ Rails.application.config.spree.calculators
177
+ end
178
+
179
+ def self.calculators=(value)
180
+ Rails.application.config.spree.calculators = value
181
+ end
182
+
183
+ def self.validators
184
+ Rails.application.config.spree.validators
185
+ end
186
+
187
+ def self.validators=(value)
188
+ Rails.application.config.spree.validators = value
189
+ end
190
+
191
+ def self.payment_methods
192
+ Rails.application.config.spree.payment_methods
193
+ end
194
+
195
+ def self.payment_methods=(value)
196
+ Rails.application.config.spree.payment_methods = value
197
+ end
198
+
199
+ def self.adjusters
200
+ Rails.application.config.spree.adjusters
201
+ end
202
+
203
+ def self.adjusters=(value)
204
+ Rails.application.config.spree.adjusters = value
205
+ end
206
+
207
+ def self.stock_splitters
208
+ Rails.application.config.spree.stock_splitters
209
+ end
210
+
211
+ def self.stock_splitters=(value)
212
+ Rails.application.config.spree.stock_splitters = value
213
+ end
214
+
215
+ def self.promotions
216
+ Rails.application.config.spree.promotions
217
+ end
218
+
219
+ def self.promotions=(value)
220
+ Rails.application.config.spree.promotions = value
221
+ end
222
+
223
+ def self.line_item_comparison_hooks
224
+ Rails.application.config.spree.line_item_comparison_hooks
225
+ end
226
+
227
+ def self.line_item_comparison_hooks=(value)
228
+ Rails.application.config.spree.line_item_comparison_hooks = value
229
+ end
230
+
231
+ def self.data_feed_types
232
+ Rails.application.config.spree.data_feed_types
233
+ end
234
+
235
+ def self.data_feed_types=(value)
236
+ Rails.application.config.spree.data_feed_types = value
237
+ end
238
+
239
+ def self.export_types
240
+ Rails.application.config.spree.export_types
241
+ end
242
+
243
+ def self.export_types=(value)
244
+ Rails.application.config.spree.export_types = value
245
+ end
246
+
247
+ def self.import_types
248
+ Rails.application.config.spree.import_types
249
+ end
250
+
251
+ def self.import_types=(value)
252
+ Rails.application.config.spree.import_types = value
253
+ end
254
+
255
+ def self.taxon_rules
256
+ Rails.application.config.spree.taxon_rules
257
+ end
258
+
259
+ def self.taxon_rules=(value)
260
+ Rails.application.config.spree.taxon_rules = value
261
+ end
262
+
263
+ def self.reports
264
+ Rails.application.config.spree.reports
265
+ end
266
+
267
+ def self.reports=(value)
268
+ Rails.application.config.spree.reports = value
269
+ end
270
+
271
+ def self.translatable_resources
272
+ Rails.application.config.spree.translatable_resources
273
+ end
274
+
275
+ def self.translatable_resources=(value)
276
+ Rails.application.config.spree.translatable_resources = value
277
+ end
278
+
279
+ def self.metafields
280
+ Rails.application.config.spree.metafields
281
+ end
282
+
283
+ def self.integrations
284
+ Rails.application.config.spree.integrations
285
+ end
286
+
287
+ def self.integrations=(value)
288
+ Rails.application.config.spree.integrations = value
289
+ end
290
+
291
+ # Page Builder configuration accessor
292
+ def self.page_builder
293
+ @page_builder ||= PageBuilderConfig.new
294
+ end
295
+
296
+ class PageBuilderConfig
297
+ def themes
298
+ Rails.application.config.spree.themes
299
+ end
300
+
301
+ def themes=(value)
302
+ Rails.application.config.spree.themes = value
303
+ end
304
+
305
+ def theme_layout_sections
306
+ Rails.application.config.spree.theme_layout_sections
307
+ end
308
+
309
+ def theme_layout_sections=(value)
310
+ Rails.application.config.spree.theme_layout_sections = value
311
+ end
312
+
313
+ def pages
314
+ Rails.application.config.spree.pages
315
+ end
316
+
317
+ def pages=(value)
318
+ Rails.application.config.spree.pages = value
319
+ end
320
+
321
+ def page_sections
322
+ Rails.application.config.spree.page_sections
323
+ end
324
+
325
+ def page_sections=(value)
326
+ Rails.application.config.spree.page_sections = value
327
+ end
328
+
329
+ def page_blocks
330
+ Rails.application.config.spree.page_blocks
331
+ end
332
+
333
+ def page_blocks=(value)
334
+ Rails.application.config.spree.page_blocks = value
335
+ end
336
+ end
337
+
338
+ def self.analytics
339
+ @analytics ||= AnalyticsConfig.new
340
+ end
341
+
342
+ # Group analytics configuration options together, but still make it backwards compatible.
343
+ class AnalyticsConfig
344
+ def events
345
+ Rails.application.config.spree.analytics_events
346
+ end
347
+
348
+ def events=(value)
349
+ Rails.application.config.spree.analytics_events = value
350
+ end
351
+
352
+ def handlers
353
+ Rails.application.config.spree.analytics_event_handlers
354
+ end
355
+
356
+ def handlers=(value)
357
+ Rails.application.config.spree.analytics_event_handlers = value
358
+ end
359
+ end
360
+
171
361
  module Core
172
362
  autoload :ProductFilters, 'spree/core/product_filters'
173
363
  autoload :TokenGenerator, 'spree/core/token_generator'
@@ -192,6 +382,7 @@ require 'spree/service_module'
192
382
  require 'spree/database_type_utilities'
193
383
  require 'spree/analytics'
194
384
 
385
+ require 'spree/core/partials'
195
386
  require 'spree/core/importer'
196
387
  require 'spree/core/query_filters'
197
388
  require 'spree/core/controller_helpers/auth'
@@ -73,7 +73,7 @@ FactoryBot.define do
73
73
 
74
74
  after(:create) do |order, evaluator|
75
75
  order.refresh_shipment_rates(evaluator.shipping_method_filter)
76
- order.update_column(:completed_at, Time.current)
76
+ order.update_column(:completed_at, order.completed_at || Time.current)
77
77
  end
78
78
 
79
79
  factory :completed_order_with_pending_payment do
@@ -110,13 +110,16 @@ FactoryBot.define do
110
110
  end
111
111
 
112
112
  factory :shipped_order do
113
+ shipment_state { 'shipped' }
114
+
113
115
  after(:create) do |order|
114
116
  order.shipments.each do |shipment|
115
117
  shipment.inventory_units.update_all state: 'shipped'
116
- shipment.update_column('state', 'shipped')
118
+ shipment.update_columns(
119
+ state: 'shipped',
120
+ tracking: '1234567890'
121
+ )
117
122
  end
118
- order.update_column('shipment_state', 'shipped')
119
- order.reload
120
123
  end
121
124
  end
122
125
  end
metadata CHANGED
@@ -1,16 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spree_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.2.0.rc3
4
+ version: 5.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean Schofield
8
8
  - Spark Solutions Sp. z o.o.
9
9
  - Vendo Connect Inc.
10
- autorequire:
11
10
  bindir: bin
12
11
  cert_chain: []
13
- date: 2025-11-18 00:00:00.000000000 Z
12
+ date: 1980-01-02 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
15
  name: i18n-tasks
@@ -1478,6 +1477,10 @@ files:
1478
1477
  - lib/generators/spree/dummy_model/templates/model.rb.tt
1479
1478
  - lib/generators/spree/install/install_generator.rb
1480
1479
  - lib/generators/spree/install/templates/config/initializers/spree.rb
1480
+ - lib/generators/spree/model/model_generator.rb
1481
+ - lib/generators/spree/model/templates/model.rb.tt
1482
+ - lib/generators/spree/model_decorator/model_decorator_generator.rb
1483
+ - lib/generators/spree/model_decorator/templates/model_decorator.rb.tt
1481
1484
  - lib/mobility/plugins/store_based_fallbacks.rb
1482
1485
  - lib/normalize_string.rb
1483
1486
  - lib/spree/analytics.rb
@@ -1500,6 +1503,7 @@ files:
1500
1503
  - lib/spree/core/importer/order.rb
1501
1504
  - lib/spree/core/importer/product.rb
1502
1505
  - lib/spree/core/number_generator.rb
1506
+ - lib/spree/core/partials.rb
1503
1507
  - lib/spree/core/preferences/configuration.rb
1504
1508
  - lib/spree/core/preferences/preferable.rb
1505
1509
  - lib/spree/core/preferences/preferable_class_methods.rb
@@ -1656,10 +1660,9 @@ licenses:
1656
1660
  - BSD-3-Clause
1657
1661
  metadata:
1658
1662
  bug_tracker_uri: https://github.com/spree/spree/issues
1659
- changelog_uri: https://github.com/spree/spree/releases/tag/v5.2.0.rc3
1663
+ changelog_uri: https://github.com/spree/spree/releases/tag/v5.2.0
1660
1664
  documentation_uri: https://docs.spreecommerce.org/
1661
- source_code_uri: https://github.com/spree/spree/tree/v5.2.0.rc3
1662
- post_install_message:
1665
+ source_code_uri: https://github.com/spree/spree/tree/v5.2.0
1663
1666
  rdoc_options: []
1664
1667
  require_paths:
1665
1668
  - lib
@@ -1674,8 +1677,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
1674
1677
  - !ruby/object:Gem::Version
1675
1678
  version: 1.8.23
1676
1679
  requirements: []
1677
- rubygems_version: 3.5.3
1678
- signing_key:
1680
+ rubygems_version: 3.6.9
1679
1681
  specification_version: 4
1680
1682
  summary: The bare bones necessary for Spree
1681
1683
  test_files: []