spree_core 5.2.6 → 5.3.0.rc1

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 (294) hide show
  1. checksums.yaml +4 -4
  2. data/app/helpers/spree/addresses_helper.rb +1 -23
  3. data/app/helpers/spree/base_helper.rb +25 -77
  4. data/app/helpers/spree/currency_helper.rb +2 -2
  5. data/app/helpers/spree/images_helper.rb +5 -0
  6. data/app/helpers/spree/mail_helper.rb +1 -1
  7. data/app/helpers/spree/products_helper.rb +1 -1
  8. data/app/jobs/spree/events/subscriber_job.rb +58 -0
  9. data/app/jobs/spree/products/refresh_metrics_job.rb +14 -0
  10. data/app/jobs/spree/products/touch_taxons_job.rb +0 -1
  11. data/app/jobs/spree/variants/touch_job.rb +9 -0
  12. data/app/models/concerns/spree/adjustment_source.rb +8 -0
  13. data/app/models/concerns/spree/parameterizable_name.rb +1 -1
  14. data/app/models/concerns/spree/product_scopes.rb +54 -8
  15. data/app/models/concerns/spree/publishable.rb +253 -0
  16. data/app/models/concerns/spree/unique_name.rb +1 -1
  17. data/app/models/concerns/spree/user_methods.rb +21 -1
  18. data/app/models/spree/ability.rb +3 -3
  19. data/app/models/spree/address.rb +0 -3
  20. data/app/models/spree/adjustable/promotion_accumulator.rb +1 -1
  21. data/app/models/spree/adjustment.rb +32 -6
  22. data/app/models/spree/asset.rb +6 -3
  23. data/app/models/spree/base.rb +3 -1
  24. data/app/models/spree/classification.rb +2 -2
  25. data/app/models/spree/credit_card.rb +0 -3
  26. data/app/models/spree/current.rb +24 -3
  27. data/app/models/spree/custom_domain.rb +1 -1
  28. data/app/models/spree/customer_group.rb +94 -0
  29. data/app/models/spree/customer_group_user.rb +16 -0
  30. data/app/models/spree/customer_return.rb +2 -3
  31. data/app/models/spree/digital.rb +2 -4
  32. data/app/models/spree/digital_link.rb +2 -3
  33. data/app/models/spree/event.rb +104 -0
  34. data/app/models/spree/export.rb +7 -1
  35. data/app/models/spree/gift_card.rb +13 -1
  36. data/app/models/spree/gift_card_batch.rb +3 -1
  37. data/app/models/spree/image.rb +20 -5
  38. data/app/models/spree/import.rb +17 -12
  39. data/app/models/spree/import_row.rb +13 -26
  40. data/app/models/spree/inventory_unit.rb +0 -3
  41. data/app/models/spree/invitation.rb +12 -6
  42. data/app/models/spree/line_item.rb +57 -4
  43. data/app/models/spree/newsletter_subscriber.rb +2 -0
  44. data/app/models/spree/option_type.rb +2 -5
  45. data/app/models/spree/option_value.rb +1 -4
  46. data/app/models/spree/order/checkout.rb +7 -2
  47. data/app/models/spree/order/emails.rb +3 -11
  48. data/app/models/spree/order/store_credit.rb +5 -1
  49. data/app/models/spree/order.rb +80 -31
  50. data/app/models/spree/order_updater.rb +28 -9
  51. data/app/models/spree/payment/custom_events.rb +37 -0
  52. data/app/models/spree/payment.rb +13 -4
  53. data/app/models/spree/payment_capture_event.rb +0 -4
  54. data/app/models/spree/payment_method.rb +1 -1
  55. data/app/models/spree/permission_sets/default_customer.rb +3 -3
  56. data/app/models/spree/policy.rb +1 -8
  57. data/app/models/spree/post.rb +2 -7
  58. data/app/models/spree/post_category.rb +2 -0
  59. data/app/models/spree/price.rb +8 -6
  60. data/app/models/spree/price_list.rb +263 -0
  61. data/app/models/spree/price_rule.rb +26 -0
  62. data/app/models/spree/price_rules/customer_group_rule.rb +21 -0
  63. data/app/models/spree/price_rules/user_rule.rb +19 -0
  64. data/app/models/spree/price_rules/volume_rule.rb +21 -0
  65. data/app/models/spree/price_rules/zone_rule.rb +19 -0
  66. data/app/models/spree/product.rb +117 -76
  67. data/app/models/spree/product_property.rb +2 -2
  68. data/app/models/spree/promotion/rules/customer_group.rb +22 -0
  69. data/app/models/spree/promotion/rules/user.rb +2 -2
  70. data/app/models/spree/promotion.rb +3 -4
  71. data/app/models/spree/promotion_handler/coupon.rb +3 -3
  72. data/app/models/spree/property.rb +3 -6
  73. data/app/models/spree/prototype.rb +0 -3
  74. data/app/models/spree/refund.rb +2 -3
  75. data/app/models/spree/reimbursement.rb +5 -3
  76. data/app/models/spree/report.rb +7 -1
  77. data/app/models/spree/reports/products_performance.rb +1 -1
  78. data/app/models/spree/reports/sales_total.rb +1 -1
  79. data/app/models/spree/return_authorization.rb +7 -3
  80. data/app/models/spree/return_item.rb +15 -4
  81. data/app/models/spree/shipment/custom_events.rb +47 -0
  82. data/app/models/spree/shipment.rb +12 -5
  83. data/app/models/spree/shipping_category.rb +0 -3
  84. data/app/models/spree/shipping_method.rb +0 -3
  85. data/app/models/spree/stock/quantifier.rb +1 -1
  86. data/app/models/spree/stock_item.rb +2 -0
  87. data/app/models/spree/stock_location.rb +0 -3
  88. data/app/models/spree/stock_movement/custom_events.rb +44 -0
  89. data/app/models/spree/stock_movement.rb +3 -0
  90. data/app/models/spree/stock_transfer.rb +2 -3
  91. data/app/models/spree/store.rb +64 -92
  92. data/app/models/spree/store_credit.rb +3 -4
  93. data/app/models/spree/store_product.rb +14 -0
  94. data/app/models/spree/subscriber.rb +186 -0
  95. data/app/models/spree/tax_category.rb +0 -4
  96. data/app/models/spree/tax_rate.rb +0 -3
  97. data/app/models/spree/taxon.rb +3 -36
  98. data/app/models/spree/taxonomy.rb +0 -3
  99. data/app/models/spree/variant.rb +114 -21
  100. data/app/models/spree/webhook_delivery.rb +60 -0
  101. data/app/models/spree/webhook_endpoint.rb +53 -0
  102. data/app/models/spree/wished_item.rb +2 -4
  103. data/app/models/spree/wishlist.rb +2 -3
  104. data/app/models/spree/zone.rb +0 -9
  105. data/app/paginators/spree/shared/paginate.rb +4 -0
  106. data/app/serializers/spree/events/asset_serializer.rb +22 -0
  107. data/app/serializers/spree/events/base_serializer.rb +61 -0
  108. data/app/serializers/spree/events/customer_return_serializer.rb +20 -0
  109. data/app/serializers/spree/events/digital_link_serializer.rb +20 -0
  110. data/app/serializers/spree/events/digital_serializer.rb +18 -0
  111. data/app/serializers/spree/events/export_serializer.rb +22 -0
  112. data/app/serializers/spree/events/gift_card_batch_serializer.rb +24 -0
  113. data/app/serializers/spree/events/gift_card_serializer.rb +29 -0
  114. data/app/serializers/spree/events/image_serializer.rb +9 -0
  115. data/app/serializers/spree/events/import_row_serializer.rb +23 -0
  116. data/app/serializers/spree/events/import_serializer.rb +24 -0
  117. data/app/serializers/spree/events/invitation_serializer.rb +28 -0
  118. data/app/serializers/spree/events/line_item_serializer.rb +31 -0
  119. data/app/serializers/spree/events/newsletter_subscriber_serializer.rb +21 -0
  120. data/app/serializers/spree/events/order_serializer.rb +39 -0
  121. data/app/serializers/spree/events/payment_serializer.rb +24 -0
  122. data/app/serializers/spree/events/post_category_serializer.rb +20 -0
  123. data/app/serializers/spree/events/post_serializer.rb +26 -0
  124. data/app/serializers/spree/events/price_serializer.rb +22 -0
  125. data/app/serializers/spree/events/product_serializer.rb +24 -0
  126. data/app/serializers/spree/events/promotion_serializer.rb +32 -0
  127. data/app/serializers/spree/events/refund_serializer.rb +23 -0
  128. data/app/serializers/spree/events/reimbursement_serializer.rb +22 -0
  129. data/app/serializers/spree/events/report_serializer.rb +23 -0
  130. data/app/serializers/spree/events/return_authorization_serializer.rb +22 -0
  131. data/app/serializers/spree/events/return_item_serializer.rb +27 -0
  132. data/app/serializers/spree/events/shipment_serializer.rb +24 -0
  133. data/app/serializers/spree/events/stock_item_serializer.rb +22 -0
  134. data/app/serializers/spree/events/stock_movement_serializer.rb +22 -0
  135. data/app/serializers/spree/events/stock_transfer_serializer.rb +22 -0
  136. data/app/serializers/spree/events/store_credit_serializer.rb +30 -0
  137. data/app/serializers/spree/events/user_serializer.rb +18 -0
  138. data/app/serializers/spree/events/variant_serializer.rb +34 -0
  139. data/app/serializers/spree/events/wished_item_serializer.rb +20 -0
  140. data/app/serializers/spree/events/wishlist_serializer.rb +22 -0
  141. data/app/services/spree/addresses/update.rb +1 -1
  142. data/app/services/spree/cart/add_item.rb +1 -1
  143. data/app/services/spree/coupon_codes/coupon_codes_handler.rb +2 -1
  144. data/app/services/spree/data_feeds/google/required_attributes.rb +4 -4
  145. data/app/services/spree/newsletter/verify.rb +5 -0
  146. data/app/services/spree/products/auto_match_taxons.rb +1 -1
  147. data/app/services/spree/seeds/all.rb +1 -1
  148. data/app/services/spree/taxons/add_products.rb +8 -4
  149. data/app/services/spree/taxons/regenerate_products.rb +8 -0
  150. data/app/services/spree/taxons/remove_products.rb +12 -7
  151. data/app/subscribers/spree/event_log_subscriber.rb +64 -0
  152. data/app/subscribers/spree/export_subscriber.rb +26 -0
  153. data/app/subscribers/spree/invitation_email_subscriber.rb +40 -0
  154. data/app/subscribers/spree/product_metrics_subscriber.rb +29 -0
  155. data/app/subscribers/spree/report_subscriber.rb +26 -0
  156. data/config/locales/en.yml +126 -0
  157. data/db/migrate/20251110120000_create_spree_price_lists.rb +22 -0
  158. data/db/migrate/20251110120001_create_spree_price_rules.rb +13 -0
  159. data/db/migrate/20251110120002_add_price_list_id_to_spree_prices.rb +6 -0
  160. data/db/migrate/20251110120003_add_price_list_id_to_spree_line_items.rb +5 -0
  161. data/db/migrate/20251201172118_fix_indexes_on_friendly_id_slugs.rb +8 -0
  162. data/db/migrate/20251214000001_create_spree_webhook_endpoints.rb +19 -0
  163. data/db/migrate/20251214000002_create_spree_webhook_deliveries.rb +23 -0
  164. data/db/migrate/20251222000000_add_performance_indexes_to_spree_adjustments.rb +25 -0
  165. data/db/migrate/20260112000000_fix_spree_prices_unique_indexes.rb +33 -0
  166. data/db/migrate/20260115120000_create_spree_customer_groups.rb +14 -0
  167. data/db/migrate/20260115120001_create_spree_customer_group_users.rb +14 -0
  168. data/db/migrate/20260117140831_remove_not_null_constraint_from_policy_name.rb +5 -0
  169. data/db/migrate/20260118120000_add_statistics_to_store_products.rb +11 -0
  170. data/db/migrate/20260119120000_add_counter_caches_to_spree_products.rb +9 -0
  171. data/db/migrate/20260119170000_add_counter_caches_to_spree_taxons.rb +9 -0
  172. data/db/migrate/20260120120000_add_image_count_to_spree_variants.rb +9 -0
  173. data/lib/generators/spree/dummy/dummy_generator.rb +14 -2
  174. data/lib/spree/core/configuration.rb +1 -0
  175. data/lib/spree/core/controller_helpers/auth.rb +0 -15
  176. data/lib/spree/core/controller_helpers/currency.rb +13 -9
  177. data/lib/spree/core/controller_helpers/search.rb +1 -1
  178. data/lib/spree/core/controller_helpers/store.rb +5 -1
  179. data/lib/spree/core/engine.rb +61 -78
  180. data/lib/spree/core/importer/order.rb +1 -1
  181. data/lib/spree/core/importer/product.rb +1 -1
  182. data/lib/spree/core/preferences/preferable.rb +14 -1
  183. data/lib/spree/core/pricing/context.rb +63 -0
  184. data/lib/spree/core/pricing/resolver.rb +129 -0
  185. data/lib/spree/core/search/base.rb +1 -1
  186. data/lib/spree/core/token_generator.rb +1 -1
  187. data/lib/spree/core/version.rb +1 -1
  188. data/lib/spree/core.rb +42 -47
  189. data/lib/spree/events/adapters/active_support_notifications.rb +112 -0
  190. data/lib/spree/events/adapters/base.rb +193 -0
  191. data/lib/spree/events/registry.rb +99 -0
  192. data/lib/spree/events.rb +240 -0
  193. data/lib/spree/permitted_attributes.rb +13 -2
  194. data/lib/spree/testing_support/common_rake.rb +68 -35
  195. data/lib/spree/testing_support/factories/customer_group_factory.rb +6 -0
  196. data/lib/spree/testing_support/factories/customer_group_user_factory.rb +6 -0
  197. data/lib/spree/testing_support/factories/price_factory.rb +4 -0
  198. data/lib/spree/testing_support/factories/price_list_factory.rb +34 -0
  199. data/lib/spree/testing_support/factories/price_rule_factory.rb +49 -0
  200. data/lib/spree/testing_support/factories/promotion_rule_factory.rb +12 -0
  201. data/lib/spree/testing_support/factories/stock_item_factory.rb +6 -4
  202. data/lib/spree/testing_support/factories/store_product_factory.rb +6 -0
  203. data/lib/spree/testing_support/factories/taxon_factory.rb +0 -1
  204. data/lib/spree/testing_support/factories/webhook_delivery_factory.rb +48 -0
  205. data/lib/spree/testing_support/factories/webhook_endpoint_factory.rb +22 -0
  206. data/lib/spree/testing_support/lifecycle_events.rb +38 -0
  207. data/lib/spree/testing_support/store.rb +4 -2
  208. data/lib/spree/webhooks.rb +22 -0
  209. data/lib/tasks/products.rake +40 -0
  210. data/lib/tasks/taxons.rake +19 -0
  211. data/lib/tasks/variants.rake +18 -0
  212. metadata +112 -114
  213. data/app/jobs/spree/themes/duplicate_components_job.rb +0 -59
  214. data/app/jobs/spree/themes/screenshot_job.rb +0 -81
  215. data/app/models/concerns/spree/has_page_links.rb +0 -53
  216. data/app/models/spree/page.rb +0 -188
  217. data/app/models/spree/page_block.rb +0 -73
  218. data/app/models/spree/page_blocks/buttons.rb +0 -29
  219. data/app/models/spree/page_blocks/heading.rb +0 -18
  220. data/app/models/spree/page_blocks/image.rb +0 -20
  221. data/app/models/spree/page_blocks/link.rb +0 -21
  222. data/app/models/spree/page_blocks/mega_nav.rb +0 -33
  223. data/app/models/spree/page_blocks/mega_nav_with_subcategories.rb +0 -32
  224. data/app/models/spree/page_blocks/metafields.rb +0 -18
  225. data/app/models/spree/page_blocks/nav.rb +0 -15
  226. data/app/models/spree/page_blocks/newsletter_form.rb +0 -18
  227. data/app/models/spree/page_blocks/products/brand.rb +0 -15
  228. data/app/models/spree/page_blocks/products/buy_buttons.rb +0 -24
  229. data/app/models/spree/page_blocks/products/description.rb +0 -18
  230. data/app/models/spree/page_blocks/products/price.rb +0 -18
  231. data/app/models/spree/page_blocks/products/quantity_selector.rb +0 -20
  232. data/app/models/spree/page_blocks/products/share.rb +0 -8
  233. data/app/models/spree/page_blocks/products/title.rb +0 -19
  234. data/app/models/spree/page_blocks/products/variant_picker.rb +0 -13
  235. data/app/models/spree/page_blocks/subheading.rb +0 -17
  236. data/app/models/spree/page_blocks/text.rb +0 -16
  237. data/app/models/spree/page_link.rb +0 -60
  238. data/app/models/spree/page_section.rb +0 -222
  239. data/app/models/spree/page_sections/announcement_bar.rb +0 -28
  240. data/app/models/spree/page_sections/breadcrumbs.rb +0 -12
  241. data/app/models/spree/page_sections/collection_banner.rb +0 -18
  242. data/app/models/spree/page_sections/custom_code.rb +0 -11
  243. data/app/models/spree/page_sections/featured_posts.rb +0 -45
  244. data/app/models/spree/page_sections/featured_product.rb +0 -50
  245. data/app/models/spree/page_sections/featured_taxon.rb +0 -90
  246. data/app/models/spree/page_sections/featured_taxons.rb +0 -45
  247. data/app/models/spree/page_sections/footer.rb +0 -101
  248. data/app/models/spree/page_sections/header.rb +0 -62
  249. data/app/models/spree/page_sections/image_banner.rb +0 -55
  250. data/app/models/spree/page_sections/image_with_text.rb +0 -65
  251. data/app/models/spree/page_sections/main_password_footer.rb +0 -18
  252. data/app/models/spree/page_sections/main_password_header.rb +0 -20
  253. data/app/models/spree/page_sections/newsletter.rb +0 -54
  254. data/app/models/spree/page_sections/page_title.rb +0 -19
  255. data/app/models/spree/page_sections/post_details.rb +0 -19
  256. data/app/models/spree/page_sections/post_grid.rb +0 -19
  257. data/app/models/spree/page_sections/product_details.rb +0 -53
  258. data/app/models/spree/page_sections/product_grid.rb +0 -13
  259. data/app/models/spree/page_sections/related_products.rb +0 -58
  260. data/app/models/spree/page_sections/rich_text.rb +0 -31
  261. data/app/models/spree/page_sections/taxon_banner.rb +0 -18
  262. data/app/models/spree/page_sections/taxon_grid.rb +0 -17
  263. data/app/models/spree/page_sections/video.rb +0 -107
  264. data/app/models/spree/pages/account.rb +0 -19
  265. data/app/models/spree/pages/cart.rb +0 -19
  266. data/app/models/spree/pages/checkout.rb +0 -15
  267. data/app/models/spree/pages/custom.rb +0 -38
  268. data/app/models/spree/pages/homepage.rb +0 -72
  269. data/app/models/spree/pages/login.rb +0 -19
  270. data/app/models/spree/pages/password.rb +0 -59
  271. data/app/models/spree/pages/post.rb +0 -27
  272. data/app/models/spree/pages/post_list.rb +0 -36
  273. data/app/models/spree/pages/product_details.rb +0 -30
  274. data/app/models/spree/pages/search_results.rb +0 -43
  275. data/app/models/spree/pages/shop_all.rb +0 -40
  276. data/app/models/spree/pages/taxon.rb +0 -29
  277. data/app/models/spree/pages/taxon_list.rb +0 -41
  278. data/app/models/spree/pages/wishlist.rb +0 -15
  279. data/app/models/spree/theme.rb +0 -233
  280. data/app/models/spree/themes/default.rb +0 -97
  281. data/app/services/spree/taxons/touch_featured_sections.rb +0 -21
  282. data/db/migrate/20250120094216_create_page_builder_models.rb +0 -78
  283. data/db/migrate/20250305121352_remove_page_builder_indices.rb +0 -11
  284. data/db/migrate/20250825175217_add_missing_page_builder_indexes.rb +0 -7
  285. data/db/migrate/20250913130044_add_page_links_counter_cache_to_spree_stores.rb +0 -10
  286. data/lib/generators/spree/dummy/templates/initializers/devise.rb +0 -3
  287. data/lib/generators/spree/install/install_generator.rb +0 -219
  288. data/lib/generators/spree/install/templates/config/initializers/spree.rb +0 -126
  289. data/lib/spree/core/webhooks.rb +0 -21
  290. data/lib/spree/testing_support/factories/page_block_factory.rb +0 -22
  291. data/lib/spree/testing_support/factories/page_factory.rb +0 -33
  292. data/lib/spree/testing_support/factories/page_link_factory.rb +0 -7
  293. data/lib/spree/testing_support/factories/page_section_factory.rb +0 -27
  294. data/lib/spree/testing_support/factories/theme_factory.rb +0 -14
