spree_core 5.3.5 → 5.4.0.beta

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 (242) hide show
  1. checksums.yaml +4 -4
  2. data/app/finders/spree/orders/find_complete.rb +33 -2
  3. data/app/finders/spree/stores/find_default.rb +17 -0
  4. data/app/finders/spree/variants/visible_finder.rb +1 -0
  5. data/app/helpers/spree/addresses_helper.rb +1 -2
  6. data/app/helpers/spree/base_helper.rb +5 -4
  7. data/app/jobs/spree/api_key_touch_job.rb +9 -0
  8. data/app/jobs/spree/images/save_from_url_job.rb +23 -47
  9. data/app/models/concerns/spree/admin_user_methods.rb +32 -0
  10. data/app/models/concerns/spree/number_as_param.rb +5 -3
  11. data/app/models/concerns/spree/prefixed_id.rb +82 -0
  12. data/app/models/concerns/spree/product_scopes.rb +33 -18
  13. data/app/models/concerns/spree/publishable.rb +47 -47
  14. data/app/models/concerns/spree/{multi_store_resource.rb → store_scoped_resource.rb} +1 -10
  15. data/app/models/concerns/spree/stores/markets.rb +124 -0
  16. data/app/models/concerns/spree/user_methods.rb +7 -7
  17. data/app/models/concerns/spree/user_payment_source.rb +2 -0
  18. data/app/models/concerns/spree/user_roles.rb +1 -0
  19. data/app/models/spree/ability.rb +13 -0
  20. data/app/models/spree/address.rb +30 -0
  21. data/app/models/spree/adjustment.rb +2 -0
  22. data/app/models/spree/api_key.rb +47 -0
  23. data/app/models/spree/asset.rb +2 -0
  24. data/app/models/spree/authentication/strategies/base_strategy.rb +55 -0
  25. data/app/models/spree/authentication/strategies/email_password_strategy.rb +47 -0
  26. data/app/models/spree/base.rb +1 -0
  27. data/app/models/spree/calculator.rb +2 -0
  28. data/app/models/spree/country.rb +56 -0
  29. data/app/models/spree/coupon_code.rb +2 -0
  30. data/app/models/spree/credit_card.rb +2 -0
  31. data/app/models/spree/current.rb +9 -4
  32. data/app/models/spree/customer_group.rb +2 -0
  33. data/app/models/spree/customer_return.rb +2 -0
  34. data/app/models/spree/data_feed.rb +2 -0
  35. data/app/models/spree/digital.rb +2 -0
  36. data/app/models/spree/digital_link.rb +2 -0
  37. data/app/models/spree/export.rb +3 -2
  38. data/app/models/spree/fulfilment_changer.rb +8 -2
  39. data/app/models/spree/gateway/bogus.rb +60 -0
  40. data/app/models/spree/gateway_customer.rb +2 -0
  41. data/app/models/spree/gift_card.rb +2 -0
  42. data/app/models/spree/gift_card_batch.rb +2 -4
  43. data/app/models/spree/image.rb +18 -0
  44. data/app/models/spree/import.rb +5 -3
  45. data/app/models/spree/import_mapping.rb +2 -0
  46. data/app/models/spree/import_row.rb +2 -0
  47. data/app/models/spree/import_schemas/customers.rb +21 -0
  48. data/app/models/spree/imports/customers.rb +9 -0
  49. data/app/models/spree/integration.rb +2 -0
  50. data/app/models/spree/inventory_unit.rb +2 -0
  51. data/app/models/spree/invitation.rb +6 -6
  52. data/app/models/spree/legacy_admin_user.rb +31 -0
  53. data/app/models/spree/legacy_user.rb +19 -1
  54. data/app/models/spree/line_item.rb +15 -4
  55. data/app/models/spree/log_entry.rb +2 -0
  56. data/app/models/spree/market.rb +83 -0
  57. data/app/models/spree/market_country.rb +25 -0
  58. data/app/models/spree/metafield.rb +2 -0
  59. data/app/models/spree/metafield_definition.rb +2 -0
  60. data/app/models/spree/newsletter_subscriber.rb +2 -0
  61. data/app/models/spree/option_type.rb +2 -0
  62. data/app/models/spree/option_value.rb +2 -0
  63. data/app/models/spree/order/address_book.rb +2 -1
  64. data/app/models/spree/order.rb +75 -47
  65. data/app/models/spree/payment.rb +6 -1
  66. data/app/models/spree/payment_capture_event.rb +2 -0
  67. data/app/models/spree/payment_method.rb +59 -1
  68. data/app/models/spree/payment_session.rb +109 -0
  69. data/app/models/spree/payment_sessions/bogus.rb +4 -0
  70. data/app/models/spree/payment_setup_session.rb +79 -0
  71. data/app/models/spree/payment_source.rb +2 -0
  72. data/app/models/spree/permission_sets/default_customer.rb +19 -0
  73. data/app/models/spree/policy.rb +2 -0
  74. data/app/models/spree/post.rb +2 -0
  75. data/app/models/spree/post_category.rb +2 -0
  76. data/app/models/spree/price.rb +26 -2
  77. data/app/models/spree/price_list.rb +2 -0
  78. data/app/models/spree/price_rule.rb +2 -0
  79. data/app/models/spree/price_rules/market_rule.rb +19 -0
  80. data/app/models/spree/product.rb +41 -29
  81. data/app/models/spree/promotion/rules/country.rb +1 -1
  82. data/app/models/spree/promotion.rb +3 -1
  83. data/app/models/spree/promotion_action.rb +2 -0
  84. data/app/models/spree/promotion_category.rb +2 -0
  85. data/app/models/spree/promotion_rule.rb +2 -0
  86. data/app/models/spree/prototype.rb +2 -0
  87. data/app/models/spree/refund.rb +2 -4
  88. data/app/models/spree/refund_reason.rb +2 -0
  89. data/app/models/spree/reimbursement/credit.rb +2 -0
  90. data/app/models/spree/reimbursement.rb +2 -0
  91. data/app/models/spree/reimbursement_type.rb +2 -0
  92. data/app/models/spree/report.rb +3 -1
  93. data/app/models/spree/return_authorization.rb +2 -0
  94. data/app/models/spree/return_authorization_reason.rb +2 -0
  95. data/app/models/spree/return_item.rb +2 -0
  96. data/app/models/spree/role.rb +2 -0
  97. data/app/models/spree/shipment.rb +11 -1
  98. data/app/models/spree/shipping_category.rb +2 -0
  99. data/app/models/spree/shipping_method.rb +2 -0
  100. data/app/models/spree/shipping_method_category.rb +2 -0
  101. data/app/models/spree/shipping_rate.rb +2 -0
  102. data/app/models/spree/state_change.rb +2 -0
  103. data/app/models/spree/stock_item.rb +2 -0
  104. data/app/models/spree/stock_location.rb +2 -0
  105. data/app/models/spree/stock_movement.rb +2 -0
  106. data/app/models/spree/stock_transfer.rb +2 -1
  107. data/app/models/spree/store.rb +110 -179
  108. data/app/models/spree/store_credit.rb +2 -4
  109. data/app/models/spree/store_credit_category.rb +2 -0
  110. data/app/models/spree/store_credit_event.rb +2 -0
  111. data/app/models/spree/store_credit_type.rb +2 -0
  112. data/app/models/spree/store_product.rb +2 -0
  113. data/app/models/spree/tax_category.rb +2 -0
  114. data/app/models/spree/tax_rate.rb +2 -0
  115. data/app/models/spree/taxon.rb +4 -1
  116. data/app/models/spree/taxon_image.rb +8 -0
  117. data/app/models/spree/taxon_rule.rb +2 -0
  118. data/app/models/spree/taxonomy.rb +2 -0
  119. data/app/models/spree/user_identity.rb +81 -0
  120. data/app/models/spree/variant.rb +13 -3
  121. data/app/models/spree/webhook_delivery.rb +2 -0
  122. data/app/models/spree/webhook_endpoint.rb +2 -17
  123. data/app/models/spree/wished_item.rb +15 -0
  124. data/app/models/spree/wishlist.rb +2 -8
  125. data/app/models/spree/zone.rb +2 -6
  126. data/app/presenters/spree/filters/price_presenter.rb +1 -0
  127. data/app/presenters/spree/filters/price_range_presenter.rb +1 -0
  128. data/app/presenters/spree/filters/quantified_price_range_presenter.rb +1 -0
  129. data/app/presenters/spree/product_summary_presenter.rb +1 -0
  130. data/app/services/spree/addresses/helper.rb +22 -3
  131. data/app/services/spree/cart/associate.rb +19 -6
  132. data/app/services/spree/checkout/select_shipping_method.rb +13 -1
  133. data/app/services/spree/classifications/reposition.rb +5 -0
  134. data/app/services/spree/data_feeds/google/required_attributes.rb +8 -3
  135. data/app/services/spree/gift_cards/apply.rb +4 -5
  136. data/app/services/spree/imports/row_processors/customer.rb +70 -0
  137. data/app/services/spree/orders/approve.rb +5 -3
  138. data/app/services/spree/orders/cancel.rb +9 -4
  139. data/app/services/spree/products/prepare_nested_attributes.rb +1 -1
  140. data/app/services/spree/sample_data/import_runner.rb +54 -0
  141. data/app/services/spree/sample_data/loader.rb +78 -0
  142. data/app/services/spree/seeds/admin_user.rb +2 -3
  143. data/app/services/spree/seeds/all.rb +1 -0
  144. data/app/services/spree/seeds/api_keys.rb +16 -0
  145. data/app/services/spree/seeds/stores.rb +2 -4
  146. data/app/sorters/spree/orders/sort.rb +4 -0
  147. data/app/subscribers/spree/product_metrics_subscriber.rb +4 -4
  148. data/config/brakeman.ignore +120 -0
  149. data/config/locales/en.yml +20 -5
  150. data/db/migrate/20250923141900_create_spree_user_identities.rb +17 -0
  151. data/db/migrate/20260123000000_create_spree_api_keys.rb +19 -0
  152. data/db/migrate/20260131000000_add_thumbnail_id_to_spree_variants_and_products.rb +9 -0
  153. data/db/migrate/20260213000000_create_spree_payment_sessions.rb +27 -0
  154. data/db/migrate/20260218000000_create_spree_payment_setup_sessions.rb +24 -0
  155. data/db/migrate/20260220000000_create_spree_markets.rb +29 -0
  156. data/db/sample_data/customers.csv +21 -0
  157. data/db/sample_data/metafield_definitions.rb +7 -0
  158. data/db/sample_data/orders.rb +131 -0
  159. data/db/sample_data/payment_methods.rb +17 -0
  160. data/db/sample_data/posts.rb +7 -0
  161. data/db/sample_data/products.csv +1083 -0
  162. data/db/sample_data/promotions.rb +8 -0
  163. data/db/sample_data/shipping_methods.rb +39 -0
  164. data/lib/generators/spree/authentication/devise/devise_generator.rb +2 -2
  165. data/lib/generators/spree/authentication/dummy/dummy_generator.rb +54 -0
  166. data/lib/generators/spree/authentication/dummy/templates/authentication_helpers.rb.tt +52 -0
  167. data/lib/generators/spree/authentication/dummy/templates/create_spree_admin_users.rb.tt +33 -0
  168. data/lib/generators/spree/dummy/dummy_generator.rb +1 -1
  169. data/lib/spree/core/configuration.rb +1 -1
  170. data/lib/spree/core/controller_helpers/common.rb +6 -0
  171. data/lib/spree/core/controller_helpers/currency.rb +5 -0
  172. data/lib/spree/core/controller_helpers/order.rb +5 -1
  173. data/lib/spree/core/controller_helpers/store.rb +1 -1
  174. data/lib/spree/core/dependencies.rb +1 -1
  175. data/lib/spree/core/engine.rb +17 -4
  176. data/lib/spree/core/pricing/context.rb +6 -3
  177. data/lib/spree/core/product_filters.rb +14 -0
  178. data/lib/spree/core/query_filters/comparable.rb +4 -0
  179. data/lib/spree/core/query_filters/text.rb +4 -0
  180. data/lib/spree/core/version.rb +1 -1
  181. data/lib/spree/core.rb +4 -4
  182. data/lib/spree/database_type_utilities.rb +7 -0
  183. data/lib/spree/events.rb +17 -10
  184. data/lib/spree/money.rb +2 -9
  185. data/lib/spree/permitted_attributes.rb +19 -7
  186. data/lib/spree/testing_support/capybara_config.rb +2 -2
  187. data/lib/spree/testing_support/common_rake.rb +15 -4
  188. data/lib/spree/testing_support/factories/api_key_factory.rb +19 -0
  189. data/lib/spree/testing_support/factories/custom_domain_factory.rb +7 -5
  190. data/lib/spree/testing_support/factories/import_factory.rb +12 -0
  191. data/lib/spree/testing_support/factories/market_factory.rb +35 -0
  192. data/lib/spree/testing_support/factories/order_factory.rb +3 -1
  193. data/lib/spree/testing_support/factories/payment_method_factory.rb +2 -0
  194. data/lib/spree/testing_support/factories/payment_session_factory.rb +47 -0
  195. data/lib/spree/testing_support/factories/payment_setup_session_factory.rb +31 -0
  196. data/lib/spree/testing_support/factories/price_rule_factory.rb +10 -0
  197. data/lib/spree/testing_support/factories/user_identity_factory.rb +15 -0
  198. data/lib/spree/testing_support/store.rb +3 -2
  199. data/lib/spree/webhooks.rb +7 -7
  200. data/lib/tasks/images.rake +20 -0
  201. data/lib/tasks/markets.rake +40 -0
  202. data/lib/tasks/sample_data.rake +15 -0
  203. data/spec/fixtures/files/customers_import.csv +4 -0
  204. metadata +88 -62
  205. data/LICENSE.md +0 -57
  206. data/app/finders/spree/stores/find_current.rb +0 -28
  207. data/app/models/spree/custom_domain.rb +0 -59
  208. data/app/serializers/spree/events/asset_serializer.rb +0 -22
  209. data/app/serializers/spree/events/base_serializer.rb +0 -61
  210. data/app/serializers/spree/events/customer_return_serializer.rb +0 -20
  211. data/app/serializers/spree/events/digital_link_serializer.rb +0 -20
  212. data/app/serializers/spree/events/digital_serializer.rb +0 -18
  213. data/app/serializers/spree/events/export_serializer.rb +0 -22
  214. data/app/serializers/spree/events/gift_card_batch_serializer.rb +0 -24
  215. data/app/serializers/spree/events/gift_card_serializer.rb +0 -29
  216. data/app/serializers/spree/events/image_serializer.rb +0 -9
  217. data/app/serializers/spree/events/import_row_serializer.rb +0 -23
  218. data/app/serializers/spree/events/import_serializer.rb +0 -24
  219. data/app/serializers/spree/events/invitation_serializer.rb +0 -28
  220. data/app/serializers/spree/events/line_item_serializer.rb +0 -31
  221. data/app/serializers/spree/events/newsletter_subscriber_serializer.rb +0 -21
  222. data/app/serializers/spree/events/order_serializer.rb +0 -39
  223. data/app/serializers/spree/events/payment_serializer.rb +0 -24
  224. data/app/serializers/spree/events/post_category_serializer.rb +0 -20
  225. data/app/serializers/spree/events/post_serializer.rb +0 -26
  226. data/app/serializers/spree/events/price_serializer.rb +0 -22
  227. data/app/serializers/spree/events/product_serializer.rb +0 -24
  228. data/app/serializers/spree/events/promotion_serializer.rb +0 -32
  229. data/app/serializers/spree/events/refund_serializer.rb +0 -23
  230. data/app/serializers/spree/events/reimbursement_serializer.rb +0 -22
  231. data/app/serializers/spree/events/report_serializer.rb +0 -23
  232. data/app/serializers/spree/events/return_authorization_serializer.rb +0 -22
  233. data/app/serializers/spree/events/return_item_serializer.rb +0 -27
  234. data/app/serializers/spree/events/shipment_serializer.rb +0 -24
  235. data/app/serializers/spree/events/stock_item_serializer.rb +0 -22
  236. data/app/serializers/spree/events/stock_movement_serializer.rb +0 -22
  237. data/app/serializers/spree/events/stock_transfer_serializer.rb +0 -22
  238. data/app/serializers/spree/events/store_credit_serializer.rb +0 -30
  239. data/app/serializers/spree/events/user_serializer.rb +0 -18
  240. data/app/serializers/spree/events/variant_serializer.rb +0 -34
  241. data/app/serializers/spree/events/wished_item_serializer.rb +0 -20
  242. data/app/serializers/spree/events/wishlist_serializer.rb +0 -22