@@ -0,0 +1,11 @@
1
+ class AddStatisticsToStoreProducts < ActiveRecord::Migration[7.0]
2
+ def change
3
+ add_column :spree_products_stores, :units_sold_count, :integer, default: 0, null: false, if_not_exists: true
4
+ add_column :spree_products_stores, :revenue, :decimal, precision: 10, scale: 2, default: 0, null: false, if_not_exists: true
5
+
6
+ add_index :spree_products_stores, [:store_id, :units_sold_count],
7
+ name: 'index_products_stores_on_store_and_units_sold', if_not_exists: true
8
+ add_index :spree_products_stores, [:store_id, :revenue],
9
+ name: 'index_products_stores_on_store_and_revenue', if_not_exists: true
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ class AddCounterCachesToSpreeProducts < ActiveRecord::Migration[7.2]
2
+ def change
3
+ add_column :spree_products, :variant_count, :integer, default: 0, null: false, if_not_exists: true
4
+ add_column :spree_products, :classification_count, :integer, default: 0, null: false, if_not_exists: true
5
+
6
+ add_index :spree_products, :variant_count, if_not_exists: true
7
+ add_index :spree_products, :classification_count, if_not_exists: true
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ class AddCounterCachesToSpreeTaxons < ActiveRecord::Migration[7.2]
2
+ def change
3
+ add_column :spree_taxons, :children_count, :integer, default: 0, null: false, if_not_exists: true
4
+ add_column :spree_taxons, :classification_count, :integer, default: 0, null: false, if_not_exists: true
5
+
6
+ add_index :spree_taxons, :children_count, if_not_exists: true
7
+ add_index :spree_taxons, :classification_count, if_not_exists: true
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ class AddImageCountToSpreeVariants < ActiveRecord::Migration[7.2]
2
+ def change
3
+ add_column :spree_variants, :image_count, :integer, default: 0, null: false, if_not_exists: true
4
+ add_column :spree_products, :total_image_count, :integer, default: 0, null: false, if_not_exists: true
5
+
6
+ add_index :spree_variants, :image_count, if_not_exists: true
7
+ add_index :spree_products, :total_image_count, if_not_exists: true
8
+ end
9
+ end
@@ -11,6 +11,8 @@ module Spree
11
11
  class_option :lib_name, default: ''
12
12
  class_option :database, default: ''
13
13
  class_option :api, type: :boolean, default: false
14
+ class_option :javascript, type: :boolean, default: false
15
+ class_option :css, type: :string, default: ''
14
16
 
15
17
  def self.source_paths
16
18
  paths = superclass.source_paths
@@ -24,12 +26,22 @@ module Spree
24
26
 
25
27
  def generate_test_dummy
26
28
  puts 'Generating dummy Rails application...'
29
+ puts "Options: #{options.inspect}"
27
30
 
28
31
  args = [File.expand_path(dummy_path, destination_root)]
29
32
 
30
33
  # Database
31
34
  args << "--database=#{options[:database].presence || 'sqlite3'}"
32
35
 
36
+ # CSS framework (e.g., tailwind)
37
+ args << "--css=#{options[:css]}" if options[:css].present?
38
+
39
+ # JavaScript
40
+ args << '--skip-javascript' unless options[:javascript]
41
+
42
+ # Skip asset pipeline if no javascript or css is required
43
+ args << '--skip-asset-pipeline' unless options[:javascript] || options[:css].present?
44
+
33
45
  # Skip options
34
46
  args << '--force'
35
47
  args << '--skip-bundle'
@@ -55,6 +67,7 @@ module Spree
55
67
  # API mode (implies skip-asset-pipeline, skip-javascript, skip-hotwire)