@@ -0,0 +1,19 @@
1
+ module Spree
2
+ module PriceRules
3
+ class MarketRule < Spree::PriceRule
4
+ preference :market_ids, :array, default: []
5
+
6
+ def applicable?(context)
7
+ return false unless context.market
8
+ return true if preferred_market_ids.empty?
9
+
10
+ # Compare as strings to support both integer and UUID primary keys
11
+ preferred_market_ids.map(&:to_s).include?(context.market.id.to_s)
12
+ end
13
+
14
+ def self.description
15
+ 'Apply pricing based on the market'
16
+ end
17
+ end
18
+ end
19
+ end
@@ -20,12 +20,14 @@
20
20
 
21
21
  module Spree
22
22
  class Product < Spree.base_class
23
+ has_prefix_id :prod # Stripe: prod_
24
+
23
25
  acts_as_paranoid
24
26
  acts_as_taggable_on :tags, :labels
25
27
  normalizes :name, with: ->(value) { value&.to_s&.squish&.presence }
26
28
 
27
29
  include Spree::ProductScopes
28
- include Spree::MultiStoreResource
30
+ include Spree::StoreScopedResource
29
31
  include Spree::TranslatableResource
30
32
  include Spree::MemoizedData
31
33
  include Spree::Metafields
@@ -117,6 +119,8 @@ module Spree
117
119
  has_many :variant_images, -> { order(:position) }, source: :images, through: :variants_including_master