56
68
  args << '--api' if options[:api]
57
69
 
70
+ puts "Rails app generator args: #{args.inspect}"
58
71
  Rails::Generators.invoke('app', args)
59
72
  inject_yaml_permitted_classes
60
73
  end
@@ -68,7 +81,6 @@ module Spree
68
81
  template 'rails/application.rb', "#{dummy_path}/config/application.rb", force: true
69
82
  template 'rails/routes.rb', "#{dummy_path}/config/routes.rb", force: true
70
83
  template 'rails/test.rb', "#{dummy_path}/config/environments/test.rb", force: true
71
- template 'initializers/devise.rb', "#{dummy_path}/config/initializers/devise.rb", force: true
72
84
  template "app/assets/config/manifest.js", "#{dummy_path}/app/assets/config/manifest.js", force: true unless options[:api]
73
85
  end
74
86
 
@@ -94,7 +106,7 @@ module Spree
94
106
  def inject_yaml_permitted_classes
95
107
  inside dummy_path do
96
108
  inject_into_file 'config/application.rb', %Q[
97
- config.active_record.yaml_column_permitted_classes = [Symbol, BigDecimal, ActiveSupport::HashWithIndifferentAccess]
109
+ config.active_record.yaml_column_permitted_classes = [Symbol, BigDecimal, ActiveSupport::HashWithIndifferentAccess, ActiveSupport::TimeWithZone]
98
110
  ], after: /config\.load_defaults.*$/, verbose: true
99
111
  end
100
112
  end
@@ -42,6 +42,7 @@ module Spree
42
42
  preference :credit_to_new_allocation, :boolean, default: false
43
43
  preference :disable_sku_validation, :boolean, default: false # when turned off disables the built-in SKU uniqueness validation
44
44
  preference :disable_store_presence_validation, :boolean, default: false # when turned off disables Store presence validation for Products and Payment Methods
45
+ preference :events_log_enabled, :boolean, default: true # Log all Spree events to Rails logger
45
46
  preference :expedited_exchanges, :boolean, default: false # NOTE this requires payment profiles to be supported on your gateway of choice as well as a delayed job handler to be configured with activejob. kicks off an exchange shipment upon return authorization save. charge customer if they do not return items within timely manner.
46
47
  preference :expedited_exchanges_days_window, :integer, default: 14 # the amount of days the customer has to return their item after the expedited exchange is shipped in order to avoid being charged
47
48
  preference :geocode_addresses, :boolean, default: true
@@ -20,21 +20,6 @@ module Spree
20
20
  @current_ability ||= Spree.ability_class.new(try_spree_current_user, { store: current_store })
21
21
  end
22
22
 
23
- def redirect_back_or_default(default)
24
- Spree::Deprecation.warn('redirect_back_or_default is deprecated and will be removed in Spree 5.2. Please use redirect_back(fallback_location: default) instead.')
25
- redirect_back(fallback_location: default)
26
- end
27
-
28
- def set_token
29
- Spree::Deprecation.warn('set_token is deprecated and will be removed in Spree 5.2. Please use create_token_cookie(token) instead.')
30
- cookies.permanent.signed[:token] ||= cookies.signed[:guest_token]
31
- cookies.permanent.signed[:token] ||= {
32
- value: generate_token,
33
- httponly: true
34
- }
35
- cookies.permanent.signed[:guest_token] ||= cookies.permanent.signed[:token]
36
- end
37
-
38
23
  def current_oauth_token
39
24
  get_last_access_token = ->(user) { Spree::OauthAccessToken.active_for(user).where(expires_in: nil).last }
40
25
  create_access_token = ->(user) { Spree::OauthAccessToken.create!(resource_owner: user) }
@@ -17,15 +17,19 @@ module Spree
17
17
  # Returns the currently selected currency.
18
18
  # @return [String] the currently selected currency, eg. `USD`
19
19
  def current_currency
20
- @current_currency ||= if defined?(session) && session.key?(:currency) && supported_currency?(session[:currency])
21
- session[:currency]
22
- elsif params[:currency].present? && supported_currency?(params[:currency])
23
- params[:currency]
24
- elsif current_store.present?
25
- current_store.default_currency
26
- else
27
- Spree::Store.default.default_currency
28
- end&.upcase
20
+ @current_currency ||= begin
21
+ currency = if defined?(session) && session.key?(:currency) && supported_currency?(session[:currency])
22
+ session[:currency]
23
+ elsif params[:currency].present? && supported_currency?(params[:currency])
24
+ params[:currency]
25
+ elsif current_store.present?
26
+ current_store.default_currency
27
+ else
28
+ Spree::Store.default.default_currency
29
+ end&.upcase
30
+ Spree::Current.currency = currency
31
+ currency
32
+ end
29
33
  end
30
34
 
31
35
  # Returns the list of supported currencies for the current store.
@@ -3,7 +3,7 @@ module Spree
3
3
  module ControllerHelpers
4
4
  module Search
5
5
  def build_searcher(params)
6
- Spree::Deprecation.warn("Spree::Core::ControllerHelpers::Search is deprecated and will be removed in Spree 6.")
6
+ Spree::Deprecation.warn("Spree::Core::ControllerHelpers::Search is deprecated and will be removed in Spree 5.5.")
7
7
 
8
8
  Spree.searcher_class.new(params).tap do |searcher|
9
9
  searcher.current_user = try_spree_current_user
@@ -60,7 +60,11 @@ module Spree
60
60
  private
61
61
 
62
62
  def current_tax_zone
63
- @current_tax_zone ||= @current_order&.tax_zone || Spree::Zone.default_tax
63
+ @current_tax_zone ||= begin
64
+ zone = @current_order&.tax_zone || Spree::Zone.default_tax || current_store.checkout_zone
65
+ Spree::Current.zone = zone
66
+ zone
67
+ end
64
68
  end
65
69
 
66
70
  def current_store_finder
@@ -12,6 +12,7 @@ module Spree
12
12
  :adjusters,
13
13
  :stock_splitters,
14
14
  :promotions,
15
+ :pricing,
15
16
  :line_item_comparison_hooks,
16
17
  :data_feed_types,
17
18
  :export_types,
@@ -27,14 +28,19 @@ module Spree
27
28
  :metafields,
28
29
  :analytics_events,
29
30
  :analytics_event_handlers,
30
- :integrations)
31
+ :integrations,
32
+ :subscribers)
31
33
  SpreeCalculators = Struct.new(:shipping_methods, :tax_rates, :promotion_actions_create_adjustments, :promotion_actions_create_item_adjustments)
32
34
  PromoEnvironment = Struct.new(:rules, :actions)