118
120
  has_many :variant_images_without_master, -> { order(:position) }, source: :images, through: :variants
119
121
 
122
+ belongs_to :thumbnail, class_name: 'Spree::Image', optional: true
123
+
120
124
  has_many :option_value_variants, class_name: 'Spree::OptionValueVariant', through: :variants
121
125
  has_many :option_values, class_name: 'Spree::OptionValue', through: :variants
122
126
 
@@ -230,11 +234,12 @@ module Spree
230
234
 
231
235
  alias options product_option_types
232
236
 
233
- self.whitelisted_ransackable_attributes = %w[description name slug discontinue_on status]
237
+ self.whitelisted_ransackable_attributes = %w[description name slug discontinue_on status available_on created_at updated_at]
234
238
  self.whitelisted_ransackable_associations = %w[taxons stores variants_including_master master variants tags labels
235
239
  shipping_category classifications option_types properties]
236
240
  self.whitelisted_ransackable_scopes = %w[not_discontinued search_by_name in_taxon price_between
237
- multi_search in_stock_items out_of_stock_items]
241
+ multi_search in_stock_items out_of_stock_items with_option_value_ids
242
+ ascend_by_price descend_by_price]
238
243
 
239
244
  [
240
245
  :sku, :barcode, :weight, :height, :width, :depth, :is_master, :dimensions_unit, :weight_unit
@@ -252,6 +257,9 @@ module Spree
252
257
  delegate :display_amount, :display_price, :has_default_price?, :track_inventory?,
253
258
  :display_compare_at_price, :images, to: :default_variant
254
259
 
260
+ # Rails doesn't provide _id methods for has_one associations by default
261
+ delegate :id, to: :master, prefix: true, allow_nil: true
262
+
255
263
  alias master_images images
256
264
 
257
265
  state_machine :status, initial: :draft do
@@ -290,12 +298,12 @@ module Spree
290
298
 
291
299
  # Can't use short form block syntax due to https://github.com/Netflix/fast_jsonapi/issues/259
292
300
  def purchasable?
293
- @purchasable ||= default_variant.purchasable? || variants.in_stock_or_backorderable.any?
301
+ @purchasable ||= default_variant.purchasable? || variants.any?(&:purchasable?)
294
302
  end
295
303
 
296
304
  # Can't use short form block syntax due to https://github.com/Netflix/fast_jsonapi/issues/259
297
305
  def in_stock?
298
- @in_stock ||= default_variant.in_stock? || variants.in_stock.any?
306
+ @in_stock ||= default_variant.in_stock? || variants.any?(&:in_stock?)
299
307
  end
300
308
 
301
309
  # Can't use short form block syntax due to https://github.com/Netflix/fast_jsonapi/issues/259
@@ -362,9 +370,10 @@ module Spree
362
370
  end
363
371
 
364
372
  # Returns default Image for Product.
373
+ # Uses cached thumbnail_id which is updated when images are added/removed/reordered.
365
374
  # @return [Spree::Image, nil]
366
375
  def default_image
367
- variant_for_images&.primary_image
376
+ thumbnail
368
377
  end
369
378
 
370
379
  # Backward compatibility for Spree 5.2 and earlier.
@@ -390,6 +399,13 @@ module Spree
390
399
  variant_for_images&.image_count || 0
391
400
  end
392
401
 
402
+ # Updates the thumbnail_id to the first image from variant_images.
403
+ # Called when images are added, removed, or reordered on any variant.
404
+ def update_thumbnail!
405
+ first_image = variant_images.order(:position).first
406
+ update_column(:thumbnail_id, first_image&.id)
407
+ end
408
+
393
409
  # Finds first variant with images using preloaded data when available.
394
410
  # @return [Spree::Variant, nil]
395
411
  def find_variant_with_images
@@ -598,15 +614,13 @@ module Spree
598
614
  nil
599
615
  elsif Spree.use_translations?
600
616
  taxons.joins(:taxonomy).
601
- join_translation_table(Taxonomy).
602
- find_by(Taxonomy.translation_table_alias => { name: Spree.t(:taxonomy_brands_name) })
603
- else
604
- if taxons.loaded?
605
- taxons.find { |taxon| taxon.taxonomy.name == Spree.t(:taxonomy_brands_name) }
606
- else
607
- taxons.joins(:taxonomy).find_by(Taxonomy.table_name => { name: Spree.t(:taxonomy_brands_name) })
608
- end
609
- end
617
+ join_translation_table(Taxonomy).
618
+ find_by(Taxonomy.translation_table_alias => { name: Spree.t(:taxonomy_brands_name) })
619
+ elsif taxons.loaded?
620
+ taxons.find { |taxon| taxon.taxonomy.name == Spree.t(:taxonomy_brands_name) }
621
+ else
622
+ taxons.joins(:taxonomy).find_by(Taxonomy.table_name => { name: Spree.t(:taxonomy_brands_name) })
623
+ end
610
624
  end
611
625
 
612
626
  # Returns the brand name for the product
@@ -638,12 +652,10 @@ module Spree
638
652
  join_translation_table(Taxonomy).
639
653
  order(depth: :desc).
640
654
  find_by(Taxonomy.translation_table_alias => { name: Spree.t(:taxonomy_categories_name) })
655
+ elsif taxons.loaded?
656
+ taxons.find { |taxon| taxon.taxonomy.name == Spree.t(:taxonomy_categories_name) }
641
657
  else
642
- if taxons.loaded?
643
- taxons.find { |taxon| taxon.taxonomy.name == Spree.t(:taxonomy_categories_name) }
644
- else
645
- taxons.joins(:taxonomy).order(depth: :desc).find_by(Taxonomy.table_name => { name: Spree.t(:taxonomy_categories_name) })
646
- end
658
+ taxons.joins(:taxonomy).order(depth: :desc).find_by(Taxonomy.table_name => { name: Spree.t(:taxonomy_categories_name) })
647
659
  end
648
660
  end
649
661
 
@@ -691,15 +703,15 @@ module Spree
691
703
  def to_csv(store = nil)
692
704
  store ||= stores.default || stores.first
693
705
  properties_for_csv = if Spree::Config[:product_properties_enabled]
694
- Spree::Property.order(:position).flat_map do |property|
695
- [
696
- property.name,
697
- product_properties.find { |pp| pp.property_id == property.id }&.value
698
- ]
699
- end
700
- else
701
- []
702
- end
706
+ Spree::Property.order(:position).flat_map do |property|
707
+ [
708
+ property.name,
709
+ product_properties.find { |pp| pp.property_id == property.id }&.value
710
+ ]
711
+ end
712
+ else
713
+ []
714
+ end
703
715
  metafields_for_csv ||= Spree::MetafieldDefinition.for_resource_type('Spree::Product').order(:namespace, :key).map do |mf_def|
704
716
  metafields.find { |mf| mf.metafield_definition_id == mf_def.id }&.csv_value
705
717
  end
@@ -30,7 +30,7 @@ module Spree
30
30
 
31
31
  def validate_eligibility_by_country_iso(order)
32
32
  country_iso = order.ship_address&.country_iso
33
- return true if country_iso == (preferred_country_iso || order.store.default_country_iso)
33
+ return true if country_iso == (preferred_country_iso || order.store.default_market&.default_country&.iso)
34
34
 
35
35
  eligibility_errors.add(:base, eligibility_error_message(:wrong_country))
36
36
  false
@@ -1,6 +1,8 @@
1
1
  module Spree
2
2
  class Promotion < Spree.base_class
3
- include Spree::MultiStoreResource
3
+ has_prefix_id :promo # Spree-specific: promotion
4
+
5
+ include Spree::StoreScopedResource
4
6
  include Spree::Metafields
5
7
  include Spree::Metadata
6
8
  if defined?(Spree::Security::Promotions)
@@ -2,6 +2,8 @@
2
2
  # PromotionActions perform the necessary tasks when a promotion is activated by an event and determined to be eligible.
3
3
  module Spree
4
4
  class PromotionAction < Spree.base_class
5
+ has_prefix_id :pact
6
+
5
7
  acts_as_paranoid
6
8
 
7
9
  belongs_to :promotion, class_name: 'Spree::Promotion', touch: true
@@ -1,5 +1,7 @@
1
1
  module Spree
2
2
  class PromotionCategory < Spree.base_class
3
+ has_prefix_id :procat
4
+
3
5
  validates :name, presence: true
4
6
  has_many :promotions
5
7
  end
@@ -1,6 +1,8 @@
1
1
  # Base class for all promotion rules
2
2
  module Spree
3
3
  class PromotionRule < Spree.base_class
4
+ has_prefix_id :prorule
5
+
4
6
  belongs_to :promotion, class_name: 'Spree::Promotion', inverse_of: :promotion_rules, touch: true
5
7
 
6
8
  delegate :stores, to: :promotion
@@ -1,5 +1,7 @@
1
1
  module Spree
2
2
  class Prototype < Spree.base_class
3
+ has_prefix_id :proto
4
+
3
5
  include Spree::Metadata
4
6
 
5
7
  has_many :property_prototypes, class_name: 'Spree::PropertyPrototype'
@@ -1,5 +1,7 @@
1
1
  module Spree
2
2
  class Refund < Spree.base_class
3
+ has_prefix_id :re # Stripe: re_
4
+
3
5
  include Spree::Metafields
4
6
  include Spree::Metadata
5
7
  if defined?(Spree::Security::Refunds)
@@ -34,10 +36,6 @@ module Spree
34
36
 
35
37
  delegate :order, :currency, to: :payment
36
38
 
37
- def amount=(amount)
38
- self[:amount] = Spree::LocalizedNumber.parse(amount)
39
- end
40
-
41
39
  def money
42
40
  Spree::Money.new(amount, currency: currency)
43
41
  end
@@ -1,5 +1,7 @@
1
1
  module Spree
2
2
  class RefundReason < Spree.base_class
3
+ has_prefix_id :rr
4
+
3
5
  include Spree::NamedType
4
6
 
5
7
  RETURN_PROCESSING_REASON = 'Return processing'
@@ -1,5 +1,7 @@
1
1
  module Spree
2
2
  class Reimbursement::Credit < Spree.base_class
3
+ has_prefix_id :rcred
4
+
3
5
  class_attribute :default_creditable_class
4
6
  self.default_creditable_class = nil
5
7
 
@@ -1,5 +1,7 @@
1
1
  module Spree
2
2
  class Reimbursement < Spree.base_class
3
+ has_prefix_id :reimb
4
+
3
5
  include Spree::Core::NumberGenerator.new(prefix: 'RI', length: 9)
4
6
  include Spree::NumberIdentifier
5
7
  include Spree::Reimbursement::Emails
@@ -1,5 +1,7 @@
1
1
  module Spree
2
2
  class ReimbursementType < Spree.base_class
3
+ has_prefix_id :rtype
4
+
3
5
  include Spree::NamedType
4
6
 
5
7
  KINDS = %w(Spree::ReimbursementType::Credit
@@ -1,5 +1,7 @@
1
1
  module Spree
2
2
  class Report < Spree.base_class
3
+ has_prefix_id :rep
4
+
3
5
  include Spree::SingleStoreResource
4
6
  include Spree::VendorConcern if defined?(Spree::VendorConcern)
5
7
 
@@ -32,7 +34,7 @@ module Spree
32
34
  has_one_attached :attachment, service: Spree.private_storage_service_name
33
35
 
34
36
  def event_serializer_class
35
- Spree::Events::ReportSerializer
37
+ 'Spree::Api::V3::ReportSerializer'.safe_constantize
36
38
  end
37
39
 
38
40
  def self.report_type
@@ -1,5 +1,7 @@
1
1
  module Spree
2
2
  class ReturnAuthorization < Spree.base_class
3
+ has_prefix_id :ra
4
+
3
5
  include Spree::Core::NumberGenerator.new(prefix: 'RA', length: 9)
4
6
  include Spree::NumberIdentifier
5
7
 
@@ -1,5 +1,7 @@
1
1
  module Spree
2
2
  class ReturnAuthorizationReason < Spree.base_class
3
+ has_prefix_id :rar
4
+
3
5
  include Spree::NamedType
4
6
 
5
7
  has_many :return_authorizations, dependent: :restrict_with_error
@@ -1,5 +1,7 @@
1
1
  module Spree
2
2
  class ReturnItem < Spree.base_class
3
+ has_prefix_id :ri
4
+
3
5
  COMPLETED_RECEPTION_STATUSES = %w(received given_to_customer)
4
6
 
5
7
  class_attribute :return_eligibility_validator
@@ -1,5 +1,7 @@
1
1
  module Spree
2
2
  class Role < Spree.base_class
3
+ has_prefix_id :role
4
+
3
5
  include Spree::UniqueName
4
6
 
5
7
  ADMIN_ROLE = 'admin'
@@ -2,9 +2,10 @@ require 'ostruct'
2
2
 
3
3
  module Spree
4
4
  class Shipment < Spree.base_class
5
+ has_prefix_id :ship # Spree-specific: shipment
6
+
5
7
  include Spree::Core::NumberGenerator.new(prefix: 'H', length: 11)
6
8
  include Spree::NumberIdentifier
7
- include Spree::NumberAsParam
8
9
  include Spree::Metafields
9
10
  include Spree::Metadata
10
11
  if defined?(Spree::Security::Shipments)
@@ -346,6 +347,15 @@ module Spree
346
347
  shipping_rates.update_all(selected: false, updated_at: Time.current)
347
348
  shipping_rates.update(id, selected: true)
348
349
  save!
350
+ # Reload associations to pick up the new selected shipping rate
351
+ shipping_rates.reset
352
+ association(:selected_shipping_rate).reset
353
+ # Update shipment cost and order totals only for incomplete orders (during checkout)
354
+ # For completed orders, totals are managed separately (e.g., in tests or admin adjustments)
355
+ return if order.completed?
356
+
357
+ update_amounts
358
+ order.set_shipments_cost
349
359
  end
350
360
 
351
361
  def set_up_inventory(state, variant, order, line_item, quantity = 1)
@@ -1,5 +1,7 @@
1
1
  module Spree
2
2
  class ShippingCategory < Spree.base_class
3
+ has_prefix_id :scat
4
+
3
5
  DIGITAL_NAME = 'Digital'
4
6
 
5
7
  include Spree::UniqueName
@@ -1,5 +1,7 @@
1
1
  module Spree
2
2
  class ShippingMethod < Spree.base_class
3
+ has_prefix_id :shpm # Spree-specific: shipping method
4
+
3
5
  acts_as_paranoid
4
6
  include Spree::CalculatedAdjustments
5
7
  include Spree::Metafields
@@ -1,5 +1,7 @@
1
1
  module Spree
2
2
  class ShippingMethodCategory < Spree.base_class
3
+ has_prefix_id :smcat
4
+
3
5
  belongs_to :shipping_method, class_name: 'Spree::ShippingMethod'
4
6
  belongs_to :shipping_category, class_name: 'Spree::ShippingCategory', inverse_of: :shipping_method_categories
5
7
  end
@@ -1,5 +1,7 @@
1
1
  module Spree
2
2
  class ShippingRate < Spree.base_class
3
+ has_prefix_id :shpr # Spree-specific: shipping rate
4
+
3
5
  belongs_to :shipment, class_name: 'Spree::Shipment'
4
6
  belongs_to :tax_rate, -> { with_deleted }, class_name: 'Spree::TaxRate'
5
7
  belongs_to :shipping_method, -> { with_deleted }, class_name: 'Spree::ShippingMethod', inverse_of: :shipping_rates
@@ -1,5 +1,7 @@
1
1
  module Spree
2
2
  class StateChange < Spree.base_class
3
+ has_prefix_id :sc
4
+
3
5
  belongs_to :user, class_name: "::#{Spree.user_class}", optional: true
4
6
  belongs_to :stateful, polymorphic: true
5
7
 
@@ -1,5 +1,7 @@
1
1
  module Spree
2
2
  class StockItem < Spree.base_class
3
+ has_prefix_id :si
4
+
3
5
  acts_as_paranoid
4
6
 
5
7
  include Spree::Metafields
@@ -1,5 +1,7 @@
1
1
  module Spree
2
2
  class StockLocation < Spree.base_class
3
+ has_prefix_id :sloc # Spree-specific: stock location
4
+
3
5
  include Spree::UniqueName
4
6
  if defined?(Spree::Security::StockLocations)
5
7
  include Spree::Security::StockLocations
@@ -1,5 +1,7 @@
1
1
  module Spree
2
2
  class StockMovement < Spree.base_class
3
+ has_prefix_id :sm
4
+
3
5
  QUANTITY_LIMITS = {
4
6
  max: 2**31 - 1,
5
7
  min: -2**31
@@ -1,8 +1,9 @@
1
1
  module Spree
2
2
  class StockTransfer < Spree.base_class
3
+ has_prefix_id :st
4
+
3
5
  include Spree::Core::NumberGenerator.new(prefix: 'T')
4
6
  include Spree::NumberIdentifier
5
- include Spree::NumberAsParam
6
7
  include Spree::Metafields
7
8
  include Spree::Metadata
8
9