35
+ PricingEnvironment = Struct.new(:rules)
33
36
  SpreeValidators = Struct.new(:addresses)
34
37
  MetafieldsEnvironment = Struct.new(:types, :enabled_resources)
35
38
  isolate_namespace Spree
36
39
  engine_name 'spree'
37
40
 
41
+ # Add app/subscribers to autoload paths
42
+ config.paths.add 'app/subscribers', eager_load: true
43
+
38
44
  rake_tasks do
39
45
  load File.join(root, 'lib', 'tasks', 'exchanges.rake')
40
46
  end
@@ -43,13 +49,18 @@ module Spree
43
49
  app.config.spree = Environment.new(SpreeCalculators.new, SpreeValidators.new, Spree::Core::Configuration.new, Spree::Core::Dependencies.new)
44
50
 
45
51
  app.config.active_record.yaml_column_permitted_classes ||= []
46
- app.config.active_record.yaml_column_permitted_classes.concat([Symbol, BigDecimal, ActiveSupport::HashWithIndifferentAccess])
52
+ app.config.active_record.yaml_column_permitted_classes.concat([Symbol, BigDecimal, ActiveSupport::HashWithIndifferentAccess, ActiveSupport::TimeWithZone])
47
53
  Spree::Config = app.config.spree.preferences
48
54
  Spree::RuntimeConfig = app.config.spree.preferences # for compatibility
49
55
  Spree::Dependencies = app.config.spree.dependencies
50
56
  Spree::Deprecation = ActiveSupport::Deprecation.new('6.0', 'Spree')
51
57
  end
52
58
 
59
+ initializer 'spree.register.subscribers', before: :load_config_initializers do |app|
60
+ # Initialize subscribers array early so engines can add subscribers via initializers
61
+ app.config.spree.subscribers = []
62
+ end
63
+
53
64
  initializer 'spree.register.calculators', before: :after_initialize do |app|
54
65
  end
55
66
 
@@ -82,6 +93,12 @@ module Spree
82
93
  initializer 'spree.promo.register.promotion.calculators' do |app|
83
94
  end
84
95
 
96
+ # Pricing configuration for price lists and price rules
97
+ initializer 'spree.pricing.environment', after: 'spree.environment' do |app|
98
+ app.config.spree.pricing = PricingEnvironment.new
99
+ app.config.spree.pricing.rules = []
100
+ end
101
+
85
102
  # Promotion rules need to be evaluated on after initialize otherwise
86
103
  # Spree.user_class would be nil and users might experience errors related
87
104
  # to malformed model associations (Spree.user_class is only defined on
@@ -139,6 +156,7 @@ module Spree
139
156
  Spree::Promotion::Rules::ItemTotal,
140
157
  Spree::Promotion::Rules::Product,
141
158
  Spree::Promotion::Rules::User,
159
+ Spree::Promotion::Rules::CustomerGroup,
142
160
  Spree::Promotion::Rules::FirstOrder,
143
161
  Spree::Promotion::Rules::UserLoggedIn,
144
162
  Spree::Promotion::Rules::OneUsePerUser,
@@ -146,6 +164,13 @@ module Spree
146
164
  Spree::Promotion::Rules::OptionValue,
147
165
  ]
148
166
 
167
+ Rails.application.config.spree.pricing.rules.concat [
168
+ Spree::PriceRules::ZoneRule,
169
+ Spree::PriceRules::UserRule,
170
+ Spree::PriceRules::CustomerGroupRule,
171
+ Spree::PriceRules::VolumeRule
172
+ ]
173
+
149
174
  Rails.application.config.spree.promotions.actions = [
150
175
  Promotion::Actions::CreateAdjustment,
151
176
  Promotion::Actions::CreateItemAdjustments,
@@ -175,82 +200,6 @@ module Spree
175
200
  Spree::TaxonRules::Sale,
176
201
  ]
177
202
 
178
- Rails.application.config.spree.themes = [
179
- Spree::Themes::Default
180
- ]
181
-
182
- Rails.application.config.spree.theme_layout_sections = [
183
- Spree::PageSections::AnnouncementBar,
184
- Spree::PageSections::Header,
185
- Spree::PageSections::Newsletter,
186
- Spree::PageSections::Footer
187
- ]
188
-
189
- Rails.application.config.spree.pages = [
190
- Spree::Pages::Cart,
191
- Spree::Pages::Post,
192
- Spree::Pages::TaxonList,
193
- Spree::Pages::Custom,
194
- Spree::Pages::ProductDetails,
195
- Spree::Pages::ShopAll,
196
- Spree::Pages::Taxon,
197
- Spree::Pages::Wishlist,
198
- Spree::Pages::SearchResults,
199
- Spree::Pages::Checkout,
200
- Spree::Pages::Password,
201
- Spree::Pages::Homepage,
202
- Spree::Pages::Login,
203
- Spree::Pages::PostList,
204
- Spree::Pages::Account
205
- ]
206
-
207
- Rails.application.config.spree.page_sections = [
208
- Spree::PageSections::Breadcrumbs,
209
- Spree::PageSections::FeaturedPosts,
210
- Spree::PageSections::TaxonGrid,
211
- Spree::PageSections::ImageWithText,
212
- Spree::PageSections::FeaturedTaxon,
213
- Spree::PageSections::CollectionBanner,
214
- Spree::PageSections::ProductDetails,
215
- Spree::PageSections::MainPasswordFooter,
216
- Spree::PageSections::RelatedProducts,
217
- Spree::PageSections::CustomCode,
218
- Spree::PageSections::TaxonBanner,
219
- Spree::PageSections::FeaturedProduct,
220
- Spree::PageSections::ProductGrid,
221
- Spree::PageSections::ImageBanner,
222
- Spree::PageSections::PageTitle,
223
- Spree::PageSections::MainPasswordHeader,
224
- Spree::PageSections::PostDetails,
225
- Spree::PageSections::PostGrid,
226
- Spree::PageSections::FeaturedTaxons,
227
- Spree::PageSections::RichText,
228
- Spree::PageSections::Video,
229
- Spree::PageSections::Footer,
230
- Spree::PageSections::Newsletter,
231
- Spree::PageSections::Header,
232
- Spree::PageSections::AnnouncementBar
233
- ]
234
-
235
- Rails.application.config.spree.page_blocks = [
236
- Spree::PageBlocks::Link,
237
- Spree::PageBlocks::MegaNav,
238
- Spree::PageBlocks::MegaNavWithSubcategories,
239
- Spree::PageBlocks::Subheading,
240
- Spree::PageBlocks::Heading,
241
- Spree::PageBlocks::Nav,
242
- Spree::PageBlocks::Buttons,
243
- Spree::PageBlocks::Text,
244
- Spree::PageBlocks::NewsletterForm,
245
- Spree::PageBlocks::Image,
246
- Spree::PageBlocks::Products::Title,
247
- Spree::PageBlocks::Products::Share,
248
- Spree::PageBlocks::Products::Price,
249
- Spree::PageBlocks::Products::QuantitySelector,
250
- Spree::PageBlocks::Products::VariantPicker,
251
- Spree::PageBlocks::Products::BuyButtons
252
- ]
253
-
254
203
  Rails.application.config.spree.reports = [
255
204
  Spree::Reports::ProductsPerformance,
256
205
  Spree::Reports::SalesTotal
@@ -341,6 +290,20 @@ module Spree
341
290
  Rails.application.config.spree.validators.addresses = [
342
291
  Spree::Addresses::PhoneValidator
343
292
  ]
293
+
294
+ # Attach event log subscriber if enabled
295
+ if Spree::Config.events_log_enabled
296
+ Spree::EventLogSubscriber.attach_to_notifications
297
+ end
298
+
299
+ # Add core event subscribers
300
+ # Other engines add their subscribers in their own after_initialize blocks
301
+ Spree.subscribers.concat [
302
+ Spree::ExportSubscriber,
303
+ Spree::ReportSubscriber,
304
+ Spree::InvitationEmailSubscriber,
305
+ Spree::ProductMetricsSubscriber
306
+ ]
344
307
  end
345
308
 
346
309
  initializer 'spree.promo.register.promotions.actions' do |app|
@@ -379,6 +342,15 @@ module Spree
379
342
  end
380
343
  end
381
344
 
345
+ # Activate event subscribers after all engines have registered their subscribers
346
+ # This registers an after_initialize callback late, ensuring it runs after all engine callbacks
347
+ # Needed for console, jobs, and other contexts where to_prepare doesn't run
348
+ initializer 'spree.events.schedule_activation', after: :load_config_initializers do |app|
349
+ app.config.after_initialize do
350
+ Spree::Events.activate!
351
+ end
352
+ end
353
+
382
354
  config.to_prepare do
383
355
  # Ensure spree locale paths are present before decorators
384
356
  I18n.load_path.unshift(*(Dir.glob(
@@ -391,6 +363,17 @@ module Spree
391
363
  Dir.glob(File.join(File.dirname(__FILE__), '../../../app/**/*_decorator*.rb')) do |c|
392
364
  Rails.configuration.cache_classes ? require(c) : load(c)
393
365
  end
366
+
367
+ # Reset and re-activate event subscribers on code reload
368
+ # activate! will register all subscribers from Spree.subscribers
369
+ # Note: resolve_subscriber in register_subscribers! handles stale class references
370
+ Spree::Events.reset!
371
+ Spree::Events.activate!
372
+
373
+ # Re-attach event log subscriber if enabled
374
+ if Spree::Config.events_log_enabled
375
+ Spree::EventLogSubscriber.attach_to_notifications
376
+ end
394
377
  end
395
378
  end
396
379
  end
@@ -3,7 +3,7 @@ module Spree
3
3
  module Importer
4
4
  class Order
5
5
  def self.import(user, params)
6
- Spree::Deprecation.warn('Spree::Core::Importer::Order is deprecated and will be removed in Spree 6.0. Please use `Spree::Imports::Order` instead.')
6
+ Spree::Deprecation.warn('Spree::Core::Importer::Order is deprecated and will be removed in Spree 5.5. Please use `Spree::Imports::Order` instead.')
7
7
 
8
8
  ensure_country_id_from_params params[:ship_address_attributes]
9
9
  ensure_state_id_from_params params[:ship_address_attributes]
@@ -5,7 +5,7 @@ module Spree
5
5
  attr_reader :product, :product_attrs, :variants_attrs, :options_attrs, :store
6
6
 
7
7
  def initialize(product, product_params, options = {})
8
- Spree::Deprecation.warn('Spree::Core::Importer::Product is deprecated and will be removed in Spree 6.0. Please use `Spree::Imports::Product` instead.')
8
+ Spree::Deprecation.warn('Spree::Core::Importer::Product is deprecated and will be removed in Spree 5.5. Please use `Spree::Imports::Product` instead.')
9
9
 
10
10
  @store = options[:store] || Spree::Store.default
11
11
  @product = product || Spree::Product.new(product_params)
@@ -131,7 +131,9 @@ module Spree::Preferences::Preferable
131
131
  decimal_value ||= 0 unless nullable
132
132
  decimal_value.present? ? decimal_value.to_s.to_d : decimal_value
133
133
  when :integer
134
- value.to_i
134
+ int_value = value.presence
135
+ int_value ||= 0 unless nullable
136
+ int_value.present? ? int_value.to_i : int_value
135
137
  when :boolean
136
138
  if value.is_a?(FalseClass) ||
137
139
  value.nil? ||
@@ -162,6 +164,17 @@ module Spree::Preferences::Preferable
162
164
  else
163
165
  value.class.ancestors.include?(Hash) ? value : {}
164
166
  end
167
+ when :datetime
168
+ return nil if value.blank?
169
+
170
+ case value
171
+ when Time, Date, DateTime, ActiveSupport::TimeWithZone
172
+ value
173
+ when String
174
+ Time.zone.parse(value)
175
+ else
176
+ value.to_time
177
+ end
165
178
  else
166
179
  value
167
180
  end
@@ -0,0 +1,63 @@
1
+ module Spree
2
+ module Pricing
3
+ class Context
4
+ attr_reader :variant, :currency, :store, :zone, :user, :quantity, :date, :order
5
+
6
+ # Initializes the context
7
+ # @param variant [Spree::Variant]
8
+ # @param currency [String]
9
+ # @param store [Spree::Store]
10
+ # @param zone [Spree::Zone]
11
+ # @param user [Spree::User]
12
+ # @param quantity [Integer]
13
+ # @param date [Time]
14
+ # @param order [Spree::Order]
15
+ def initialize(variant: nil, currency:, store: nil, zone: nil, user: nil, quantity: nil, date: nil, order: nil)
16
+ @variant = variant
17
+ @currency = currency
18
+ @store = store || Spree::Current.store
19
+ @zone = zone || Spree::Current.zone
20
+ @user = user
21
+ @quantity = quantity
22
+ @date = date || Time.current
23
+ @order = order
24
+ end
25
+
26
+ # Returns a new context from a variant and currency
27
+ # @param variant [Spree::Variant]
28
+ # @param currency [String]
29
+ # @return [Spree::Pricing::Context]
30
+ def self.from_currency(variant, currency)
31
+ new(variant: variant, currency: currency)
32
+ end
33
+
34
+ def self.from_order(variant, order, quantity: nil)
35
+ new(
36
+ variant: variant,
37
+ currency: order.currency,
38
+ store: order.store,
39
+ zone: order.tax_zone || order.store.checkout_zone,
40
+ user: order.user,
41
+ quantity: quantity || order.line_items.find_by(variant: variant)&.quantity,
42
+ order: order
43
+ )
44
+ end
45
+
46
+ # Returns the cache key for the context
47
+ # @return [String]
48
+ def cache_key
49
+ [
50
+ 'spree',
51
+ 'pricing',
52
+ variant.id,
53
+ currency,
54
+ store&.id,
55
+ zone&.id,
56
+ user&.id,
57
+ quantity,
58
+ date&.to_i
59
+ ].compact.join('/')
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,129 @@
1
+ module Spree
2
+ module Pricing
3
+ class Resolver
4
+ attr_reader :context
5
+
6
+ # Initializes the resolver
7
+ # @param context [Spree::Pricing::Context]
8
+ def initialize(context)
9
+ @context = context
10
+ end
11
+
12
+ # Returns the best price for the variant
13
+ # @return [Spree::Price]
14
+ def resolve
15
+ Rails.cache.fetch(cache_key, expires_in: 15.minutes) do
16
+ find_best_price
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ # Returns the best price for the variant
23
+ # @return [Spree::Price]
24
+ def find_best_price
25
+ # Try to find a price from applicable price lists first
26
+ price_from_list = find_price_from_lists
27
+ return price_from_list if price_from_list
28
+
29
+ # Fall back to base price (no price_list_id)
30
+ find_base_price
31
+ end
32
+
33
+ # Returns the price from applicable price lists
34
+ # @return [Spree::Price]
35
+ def find_price_from_lists
36
+ applicable_price_lists.each do |price_list|
37
+ price = find_price_for_list(price_list)
38
+ return price if price
39
+ end
40
+
41
+ nil
42
+ end
43
+
44
+ # Returns the price lists that are applicable to the context
45
+ # @return [Array<Spree::PriceList>]
46
+ def applicable_price_lists
47
+ @applicable_price_lists ||= price_lists_for_context.select { |list| list.applicable?(context) }
48
+ end
49
+
50
+ # Returns the price lists for the context's store
51
+ # Uses Spree::Current.price_lists if the context matches, otherwise fetches directly
52
+ # @return [ActiveRecord::Relation<Spree::PriceList>]
53
+ def price_lists_for_context
54
+ if context.store == Spree::Current.store && context.currency == Spree::Current.currency
55
+ Spree::Current.price_lists
56
+ else
57
+ Spree::PriceList.for_context(context)
58
+ end
59
+ end
60
+
61
+ # Returns the price for a given price list
62
+ # @param price_list [Spree::PriceList]
63
+ # @return [Spree::Price]
64
+ def find_price_for_list(price_list)
65
+ currency = context.currency&.upcase
66
+
67
+ if prices.loaded?
68
+ prices.detect do |p|
69
+ p.currency == currency &&
70
+ p.price_list_id == price_list.id &&
71
+ p.amount.present? &&
72
+ !p.amount.zero?
73
+ end
74
+ else
75
+ context.variant.prices
76
+ .with_currency(currency)
77
+ .where(price_list_id: price_list.id)
78
+ .non_zero
79
+ .first
80
+ end
81
+ end
82
+
83
+ # Returns the base price for the variant in the current currency
84
+ # @return [Spree::Price]
85
+ def find_base_price
86
+ currency = context.currency&.upcase
87
+
88
+ price = if prices.loaded?
89
+ prices.detect do |p|
90
+ p.currency == currency &&
91
+ p.price_list_id.nil? &&
92
+ p.amount.present?
93
+ end
94
+ else
95
+ context.variant.prices
96
+ .with_currency(currency)
97
+ .where(price_list_id: nil)
98
+ .where.not(amount: nil)
99
+ .first
100
+ end
101
+
102
+ price || build_empty_price
103
+ end
104
+
105
+ # Returns the prices for the variant
106
+ # @return [ActiveRecord::Relation<Spree::Price>]
107
+ def prices
108
+ context.variant.prices
109
+ end
110
+
111
+ # Builds an empty price for the variant
112
+ # @return [Spree::Price]
113
+ def build_empty_price
114
+ context.variant.prices.build(
115
+ variant: context.variant,
116
+ currency: context.currency,
117
+ amount: nil,
118
+ price_list_id: nil
119
+ )
120
+ end
121
+
122
+ # Returns the cache key for the resolver
123
+ # @return [String]
124
+ def cache_key
125
+ "#{context.cache_key}/resolved_price"
126
+ end
127
+ end
128
+ end
129
+ end
@@ -5,7 +5,7 @@ module Spree
5
5
  attr_accessor :properties, :current_user, :current_currency, :current_store, :taxon
6
6
 
7
7
  def initialize(params)
8
- Spree::Deprecation.warn("Spree::Core::Search::Base is deprecated and will be removed in Spree 6. Please use `Spree::Products::Find` finder instead.")
8
+ Spree::Deprecation.warn("Spree::Core::Search::Base is deprecated and will be removed in Spree 5.5. Please use `Spree::Products::Find` finder instead.")
9
9
 
10
10
  @properties = {}
11
11
  @current_store = params[:current_store] || Spree::Store.default
@@ -2,7 +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
+ Spree::Deprecation.warn('generate_token is deprecated and will be removed in Spree 5.5. Please use Rails secure token generator: https://api.rubyonrails.org/classes/ActiveRecord/SecureToken/ClassMethods.html')
6
6
  loop do
7
7
  token = "#{random_token}#{unique_ending}"
8
8
  break token unless model_class.exists?(token: token)